From 605068982d945d4386a2df4915f5df5dadc55834 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Fri, 27 Sep 2019 11:36:53 -0300 Subject: [PATCH 01/49] api: WIP api rns resolver --- api/api.go | 10 ++++++++++ api/api_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/api/api.go b/api/api.go index 57633cbbef..a34abb0dd2 100644 --- a/api/api.go +++ b/api/api.go @@ -47,6 +47,7 @@ import ( "github.com/ethersphere/swarm/storage/feed" "github.com/ethersphere/swarm/storage/feed/lookup" "github.com/opentracing/opentracing-go" + rns "github.com/rsksmart/rds-swarm/resolver" ) var ( @@ -217,6 +218,15 @@ func (a *API) Store(ctx context.Context, data io.Reader, size int64, toEncrypt b // Resolve a name into a content-addressed hash // where address could be an ENS name, or a content addressed hash func (a *API) Resolve(ctx context.Context, address string) (storage.Address, error) { + // if address is .rsk, resolve it with RNS resolver + tld := path.Ext(address) + if strings.ToLower(tld) == ".rsk" { + resolved, err := rns.ResolveDomainAddress(address) + if err != nil { + return nil, err + } + return resolved[:], nil + } // if DNS is not configured, return an error if a.dns == nil { if hashMatcher.MatchString(address) { diff --git a/api/api_test.go b/api/api_test.go index b2dbebf8a6..dcf6abb3ce 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -303,6 +303,50 @@ func TestAPIResolve(t *testing.T) { } } +// TestRNSResolver tests resolving Address which can either contain content hashes +// or RNS names +func TestRNSResolver(t *testing.T) { + //doesntResolve := newTestResolveValidator("") + + rnsDomain := "marcelosdomain.rsk" + rnsAddress := "0xfF33bC3B7324C2A808A9D415935f8D991E6C406c" + api := NewAPI(nil, nil, nil, nil, nil) + + tests := []struct { + desc string + r Resolver + addr string + result string + err error + }{ + { + desc: "No resolvers, returns error", + r: api.Resolve(nil, rnsDomain), + addr: rnsAddress, + }, + } + for _, x := range tests { + t.Run(x.desc, func(t *testing.T) { + res, err := x.r.Resolve(x.addr) + if err == nil { + if x.err != nil { + t.Fatalf("expected error %q, got result %q", x.err, res.Hex()) + } + if res.Hex() != x.result { + t.Fatalf("expected result %q, got %q", x.result, res.Hex()) + } + } else { + if x.err == nil { + t.Fatalf("expected no error, got %q", err) + } + if err.Error() != x.err.Error() { + t.Fatalf("expected error %q, got %q", x.err, err) + } + } + }) + } +} + func TestMultiResolver(t *testing.T) { doesntResolve := newTestResolveValidator("") From a2f4fec5e6634d2a4551722a8f516760150cb04b Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 30 Sep 2019 11:58:49 -0300 Subject: [PATCH 02/49] rns test --- api/api_test.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index dcf6abb3ce..af36369551 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -306,28 +306,31 @@ func TestAPIResolve(t *testing.T) { // TestRNSResolver tests resolving Address which can either contain content hashes // or RNS names func TestRNSResolver(t *testing.T) { - //doesntResolve := newTestResolveValidator("") + ctx := context.TODO() rnsDomain := "marcelosdomain.rsk" rnsAddress := "0xfF33bC3B7324C2A808A9D415935f8D991E6C406c" - api := NewAPI(nil, nil, nil, nil, nil) tests := []struct { desc string - r Resolver + api *API + ctx context.Context + domain string addr string result string err error }{ { - desc: "No resolvers, returns error", - r: api.Resolve(nil, rnsDomain), - addr: rnsAddress, + desc: "No resolvers, returns error", + api: NewAPI(nil, nil, nil, nil, nil), + domain: rnsDomain, + addr: rnsAddress, + ctx: ctx, }, } for _, x := range tests { t.Run(x.desc, func(t *testing.T) { - res, err := x.r.Resolve(x.addr) + res, err := x.api.Resolve(x.ctx, x.addr) if err == nil { if x.err != nil { t.Fatalf("expected error %q, got result %q", x.err, res.Hex()) From b5fb1dc6696424f5b7e9d760721da1fc5117c3e2 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 7 Oct 2019 11:08:56 -0300 Subject: [PATCH 03/49] swarm module added rns --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 41c35c3c4e..0da90b227b 100644 --- a/go.mod +++ b/go.mod @@ -67,6 +67,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect + github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect diff --git a/go.sum b/go.sum index 53aa19a0e9..cc6a1e37ee 100644 --- a/go.sum +++ b/go.sum @@ -228,6 +228,8 @@ github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwde github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8 h1:yl0A7ymLJZUjllzSWQgz+68yDDljclq4VOwIR9HPO6g= +github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= From 71ca0c4d9832b0381f24a95a24748468d3fee8ef Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 7 Oct 2019 14:44:41 -0300 Subject: [PATCH 04/49] api: fixed test rns --- api/api_test.go | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 1aeda53d38..f4432dd3f0 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -309,7 +309,7 @@ func TestRNSResolver(t *testing.T) { ctx := context.TODO() rnsDomain := "marcelosdomain.rsk" - rnsAddress := "0xfF33bC3B7324C2A808A9D415935f8D991E6C406c" + rnsAddress := "000000000000000000000000ff33bc3b7324c2a808a9d415935f8d991e6c406c" tests := []struct { desc string @@ -330,22 +330,14 @@ func TestRNSResolver(t *testing.T) { } for _, x := range tests { t.Run(x.desc, func(t *testing.T) { - res, err := x.api.Resolve(x.ctx, x.addr) - if err == nil { - if x.err != nil { - t.Fatalf("expected error %q, got result %q", x.err, res.Hex()) - } - if res.Hex() != x.result { - t.Fatalf("expected result %q, got %q", x.result, res.Hex()) - } - } else { - if x.err == nil { - t.Fatalf("expected no error, got %q", err) - } - if err.Error() != x.err.Error() { - t.Fatalf("expected error %q, got %q", x.err, err) - } + res, err := x.api.Resolve(x.ctx, x.domain) + if err != nil { + t.Fatalf(err.Error()) } + if res.Hex() != x.addr { + t.Fatalf("expected result %q, got %q", x.addr, res.Hex()) + } + }) } } From 99d1211f273a79520ea5f3d3dbb1151196e04bce Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Tue, 29 Oct 2019 16:49:14 -0300 Subject: [PATCH 05/49] added rds-swarm mod --- go.mod | 3 ++- go.sum | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 72c189a4d9..48a283b685 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 // indirect github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 // indirect + github.com/caarlos0/env v3.5.0+incompatible // indirect github.com/cespare/cp v1.1.1 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect github.com/containerd/containerd v1.2.7 // indirect @@ -68,7 +69,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8 + github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect diff --git a/go.sum b/go.sum index ead06bec8a..ba6fc59d90 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= +github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -232,6 +234,10 @@ github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8 h1:yl0A7ymLJZUjllzSWQgz+68yDDljclq4VOwIR9HPO6g= github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= +github.com/rsksmart/rds-swarm v0.0.0-20191010175109-4fd7cae9e538 h1:SPSBFh4syBY8X16kkJe6SBMEZuO/oXQu2gv4XFfKmiY= +github.com/rsksmart/rds-swarm v0.0.0-20191010175109-4fd7cae9e538/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= +github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad h1:RPQtR6EeZtD4SGCeJwPde88ZNWa1FCRrkyRvoz05WV8= +github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= From 2bee967298a9c2df3888c68eb7f77e71ab4b8c64 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Wed, 6 Nov 2019 10:53:54 -0300 Subject: [PATCH 06/49] api: changed resolution to ResolveDomainContent --- api/api.go | 2 +- api/api_test.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api/api.go b/api/api.go index a34abb0dd2..329fa17113 100644 --- a/api/api.go +++ b/api/api.go @@ -221,7 +221,7 @@ func (a *API) Resolve(ctx context.Context, address string) (storage.Address, err // if address is .rsk, resolve it with RNS resolver tld := path.Ext(address) if strings.ToLower(tld) == ".rsk" { - resolved, err := rns.ResolveDomainAddress(address) + resolved, err := rns.ResolveDomainContent(address) if err != nil { return nil, err } diff --git a/api/api_test.go b/api/api_test.go index 2556755514..6129050c69 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -303,13 +303,14 @@ func TestAPIResolve(t *testing.T) { } } -// TestRNSResolver tests resolving Address which can either contain content hashes +// TestRNSResolver tests resolving Content which can either contain content hashes // or RNS names func TestRNSResolver(t *testing.T) { ctx := context.TODO() rnsDomain := "marcelosdomain.rsk" - rnsAddress := "000000000000000000000000ff33bc3b7324c2a808a9d415935f8d991e6c406c" + //rnsAddress := "000000000000000000000000ff33bc3b7324c2a808a9d415935f8d991e6c406c" + rnsContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" tests := []struct { desc string @@ -324,7 +325,7 @@ func TestRNSResolver(t *testing.T) { desc: "No resolvers, returns error", api: NewAPI(nil, nil, nil, nil, nil), domain: rnsDomain, - addr: rnsAddress, + addr: rnsContent, ctx: ctx, }, } From 1ab9295ca51bb37a64df52f28e0d3065cb308d57 Mon Sep 17 00:00:00 2001 From: mortelli Date: Thu, 7 Nov 2019 15:22:04 -0300 Subject: [PATCH 07/49] api: refactor TestRNSResolver function --- api/api_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 6129050c69..d97f1a09d2 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -306,13 +306,10 @@ func TestAPIResolve(t *testing.T) { // TestRNSResolver tests resolving Content which can either contain content hashes // or RNS names func TestRNSResolver(t *testing.T) { - ctx := context.TODO() - rnsDomain := "marcelosdomain.rsk" - //rnsAddress := "000000000000000000000000ff33bc3b7324c2a808a9d415935f8d991e6c406c" rnsContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" - tests := []struct { + type test struct { desc string api *API ctx context.Context @@ -320,15 +317,18 @@ func TestRNSResolver(t *testing.T) { addr string result string err error - }{ + } + + tests := []*test{ { desc: "No resolvers, returns error", api: NewAPI(nil, nil, nil, nil, nil), domain: rnsDomain, addr: rnsContent, - ctx: ctx, + ctx: context.TODO(), }, } + for _, x := range tests { t.Run(x.desc, func(t *testing.T) { res, err := x.api.Resolve(x.ctx, x.domain) From 26239b38d29b786f1a4f38a03b013346f0165a8f Mon Sep 17 00:00:00 2001 From: mortelli Date: Thu, 7 Nov 2019 16:06:11 -0300 Subject: [PATCH 08/49] api: refactor TestRNSResolver function --- api/api_test.go | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index d97f1a09d2..719a8f71f3 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -306,37 +306,34 @@ func TestAPIResolve(t *testing.T) { // TestRNSResolver tests resolving Content which can either contain content hashes // or RNS names func TestRNSResolver(t *testing.T) { - rnsDomain := "marcelosdomain.rsk" - rnsContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" + rnsAddr := "marcelosdomain.rsk" + resolvedContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" type test struct { - desc string - api *API - ctx context.Context - domain string - addr string - result string - err error + desc string + ctx context.Context + addr string + content string } tests := []*test{ { - desc: "No resolvers, returns error", - api: NewAPI(nil, nil, nil, nil, nil), - domain: rnsDomain, - addr: rnsContent, - ctx: context.TODO(), + desc: "resolve known RSK domain", + addr: rnsAddr, + content: resolvedContent, + ctx: context.TODO(), }, } for _, x := range tests { t.Run(x.desc, func(t *testing.T) { - res, err := x.api.Resolve(x.ctx, x.domain) + api := NewAPI(nil, nil, nil, nil, nil) + res, err := api.Resolve(x.ctx, x.addr) if err != nil { t.Fatalf(err.Error()) } - if res.Hex() != x.addr { - t.Fatalf("expected result %q, got %q", x.addr, res.Hex()) + if res.Hex() != x.content { + t.Fatalf("expected result %q, got %q", x.content, res.Hex()) } }) From 402c6ee77503d29dcc3b739e0061554a4d7c948c Mon Sep 17 00:00:00 2001 From: mortelli Date: Thu, 7 Nov 2019 16:44:03 -0300 Subject: [PATCH 09/49] api: replace path.Ext call with publicsuffix.PublicSuffix call in Resolve function --- api/api.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/api.go b/api/api.go index 329fa17113..3ef6119930 100644 --- a/api/api.go +++ b/api/api.go @@ -48,6 +48,7 @@ import ( "github.com/ethersphere/swarm/storage/feed/lookup" "github.com/opentracing/opentracing-go" rns "github.com/rsksmart/rds-swarm/resolver" + "golang.org/x/net/publicsuffix" ) var ( @@ -219,8 +220,8 @@ func (a *API) Store(ctx context.Context, data io.Reader, size int64, toEncrypt b // where address could be an ENS name, or a content addressed hash func (a *API) Resolve(ctx context.Context, address string) (storage.Address, error) { // if address is .rsk, resolve it with RNS resolver - tld := path.Ext(address) - if strings.ToLower(tld) == ".rsk" { + eTLD, _ := publicsuffix.PublicSuffix(address) + if strings.ToLower(eTLD) == "rsk" { resolved, err := rns.ResolveDomainContent(address) if err != nil { return nil, err From 2fc2b51e03fe83b9e9b6e7f82867e246e0ad1adf Mon Sep 17 00:00:00 2001 From: mortelli Date: Thu, 7 Nov 2019 16:55:56 -0300 Subject: [PATCH 10/49] api: remove ToLower call for TLD in Resolve function --- api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.go b/api/api.go index 3ef6119930..70bc659170 100644 --- a/api/api.go +++ b/api/api.go @@ -221,7 +221,7 @@ func (a *API) Store(ctx context.Context, data io.Reader, size int64, toEncrypt b func (a *API) Resolve(ctx context.Context, address string) (storage.Address, error) { // if address is .rsk, resolve it with RNS resolver eTLD, _ := publicsuffix.PublicSuffix(address) - if strings.ToLower(eTLD) == "rsk" { + if eTLD == "rsk" { resolved, err := rns.ResolveDomainContent(address) if err != nil { return nil, err From b8a1461ef6c38607619fc3fd627cc1849965e674 Mon Sep 17 00:00:00 2001 From: mortelli Date: Thu, 7 Nov 2019 16:58:36 -0300 Subject: [PATCH 11/49] api: refactor TestRNSResolve function --- api/api_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 719a8f71f3..d9f521ee8f 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -303,9 +303,8 @@ func TestAPIResolve(t *testing.T) { } } -// TestRNSResolver tests resolving Content which can either contain content hashes -// or RNS names -func TestRNSResolver(t *testing.T) { +// TestRNSResolve tests resolving content from RNS names +func TestRNSResolve(t *testing.T) { rnsAddr := "marcelosdomain.rsk" resolvedContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" @@ -318,7 +317,7 @@ func TestRNSResolver(t *testing.T) { tests := []*test{ { - desc: "resolve known RSK domain", + desc: "resolve valid RSK domain", addr: rnsAddr, content: resolvedContent, ctx: context.TODO(), From dd9bc013ae1b0cfec381d005d75130678f735bf2 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Thu, 7 Nov 2019 17:47:56 -0300 Subject: [PATCH 12/49] api,cmd: added rns flag --- api/config.go | 2 + cmd/swarm/config.go | 9 + cmd/swarm/flags.go | 5 + cmd/swarm/main.go | 1 + go.mod | 4 +- go.sum | 8 +- swarm.go | 9 + vendor/github.com/caarlos0/env | 1 + vendor/github.com/rsksmart/rds-swarm | 1 + .../x/net/publicsuffix/example_test.go | 93 + vendor/golang.org/x/net/publicsuffix/gen.go | 717 + vendor/golang.org/x/net/publicsuffix/list.go | 181 + .../x/net/publicsuffix/list_test.go | 509 + vendor/golang.org/x/net/publicsuffix/table.go | 9962 +++++++++ .../x/net/publicsuffix/table_test.go | 17632 ++++++++++++++++ 15 files changed, 29128 insertions(+), 6 deletions(-) create mode 160000 vendor/github.com/caarlos0/env create mode 160000 vendor/github.com/rsksmart/rds-swarm create mode 100755 vendor/golang.org/x/net/publicsuffix/example_test.go create mode 100755 vendor/golang.org/x/net/publicsuffix/gen.go create mode 100755 vendor/golang.org/x/net/publicsuffix/list.go create mode 100755 vendor/golang.org/x/net/publicsuffix/list_test.go create mode 100755 vendor/golang.org/x/net/publicsuffix/table.go create mode 100755 vendor/golang.org/x/net/publicsuffix/table_test.go diff --git a/api/config.go b/api/config.go index 08eda51449..ef2098c745 100644 --- a/api/config.go +++ b/api/config.go @@ -67,6 +67,7 @@ type Config struct { Pss *pss.Params EnsRoot common.Address EnsAPIs []string + RnsAPI string Path string ListenAddr string Port string @@ -104,6 +105,7 @@ func NewConfig() *Config { Pss: pss.NewParams(), EnsRoot: ens.TestNetAddress, EnsAPIs: nil, + RnsAPI: "", Path: node.DefaultDataDir(), ListenAddr: DefaultHTTPListenAddr, Port: DefaultHTTPPort, diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index c5f32a92b6..c7155fd4c5 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -78,6 +78,7 @@ const ( SwarmEnvLightNodeEnable = "SWARM_LIGHT_NODE_ENABLE" SwarmEnvDeliverySkipCheck = "SWARM_DELIVERY_SKIP_CHECK" SwarmEnvENSAPI = "SWARM_ENS_API" + SwarmEnvRNSAPI = "SWARM_RNS_API" SwarmEnvENSAddr = "SWARM_ENS_ADDR" SwarmEnvCORS = "SWARM_CORS" SwarmEnvBootnodes = "SWARM_BOOTNODES" @@ -246,6 +247,14 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi } currentConfig.EnsAPIs = ensAPIs } + if ctx.GlobalIsSet(RnsAPIFlag.Name) { + rnsAPI := ctx.GlobalStringSlice(RnsAPIFlag.Name) + // preserve backward compatibility to disable RNS with --rns-api="" + if len(rnsAPI) == 1 && rnsAPI[0] == "" { + rnsAPI = nil + } + currentConfig.RnsAPI = rnsAPI[0] + } if cors := ctx.GlobalString(CorsStringFlag.Name); cors != "" { currentConfig.Cors = cors } diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index efff6af25f..523405ebf6 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -126,6 +126,11 @@ var ( Usage: "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url", EnvVar: SwarmEnvENSAPI, } + RnsAPIFlag = cli.StringSliceFlag{ + Name: "rns-api", + Usage: "RNS API endpoint for a TLD and with contract address, can be repeated, format [contract-addr@]url", + EnvVar: SwarmEnvRNSAPI, + } SwarmApiFlag = cli.StringFlag{ Name: "bzzapi", Usage: "Specifies the Swarm HTTP endpoint to connect to", diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index b7c5123732..40400dd121 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -176,6 +176,7 @@ func init() { // bzzd-specific flags CorsStringFlag, EnsAPIFlag, + RnsAPIFlag, SwarmTomlConfigPathFlag, //swap flags SwarmSwapEnabledFlag, diff --git a/go.mod b/go.mod index 48a283b685..89588a95b3 100644 --- a/go.mod +++ b/go.mod @@ -69,7 +69,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad + github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect @@ -83,7 +83,7 @@ require ( github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect go.uber.org/atomic v1.4.0 // indirect golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 - golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 + golang.org/x/net v0.0.0-20191105084925-a882066a44e0 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect diff --git a/go.sum b/go.sum index ba6fc59d90..62f5ec20a3 100644 --- a/go.sum +++ b/go.sum @@ -232,12 +232,10 @@ github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwde github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8 h1:yl0A7ymLJZUjllzSWQgz+68yDDljclq4VOwIR9HPO6g= -github.com/rsksmart/rds-swarm v0.0.0-20190701203119-a553ab7dc3f8/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= -github.com/rsksmart/rds-swarm v0.0.0-20191010175109-4fd7cae9e538 h1:SPSBFh4syBY8X16kkJe6SBMEZuO/oXQu2gv4XFfKmiY= -github.com/rsksmart/rds-swarm v0.0.0-20191010175109-4fd7cae9e538/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad h1:RPQtR6EeZtD4SGCeJwPde88ZNWa1FCRrkyRvoz05WV8= github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= +github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a h1:wH3H0+fVZPrjTFV1DVypY96/gocO7cXWwRUMQTV6/Y8= +github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -294,6 +292,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg= +golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= diff --git a/swarm.go b/swarm.go index 235c8b34aa..d62eef281e 100644 --- a/swarm.go +++ b/swarm.go @@ -61,6 +61,7 @@ import ( "github.com/ethersphere/swarm/storage/pin" "github.com/ethersphere/swarm/swap" "github.com/ethersphere/swarm/tracing" + rns "github.com/rsksmart/rds-swarm/config" ) var ( @@ -182,6 +183,14 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e resolver = api.NewMultiResolver(opts...) self.dns = resolver } + if config.RnsAPI != "" { + _, endpoint, addr := parseEnsAPIAddress(config.RnsAPI) + if err != nil { + return nil, err + } + rns.SetRSKConfiguration(endpoint, addr.String()) + } + // check that we are not in the old database schema // if so - fail and exit isLegacy := localstore.IsLegacyDatabase(config.ChunkDbPath) diff --git a/vendor/github.com/caarlos0/env b/vendor/github.com/caarlos0/env new file mode 160000 index 0000000000..c67acb9fd5 --- /dev/null +++ b/vendor/github.com/caarlos0/env @@ -0,0 +1 @@ +Subproject commit c67acb9fd501532e9a396a2f185f617f849727dd diff --git a/vendor/github.com/rsksmart/rds-swarm b/vendor/github.com/rsksmart/rds-swarm new file mode 160000 index 0000000000..85b02e96e2 --- /dev/null +++ b/vendor/github.com/rsksmart/rds-swarm @@ -0,0 +1 @@ +Subproject commit 85b02e96e2adf3f771b3be2994b72d982adb24ea diff --git a/vendor/golang.org/x/net/publicsuffix/example_test.go b/vendor/golang.org/x/net/publicsuffix/example_test.go new file mode 100755 index 0000000000..3f44dcfe75 --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/example_test.go @@ -0,0 +1,93 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package publicsuffix_test + +import ( + "fmt" + "strings" + + "golang.org/x/net/publicsuffix" +) + +// This example demonstrates looking up several domains' eTLDs (effective Top +// Level Domains) in the PSL (Public Suffix List) snapshot. For each eTLD, the +// example also determines whether the eTLD is ICANN managed, privately +// managed, or unmanaged (not explicitly in the PSL). +// +// See https://publicsuffix.org/ for the underlying PSL data. +func ExamplePublicSuffix_manager() { + domains := []string{ + "amazon.co.uk", + "books.amazon.co.uk", + "www.books.amazon.co.uk", + "amazon.com", + "", + "example0.debian.net", + "example1.debian.org", + "", + "golang.dev", + "golang.net", + "play.golang.org", + "gophers.in.space.museum", + "", + "0emm.com", + "a.0emm.com", + "b.c.d.0emm.com", + "", + "there.is.no.such-tld", + "", + // Examples from the PublicSuffix function's documentation. + "foo.org", + "foo.co.uk", + "foo.dyndns.org", + "foo.blogspot.co.uk", + "cromulent", + } + + for _, domain := range domains { + if domain == "" { + fmt.Println(">") + continue + } + eTLD, icann := publicsuffix.PublicSuffix(domain) + + // Only ICANN managed domains can have a single label. Privately + // managed domains must have multiple labels. + manager := "Unmanaged" + if icann { + manager = "ICANN Managed" + } else if strings.IndexByte(eTLD, '.') >= 0 { + manager = "Privately Managed" + } + + fmt.Printf("> %24s%16s is %s\n", domain, eTLD, manager) + } + + // Output: + // > amazon.co.uk co.uk is ICANN Managed + // > books.amazon.co.uk co.uk is ICANN Managed + // > www.books.amazon.co.uk co.uk is ICANN Managed + // > amazon.com com is ICANN Managed + // > + // > example0.debian.net debian.net is Privately Managed + // > example1.debian.org org is ICANN Managed + // > + // > golang.dev dev is ICANN Managed + // > golang.net net is ICANN Managed + // > play.golang.org org is ICANN Managed + // > gophers.in.space.museum space.museum is ICANN Managed + // > + // > 0emm.com com is ICANN Managed + // > a.0emm.com a.0emm.com is Privately Managed + // > b.c.d.0emm.com d.0emm.com is Privately Managed + // > + // > there.is.no.such-tld such-tld is Unmanaged + // > + // > foo.org org is ICANN Managed + // > foo.co.uk co.uk is ICANN Managed + // > foo.dyndns.org dyndns.org is Privately Managed + // > foo.blogspot.co.uk blogspot.co.uk is Privately Managed + // > cromulent cromulent is Unmanaged +} diff --git a/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/golang.org/x/net/publicsuffix/gen.go new file mode 100755 index 0000000000..372ffbb24c --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/gen.go @@ -0,0 +1,717 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates table.go and table_test.go based on the authoritative +// public suffix list at https://publicsuffix.org/list/effective_tld_names.dat +// +// The version is derived from +// https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat +// and a human-readable form is at +// https://github.com/publicsuffix/list/commits/master/public_suffix_list.dat +// +// To fetch a particular git revision, such as 5c70ccd250, pass +// -url "https://raw.githubusercontent.com/publicsuffix/list/5c70ccd250/public_suffix_list.dat" +// and -version "an explicit version string". + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "go/format" + "io" + "io/ioutil" + "net/http" + "os" + "regexp" + "sort" + "strings" + + "golang.org/x/net/idna" +) + +const ( + // These sum of these four values must be no greater than 32. + nodesBitsChildren = 10 + nodesBitsICANN = 1 + nodesBitsTextOffset = 15 + nodesBitsTextLength = 6 + + // These sum of these four values must be no greater than 32. + childrenBitsWildcard = 1 + childrenBitsNodeType = 2 + childrenBitsHi = 14 + childrenBitsLo = 14 +) + +var ( + maxChildren int + maxTextOffset int + maxTextLength int + maxHi uint32 + maxLo uint32 +) + +func max(a, b int) int { + if a < b { + return b + } + return a +} + +func u32max(a, b uint32) uint32 { + if a < b { + return b + } + return a +} + +const ( + nodeTypeNormal = 0 + nodeTypeException = 1 + nodeTypeParentOnly = 2 + numNodeType = 3 +) + +func nodeTypeStr(n int) string { + switch n { + case nodeTypeNormal: + return "+" + case nodeTypeException: + return "!" + case nodeTypeParentOnly: + return "o" + } + panic("unreachable") +} + +const ( + defaultURL = "https://publicsuffix.org/list/effective_tld_names.dat" + gitCommitURL = "https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat" +) + +var ( + labelEncoding = map[string]uint32{} + labelsList = []string{} + labelsMap = map[string]bool{} + rules = []string{} + numICANNRules = 0 + + // validSuffixRE is used to check that the entries in the public suffix + // list are in canonical form (after Punycode encoding). Specifically, + // capital letters are not allowed. + validSuffixRE = regexp.MustCompile(`^[a-z0-9_\!\*\-\.]+$`) + + shaRE = regexp.MustCompile(`"sha":"([^"]+)"`) + dateRE = regexp.MustCompile(`"committer":{[^{]+"date":"([^"]+)"`) + + comments = flag.Bool("comments", false, "generate table.go comments, for debugging") + subset = flag.Bool("subset", false, "generate only a subset of the full table, for debugging") + url = flag.String("url", defaultURL, "URL of the publicsuffix.org list. If empty, stdin is read instead") + v = flag.Bool("v", false, "verbose output (to stderr)") + version = flag.String("version", "", "the effective_tld_names.dat version") +) + +func main() { + if err := main1(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func main1() error { + flag.Parse() + if nodesBitsTextLength+nodesBitsTextOffset+nodesBitsICANN+nodesBitsChildren > 32 { + return fmt.Errorf("not enough bits to encode the nodes table") + } + if childrenBitsLo+childrenBitsHi+childrenBitsNodeType+childrenBitsWildcard > 32 { + return fmt.Errorf("not enough bits to encode the children table") + } + if *version == "" { + if *url != defaultURL { + return fmt.Errorf("-version was not specified, and the -url is not the default one") + } + sha, date, err := gitCommit() + if err != nil { + return err + } + *version = fmt.Sprintf("publicsuffix.org's public_suffix_list.dat, git revision %s (%s)", sha, date) + } + var r io.Reader = os.Stdin + if *url != "" { + res, err := http.Get(*url) + if err != nil { + return err + } + if res.StatusCode != http.StatusOK { + return fmt.Errorf("bad GET status for %s: %d", *url, res.Status) + } + r = res.Body + defer res.Body.Close() + } + + var root node + icann := false + br := bufio.NewReader(r) + for { + s, err := br.ReadString('\n') + if err != nil { + if err == io.EOF { + break + } + return err + } + s = strings.TrimSpace(s) + if strings.Contains(s, "BEGIN ICANN DOMAINS") { + if len(rules) != 0 { + return fmt.Errorf(`expected no rules before "BEGIN ICANN DOMAINS"`) + } + icann = true + continue + } + if strings.Contains(s, "END ICANN DOMAINS") { + icann, numICANNRules = false, len(rules) + continue + } + if s == "" || strings.HasPrefix(s, "//") { + continue + } + s, err = idna.ToASCII(s) + if err != nil { + return err + } + if !validSuffixRE.MatchString(s) { + return fmt.Errorf("bad publicsuffix.org list data: %q", s) + } + + if *subset { + switch { + case s == "ac.jp" || strings.HasSuffix(s, ".ac.jp"): + case s == "ak.us" || strings.HasSuffix(s, ".ak.us"): + case s == "ao" || strings.HasSuffix(s, ".ao"): + case s == "ar" || strings.HasSuffix(s, ".ar"): + case s == "arpa" || strings.HasSuffix(s, ".arpa"): + case s == "cy" || strings.HasSuffix(s, ".cy"): + case s == "dyndns.org" || strings.HasSuffix(s, ".dyndns.org"): + case s == "jp": + case s == "kobe.jp" || strings.HasSuffix(s, ".kobe.jp"): + case s == "kyoto.jp" || strings.HasSuffix(s, ".kyoto.jp"): + case s == "om" || strings.HasSuffix(s, ".om"): + case s == "uk" || strings.HasSuffix(s, ".uk"): + case s == "uk.com" || strings.HasSuffix(s, ".uk.com"): + case s == "tw" || strings.HasSuffix(s, ".tw"): + case s == "zw" || strings.HasSuffix(s, ".zw"): + case s == "xn--p1ai" || strings.HasSuffix(s, ".xn--p1ai"): + // xn--p1ai is Russian-Cyrillic "рф". + default: + continue + } + } + + rules = append(rules, s) + + nt, wildcard := nodeTypeNormal, false + switch { + case strings.HasPrefix(s, "*."): + s, nt = s[2:], nodeTypeParentOnly + wildcard = true + case strings.HasPrefix(s, "!"): + s, nt = s[1:], nodeTypeException + } + labels := strings.Split(s, ".") + for n, i := &root, len(labels)-1; i >= 0; i-- { + label := labels[i] + n = n.child(label) + if i == 0 { + if nt != nodeTypeParentOnly && n.nodeType == nodeTypeParentOnly { + n.nodeType = nt + } + n.icann = n.icann && icann + n.wildcard = n.wildcard || wildcard + } + labelsMap[label] = true + } + } + labelsList = make([]string, 0, len(labelsMap)) + for label := range labelsMap { + labelsList = append(labelsList, label) + } + sort.Strings(labelsList) + + if err := generate(printReal, &root, "table.go"); err != nil { + return err + } + if err := generate(printTest, &root, "table_test.go"); err != nil { + return err + } + return nil +} + +func generate(p func(io.Writer, *node) error, root *node, filename string) error { + buf := new(bytes.Buffer) + if err := p(buf, root); err != nil { + return err + } + b, err := format.Source(buf.Bytes()) + if err != nil { + return err + } + return ioutil.WriteFile(filename, b, 0644) +} + +func gitCommit() (sha, date string, retErr error) { + res, err := http.Get(gitCommitURL) + if err != nil { + return "", "", err + } + if res.StatusCode != http.StatusOK { + return "", "", fmt.Errorf("bad GET status for %s: %d", gitCommitURL, res.Status) + } + defer res.Body.Close() + b, err := ioutil.ReadAll(res.Body) + if err != nil { + return "", "", err + } + if m := shaRE.FindSubmatch(b); m != nil { + sha = string(m[1]) + } + if m := dateRE.FindSubmatch(b); m != nil { + date = string(m[1]) + } + if sha == "" || date == "" { + retErr = fmt.Errorf("could not find commit SHA and date in %s", gitCommitURL) + } + return sha, date, retErr +} + +func printTest(w io.Writer, n *node) error { + fmt.Fprintf(w, "// generated by go run gen.go; DO NOT EDIT\n\n") + fmt.Fprintf(w, "package publicsuffix\n\nconst numICANNRules = %d\n\nvar rules = [...]string{\n", numICANNRules) + for _, rule := range rules { + fmt.Fprintf(w, "%q,\n", rule) + } + fmt.Fprintf(w, "}\n\nvar nodeLabels = [...]string{\n") + if err := n.walk(w, printNodeLabel); err != nil { + return err + } + fmt.Fprintf(w, "}\n") + return nil +} + +func printReal(w io.Writer, n *node) error { + const header = `// generated by go run gen.go; DO NOT EDIT + +package publicsuffix + +const version = %q + +const ( + nodesBitsChildren = %d + nodesBitsICANN = %d + nodesBitsTextOffset = %d + nodesBitsTextLength = %d + + childrenBitsWildcard = %d + childrenBitsNodeType = %d + childrenBitsHi = %d + childrenBitsLo = %d +) + +const ( + nodeTypeNormal = %d + nodeTypeException = %d + nodeTypeParentOnly = %d +) + +// numTLD is the number of top level domains. +const numTLD = %d + +` + fmt.Fprintf(w, header, *version, + nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength, + childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo, + nodeTypeNormal, nodeTypeException, nodeTypeParentOnly, len(n.children)) + + text := combineText(labelsList) + if text == "" { + return fmt.Errorf("internal error: makeText returned no text") + } + for _, label := range labelsList { + offset, length := strings.Index(text, label), len(label) + if offset < 0 { + return fmt.Errorf("internal error: could not find %q in text %q", label, text) + } + maxTextOffset, maxTextLength = max(maxTextOffset, offset), max(maxTextLength, length) + if offset >= 1<= 1< 64 { + n, plus = 64, " +" + } + fmt.Fprintf(w, "%q%s\n", text[:n], plus) + text = text[n:] + } + + if err := n.walk(w, assignIndexes); err != nil { + return err + } + + fmt.Fprintf(w, ` + +// nodes is the list of nodes. Each node is represented as a uint32, which +// encodes the node's children, wildcard bit and node type (as an index into +// the children array), ICANN bit and text. +// +// If the table was generated with the -comments flag, there is a //-comment +// after each node's data. In it is the nodes-array indexes of the children, +// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The +// nodeType is printed as + for normal, ! for exception, and o for parent-only +// nodes that have children but don't match a domain label in their own right. +// An I denotes an ICANN domain. +// +// The layout within the uint32, from MSB to LSB, is: +// [%2d bits] unused +// [%2d bits] children index +// [%2d bits] ICANN bit +// [%2d bits] text index +// [%2d bits] text length +var nodes = [...]uint32{ +`, + 32-nodesBitsChildren-nodesBitsICANN-nodesBitsTextOffset-nodesBitsTextLength, + nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength) + if err := n.walk(w, printNode); err != nil { + return err + } + fmt.Fprintf(w, `} + +// children is the list of nodes' children, the parent's wildcard bit and the +// parent's node type. If a node has no children then their children index +// will be in the range [0, 6), depending on the wildcard bit and node type. +// +// The layout within the uint32, from MSB to LSB, is: +// [%2d bits] unused +// [%2d bits] wildcard bit +// [%2d bits] node type +// [%2d bits] high nodes index (exclusive) of children +// [%2d bits] low nodes index (inclusive) of children +var children=[...]uint32{ +`, + 32-childrenBitsWildcard-childrenBitsNodeType-childrenBitsHi-childrenBitsLo, + childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo) + for i, c := range childrenEncoding { + s := "---------------" + lo := c & (1<> childrenBitsLo) & (1<>(childrenBitsLo+childrenBitsHi)) & (1<>(childrenBitsLo+childrenBitsHi+childrenBitsNodeType) != 0 + if *comments { + fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n", + c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType)) + } else { + fmt.Fprintf(w, "0x%x,\n", c) + } + } + fmt.Fprintf(w, "}\n\n") + fmt.Fprintf(w, "// max children %d (capacity %d)\n", maxChildren, 1<= 1<= 1<= 1< 0 && ss[0] == "" { + ss = ss[1:] + } + return ss +} + +// crush combines a list of strings, taking advantage of overlaps. It returns a +// single string that contains each input string as a substring. +func crush(ss []string) string { + maxLabelLen := 0 + for _, s := range ss { + if maxLabelLen < len(s) { + maxLabelLen = len(s) + } + } + + for prefixLen := maxLabelLen; prefixLen > 0; prefixLen-- { + prefixes := makePrefixMap(ss, prefixLen) + for i, s := range ss { + if len(s) <= prefixLen { + continue + } + mergeLabel(ss, i, prefixLen, prefixes) + } + } + + return strings.Join(ss, "") +} + +// mergeLabel merges the label at ss[i] with the first available matching label +// in prefixMap, where the last "prefixLen" characters in ss[i] match the first +// "prefixLen" characters in the matching label. +// It will merge ss[i] repeatedly until no more matches are available. +// All matching labels merged into ss[i] are replaced by "". +func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) { + s := ss[i] + suffix := s[len(s)-prefixLen:] + for _, j := range prefixes[suffix] { + // Empty strings mean "already used." Also avoid merging with self. + if ss[j] == "" || i == j { + continue + } + if *v { + fmt.Fprintf(os.Stderr, "%d-length overlap at (%4d,%4d): %q and %q share %q\n", + prefixLen, i, j, ss[i], ss[j], suffix) + } + ss[i] += ss[j][prefixLen:] + ss[j] = "" + // ss[i] has a new suffix, so merge again if possible. + // Note: we only have to merge again at the same prefix length. Shorter + // prefix lengths will be handled in the next iteration of crush's for loop. + // Can there be matches for longer prefix lengths, introduced by the merge? + // I believe that any such matches would by necessity have been eliminated + // during substring removal or merged at a higher prefix length. For + // instance, in crush("abc", "cde", "bcdef"), combining "abc" and "cde" + // would yield "abcde", which could be merged with "bcdef." However, in + // practice "cde" would already have been elimintated by removeSubstrings. + mergeLabel(ss, i, prefixLen, prefixes) + return + } +} + +// prefixMap maps from a prefix to a list of strings containing that prefix. The +// list of strings is represented as indexes into a slice of strings stored +// elsewhere. +type prefixMap map[string][]int + +// makePrefixMap constructs a prefixMap from a slice of strings. +func makePrefixMap(ss []string, prefixLen int) prefixMap { + prefixes := make(prefixMap) + for i, s := range ss { + // We use < rather than <= because if a label matches on a prefix equal to + // its full length, that's actually a substring match handled by + // removeSubstrings. + if prefixLen < len(s) { + prefix := s[:prefixLen] + prefixes[prefix] = append(prefixes[prefix], i) + } + } + + return prefixes +} diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go new file mode 100755 index 0000000000..200617ea86 --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/list.go @@ -0,0 +1,181 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// Package publicsuffix provides a public suffix list based on data from +// https://publicsuffix.org/ +// +// A public suffix is one under which Internet users can directly register +// names. It is related to, but different from, a TLD (top level domain). +// +// "com" is a TLD (top level domain). Top level means it has no dots. +// +// "com" is also a public suffix. Amazon and Google have registered different +// siblings under that domain: "amazon.com" and "google.com". +// +// "au" is another TLD, again because it has no dots. But it's not "amazon.au". +// Instead, it's "amazon.com.au". +// +// "com.au" isn't an actual TLD, because it's not at the top level (it has +// dots). But it is an eTLD (effective TLD), because that's the branching point +// for domain name registrars. +// +// Another name for "an eTLD" is "a public suffix". Often, what's more of +// interest is the eTLD+1, or one more label than the public suffix. For +// example, browsers partition read/write access to HTTP cookies according to +// the eTLD+1. Web pages served from "amazon.com.au" can't read cookies from +// "google.com.au", but web pages served from "maps.google.com" can share +// cookies from "www.google.com", so you don't have to sign into Google Maps +// separately from signing into Google Web Search. Note that all four of those +// domains have 3 labels and 2 dots. The first two domains are each an eTLD+1, +// the last two are not (but share the same eTLD+1: "google.com"). +// +// All of these domains have the same eTLD+1: +// - "www.books.amazon.co.uk" +// - "books.amazon.co.uk" +// - "amazon.co.uk" +// Specifically, the eTLD+1 is "amazon.co.uk", because the eTLD is "co.uk". +// +// There is no closed form algorithm to calculate the eTLD of a domain. +// Instead, the calculation is data driven. This package provides a +// pre-compiled snapshot of Mozilla's PSL (Public Suffix List) data at +// https://publicsuffix.org/ +package publicsuffix // import "golang.org/x/net/publicsuffix" + +// TODO: specify case sensitivity and leading/trailing dot behavior for +// func PublicSuffix and func EffectiveTLDPlusOne. + +import ( + "fmt" + "net/http/cookiejar" + "strings" +) + +// List implements the cookiejar.PublicSuffixList interface by calling the +// PublicSuffix function. +var List cookiejar.PublicSuffixList = list{} + +type list struct{} + +func (list) PublicSuffix(domain string) string { + ps, _ := PublicSuffix(domain) + return ps +} + +func (list) String() string { + return version +} + +// PublicSuffix returns the public suffix of the domain using a copy of the +// publicsuffix.org database compiled into the library. +// +// icann is whether the public suffix is managed by the Internet Corporation +// for Assigned Names and Numbers. If not, the public suffix is either a +// privately managed domain (and in practice, not a top level domain) or an +// unmanaged top level domain (and not explicitly mentioned in the +// publicsuffix.org list). For example, "foo.org" and "foo.co.uk" are ICANN +// domains, "foo.dyndns.org" and "foo.blogspot.co.uk" are private domains and +// "cromulent" is an unmanaged top level domain. +// +// Use cases for distinguishing ICANN domains like "foo.com" from private +// domains like "foo.appspot.com" can be found at +// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases +func PublicSuffix(domain string) (publicSuffix string, icann bool) { + lo, hi := uint32(0), uint32(numTLD) + s, suffix, icannNode, wildcard := domain, len(domain), false, false +loop: + for { + dot := strings.LastIndex(s, ".") + if wildcard { + icann = icannNode + suffix = 1 + dot + } + if lo == hi { + break + } + f := find(s[1+dot:], lo, hi) + if f == notFound { + break + } + + u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) + icannNode = u&(1<>= nodesBitsICANN + u = children[u&(1<>= childrenBitsLo + hi = u & (1<>= childrenBitsHi + switch u & (1<>= childrenBitsNodeType + wildcard = u&(1<>= nodesBitsTextLength + offset := x & (1<= len(rules) { + t.Fatal("no Private rules") + } + // Check the last ICANN and first Private rules. If the underlying public + // suffix list changes, we may need to update these hard-coded checks. + if got, want := rules[numICANNRules-1], "zuerich"; got != want { + t.Errorf("last ICANN rule: got %q, wawnt %q", got, want) + } + if got, want := rules[numICANNRules], "cc.ua"; got != want { + t.Errorf("first Private rule: got %q, wawnt %q", got, want) + } +} + +type slowPublicSuffixRule struct { + ruleParts []string + icann bool +} + +// slowPublicSuffix implements the canonical (but O(number of rules)) public +// suffix algorithm described at http://publicsuffix.org/list/. +// +// 1. Match domain against all rules and take note of the matching ones. +// 2. If no rules match, the prevailing rule is "*". +// 3. If more than one rule matches, the prevailing rule is the one which is an exception rule. +// 4. If there is no matching exception rule, the prevailing rule is the one with the most labels. +// 5. If the prevailing rule is a exception rule, modify it by removing the leftmost label. +// 6. The public suffix is the set of labels from the domain which directly match the labels of the prevailing rule (joined by dots). +// 7. The registered or registrable domain is the public suffix plus one additional label. +// +// This function returns the public suffix, not the registrable domain, and so +// it stops after step 6. +func slowPublicSuffix(domain string) (string, bool) { + match := func(rulePart, domainPart string) bool { + switch rulePart[0] { + case '*': + return true + case '!': + return rulePart[1:] == domainPart + } + return rulePart == domainPart + } + + domainParts := strings.Split(domain, ".") + var matchingRules []slowPublicSuffixRule + +loop: + for i, rule := range rules { + ruleParts := strings.Split(rule, ".") + if len(domainParts) < len(ruleParts) { + continue + } + for i := range ruleParts { + rulePart := ruleParts[len(ruleParts)-1-i] + domainPart := domainParts[len(domainParts)-1-i] + if !match(rulePart, domainPart) { + continue loop + } + } + matchingRules = append(matchingRules, slowPublicSuffixRule{ + ruleParts: ruleParts, + icann: i < numICANNRules, + }) + } + if len(matchingRules) == 0 { + matchingRules = append(matchingRules, slowPublicSuffixRule{ + ruleParts: []string{"*"}, + icann: false, + }) + } else { + sort.Sort(byPriority(matchingRules)) + } + + prevailing := matchingRules[0] + if prevailing.ruleParts[0][0] == '!' { + prevailing.ruleParts = prevailing.ruleParts[1:] + } + if prevailing.ruleParts[0][0] == '*' { + replaced := domainParts[len(domainParts)-len(prevailing.ruleParts)] + prevailing.ruleParts = append([]string{replaced}, prevailing.ruleParts[1:]...) + } + return strings.Join(prevailing.ruleParts, "."), prevailing.icann +} + +type byPriority []slowPublicSuffixRule + +func (b byPriority) Len() int { return len(b) } +func (b byPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byPriority) Less(i, j int) bool { + if b[i].ruleParts[0][0] == '!' { + return true + } + if b[j].ruleParts[0][0] == '!' { + return false + } + return len(b[i].ruleParts) > len(b[j].ruleParts) +} + +// eTLDPlusOneTestCases come from +// https://github.com/publicsuffix/list/blob/master/tests/test_psl.txt +var eTLDPlusOneTestCases = []struct { + domain, want string +}{ + // Empty input. + {"", ""}, + // Unlisted TLD. + {"example", ""}, + {"example.example", "example.example"}, + {"b.example.example", "example.example"}, + {"a.b.example.example", "example.example"}, + // TLD with only 1 rule. + {"biz", ""}, + {"domain.biz", "domain.biz"}, + {"b.domain.biz", "domain.biz"}, + {"a.b.domain.biz", "domain.biz"}, + // TLD with some 2-level rules. + {"com", ""}, + {"example.com", "example.com"}, + {"b.example.com", "example.com"}, + {"a.b.example.com", "example.com"}, + {"uk.com", ""}, + {"example.uk.com", "example.uk.com"}, + {"b.example.uk.com", "example.uk.com"}, + {"a.b.example.uk.com", "example.uk.com"}, + {"test.ac", "test.ac"}, + // TLD with only 1 (wildcard) rule. + {"mm", ""}, + {"c.mm", ""}, + {"b.c.mm", "b.c.mm"}, + {"a.b.c.mm", "b.c.mm"}, + // More complex TLD. + {"jp", ""}, + {"test.jp", "test.jp"}, + {"www.test.jp", "test.jp"}, + {"ac.jp", ""}, + {"test.ac.jp", "test.ac.jp"}, + {"www.test.ac.jp", "test.ac.jp"}, + {"kyoto.jp", ""}, + {"test.kyoto.jp", "test.kyoto.jp"}, + {"ide.kyoto.jp", ""}, + {"b.ide.kyoto.jp", "b.ide.kyoto.jp"}, + {"a.b.ide.kyoto.jp", "b.ide.kyoto.jp"}, + {"c.kobe.jp", ""}, + {"b.c.kobe.jp", "b.c.kobe.jp"}, + {"a.b.c.kobe.jp", "b.c.kobe.jp"}, + {"city.kobe.jp", "city.kobe.jp"}, + {"www.city.kobe.jp", "city.kobe.jp"}, + // TLD with a wildcard rule and exceptions. + {"ck", ""}, + {"test.ck", ""}, + {"b.test.ck", "b.test.ck"}, + {"a.b.test.ck", "b.test.ck"}, + {"www.ck", "www.ck"}, + {"www.www.ck", "www.ck"}, + // US K12. + {"us", ""}, + {"test.us", "test.us"}, + {"www.test.us", "test.us"}, + {"ak.us", ""}, + {"test.ak.us", "test.ak.us"}, + {"www.test.ak.us", "test.ak.us"}, + {"k12.ak.us", ""}, + {"test.k12.ak.us", "test.k12.ak.us"}, + {"www.test.k12.ak.us", "test.k12.ak.us"}, + // Punycoded IDN labels + {"xn--85x722f.com.cn", "xn--85x722f.com.cn"}, + {"xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"}, + {"www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"}, + {"shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn"}, + {"xn--55qx5d.cn", ""}, + {"xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"}, + {"www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"}, + {"shishi.xn--fiqs8s", "shishi.xn--fiqs8s"}, + {"xn--fiqs8s", ""}, + + // Invalid input + {".", ""}, + {"de.", ""}, + {".de", ""}, + {".com.au", ""}, + {"com.au.", ""}, + {"com..au", ""}, +} + +func TestEffectiveTLDPlusOne(t *testing.T) { + for _, tc := range eTLDPlusOneTestCases { + got, _ := EffectiveTLDPlusOne(tc.domain) + if got != tc.want { + t.Errorf("%q: got %q, want %q", tc.domain, got, tc.want) + } + } +} diff --git a/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/golang.org/x/net/publicsuffix/table.go new file mode 100755 index 0000000000..c1347ced4d --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/table.go @@ -0,0 +1,9962 @@ +// generated by go run gen.go; DO NOT EDIT + +package publicsuffix + +const version = "publicsuffix.org's public_suffix_list.dat, git revision 6f03f42a65d006c8ae657f125f14fb8f9d3337f4 (2019-05-31T16:38:49Z)" + +const ( + nodesBitsChildren = 10 + nodesBitsICANN = 1 + nodesBitsTextOffset = 15 + nodesBitsTextLength = 6 + + childrenBitsWildcard = 1 + childrenBitsNodeType = 2 + childrenBitsHi = 14 + childrenBitsLo = 14 +) + +const ( + nodeTypeNormal = 0 + nodeTypeException = 1 + nodeTypeParentOnly = 2 +) + +// numTLD is the number of top level domains. +const numTLD = 1539 + +// Text is the combined text of all labels. +const text = "9guacuiababia-goracleaningroks-theatree164-baltimore-og-romsdali" + + "payboltateshinanomachimkentateyamagrocerybnikeisenbahnatuurweten" + + "schappenaumburggfarmerseineastcoastaldefenceatonsbergjemnes3-ap-" + + "southeast-2ix4432-balsfjordd-dnsiskinkyotobetsulikes-piedmontice" + + "llodingenaturhistorisches3-ap-south-16-b-datainaioirasebastopolo" + + "gyeongnamegawakembuchikumagayagawakkanaibetsubamericanfamilydscl" + + "oudeitychyattorneyagawakayamadridvagsoyereplanetariumemsettsuppo" + + "rtashkentatamotors3-ap-northeast-2038bloxcms3-website-us-east-1b" + + "luedancebmoattachments3-website-us-west-1bms3-website-us-west-2b" + + "mwegroweibolognagasakimobetsuitaipeiheijindianmarketinglitchasel" + + "jeepsongdalenviknagatorockartuzyuzawabnpparibaselburgliwicebnrwe" + + "irbomloabathsbcatholicaxiashorokanaiebondray-dnsupdaternopilawat" + + "ches5ybonnishiharabookinghostfoldnavyboomlahppiacenzachpomorskie" + + "nishiizunazukindigenaklodzkochikushinonsenergyboschaefflerdalimi" + + "tedrayddnsfreebox-osascoli-picenordre-landraydnsakyotanabellunor" + + "d-aurdalvdalaskanittedallasalleangaviikaascolipicenoduminamidait" + + "omandalimoldeloittemp-dnsalangenishikatakazakindustriabostikarel" + + "iancebostonakijinsekikogentinglobalashovhachinohedmarkariyamelbo" + + "urnebotanicalgardenishikatsuragit-reposalondonetskarlsoybotanicg" + + "ardenishikawazukamisunagawabotanybouncemerckmsdnipropetrovskjerv" + + "oyagebounty-fullensakerrypropertiesaltdalinkyard-cloudnsaludrive" + + "fsnillfjordrobaknoluoktagajobojindustriesteamfamberkeleyboutique" + + "becheltenham-radio-openairbusantiquest-a-la-maisondre-landroidru" + + "dunsalvadordalibabalestrandabergamo-siemensncfdupontariodejaneir" + + "odoybozen-sudtirolivornobozen-suedtirolombardynaliaskimitsubatam" + + "ibugattiffanynysadoes-itvedestrandurbanamexnetlifyinfinitintuitj" + + "omemorialomzaporizhzhegurinuyamashinatsukigatakasakitchenishimer" + + "abplacedogawarabikomaezakirunorddalondrinamsskoganeinvestmentsal" + + "zburgloboavistaprintelligencebrandywinevalleybrasiliabrindisiben" + + "ikinderoybristoloseyouriparliamentjxfinitybritishcolumbialowieza" + + "ganquanpachigasakievennodesabaerobaticketsamegawabroadcastlecler" + + "chernihivgubananarepublicasadelamonedatingjesdalavangenayorovnoc" + + "eanographics3-fips-us-gov-west-1broadwaybroke-itkmaxxjavald-aost" + + "aplesamnangerbrokerbronnoysundurhamburglogowfarmsteadweberbrothe" + + "rmesaverdealstahaugesunderseaportsinfolldalorenskogloppenzaolbia" + + "-tempio-olbiatempioolbialystokkepnogataijinzais-a-candidatebrows" + + "ersafetymarketsampalacebrumunddalotenkawabrunelasticbeanstalkarm" + + "oybrusselsamsclubartowhalinglugmbhartipscbgminakamichiharabruxel" + + "lesamsungmodalenishinomiyashironobryansklepparmattelefonicarboni" + + "a-iglesias-carboniaiglesiascarboniabrynewjerseybuskerudinewportl" + + "ligatksatxn--0trq7p7nnishinoomotegobuzentsujiiebuzzlgmxn--11b4c3" + + "dynathomebuiltmparochernigovernmentoyosatoyokawabwhoswhokksundyn" + + "dns-at-homedepotenzamamidsundyndns-at-workisboringrimstadyndns-b" + + "logdnsandnessjoenishinoshimatsuurabzhitomirumalatvuopmicrolighti" + + "ngripebzzparsandoycolognexus-2colonialwilliamsburgrongausdalucan" + + "iacoloradoplateaudiocolumbusheycommunecommunitycomoarekecomparem" + + "arkerryhotelsaobernardocompute-1computerhistoryofscience-fiction" + + "comsecuritytacticsaogoncartiercondoshichinohealth-carereforminam" + + "iiselectraniandriabarlettatraniandriaconferenceconstructionconsu" + + "ladonnakamagayahabaghdadyndns-wikirkenesaotomembersapporoconsult" + + "anthropologyconsultingrossetouchihayaakasakawaharacontactranoyco" + + "ntagematsubaracontemporaryarteducationalchikugodaddyn-vpndnsarde" + + "gnaroycontractorskenconventureshinodebalancertificationcookingch" + + "annelsdvrdnsfor-better-thanawatchandclockashiharacooluccapitalon" + + "ewspapercooperativano-frankivskolegallocus-3copenhagencyclopedic" + + "hiryukyuragifuchungbukharaumalborkarpaczeladzwiiheyakumoduminami" + + "echizenishiokoppegardyndns-freeboxosloftranakanojoetsuwanouchiku" + + "jogaszkolajollamericanexpressexycorsicafederationcorvettemasekas" + + "hiwaracosenzakopanecosidnshome-webserverdalucernecostumedio-camp" + + "idano-mediocampidanomediocouchpotatofriesardiniacouncilukowildli" + + "fedorainfraclouderacouponsarluroycq-acranbrookuwanalyticsarpsbor" + + "groundhandlingroznycrdyndns-workshoppingrpasadenarashinocreditca" + + "rdyndns1creditunioncremonashgabadaddjaguarqhachirogatakanezawacr" + + "ewilliamhillutskashiwazakiyosatokamachintaifun-dnsdojolstercrick" + + "etrzyncrimeast-kazakhstanangercrotonecrownipassagensarufutsunomi" + + "yawakasaikaitakoelncrsvpassenger-associationcruisesasayamacrypto" + + "nomichigangwoncuisinellair-traffic-controlleyculturalcentertainm" + + "entransportecuneocupcakecuritibahcavuotnagaivuotnagaokakyotambab" + + "yeniwaizumiotsukumiyamazonawsagaeroclubmedecincinnationwidealeri" + + "mo-i-ranaamesjevuemielno-ipifonychitachinakagawashtenawdev-myqna" + + "pcloudcontrolledekagaminogiftsandvikcoromantovalle-d-aostathelle" + + "cxn--12c1fe0bradescorporationcymrussiacyonabaruminamiizukamiokam" + + "eokameyamatotakadacyoutheworkpccwinbanzaicloudcontrolappleborkda" + + "lpha-myqnapcloud66ferrerotikagoshimalselvendrelluzernfetsundynse" + + "rvebbsaskatchewanfguitarsavannahgafhvalerfidoomdnstracefieldynuc" + + "onnectransurluxembourgruefigueresinstagingujohanamakinoharafilat" + + "eliafilegear-audnedalnfilegear-deatnurembergulenfilegear-gbizfil" + + "egear-iefilegear-jpmorganfilegear-sgunmaoris-a-financialadvisor-" + + "aurdalvivanovoldafilminamiminowafinalfinancefineartsaves-the-wha" + + "lessandria-trani-barletta-andriatranibarlettaandriafinlandynv6fi" + + "nnoyfirebaseapplinzis-a-geekasukabedzin-berlindasdaburfirenzefir" + + "estonefirmdalegokasells-itravelchannelfishingoldpoint2thisamitsu" + + "kefitjarvodkafjordynvpnplus-4fitnessettlementravelersinsurancefj" + + "alerflesberguovdageaidnulminamioguni5flickragerogersavonarusawaf" + + "lightsaxoflirfloginlinefloraflorencefloridattorelayfloripaderbor" + + "nfloristanohatakahamalvikasumigaurawa-mazowszextraspace-to-renta" + + "lstomakomaibaraflorokunohealthcareerschoenbrunnflowerschokokeksc" + + "hokoladenfltrdyroyrvikinguidegreeflynnhosting-clusterflynnhubarc" + + "laycards3-sa-east-1fndfor-ourfor-someeresistancefor-theaterforex" + + "rothadanorthwesternmutualforgotdnscholarshipschoolforli-cesena-f" + + "orlicesenaforlikescandyn53forsaleikangerforsandasuologoipatriafo" + + "rtalfortmissoulancashirecreationfortworthadselfipaviancarrdforum" + + "zfosneschulefotaris-a-greenfoxfordebianfozorafredrikstadtvschwar" + + "zgwangjuniperfreeddnsgeekgalaxyfreedesktopocznore-og-uvdalfreema" + + "sonryfreesitevadsoccertmgretakahashimamakirovogradoyfreetlschwei" + + "zfreiburgushikamifuranorth-kazakhstanfreightrentin-sud-tirolfres" + + "eniuscountryestateofdelawarezzoologyfribourgwiddleitungsenfriuli" + + "-v-giuliafriuli-ve-giuliafriuli-vegiuliafriuli-venezia-giuliafri" + + "uli-veneziagiuliafriuli-vgiuliafriuliv-giuliafriulive-giuliafriu" + + "livegiuliafriulivenezia-giuliafriuliveneziagiuliafriulivgiuliafr" + + "lfrogansciencecentersciencehistoryfrognfrolandfrom-akrehamnfrom-" + + "alfrom-arfrom-azimuthdfcbankasuyanagawafrom-capebretonamicrosoft" + + "bankaszubyfrom-codyn-o-saurlandescientistordalfrom-ctrentin-sudt" + + "irolfrom-dchitosetogitsuldalottefrom-dedyn-berlincolnfrom-flande" + + "rscjohnsonfrom-gaulardalfrom-hichisochildrensgardenfrom-iafrom-i" + + "dfrom-ilfrom-in-brbarclays3-us-east-2from-kscotlandfrom-kyowaria" + + "sahikawawindmillfrom-lancasterfrom-mamurogawafrom-mdfrom-meethno" + + "logyfrom-mifunefrom-mnfrom-mochizukiryuohdattowebcampinashikimin" + + "ohostre-totendofinternet-dnsaliasiafrom-mscrapper-sitefrom-mtnfr" + + "om-nctulanciafrom-ndfrom-nefrom-nh-serveblogsiteleafamilycompany" + + "minamisanrikubetsurfastly-terrariuminamimakis-a-designerfrom-nja" + + "worznoticiasnesoddenmarkhangelskjakdnepropetrovskiervaapsteierma" + + "rkatowicefrom-nminamitanefrom-nvalled-aostavangerfrom-nyfrom-ohk" + + "urafrom-oketogurafrom-orfrom-padovaksdalfrom-pratohmangolffanscr" + + "appingxn--12co0c3b4evalleaostaticscrysechocolatelemarkaruizawafr" + + "om-ris-a-gurulvikatsushikabeeldengeluidfrom-schmidtre-gauldalfro" + + "m-sdfrom-tnfrom-txn--1ck2e1barefootballfinanzgoraustraliaisondri" + + "obranconagawalbrzycharitysfjordds3-eu-west-1from-utazuerichardli" + + "llehammerfeste-ipfizerfrom-val-daostavalleyfrom-vtrentin-sued-ti" + + "rolfrom-wafrom-wielunnerfrom-wvalledaostavernfrom-wyfrosinonefro" + + "stalowa-wolawafroyahooguyfstcgroupgfoggiafujiiderafujikawaguchik" + + "onefujiminokamoenairlinedre-eikerfujinomiyadavvenjargap-northeas" + + "t-3fujiokayamangyshlakasamatsudovre-eikerfujisatoshonairportland" + + "-4-salernoboribetsuckserveminecraftrentin-suedtirolfujisawafujis" + + "hiroishidakabiratoridefensells-for-lesservemp3fujitsurugashimani" + + "wakuratexaskoyabearalvahkihokumakogengerdalcesurancechirealmpmnf" + + "ujixeroxn--1ctwolominamataobaomoriguchiharagusartservep2pharmaci" + + "enservepicservequakefujiyoshidavvesiidatsunanjoburgfukayabeatser" + + "vesarcasmatartanddesignfukuchiyamadazaifudaigodontexistmein-iser" + + "vebeerfukudominichofunatoriginstitutelevisionishitosashimizunami" + + "namibosogndalottokonamegatakatsukis-a-catererfukuis-a-hard-worke" + + "rservicesevastopolefukumitsubishigakisarazurecontainerdpolicefuk" + + "uokazakishiwadafukuroishikarikaturindalfukusakisofukushimannorfo" + + "lkebibleirfjordfukuyamagatakahatakaishimogosenfunabashiriuchinad" + + "afunagatakamatsukawafunahashikamiamakusatsumasendaisennangonohej" + + "is-a-hunterfundaciofuoiskujukuriyamansionsevenassisicilyfuosskoc" + + "zowindowsewinnersharis-a-knightpointtohobby-sitefurnitureggio-ca" + + "labriafurubirafurudonostiaafurukawairtelebitballooningfusodegaur" + + "afussaikisosakitagawafutabayamaguchinomigawafutboldlygoingnowher" + + "e-for-morenakatombetsumitakagiizefuttsurugimperiafuturecmsharpha" + + "rmacyshawaiijimarnardalfuturehostingfuturemailingfvgfylkesbiblac" + + "kbaudcdn77-securebungoonord-odalwaysdatabaseballangenoamishirasa" + + "tochigiessensiositelekommunikationionjukudoyamaintenanceofyresda" + + "lhangglidinghangoutsystemscloudyclusterhannanmokuizumodellinghan" + + "nosegawahanyuzenhapmirhareidsbergenharstadharvestcelebrationhasa" + + "marburghasaminami-alpshimojis-a-liberalhashbanghasudahasura-apph" + + "dhasvikatsuyamarylandhatogayaizuwakamatsubushikusakadogawahatoya" + + "mazakitakamiizumisanofidelityhatsukaichikaiseis-a-libertarianhat" + + "tfjelldalhayashimamotobungotakadapliernewmexicoalhazuminobusells" + + "yourhomegoodshimokawahelsinkitakatakaokalmykiahembygdsforbundhem" + + "neshimokitayamahemsedalhepforgeherokussldheroyhgtvallee-aosteroy" + + "higashiagatsumagoianiahigashichichibunkyonanaoshimageandsoundand" + + "visionhigashihiroshimanehigashiizumozakitakyushuaiahigashikagawa" + + "higashikagurasoedahigashikawakitaaikitamihamadahigashikurumeguro" + + "roshimonitayanagithubusercontentrentino-a-adigehigashimatsushima" + + "rcheapigeelvinckaufenhigashimatsuyamakitaakitadaitoigawahigashim" + + "urayamamotorcycleshimonosekikawahigashinarusembokukitamotosumy-g" + + "atewayhigashinehigashiomihachimanaustdalhigashiosakasayamanakako" + + "gawahigashishirakawamatakarazukaluganskypehigashisumiyoshikawami" + + "namiaikitanakagusukumodenakayamaritimodernhigashitsunoshiroomura" + + "higashiurausukitashiobarahigashiyamatokoriyamanashifteditchyouri" + + "philadelphiaareadmyblogspotrentino-aadigehigashiyodogawahigashiy" + + "oshinogaris-a-linux-useranishiaritabashijonawatehiraizumisatohno" + + "shoooshikamaishimodatehirakatashinagawahiranairtrafficplexus-1hi" + + "rarahiratsukagawahirayakagehistorichouseshimosuwalkis-a-llamarri" + + "ottrentino-alto-adigehitachiomiyagildeskaliszhitachiotagooglecod" + + "espotaruis-a-musicianhitraeumtgeradelmenhorstalbanshimotsukehjar" + + "tdalhjelmelandholeckobierzyceholidayhomeiphilatelyhomelinkitools" + + "ztynsettlershimotsumahomelinuxn--1lqs03nhomeofficehomesecurityma" + + "caparecidahomesecuritypchonanbulsan-suedtirolouvreisenishiwakis-" + + "a-celticsfanissandiegohomesenseminehomeunixn--1lqs71dhondahoneyw" + + "ellbeingzonehongoppdalhonjyoitakasagotembaixadahornindalhorseoul" + + "lensvanguardhorteneis-a-nascarfanhospitalhoteleshinichinanhotmai" + + "lhoyangerhoylandetroitskautokeinotteroyhumanitieshinjournalismai" + + "lillesandefjordhurdalhurumajis-a-nurservegame-serverhyllestadhyo" + + "goris-a-painteractivegaskvollhyugawarahyundaiwafuneis-very-sweet" + + "pepperis-with-thebandoisleofmanchesterjewelryjewishartgalleryjfk" + + "fhappounzenjgorajlljmphonefosshioyanaizuslivinghistoryjnjcphoeni" + + "xn--1qqw23ajoyentrentino-stiroljoyokaichibalatinoipirangamvikhak" + + "assiajpnjprshirahamatonbetsurnadaljurkoseis-a-photographerokuapp" + + "hilipsyno-dshinjukumanowtvallee-d-aosteigenkosherbrookegawakoshi" + + "mizumakiyosunndalkoshunantankharkovalleedaostekosugekotohiradoma" + + "insureggioemiliaromagnamsosnowiechoseiroumuenchenissayokkaichiro" + + "practichernivtsiciliakotourakouhokutamakizunokunimimatakatoris-a" + + "-playerkounosupplieshiranukamitsuekouyamashikekouzushimashikis-a" + + "-republicancerresearchaeologicaliforniakozagawakozakis-a-rocksta" + + "rachowicekozowioshiraois-a-socialistdlibestadkpnkppspdnshiraokam" + + "ogawakrasnikahokutokashikis-a-soxfankrasnodarkredstonekristiansa" + + "ndcatshiratakahagitlaborkristiansundkrodsheradkrokstadelvaldaost" + + "arnbergkryminamiuonumassa-carrara-massacarraramassabusinessebykl" + + "ecznagasukekumatorinokumejimasoykumenantokigawakunisakis-a-stude" + + "ntalkunitachiarailwaykunitomigusukumamotoyamashikokuchuokunneppu" + + "eblockbustermezkunstsammlungkunstunddesignkuokgroupictetrentino-" + + "sud-tirolkurehabmerkurgankurobelaudibleasingleshishikuis-a-teach" + + "erkassyncloudkurogiminamiashigarakuroisoftwarendalenugkuromatsun" + + "ais-a-techietis-a-patsfankurotakikawasakis-a-therapistoiakushiro" + + "gawakustanais-an-accountantshinkamigotoyohashimototalkusupplykut" + + "chanelkutnokuzumakis-an-actorkvafjordkvalsundkvamlidlugolekadena" + + "gahamaroygardenebakkeshibechambagriculturennebudejjuedischesapea" + + "kebayernuorochesterkvanangenkvinesdalkvinnheradkviteseidskogkvit" + + "soykwpspectruminamiyamashirokawanabelembetsukubankhersonkzmisugi" + + "tokorozawamitourismolangevagrigentomologyeonggiehtavuoatnadexete" + + "rmitoyoakemiuramiyazurewebsiteshikagamiishibukawamiyotamanomjond" + + "alenmlbfanmombetsurgeonshalloffamelhusdecorativeartshisuifuelver" + + "uminanomonstermontrealestatefarmequipmentrentino-sued-tirolmonza" + + "-brianzapposhitaramamonza-e-della-brianzaptokuyamatsumotofukemon" + + "zabrianzaramonzaebrianzamonzaedellabrianzamoonscalevangermoparac" + + "hutingmordoviamoriyamatsunomoriyoshiminamiawajikis-an-artistgory" + + "mormonmouthagakhanamigawamoroyamatsusakahoginankokubunjis-an-eng" + + "ineeringmortgagemoscowitdkhmelnitskiyamarylhurstjordalshalsenmos" + + "eushistorymosjoenmoskeneshizukuishimofusaitamatsukuris-an-entert" + + "ainermosshizuokanagawamosvikhmelnytskyivanylvenicemoteginowaniih" + + "amatamakawajimanxn--2scrj9choshibuyachtsanfranciscofreakunemuror" + + "angeiseiyoichippubetsubetsugarugbydgoszczecinemagentositecnologi" + + "amoviemovimientokyotangotsukitahatakamoriokakegawamovistargardmo" + + "zilla-iotrentino-suedtirolmtranbymuenstermuginozawaonsenmuikamis" + + "atokaizukamikitayamatsuris-bytomaritimekeepingmukodairamulhouser" + + "vehalflifestylewismillermunakatanemuncienciamuosattemupicturesho" + + "ujis-certifieducatorahimeshimamateramobaramurmanskhplaystationmu" + + "rotorcraftrentinoa-adigemusashimurayamatsushigemusashinoharamuse" + + "etrentinoaadigemuseumverenigingmusicargoboatshowamutsuzawamy-vig" + + "orgemy-wanggouvichoyodobashichikashukujitawaravennaharimalopolsk" + + "anlandyndns-homednsangomyactivedirectorymyasustor-elvdalmycdn77-" + + "sslattumincomcastresindevicenzaporizhzhiamydattolocalhistorymydd" + + "nskingmydissentrentinoalto-adigemydobisshikis-foundationmydroboe" + + "hringerikemydshowtimemergencyahikobeardubaiduckdnshriramsterdamn" + + "serverbaniamyeffectrentinoaltoadigemyfirewallonieruchomosciencea" + + "ndindustrynmyfritzmyftpaccessienarutolgamyhome-servermyjinomykol" + + "aivaomymailermymediapchristiansburgriwataraidyndns-ipartis-a-che" + + "farsundyndns-mailowiczest-le-patronissedalplfinancialpuserconten" + + "toyotapartsanjotoyotomiyazakis-a-conservativegarsheis-a-cpaduals" + + "tackhero-networkinggroupartymyokohamamatsudamypepiemontemypetsig" + + "dalmyphotoshibalena-devicesilklabudhabikinokawabarthaebaruericss" + + "onyoursidell-ogliastradermypiagetmyiphostrodawaramypsxn--30rr7ym" + + "ysecuritycamerakermyshopblocksimple-urlmytis-a-bookkeeperugiamyt" + + "uleapilotsirdalmyvnchristmasakindlefrakkestadyndns-office-on-the" + + "-webhopencraftoyotsukaidomywireitrentinos-tirolpiszpittsburghoff" + + "icialpiwatepixolinopizzapknx-serversailleshirakofuefukihaboromsk" + + "ogplantationplantsjcbnlplatformshangrilanslupskolobrzegersundpla" + + "zaplcube-serversicherungplumbingoplurinacionalpodhalezajskomagan" + + "epodlasiellaktyubinskiptveterinaireadthedocscappgafannefrankfurt" + + "rentinosud-tirolpodzonepohlpoivronpokerpokrovskomakiyosemitepoli" + + "ticarrierpolitiendapolkowicepoltavalle-aostarostwodzislawithgoog" + + "leapisa-hockeynutsiracusakatakkoebenhavnpomorzeszowithyoutubersp" + + "acekitagatamayufuettertdasnetzponpesaro-urbino-pesarourbinopesar" + + "omasvuotnaritakurashikis-goneponypordenonepornporsangerporsangug" + + "eporsgrunnanyokoshibahikariwanumatakinouepoznanpraxis-a-bruinsfa" + + "nprdpreservationpresidioprgmrprimeloyalistorageprincipeprivatize" + + "healthinsuranceprochowiceproductionslzprofesionalprogressivennes" + + "laskerrylogisticsnoasaitoshimayfirstockholmestrandpromomahachijo" + + "invilleksvikomatsushimasfjordenpropertyprotectionprotonetrentino" + + "sudtirolprudentialpruszkowiwatsukiyonotairestaurantrentinosued-t" + + "irolprvcyberlevagangaviikanonjis-into-animeiwamarshallstatebanka" + + "zoprzeworskogptplusgardenpupimientaketomisatomobellevuelosangele" + + "sjabbottrentinostirolpvhagebostadpvtrentinosuedtirolpwchromedici" + + "nakaiwamizawassamukawataricoharuovatoyourapzqldqponiatowadaqslin" + + "gquicksytestingquipelementsokananiimihoboleslawiechryslerqvchung" + + "namdalseidfjordyndns-picsannanisshingucciprianiigataishinomakink" + + "obayashikaoirmitakeharasuzakanazawasuzukaneyamazoesuzukis-into-g" + + "amessinazawasvalbardunloppacificircleverappsseljordyndns-webhost" + + "ingroks-thisayamanobeokakudamatsuesveiosvelvikomonowruzhgorodeos" + + "vizzerasvn-reposomnarviikamishihoronobeauxartsandcraftsolarssons" + + "wedenswidnicartoonartdecologiaswidnikkokaminokawanishiaizubanges" + + "wiebodzin-butterswiftcoverswinoujscienceandhistoryswissmartertha" + + "nyousrcfastpanelblagrarchaeologyeongbuk0emmafann-arboretumbriama" + + "llamaceiobbcg120001wwwebspace12hpalermoliserniabogadodgehirnrt3l" + + "3p0rtarnobrzegyptian4tarumizusawabruzzoologicalvinklein-addramme" + + "nuernbergdyniaetnabudapest-a-la-masion-webredirectmedicaltanisse" + + "ttachikawafflecellclaims3-ap-northeast-1337synology-diskstations" + + "ynology-dsootunesor-varangertunkomorotsukaminoyamaxunjargaturyst" + + "ykanmakiwientuscanytushuissier-justicetuvalle-daostatic-accessor" + + "foldtuxfamilytwmailvestfoldvestnesorocabalsan-sudtirollagdenesna" + + "aseralingenkainanaejrietisalatinabenonichurcharternidyndns-remot" + + "ewdyndns-serverisigniyodogawavestre-slidrepbodynamic-dnsorreisah" + + "ayakawakamiichikawamisatottoris-into-carshinshirovestre-totennis" + + "hiawakuravestvagoyvevelstadvibo-valentiavibovalentiavideovillaso" + + "rtlandvinnicasacamdvrcampinagrandebuilderschlesischesoruminiserv" + + "ervinnytsiavirginiavirtual-userveexchangevirtualservervirtualuse" + + "rveftpioneervirtueeldomein-vigorlicevirtuelvisakegawaviterboknow" + + "sitallvivolkenkundenvixn--32vp30haibarakitahiroshimapartmentshel" + + "laspeziavlaanderenvladikavkazimierz-dolnyvladimirvlogintoyonezaw" + + "avminnesotaketakayamasudavologdanskomvuxn--2m4a15evolvolkswagent" + + "soundcastronomy-routervolyngdalvoorloperauniterois-leetnedalvoss" + + "evangenvotevotingvotoyonownextdirectrentoyonakagyokutoyakokonoew" + + "orldworse-thandawowloclawekongsbergwpcomstagingwpdevcloudwritest" + + "hisblogsytewroclawmflabsouthcarolinarvikommunalforbundwtcmintern" + + "ationalfirearmshisognewtfastvps-serveronakasatsunairguardiannaka" + + "domarinebraskauniversitydalaheadjudaicable-modemocraciawuozustka" + + "nnamilanotogawawzmiuwajimaxn--3pxu8kongsvingerxn--42c2d9axn--45b" + + "r5cylxn--45brj9cistrondheimmobilienxn--45q11citadeliveryggeexn--" + + "4gbriminingxn--4it168dxn--4it797koninjambylxn--4pvxs4allxn--54b7" + + "fta0ccitichernovtsymantechnologyxn--55qw42gxn--55qx5dxn--5js045d" + + "xn--5rtp49civilaviationxn--5rtq34konskowolayangrouphotographysio" + + "xn--5su34j936bgsgxn--5tzm5gxn--6btw5axn--6frz82gxn--6orx2rxn--6q" + + "q986b3xlxn--7t0a264civilisationxn--80adxhksouthwestfalenxn--80ao" + + "21axn--80aqecdr1axn--80asehdbarrell-of-knowledgeologyonagoyautom" + + "otiveconomiasakuchinotsuchiurakawalesundevelopmentattoobninskara" + + "coldwarmiastagebizenakanotoddenavuotnaples3-eu-west-2xn--80aswgx" + + "n--80augustownproviderxn--8ltr62konsulatrobeepilepsykkylvenetoei" + + "dsvollxn--8pvr4utwentexn--8y0a063axn--90a3academiamicaaarborteac" + + "hes-yogasawaracingxn--90aeroportalabamagasakishimabaraogakibichu" + + "oxn--90aishobarakawagoexn--90azhytomyravendbarsycenterprisesakik" + + "ugawalmartaxihuanflfanfshostrowwlkpmgjovikaragandautoscanadaegua" + + "mbulancehimejibmdgcagliaribeiraokinawashirosatochiokinoshimaizur" + + "uhreviewskrakoweddingjerstadotsuruokakamigaharaurskog-holandingj" + + "erdrumetacentrumeteorappalmaserati234lima-cityeatselinogradultat" + + "arantours3-ap-southeast-1kappchizip6xn--9dbhblg6dietcimdbarsyonl" + + "inewhampshirealtysnes3-us-gov-west-1xn--9dbq2axn--9et52uxn--9krt" + + "00axn--andy-iraxn--aroport-byandexn--3bst00misakis-an-actresshin" + + "shinotsurgeryxn--asky-iraxn--aurskog-hland-jnbashkiriaveroykengl" + + "andiscountyolasitempresashibetsukuiitatebayashiibajddarchitectur" + + "ealtorlandiscourses3-eu-west-3utilitiesquare7xn--avery-yuasakuho" + + "kkaidownloadxn--b-5gaxn--b4w605ferdxn--balsan-sdtirol-nsbsowaxn-" + + "-bck1b9a5dre4civilizationxn--bdddj-mrabdxn--bearalvhki-y4axn--be" + + "rlevg-jxaxn--bhcavuotna-s4axn--bhccavuotna-k7axn--bidr-5nachikat" + + "suuraxn--bievt-0qa2xn--bjarky-fyaotsurreyxn--bjddar-ptargets-itr" + + "evisohughesopotrentinsud-tirolxn--blt-elabourxn--bmlo-graingerxn" + + "--bod-2natalxn--bozen-sdtirol-2obanazawaxn--brnny-wuacademy-fire" + + "wall-gatewayxn--brnnysund-m8accident-investigation-aptibleadpage" + + "st-mon-blogueurovision-rancherkasydneyxn--brum-voagatritonxn--bt" + + "sfjord-9zaxn--bulsan-sdtirol-nsbasicservercelliguriavocatanzarow" + + "edeployombolzano-altoadigemrevistanbulsan-sudtirolavagiskeu-1xn-" + + "-c1avgxn--c2br7gxn--c3s14misasaguris-an-anarchistoricalsocietyxn" + + "--cck2b3basilicataniavoues3-external-1xn--cesena-forl-mcbremange" + + "rxn--cesenaforl-i8axn--cg4bkis-lostrolekamakurazakiwakunigamihar" + + "unusualpersonxn--ciqpnxn--clchc0ea0b2g2a9gcdxn--comunicaes-v6a2o" + + "xn--correios-e-telecomunicaes-ghc29axn--czr694basketballyngenvir" + + "onmentalconservationrenderxn--czrs0troandinosaurepaircraftingvol" + + "lombardiamondsor-odalxn--czru2dxn--czrw28batodayonagunicommbanka" + + "rasjohkamikoaniikappuboliviajessheimetlifeinsuranceu-4xn--d1acj3" + + "batsfjordishakotanhktcp4xn--d1alfaromeoxn--d1atrogstadxn--d5qv7z" + + "876civilwarmanagementoystre-slidrettozawaxn--davvenjrga-y4axn--d" + + "jrs72d6uyxn--djty4konyvelolxn--dnna-grajewolterskluwerxn--drbak-" + + "wuaxn--dyry-iraxn--e1a4clanbibaidarmeniaxn--eckvdtc9dxn--efvn9sp" + + "eedpartnersolognexn--efvy88hair-surveillancexn--ehqz56nxn--elqq1" + + "6hakatanortonxn--estv75gxn--eveni-0qa01gaxn--f6qx53axn--fct429ko" + + "oris-a-personaltrainerxn--fhbeiarnxn--finny-yuaxn--fiq228c5hspje" + + "lkavikommunexn--fiq64bauhausposts-and-telecommunicationswatch-an" + + "d-clockerxn--fiqs8spreadbettingxn--fiqz9spydebergxn--fjord-lraxn" + + "--fjq720axn--fl-ziaxn--flor-jraxn--flw351exn--forl-cesena-fcbsrl" + + "xn--forlcesena-c8axn--fpcrj9c3dxn--frde-grandrapidsrtrentinsudti" + + "rolxn--frna-woaraisaijosoyrovigotpantheonsitextileirvikopervikha" + + "rkivalleeaosteinkjerusalembroideryxn--frya-hraxn--fzc2c9e2cldmai" + + "lubindalublindesnesannohelpagesanokarumaifashionxn--fzys8d69uvgm" + + "ailxn--g2xx48clickasaokamiminersantabarbaraxn--gckr3f0fauskedsmo" + + "korsetagayasells-for-ufcfanxn--gecrj9clinichirurgiens-dentistes-" + + "en-francexn--ggaviika-8ya47hakodatexn--gildeskl-g0axn--givuotna-" + + "8yasakaiminatoyookaniepcexn--gjvik-wuaxn--gk3at1exn--gls-elacaix" + + "axn--gmq050is-not-certifiedugit-pagespeedmobilizeroticahcesuoloa" + + "nshintomikasaharaxn--gmqw5axn--h-2failxn--h1aeghakonexn--h2breg3" + + "evenesrvaporcloudxn--h2brj9c8cliniquenoharaxn--h3cuzk1digitalxn-" + + "-hbmer-xqaxn--hcesuolo-7ya35beneventogakushimotoganewhollandisre" + + "chtrainingladefinimakanegasakiraxaustevoll-o-g-i-naval-d-aosta-v" + + "alleyokosukanumazuryokotebinagisobetsumidatlantic66xn--hery-irax" + + "n--hgebostad-g3axn--hkkinen-5waxn--hmmrfeasta-s4accident-prevent" + + "ion-riopretobamaceratabuseating-organicbcn-north-1xn--hnefoss-q1" + + "axn--hobl-iraxn--holtlen-hxaxn--hpmir-xqaxn--hxt814exn--hyanger-" + + "q1axn--hylandet-54axn--i1b6b1a6a2exn--imr513nxn--indery-fyasugiv" + + "ingxn--io0a7is-savedunetbankazunow-dnshinyoshitomiokamitondabaya" + + "shiogamagoriziaxn--j1aefbsbxn--12cfi8ixb8luxuryxn--j1amhakubahcc" + + "avuotnagarahkkeravjuegoshikikuchikuseikarugalsacexn--j6w193gxn--" + + "jlq61u9w7bentleyoriikarasjokarasuyamarumorimachidaxn--jlster-bya" + + "suokanoyaltakashimarugame-hostrowieclintonoshoesantacruzsantafed" + + "jejuifminamifuranoxn--jrpeland-54axn--jvr189misawaxn--k7yn95exn-" + + "-karmy-yuaxn--kbrq7oxn--kcrx77d1x4axn--kfjord-iuaxn--klbu-woaxn-" + + "-klt787dxn--kltp7dxn--kltx9axn--klty5xn--3ds443gxn--koluokta-7ya" + + "57hakuis-a-landscaperxn--kprw13dxn--kpry57dxn--kpu716fbx-osassar" + + "is-a-doctorayxn--kput3is-slickddielddanuorrikuzentakatajimidoris" + + "sagamiharaxn--krager-gyatomitamamuraxn--kranghke-b0axn--krdshera" + + "d-m8axn--krehamn-dxaxn--krjohka-hwab49jdfastlylbarcelonagareyama" + + "keupowiat-band-campaniaustinnavigationavoizumizakibigawajudygarl" + + "anddnslivelanddnss3-ca-central-1xn--ksnes-uuaxn--kvfjord-nxaxn--" + + "kvitsy-fyatsukanraxn--kvnangen-k0axn--l-1fairwindstorfjordxn--l1" + + "accentureklamborghinikolaeventstorjdevcloudfunctionshiojirishiri" + + "fujiedaxn--laheadju-7yatsushiroxn--langevg-jxaxn--lcvr32dxn--ldi" + + "ngen-q1axn--leagaviika-52beppublishproxyzgorzeleccoffeedbackplan" + + "eapplicationcloudaccesscambridgestonewyorkshirecifedexhibitionhl" + + "fanhs3-us-west-1xn--lesund-huaxn--lgbbat1ad8jelenia-goraxn--lgrd" + + "-poacctromsakakinokiaxn--lhppi-xqaxn--linds-pramericanartromsoja" + + "misonxn--lns-qlanxesstpetersburgxn--loabt-0qaxn--lrdal-sraxn--lr" + + "enskog-54axn--lt-liaclothingdustdataitogliattiresantamariakexn--" + + "lten-granexn--lury-iraxn--m3ch0j3axn--mely-iraxn--merker-kuaxn--" + + "mgb2ddestreamuneuesolundbeckomforbarreauctionredumbrella-speziau" + + "strheimatunduhrennesoyokozebinordreisa-geek12xn--mgb9awbfbxosaud" + + "axn--mgba3a3ejtrusteexn--mgba3a4f16axn--mgba3a4franamizuholdings" + + "tudioxn--mgba7c0bbn0axn--mgbaakc7dvfedorapeoplegnicanonoichinomi" + + "yakexn--mgbaam7a8hakusanagochijiwadellogliastradingxn--mgbab2bdx" + + "n--mgbai9a5eva00beskidyn-ip24xn--mgbai9azgqp6jeonnamerikawauexn-" + + "-mgbayh7gpaleoxn--mgbb9fbpobihirosakikamijimatsuzakis-uberleetre" + + "ntino-altoadigexn--mgbbh1a71exn--mgbc0a9azcgxn--mgbca7dzdoxn--mg" + + "berp4a5d4a87gxn--mgberp4a5d4arxn--mgbgu82axn--mgbi4ecexposedxn--" + + "mgbpl2fhskydivingxn--mgbqly7c0a67fbcn-northwest-1xn--mgbqly7cvaf" + + "ranziskanerimaringatlantakaharuxn--mgbt3dhdxn--mgbtf8flatangerxn" + + "--mgbtx2bestbuyshouses3-us-west-2xn--mgbx4cd0abbvieeexn--mix082f" + + "edoraprojectrapaniizaxn--mix891feiraquarelleaseeklogesauheradynn" + + "sasebofageorgeorgiaxn--mjndalen-64axn--mk0axin-dslgbtrvareserveh" + + "ttpinkmpspbargainstantcloudfrontdoorhcloudiscoveryomitanoceanogr" + + "aphiqueu-3xn--mk1bu44cngrondarxn--mkru45is-very-badajozxn--mlatv" + + "uopmi-s4axn--mli-tlapyxn--mlselv-iuaxn--moreke-juaxn--mori-qsaku" + + "ragawaxn--mosjen-eyawaraxn--mot-tlaquilancomeldalxn--mre-og-roms" + + "dal-qqbetainaboxfusejnyoshiokanzakiyokawaraxn--msy-ula0haldenxn-" + + "-mtta-vrjjat-k7aflakstadaokagakicks-assnasaarlandxn--muost-0qaxn" + + "--mxtq1misconfusedxn--ngbc5azdxn--ngbe9e0axn--ngbrxn--3e0b707exn" + + "--nit225koryokamikawanehonbetsurutaharaxn--nmesjevuemie-tcbalsan" + + "-suedtirolkuszczytnombresciaxn--nnx388axn--nodessakurais-very-ev" + + "illagexn--nqv7fs00emaxn--nry-yla5gxn--ntso0iqx3axn--ntsq17gxn--n" + + "ttery-byaeservehumourxn--nvuotna-hwaxn--nyqy26axn--o1achattanoog" + + "anordlandxn--o3cw4halsaintlouis-a-anarchistoireggio-emilia-romag" + + "nakatsugawaxn--o3cyx2axn--od0algxn--od0aq3bhzcaseihicampobassoci" + + "atest-iservecounterstrikeverbankaratevje-og-hornnes3-website-ap-" + + "northeast-1xn--ogbpf8flekkefjordxn--oppegrd-ixaxn--ostery-fyawat" + + "ahamaxn--osyro-wuaxn--otu796dxn--p1acfermobilyxn--p1ais-very-goo" + + "dyearxn--pbt977cnpyatigorskodjeffersonxn--pgbs0dhlxn--porsgu-sta" + + "26ferraraxn--pssu33lxn--pssy2uxn--q9jyb4cnsantoandreamhostersanu" + + "kis-a-cubicle-slavellinodearthachiojiyaitakanabeautysvardoesntex" + + "isteingeekashibatakasugais-a-democratozsdeltaiwanairforcebetsuik" + + "idsmynasushiobarackmazerbaijan-mayendoftheinternetflixilovecolle" + + "gefantasyleaguernseyxn--qcka1pmckinseyxn--qqqt11mishimatsumaebas" + + "hikshacknetrentino-sudtirolxn--qxamusementdllxn--rady-iraxn--rda" + + "l-poaxn--rde-ularvikosaigawaxn--rdy-0nabaris-very-nicexn--rennes" + + "y-v1axn--rhkkervju-01aferrarivnexn--rholt-mragowoodsidemoneyxn--" + + "rhqv96gxn--rht27zxn--rht3dxn--rht61exn--risa-5nativeamericananti" + + "questudynamisches-dnsolutionsokndalxn--risr-iraxn--rland-uuaxn--" + + "rlingen-mxaxn--rmskog-byaxn--rny31hammarfeastafricapetownnews-st" + + "agingxn--rovu88bieigersundivtasvuodnakamuratajirittogojomedizinh" + + "istorisches3-website-ap-southeast-1xn--rros-granvindafjordxn--rs" + + "kog-uuaxn--rst-0naturalhistorymuseumcenterxn--rsta-francaisehara" + + "xn--rvc1e0am3exn--ryken-vuaxn--ryrvik-byaxn--s-1faithruherecipes" + + "caravantaarpippulawyxn--s9brj9cntrani-andria-barletta-trani-andr" + + "iaxn--sandnessjen-ogbielawalterxn--sandy-yuaxn--sdtirol-n2axn--s" + + "eral-lraxn--ses554gxn--sgne-gratangenxn--skierv-utazastuff-4-sal" + + "exn--skjervy-v1axn--skjk-soaxn--sknit-yqaxn--sknland-fxaxn--slat" + + "-5naturalsciencesnaturellestufftoread-booksnesomaxn--slt-elabcie" + + "szynxn--smla-hraxn--smna-gratis-a-bulls-fanxn--snase-nraxn--sndr" + + "e-land-0cbielladbrokes3-website-ap-southeast-2xn--snes-poaxn--sn" + + "sa-roaxn--sr-aurdal-l8axn--sr-fron-q1axn--sr-odal-q1axn--sr-vara" + + "nger-ggbieszczadygeyachiyodaejeonbuklugsmilebtimnetzjampagefront" + + "appanamatta-varjjatjeldsundivttasvuotnakaniikawatanaguraxn--srfo" + + "ld-byaxn--srreisa-q1axn--srum-grazxn--stfold-9xaxn--stjrdal-s1ax" + + "n--stjrdalshalsen-sqbievathletajimabaridagawakuyabukijobserverra" + + "nkoshigayachimataikikonaikawachinaganoharamcoachampionshiphoptob" + + "ishimagazineat-urlillyukiiyamanouchikuhokuryugasakitaurayasudaxn" + + "--stre-toten-zcbifukagawarszawashingtondclkaratsuginamikatagamil" + + "itaryukuhashimoichinosekigaharaxn--t60b56axn--tckweatherchannelx" + + "n--tiq49xqyjetztrentino-s-tirolxn--tjme-hraxn--tn0agrinet-freaks" + + "tuttgartrentinsued-tirolxn--tnsberg-q1axn--tor131oxn--trany-yuax" + + "n--trentin-sd-tirol-rzbigv-infoodnetworkangerxn--trentin-sdtirol" + + "-7vbihorologyurihonjournalistjohnikonanporohtawaramotoineppuglia" + + "xn--trentino-sd-tirol-c3bikedagestangeometre-experts-comptables3" + + "-website-eu-west-1xn--trentino-sdtirol-szbilbaogashimadachicago-" + + "vipsinaappanasonicasertairanzaninohekinannestadiyusuharaxn--tren" + + "tinosd-tirol-rzbillustrationthewifiatmallorcadaques3-website-sa-" + + "east-1xn--trentinosdtirol-7vbiomutashinain-the-bandain-vpncasino" + + "rdkapparaglidinglassassinationalheritagexn--trentinsd-tirol-6vbi" + + "rdartcenterprisecloudappspotagerxn--trentinsdtirol-nsbirkenesodd" + + "tangenovaraholtaleninomiyakonojorpelandnparisor-fronirasakincheo" + + "nishiazaindianapolis-a-bloggerxn--trgstad-r1axn--trna-woaxn--tro" + + "ms-zuaxn--tysvr-vraxn--uc0atvarggatrentinsuedtirolxn--uc0ay4axn-" + + "-uist22hamurakamigoris-a-lawyerxn--uisz3gxn--unjrga-rtargivestby" + + "temarkosakaerodromegallupinbarrel-of-knowledgemologicallazioddau" + + "thordalandeportenrightathomeftpalmspringsakereportatsunobiraukra" + + "anghkeymachineustarhubss3-eu-central-1xn--unup4yxn--uuwu58axn--v" + + "ads-jraxn--valle-aoste-ebbtrysiljanxn--valle-d-aoste-ehbodollsus" + + "akis-into-cartoonshintokushimaxn--valleaoste-e7axn--valledaoste-" + + "ebbvacationsusonoxn--vard-jraxn--vegrshei-c0axn--vermgensberater" + + "-ctbirthplacexn--vermgensberatung-pwbjarkoyusuisserveircateringe" + + "buildingleezexn--vestvgy-ixa6oxn--vg-yiabkhaziaxn--vgan-qoaxn--v" + + "gsy-qoa0jevnakershuscultureggiocalabriaxn--vgu402coguchikuzenxn-" + + "-vhquvaroyxn--vler-qoaxn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla" + + "5gxn--vuq861bjerkreimbamblebesbyglandroverhallaakesvuemielecceu-" + + "2xn--w4r85el8fhu5dnraxn--w4rs40lxn--wcvs22dxn--wgbh1collectionxn" + + "--wgbl6axn--xhq521bjugnieznord-frontierxn--xkc2al3hye2axn--xkc2d" + + "l3a5ee0handsonxn--y9a3aquariumissilelxn--yer-znaturbruksgymnxn--" + + "yfro4i67oxn--ygarden-p1axn--ygbi2ammxn--3hcrj9circustomerxn--yst" + + "re-slidre-ujblackfridayuu2-localhostoregontrailroadrangedalimano" + + "warudaxn--zbx025dxn--zf0ao64axn--zf0avxn--3oq18vl8pn36axn--zfr16" + + "4bloombergbauernishigovtjmaxxxboxenapponazure-mobilexnbayxz" + +// nodes is the list of nodes. Each node is represented as a uint32, which +// encodes the node's children, wildcard bit and node type (as an index into +// the children array), ICANN bit and text. +// +// If the table was generated with the -comments flag, there is a //-comment +// after each node's data. In it is the nodes-array indexes of the children, +// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The +// nodeType is printed as + for normal, ! for exception, and o for parent-only +// nodes that have children but don't match a domain label in their own right. +// An I denotes an ICANN domain. +// +// The layout within the uint32, from MSB to LSB, is: +// [ 0 bits] unused +// [10 bits] children index +// [ 1 bits] ICANN bit +// [15 bits] text index +// [ 6 bits] text length +var nodes = [...]uint32{ + 0x32bd43, + 0x3ac204, + 0x2e8b86, + 0x2fe083, + 0x2fe086, + 0x389b46, + 0x3b0ec3, + 0x31f984, + 0x309b87, + 0x2e87c8, + 0x1a000c2, + 0x1f3dd07, + 0x375009, + 0x2c444a, + 0x2c444b, + 0x22d043, + 0x2342c5, + 0x2206702, + 0x2483c4, + 0x25ba43, + 0x331e45, + 0x260dcc2, + 0x32eec3, + 0x2a1e744, + 0x30b345, + 0x2e240c2, + 0x26dc8e, + 0x253f83, + 0x3a7b46, + 0x3201842, + 0x2d02c7, + 0x236c86, + 0x3604b02, + 0x227483, + 0x280a84, + 0x2165c6, + 0x39fc48, + 0x289886, + 0x26f844, + 0x3a00b02, + 0x34a789, + 0x217307, + 0x200f46, + 0x274909, + 0x2fccc8, + 0x346d44, + 0x368ac6, + 0x255fc6, + 0x3e017c2, + 0x23938f, + 0x205b8e, + 0x2199c4, + 0x215ac5, + 0x32bc45, + 0x2e1d89, + 0x23cc09, + 0x216dc7, + 0x21e046, + 0x248903, + 0x4220f02, + 0x222e83, + 0x317cca, + 0x46020c3, + 0x248d45, + 0x2ffe82, + 0x38a8c9, + 0x4e02442, + 0x20c3c4, + 0x3b89c6, + 0x336d45, + 0x36c084, + 0x5637884, + 0x20a683, + 0x233684, + 0x5a026c2, + 0x250bc4, + 0x5e6c7c4, + 0x398e8a, + 0x6200882, + 0x3b7607, + 0x206288, + 0x7202202, + 0x37e987, + 0x22d3c4, + 0x2c1807, + 0x22d3c5, + 0x351647, + 0x3cbf86, + 0x2ad604, + 0x32ec45, + 0x25bc47, + 0x82052c2, + 0x244683, + 0x20b582, + 0x3607c3, + 0x860d242, + 0x283a05, + 0x8a00202, + 0x243f44, + 0x2e1a05, + 0x219907, + 0x21f2ce, + 0x2b0444, + 0x265604, + 0x218a43, + 0x371bc9, + 0x257f0b, + 0x269488, + 0x2746c8, + 0x38c288, + 0x28da08, + 0x346b8a, + 0x351547, + 0x2c7086, + 0x8e4a0c2, + 0x309243, + 0x3ce603, + 0x3d0044, + 0x309283, + 0x3639c3, + 0x1739742, + 0x9202c42, + 0x27fe45, + 0x39eb86, + 0x281084, + 0x369247, + 0x250a06, + 0x2ba9c4, + 0x389207, + 0x203a83, + 0x96cb182, + 0x9a25a42, + 0x9e25802, + 0x225806, + 0xa200282, + 0x2850c5, + 0x33ac83, + 0x3c0604, + 0x2ef704, + 0x2ef705, + 0x3c4703, + 0xa64ce83, + 0xab3b5c2, + 0x28cf05, + 0x3da30b, + 0x2c004b, + 0x22afc4, + 0x3dc049, + 0x207fc4, + 0xae08202, + 0x208a43, + 0x208fc3, + 0xb201a42, + 0x2ee503, + 0x20a94a, + 0xb6010c2, + 0x2dca05, + 0x2e0f4a, + 0x38b104, + 0x20b083, + 0x20b944, + 0x20c483, + 0x20c484, + 0x20c487, + 0x20db85, + 0x210d86, + 0x211146, + 0x212103, + 0x215e08, + 0x20e383, + 0xba1c742, + 0x247308, + 0x37868b, + 0x220808, + 0x221346, + 0x221e87, + 0x225088, + 0xca07c02, + 0xcf25802, + 0x30b488, + 0x219047, + 0x314885, + 0x314888, + 0xd2bdcc8, + 0x2d4803, + 0x228bc4, + 0x389bc2, + 0xd629c02, + 0xda43fc2, + 0xe22b882, + 0x22b883, + 0xe605cc2, + 0x30f943, + 0x239944, + 0x212283, + 0x3cbd04, + 0x30ab0b, + 0x23af03, + 0x2ea246, + 0x23af04, + 0x2b920e, + 0x381c85, + 0x3a7c48, + 0x235dc7, + 0x235dca, + 0x226e43, + 0x3ac007, + 0x2580c5, + 0x22fc84, + 0x256786, + 0x256787, + 0x312944, + 0x22f5c7, + 0xea1f604, + 0x398b44, + 0x398b46, + 0x25b444, + 0x3c4e86, + 0x20b383, + 0x3d1dc8, + 0x20b388, + 0x2655c3, + 0x2ee4c3, + 0x343dc4, + 0x353ec3, + 0xf235d82, + 0xf68d142, + 0x208183, + 0x242d46, + 0x28ed83, + 0x23ab04, + 0xfa17b02, + 0x308183, + 0x217b03, + 0x212f82, + 0xfe014c2, + 0x2c5006, + 0x234f87, + 0x275487, + 0x209e85, + 0x396d84, + 0x29b045, + 0x23f907, + 0x2eb4c9, + 0x2fed86, + 0x300c48, + 0x3109c6, + 0x1022ec82, + 0x3019c8, + 0x3037c6, + 0x2d4b85, + 0x321b07, + 0x323144, + 0x323145, + 0x10731a84, + 0x331a88, + 0x10a0a602, + 0x10e00482, + 0x30c486, + 0x200488, + 0x358345, + 0x359946, + 0x35e748, + 0x37c508, + 0x11205f85, + 0x11625344, + 0x2448c7, + 0x11a07a42, + 0x11ed5e42, + 0x13202782, + 0x3b8ac5, + 0x2a5f45, + 0x377c46, + 0x3a0ec7, + 0x22c487, + 0x13a2d7c3, + 0x2df287, + 0x348dc8, + 0x1da2d989, + 0x26de47, + 0x22de07, + 0x22e808, + 0x22f006, + 0x22f786, + 0x230bcc, + 0x23230a, + 0x232c87, + 0x23418b, + 0x234dc7, + 0x234dce, + 0x1de35c44, + 0x236204, + 0x239807, + 0x260147, + 0x23c4c6, + 0x23c4c7, + 0x337307, + 0x1e22bdc2, + 0x23de06, + 0x23de0a, + 0x23e20b, + 0x23fec7, + 0x240945, + 0x2414c3, + 0x241b06, + 0x241b07, + 0x272803, + 0x1e600102, + 0x24238a, + 0x1eb76cc2, + 0x1ee487c2, + 0x1f247002, + 0x1f636d82, + 0x247745, + 0x248484, + 0x1fe37982, + 0x250c45, + 0x231543, + 0x2080c5, + 0x204a44, + 0x20bc84, + 0x21f906, + 0x27f946, + 0x2a7843, + 0x3ba9c4, + 0x275783, + 0x20e02942, + 0x222204, + 0x244e46, + 0x222205, + 0x2576c6, + 0x321c08, + 0x28fd84, + 0x2102c8, + 0x39fa05, + 0x39f748, + 0x2bef86, + 0x359d87, + 0x26ec04, + 0x2226ec06, + 0x22645dc3, + 0x39cbc3, + 0x348188, + 0x332c04, + 0x22b5ed87, + 0x232de7c6, + 0x2de7c9, + 0x336088, + 0x38ca48, + 0x34a204, + 0x3c2b83, + 0x23e8c2, + 0x23652282, + 0x23a03e02, + 0x3c7983, + 0x23e12ac2, + 0x2f0a04, + 0x36f146, + 0x309cc5, + 0x21b1c3, + 0x2b5f07, + 0x3306c3, + 0x338108, + 0x214ec5, + 0x25cdc3, + 0x2e1985, + 0x2e1ac4, + 0x3034c6, + 0x217004, + 0x217b86, + 0x219846, + 0x206804, + 0x235183, + 0x2420d602, + 0x2479e645, + 0x200843, + 0x24e16042, + 0x22d943, + 0x246385, + 0x25233743, + 0x25a33749, + 0x25e00942, + 0x26605242, + 0x28ca45, + 0x213986, + 0x20da06, + 0x2d0f48, + 0x2d0f4b, + 0x32dc4b, + 0x20a085, + 0x2cc809, + 0x1601982, + 0x2e8e88, + 0x21f084, + 0x26e01242, + 0x337943, + 0x27660306, + 0x27db08, + 0x27a01f02, + 0x310588, + 0x27e758c2, + 0x33f30a, + 0x282d2003, + 0x28b75646, + 0x399608, + 0x315848, + 0x3c0b46, + 0x386d47, + 0x239587, + 0x255b4a, + 0x38b184, + 0x35d884, + 0x374a49, + 0x28fabc05, + 0x205d86, + 0x219243, + 0x271e84, + 0x29202404, + 0x202407, + 0x29757a47, + 0x26e4c4, + 0x378c45, + 0x377d08, + 0x3a4587, + 0x249487, + 0x29a19d02, + 0x3c3844, + 0x293548, + 0x24aa44, + 0x24e444, + 0x24e805, + 0x24e947, + 0x29e4dbc9, + 0x250104, + 0x250f49, + 0x251188, + 0x251984, + 0x251987, + 0x2a252083, + 0x252747, + 0x1603582, + 0x16b0f82, + 0x253946, + 0x253fc7, + 0x254244, + 0x255047, + 0x256bc7, + 0x257843, + 0x2b06c2, + 0x20c742, + 0x2747c3, + 0x3be744, + 0x3be74b, + 0x2a6747c8, + 0x25c784, + 0x258ec5, + 0x25a687, + 0x25bec5, + 0x2e0b8a, + 0x25c6c3, + 0x2aa0e282, + 0x20e284, + 0x25ff09, + 0x263f83, + 0x264047, + 0x38c6c9, + 0x3d77c8, + 0x238983, + 0x27cb87, + 0x27dfc9, + 0x23fac3, + 0x2872c4, + 0x288c09, + 0x28ab06, + 0x219c03, + 0x205282, + 0x236883, + 0x2b0d87, + 0x236885, + 0x3cb4c6, + 0x2aea44, + 0x302fc5, + 0x279d03, + 0x212346, + 0x237482, + 0x24ce44, + 0x2ae0a1c2, + 0x2b22b083, + 0x2b604182, + 0x24c203, + 0x2115c4, + 0x2115c7, + 0x38b206, + 0x2023c2, + 0x2ba02382, + 0x321e04, + 0x2be0c602, + 0x2c212782, + 0x246644, + 0x246645, + 0x3cae05, + 0x365f46, + 0x2c609d82, + 0x360245, + 0x3c53c5, + 0x2270c3, + 0x211746, + 0x21c105, + 0x225782, + 0x357f85, + 0x225784, + 0x226203, + 0x228d03, + 0x2ca05142, + 0x233b47, + 0x251b04, + 0x251b09, + 0x271d84, + 0x28d503, + 0x39bf48, + 0x2cea5dc4, + 0x2a5dc6, + 0x2ab3c3, + 0x259703, + 0x220583, + 0x2d2ee042, + 0x300002, + 0x2d600642, + 0x33cd88, + 0x220108, + 0x3b1646, + 0x25c585, + 0x22c045, + 0x201887, + 0x2da78745, + 0x2068c2, + 0x2de96bc2, + 0x2e200042, + 0x31ed08, + 0x301905, + 0x2f5f44, + 0x257605, + 0x24a487, + 0x273244, + 0x242282, + 0x2e605002, + 0x34e6c4, + 0x221807, + 0x28f307, + 0x351604, + 0x3ced83, + 0x265504, + 0x265508, + 0x22fac6, + 0x25660a, + 0x3575c4, + 0x295548, + 0x28af44, + 0x221f86, + 0x296b84, + 0x3b8dc6, + 0x251dc9, + 0x245847, + 0x21f183, + 0x2ea07102, + 0x34a483, + 0x208402, + 0x2ee01d02, + 0x2f3206, + 0x380e08, + 0x2a7747, + 0x22a1c9, + 0x295109, + 0x2a8c85, + 0x2aa589, + 0x2aad45, + 0x2aae89, + 0x2abe05, + 0x2ac848, + 0x2f20c644, + 0x2f657987, + 0x22e1c3, + 0x2aca47, + 0x22e1c6, + 0x2ace87, + 0x2a48c5, + 0x2ba0c3, + 0x2fa320c2, + 0x20b2c4, + 0x2fe2bf42, + 0x302373c2, + 0x33c146, + 0x206205, + 0x2af987, + 0x32f343, + 0x363944, + 0x203f43, + 0x2c6883, + 0x306067c2, + 0x30e03d82, + 0x389c44, + 0x36b103, + 0x2fc5c5, + 0x31205e42, + 0x31a00bc2, + 0x2da6c6, + 0x332d44, + 0x321644, + 0x32164a, + 0x322005c2, + 0x244b03, + 0x2157ca, + 0x219c88, + 0x32622884, + 0x2005c3, + 0x32a038c3, + 0x281709, + 0x252d49, + 0x2b6006, + 0x32e19e43, + 0x21c445, + 0x31de8d, + 0x219e46, + 0x21bccb, + 0x33204c02, + 0x2b2c48, + 0x36215f02, + 0x36604c82, + 0x375e05, + 0x36a01b82, + 0x230047, + 0x2adec7, + 0x204383, + 0x341788, + 0x36e06102, + 0x3b9c84, + 0x219583, + 0x328085, + 0x23e906, + 0x220d44, + 0x2ee483, + 0x2b1e03, + 0x37202d42, + 0x20a004, + 0x3bc2c5, + 0x2b0987, + 0x27a143, + 0x2b1403, + 0x16b14c2, + 0x2b14c3, + 0x2b1d83, + 0x376035c2, + 0x3b7d44, + 0x27fb46, + 0x2e6343, + 0x2b22c3, + 0x37a4d442, + 0x24d448, + 0x2b3204, + 0x368486, + 0x25d187, + 0x29b3c6, + 0x36f744, + 0x45a015c2, + 0x22e08b, + 0x2f90ce, + 0x21450f, + 0x2b0fc3, + 0x4625d602, + 0x1637542, + 0x46603882, + 0x295ac3, + 0x209503, + 0x21d046, + 0x2eb746, + 0x21ac87, + 0x30e184, + 0x46a13ac2, + 0x46e0a3c2, + 0x241385, + 0x2fa2c7, + 0x2b4ac6, + 0x47248702, + 0x32e844, + 0x2bab43, + 0x47653a42, + 0x47b70e03, + 0x2bbb44, + 0x2c0a89, + 0x47ec80c2, + 0x48203942, + 0x203945, + 0x486c8e02, + 0x48a06ac2, + 0x35be87, + 0x3b2349, + 0x37528b, + 0x239345, + 0x26a549, + 0x26d1c6, + 0x38f987, + 0x48e0e984, + 0x3d5849, + 0x37b387, + 0x20f607, + 0x22bb83, + 0x2b2ac6, + 0x32a947, + 0x20bec3, + 0x3ca646, + 0x4960ac02, + 0x49a339c2, + 0x3b5543, + 0x38aa85, + 0x21ee87, + 0x2eb846, + 0x236805, + 0x251304, + 0x2a3dc5, + 0x38bc44, + 0x49e00f82, + 0x274d87, + 0x2c5c44, + 0x23bf84, + 0x34998d, + 0x2d9189, + 0x22be88, + 0x203bc4, + 0x3b9445, + 0x20df07, + 0x210184, + 0x267b87, + 0x357285, + 0x4a214a04, + 0x2b4085, + 0x262c44, + 0x2b1a46, + 0x3a0cc5, + 0x4a624ec2, + 0x30c403, + 0x35cf44, + 0x35cf45, + 0x3520c6, + 0x236945, + 0x238904, + 0x34c603, + 0x4aa12a06, + 0x2676c5, + 0x282305, + 0x3a0dc4, + 0x2e5a43, + 0x2e5a4c, + 0x4aeb0a82, + 0x4b203502, + 0x4b600b42, + 0x214903, + 0x214904, + 0x4ba08002, + 0x37e508, + 0x3cb585, + 0x24b304, + 0x367a46, + 0x4be0f1c2, + 0x4c205e82, + 0x4c601442, + 0x28c045, + 0x2066c6, + 0x357984, + 0x216b06, + 0x371f86, + 0x210043, + 0x4cb4b2ca, + 0x271cc5, + 0x317c83, + 0x209b86, + 0x209b89, + 0x224207, + 0x2a4ec8, + 0x2fcb89, + 0x331688, + 0x226b86, + 0x218a03, + 0x4cedf302, + 0x3a1788, + 0x4d24ab82, + 0x4d6024c2, + 0x22a243, + 0x2e43c5, + 0x26ae44, + 0x211ec9, + 0x2e14c4, + 0x21a048, + 0x4de08443, + 0x4e30af84, + 0x2139c8, + 0x3498c7, + 0x4e65e5c2, + 0x23f1c2, + 0x32bbc5, + 0x265dc9, + 0x205e03, + 0x281304, + 0x31de44, + 0x20df83, + 0x2835ca, + 0x4ea01582, + 0x4ee0b102, + 0x2cb103, + 0x38e683, + 0x162d842, + 0x308a43, + 0x4f202dc2, + 0x4f600c02, + 0x4fb216c4, + 0x3dcb86, + 0x39ba06, + 0x226244, + 0x279343, + 0x3bb343, + 0x4fecb283, + 0x23e586, + 0x3a4dc5, + 0x2cc1c7, + 0x2cee45, + 0x2d0006, + 0x2d1208, + 0x2d1406, + 0x207304, + 0x29c1cb, + 0x2d6043, + 0x2d6045, + 0x2d6c88, + 0x2104c2, + 0x35c182, + 0x502477c2, + 0x50600e82, + 0x200e83, + 0x50a6cec2, + 0x26cec3, + 0x2d7683, + 0x51224682, + 0x516dc3c6, + 0x2594c6, + 0x51ab2e42, + 0x51e09002, + 0x52228d42, + 0x52645ec2, + 0x52a1a282, + 0x52e01342, + 0x20ed83, + 0x2c9e05, + 0x327d86, + 0x53205184, + 0x244c4a, + 0x3aa406, + 0x20c844, + 0x201c43, + 0x53e02a42, + 0x202642, + 0x22d903, + 0x54206b43, + 0x366547, + 0x3a0bc7, + 0x55ee7247, + 0x3cd307, + 0x227983, + 0x35fc8a, + 0x235fc4, + 0x31b684, + 0x31b68a, + 0x22c5c5, + 0x56205d42, + 0x255003, + 0x56600602, + 0x251ac3, + 0x34a443, + 0x56e00582, + 0x348d44, + 0x201a84, + 0x3bf805, + 0x322885, + 0x2aa2c6, + 0x2b6c06, + 0x5724fd42, + 0x576013c2, + 0x37a405, + 0x2591d2, + 0x34f1c6, + 0x24e703, + 0x304c46, + 0x2b4545, + 0x160a982, + 0x5fa0af02, + 0x3743c3, + 0x20af03, + 0x288883, + 0x5fe1a682, + 0x23d443, + 0x6060cc82, + 0x2a7503, + 0x3b7d88, + 0x2a8b03, + 0x2a8b06, + 0x32f7c7, + 0x324a06, + 0x324a0b, + 0x20c787, + 0x347f84, + 0x60e00e42, + 0x3cb405, + 0x61212b03, + 0x2050c3, + 0x28e805, + 0x332f43, + 0x61b32f46, + 0x2e900a, + 0x2a3083, + 0x2164c4, + 0x2003c6, + 0x2d4f86, + 0x61e3cf83, + 0x363807, + 0x281607, + 0x29dbc5, + 0x2ec406, + 0x267703, + 0x64a11983, + 0x64e01002, + 0x6533ef04, + 0x3c2249, + 0x3c7a05, + 0x22c244, + 0x34e0c8, + 0x2e6185, + 0x656e75c5, + 0x240ac9, + 0x201003, + 0x248744, + 0x65a02142, + 0x213d03, + 0x65e76402, + 0x276406, + 0x1678842, + 0x662201c2, + 0x28bf48, + 0x291f83, + 0x2b3fc7, + 0x2b1545, + 0x2b3b85, + 0x324c8b, + 0x2e8146, + 0x324e86, + 0x2e96c6, + 0x27f1c4, + 0x2c0c86, + 0x666d9d88, + 0x23afc3, + 0x23d903, + 0x23d904, + 0x38c084, + 0x316147, + 0x2ed4c5, + 0x66aed602, + 0x66e06a82, + 0x6761b085, + 0x2b8044, + 0x2daccb, + 0x2ef608, + 0x2525c4, + 0x67a2bd02, + 0x67e23802, + 0x3c4e03, + 0x2f15c4, + 0x2f1885, + 0x2f2247, + 0x2f5a84, + 0x351704, + 0x68213c42, + 0x37ab09, + 0x2f6bc5, + 0x239605, + 0x2f7745, + 0x68613c43, + 0x2f8644, + 0x2f864b, + 0x2f8984, + 0x2f8c4b, + 0x2f9c85, + 0x21464a, + 0x2fa7c8, + 0x2fa9ca, + 0x2fb203, + 0x2fb20a, + 0x68e0a0c2, + 0x69241f42, + 0x6961f4c3, + 0x69afed02, + 0x2fed03, + 0x69f52a42, + 0x6a33b402, + 0x2ffbc4, + 0x215f46, + 0x216845, + 0x300e43, + 0x32c306, + 0x216345, + 0x2e4a44, + 0x6a600902, + 0x2a1344, + 0x2cc48a, + 0x336fc7, + 0x3332c6, + 0x3abe47, + 0x23de43, + 0x2bbb88, + 0x37eb4b, + 0x2c12c5, + 0x2a9c05, + 0x2a9c06, + 0x2ec744, + 0x210f48, + 0x222b03, + 0x255ec4, + 0x255ec7, + 0x347bc6, + 0x3ccb06, + 0x2b904a, + 0x250fc4, + 0x2fba4a, + 0x6ab30086, + 0x330087, + 0x258f47, + 0x275dc4, + 0x275dc9, + 0x2ff605, + 0x3cc44b, + 0x2ee903, + 0x217d43, + 0x6ae1d583, + 0x2ca004, + 0x6b200682, + 0x229446, + 0x6b6b9e45, + 0x304e85, + 0x253b86, + 0x29fe44, + 0x6ba02542, + 0x241504, + 0x6be16f82, + 0x2d5745, + 0x32ffc4, + 0x6ca1b683, + 0x6ce01e82, + 0x201e83, + 0x237086, + 0x6d209482, + 0x391a48, + 0x224084, + 0x224086, + 0x38ef06, + 0x6d65a744, + 0x212985, + 0x225248, + 0x226087, + 0x246747, + 0x24674f, + 0x293446, + 0x231c83, + 0x23c644, + 0x20e4c3, + 0x2220c4, + 0x254144, + 0x6da02c02, + 0x28ce43, + 0x338dc3, + 0x6de02002, + 0x227683, + 0x2259c3, + 0x20dc0a, + 0x273b07, + 0x25984c, + 0x259b06, + 0x25c186, + 0x25ce87, + 0x6e22ec47, + 0x268049, + 0x247444, + 0x269ac4, + 0x6e600ec2, + 0x6ea01bc2, + 0x2b9406, + 0x363604, + 0x28d2c6, + 0x22f0c8, + 0x38ab44, + 0x230086, + 0x20d9c5, + 0x6ee83048, + 0x241c03, + 0x287a45, + 0x288203, + 0x239703, + 0x239704, + 0x20e243, + 0x6f24d882, + 0x6f601282, + 0x2ee7c9, + 0x28be45, + 0x28c144, + 0x317f05, + 0x297104, + 0x3a1fc7, + 0x36aac5, + 0x6fa3d804, + 0x23d808, + 0x2d9f46, + 0x2dcb04, + 0x2e1348, + 0x2e1c47, + 0x6fe037c2, + 0x2e8684, + 0x303104, + 0x2c1a07, + 0x70207c44, + 0x22b302, + 0x70603842, + 0x203843, + 0x203844, + 0x29e943, + 0x29e945, + 0x70a388c2, + 0x2fff05, + 0x2801c2, + 0x307d85, + 0x3b49c5, + 0x70e15042, + 0x217a84, + 0x71203002, + 0x25e406, + 0x2ba6c6, + 0x265f08, + 0x2c2988, + 0x33c0c4, + 0x305d85, + 0x3a6509, + 0x20a104, + 0x2e8fc4, + 0x206903, + 0x71655c85, + 0x243185, + 0x2a15c4, + 0x35248d, + 0x308102, + 0x353f43, + 0x354c83, + 0x71a02702, + 0x391505, + 0x220f87, + 0x2b9f44, + 0x3cd3c7, + 0x2fcd89, + 0x2cc5c9, + 0x202703, + 0x278688, + 0x2f9889, + 0x2f7a07, + 0x3da885, + 0x37e1c6, + 0x380fc6, + 0x3a60c5, + 0x2d9285, + 0x71e03b42, + 0x27b445, + 0x2b8308, + 0x2c4dc6, + 0x72206ec7, + 0x26e404, + 0x335187, + 0x302c86, + 0x72641542, + 0x351dc6, + 0x30740a, + 0x307c85, + 0x72ae9d02, + 0x72e8f4c2, + 0x33f806, + 0x323448, + 0x7328f4c7, + 0x73639102, + 0x28a5c3, + 0x209786, + 0x224e44, + 0x27e606, + 0x33bd46, + 0x20720a, + 0x331f45, + 0x328c46, + 0x32e243, + 0x32e244, + 0x202742, + 0x332cc3, + 0x73a14942, + 0x2d15c3, + 0x215a44, + 0x2c3184, + 0x73f2358a, + 0x21c4c3, + 0x226c4a, + 0x239dc7, + 0x312e86, + 0x25e2c4, + 0x20c702, + 0x2a6742, + 0x742007c2, + 0x2654c3, + 0x258d07, + 0x2007c7, + 0x2895c4, + 0x21e8c7, + 0x2f2346, + 0x219187, + 0x225904, + 0x37cb05, + 0x218345, + 0x74619f82, + 0x3dc5c6, + 0x21d843, + 0x220bc2, + 0x220bc6, + 0x74a19b42, + 0x74e1be02, + 0x3c3905, + 0x75243982, + 0x75602b42, + 0x348ac5, + 0x2d6385, + 0x2a7ec5, + 0x75a04e83, + 0x36f205, + 0x2e8207, + 0x2c4c05, + 0x332105, + 0x32a284, + 0x2e6006, + 0x34b504, + 0x75e008c2, + 0x76ae94c5, + 0x382b07, + 0x360088, + 0x251646, + 0x25164d, + 0x252b09, + 0x252b12, + 0x380385, + 0x38bd03, + 0x76e062c2, + 0x2f3e44, + 0x219ec3, + 0x30d305, + 0x30e4c5, + 0x772195c2, + 0x25ce03, + 0x7765b8c2, + 0x77ee3402, + 0x78200082, + 0x2c8b45, + 0x3cd503, + 0x24af88, + 0x78619082, + 0x78a0d2c2, + 0x348d06, + 0x31f38a, + 0x20ef03, + 0x25ac43, + 0x2eeac3, + 0x79e07d82, + 0x8821a6c2, + 0x88a0a742, + 0x206842, + 0x3d00c9, + 0x2c7504, + 0x2ac108, + 0x88efc182, + 0x89214f82, + 0x2af4c5, + 0x2345c8, + 0x311308, + 0x2ef30c, + 0x239d03, + 0x8961f202, + 0x89a0a342, + 0x349646, + 0x313d05, + 0x2dcf43, + 0x2574c6, + 0x313e46, + 0x29b2c3, + 0x3c2003, + 0x3152c6, + 0x316ac4, + 0x2819c6, + 0x21c28a, + 0x24e184, + 0x317184, + 0x31820a, + 0x89e1ff02, + 0x252205, + 0x319d4a, + 0x319c85, + 0x31b1c4, + 0x31b2c6, + 0x31b444, + 0x213fc6, + 0x8a22bc42, + 0x2fdd06, + 0x328805, + 0x32e0c7, + 0x3ad646, + 0x25d084, + 0x2dd1c7, + 0x34b206, + 0x20bf45, + 0x20bf47, + 0x3bbc47, + 0x3bbc4e, + 0x26bb86, + 0x221d45, + 0x207b87, + 0x306003, + 0x330387, + 0x209185, + 0x20af84, + 0x221ac2, + 0x229c47, + 0x30e204, + 0x231784, + 0x23f04b, + 0x21c8c3, + 0x288087, + 0x21c8c4, + 0x288287, + 0x294a03, + 0x34ca4d, + 0x3a4bc8, + 0x8a62a984, + 0x23d705, + 0x31bfc5, + 0x31c403, + 0x8aa23f82, + 0x31dd83, + 0x31e583, + 0x3dc744, + 0x27e0c5, + 0x21d8c7, + 0x32e2c6, + 0x38bac3, + 0x228d8b, + 0x27444b, + 0x2b200b, + 0x2d440b, + 0x2e9d4a, + 0x33484b, + 0x36d94b, + 0x392c8c, + 0x3d990b, + 0x3db991, + 0x32068a, + 0x320b8b, + 0x320e4c, + 0x32114b, + 0x3218ca, + 0x321f0a, + 0x322e0e, + 0x32380b, + 0x323aca, + 0x325011, + 0x32544a, + 0x32594b, + 0x325e8e, + 0x3267cc, + 0x326e0b, + 0x3270ce, + 0x32744c, + 0x329d4a, + 0x32b58c, + 0x8af2b88a, + 0x32c488, + 0x32d049, + 0x33390a, + 0x333b8a, + 0x333e0b, + 0x33854e, + 0x338f51, + 0x341f49, + 0x34218a, + 0x342f8b, + 0x3444ca, + 0x345596, + 0x34690b, + 0x34768a, + 0x34854a, + 0x349d8b, + 0x34a609, + 0x34d3c9, + 0x34da0d, + 0x34e44b, + 0x34f34b, + 0x34fd0b, + 0x350589, + 0x350bce, + 0x35130a, + 0x35224a, + 0x3527ca, + 0x352f8b, + 0x3537cb, + 0x35448d, + 0x356b8d, + 0x357c10, + 0x3580cb, + 0x358acc, + 0x3596cb, + 0x35b98b, + 0x35dd4e, + 0x35e44b, + 0x35e44d, + 0x364a4b, + 0x3654cf, + 0x36588b, + 0x3660ca, + 0x3673c9, + 0x367bc9, + 0x8b368c4b, + 0x368f0e, + 0x36b88b, + 0x36c50f, + 0x36e54b, + 0x36e80b, + 0x36eacb, + 0x36f34a, + 0x374e89, + 0x37978f, + 0x37df0c, + 0x37fb4c, + 0x38004e, + 0x38054f, + 0x38090e, + 0x381150, + 0x38154f, + 0x38210e, + 0x382ccc, + 0x382fd2, + 0x383751, + 0x383f4e, + 0x38438e, + 0x3853cb, + 0x3853ce, + 0x38574f, + 0x385b0e, + 0x385e93, + 0x386351, + 0x38678c, + 0x386a8e, + 0x386f0c, + 0x387453, + 0x387c50, + 0x3887cc, + 0x388acc, + 0x388f8b, + 0x38984e, + 0x389d4b, + 0x38a54b, + 0x38d28c, + 0x391f8a, + 0x39248c, + 0x39278c, + 0x392a89, + 0x39470b, + 0x3949c8, + 0x395189, + 0x39518f, + 0x39690b, + 0x8b79724a, + 0x39a2cc, + 0x39b48b, + 0x39b749, + 0x39bb88, + 0x39c14b, + 0x39c98b, + 0x39d50a, + 0x39d78b, + 0x3a150c, + 0x3a26c8, + 0x3a4f0b, + 0x3a814b, + 0x3ab00e, + 0x3ac50b, + 0x3ae20b, + 0x3bb7cb, + 0x3bba89, + 0x3bbfcd, + 0x3cd98a, + 0x3d0b57, + 0x3d1358, + 0x3d3f49, + 0x3d508b, + 0x3d6054, + 0x3d654b, + 0x3d6aca, + 0x3d6f8a, + 0x3d720b, + 0x3d79d0, + 0x3d7dd1, + 0x3d838a, + 0x3d8f0d, + 0x3d960d, + 0x3dbdcb, + 0x3dc6c3, + 0x8bb77983, + 0x2d4886, + 0x278445, + 0x30db87, + 0x334706, + 0x1605042, + 0x2dd4c9, + 0x32c104, + 0x2e7748, + 0x21d4c3, + 0x2f3d87, + 0x22f282, + 0x2af9c3, + 0x8be0a842, + 0x2cd186, + 0x2ce1c4, + 0x35cbc4, + 0x332803, + 0x8c6c8e42, + 0x8caab204, + 0x275d07, + 0x8ce37b02, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0xecf48, + 0x2013c3, + 0x2000c2, + 0xa14c8, + 0x202782, + 0x220583, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x202003, + 0x33e716, + 0x362c13, + 0x21e749, + 0x2447c8, + 0x3cb289, + 0x319ec6, + 0x34e710, + 0x2425d3, + 0x347c88, + 0x279447, + 0x27ad47, + 0x2a3b0a, + 0x32efc9, + 0x3a2849, + 0x24184b, + 0x3cbf86, + 0x289b0a, + 0x221346, + 0x32bd03, + 0x2dc8c5, + 0x3d1dc8, + 0x234a8d, + 0x3b8b8c, + 0x310ac7, + 0x32428d, + 0x225344, + 0x23094a, + 0x231e4a, + 0x23230a, + 0x2428c7, + 0x23bc07, + 0x23ef84, + 0x26ec06, + 0x32f404, + 0x2da308, + 0x2e1509, + 0x2d0f46, + 0x2d0f48, + 0x242d8d, + 0x2cc809, + 0x315848, + 0x239587, + 0x2399ca, + 0x253fc6, + 0x25f947, + 0x2cbe44, + 0x28f147, + 0x22964a, + 0x23d00e, + 0x278745, + 0x28f04b, + 0x229149, + 0x252d49, + 0x2add07, + 0x3bf4ca, + 0x2c1947, + 0x2f9209, + 0x3b9108, + 0x28eb4b, + 0x2e43c5, + 0x22bd4a, + 0x28fd09, + 0x37270a, + 0x2ceecb, + 0x3c514b, + 0x2415d5, + 0x2eb105, + 0x239605, + 0x2f864a, + 0x25b58a, + 0x311a07, + 0x234703, + 0x2b9388, + 0x2db00a, + 0x224086, + 0x266809, + 0x283048, + 0x2dcb04, + 0x387209, + 0x2c2988, + 0x2beec7, + 0x2e94c6, + 0x382b07, + 0x3503c7, + 0x23e385, + 0x2e730c, + 0x23d705, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x202782, + 0x22d7c3, + 0x206b43, + 0x2013c3, + 0x23cf83, + 0x22d7c3, + 0x206b43, + 0x13c3, + 0x2a8b03, + 0x23cf83, + 0x1cdd43, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0xa14c8, + 0x202782, + 0x22d7c3, + 0x22d7c7, + 0x206b43, + 0x23cf83, + 0x202782, + 0x203dc2, + 0x31b402, + 0x206102, + 0x200d42, + 0x2ea5c2, + 0x91d46, + 0x54389, + 0x481b683, + 0x89947, + 0x7b83, + 0x11b645, + 0xc1, + 0x522d7c3, + 0x233743, + 0x228843, + 0x220583, + 0x219e43, + 0x205e03, + 0x2dc7c6, + 0x206b43, + 0x23cf83, + 0x204283, + 0xa14c8, + 0x200984, + 0x30ad47, + 0x332843, + 0x375e04, + 0x21a5c3, + 0x212003, + 0x220583, + 0x14c47, + 0x109744, + 0x3283, + 0x131905, + 0x2000c2, + 0x4ce83, + 0x6602782, + 0x688bc49, + 0x8c5cd, + 0x8c90d, + 0x31b402, + 0x22884, + 0x131949, + 0x2003c2, + 0x6e22788, + 0xf7dc4, + 0xa14c8, + 0x1419a42, + 0x14005c2, + 0x1419a42, + 0x1517386, + 0x22f303, + 0x26f283, + 0x762d7c3, + 0x230944, + 0x7a33743, + 0x7e20583, + 0x2067c2, + 0x222884, + 0x206b43, + 0x305f83, + 0x201642, + 0x23cf83, + 0x218142, + 0x2ffb03, + 0x209482, + 0x207043, + 0x283103, + 0x205302, + 0xa14c8, + 0x22f303, + 0x305f83, + 0x201642, + 0x2ffb03, + 0x209482, + 0x207043, + 0x283103, + 0x205302, + 0x2ffb03, + 0x209482, + 0x207043, + 0x283103, + 0x205302, + 0x22d7c3, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x219e43, + 0x205e03, + 0x205184, + 0x206b43, + 0x23cf83, + 0x202102, + 0x213c43, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x206b43, + 0x23cf83, + 0x3da885, + 0x2195c2, + 0x2000c2, + 0xa14c8, + 0x144b148, + 0x103e4a, + 0x220583, + 0x207881, + 0x2009c1, + 0x203281, + 0x202ec1, + 0x200a41, + 0x20c101, + 0x200a01, + 0x228441, + 0x207901, + 0x200001, + 0x2000c1, + 0x200201, + 0x12dac5, + 0xa14c8, + 0x200101, + 0x200f01, + 0x200501, + 0x202401, + 0x200041, + 0x200801, + 0x200181, + 0x202d41, + 0x200701, + 0x2004c1, + 0x200c01, + 0x200581, + 0x2003c1, + 0x201001, + 0x215f41, + 0x200401, + 0x200741, + 0x2007c1, + 0x200081, + 0x206841, + 0x201ec1, + 0x203301, + 0x201081, + 0x20a781, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x2003c2, + 0x23cf83, + 0x1b043, + 0x14c47, + 0x5f07, + 0x29f46, + 0x3530a, + 0x8b088, + 0x58748, + 0x58c07, + 0x108a46, + 0xe3485, + 0x45585, + 0x125d43, + 0x5bac6, + 0xec046, + 0x241844, + 0x37e847, + 0xa14c8, + 0x2dd2c4, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x2782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x32ba88, + 0x201844, + 0x233684, + 0x22afc4, + 0x349547, + 0x2d9947, + 0x22d7c3, + 0x23620b, + 0x31fb4a, + 0x3cc247, + 0x306588, + 0x328108, + 0x233743, + 0x336447, + 0x228843, + 0x20d348, + 0x210b49, + 0x222884, + 0x219e43, + 0x2fee88, + 0x205e03, + 0x2d618a, + 0x2dc7c6, + 0x3aa407, + 0x206b43, + 0x394486, + 0x26f108, + 0x23cf83, + 0x25ae06, + 0x2ef84d, + 0x2f1f08, + 0x2f898b, + 0x2bff86, + 0x3416c7, + 0x214dc5, + 0x2d5dca, + 0x228105, + 0x24308a, + 0x2195c2, + 0x207b83, + 0x231784, + 0x200006, + 0x3b0ec3, + 0x2a13c3, + 0x24de03, + 0x201843, + 0x372dc3, + 0x2017c2, + 0x300745, + 0x2a9049, + 0x23ea03, + 0x20a683, + 0x202b03, + 0x200201, + 0x2e8d87, + 0x2c8885, + 0x398a83, + 0x3c4703, + 0x22afc4, + 0x32f383, + 0x21c1c8, + 0x367603, + 0x31454d, + 0x26bc48, + 0x20b546, + 0x332d03, + 0x38d543, + 0x3ac783, + 0xbe2d7c3, + 0x232f88, + 0x236204, + 0x23fec3, + 0x200106, + 0x243608, + 0x202943, + 0x2d5e03, + 0x22d943, + 0x233743, + 0x210483, + 0x2416c3, + 0x2a6003, + 0x332c83, + 0x209c83, + 0x202403, + 0x38a7c5, + 0x254344, + 0x254cc7, + 0x2b06c2, + 0x2584c3, + 0x25af86, + 0x25c303, + 0x25c9c3, + 0x278643, + 0x309303, + 0x202383, + 0x2973c7, + 0xc220583, + 0x24b543, + 0x3d54c3, + 0x209a03, + 0x219c83, + 0x2fe043, + 0x3b4d05, + 0x371983, + 0x2f9f89, + 0x2035c3, + 0x30e7c3, + 0xc636803, + 0x3d8883, + 0x21b888, + 0x2a8f86, + 0x3090c6, + 0x29d786, + 0x388307, + 0x226b83, + 0x22a243, + 0x205e03, + 0x28b186, + 0x2104c2, + 0x2a6343, + 0x33d1c5, + 0x206b43, + 0x31aa87, + 0x16013c3, + 0x26f103, + 0x234203, + 0x218003, + 0x2050c3, + 0x23cf83, + 0x20e486, + 0x3315c6, + 0x37a043, + 0x2f0b83, + 0x213c43, + 0x225983, + 0x3c2083, + 0x2fe543, + 0x2ffec3, + 0x216345, + 0x25b583, + 0x378b46, + 0x32f608, + 0x217d43, + 0x274f89, + 0x363108, + 0x2170c8, + 0x224385, + 0x37cc0a, + 0x39da8a, + 0x22e30b, + 0x22f448, + 0x2ee443, + 0x38bc03, + 0x2f88c3, + 0x30f848, + 0x35e143, + 0x32e244, + 0x202742, + 0x260403, + 0x2007c3, + 0x229343, + 0x2572c3, + 0x204283, + 0x2195c2, + 0x227d43, + 0x239d03, + 0x317503, + 0x318c44, + 0x231784, + 0x228c83, + 0xa14c8, + 0x2000c2, + 0x200b02, + 0x2017c2, + 0x2020c2, + 0x200202, + 0x201942, + 0x258542, + 0x201242, + 0x200382, + 0x201442, + 0x25e5c2, + 0x200e82, + 0x26cec2, + 0x201002, + 0x2ea5c2, + 0x202142, + 0x203d42, + 0x213c42, + 0x2b0942, + 0x206382, + 0x200682, + 0x214582, + 0x202542, + 0x202002, + 0x201bc2, + 0x236082, + 0x202b42, + 0xc2, + 0xb02, + 0x17c2, + 0x20c2, + 0x202, + 0x1942, + 0x58542, + 0x1242, + 0x382, + 0x1442, + 0x5e5c2, + 0xe82, + 0x6cec2, + 0x1002, + 0xea5c2, + 0x2142, + 0x3d42, + 0x13c42, + 0xb0942, + 0x6382, + 0x682, + 0x14582, + 0x2542, + 0x2002, + 0x1bc2, + 0x36082, + 0x2b42, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x1ec2, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x2782, + 0x202782, + 0x23cf83, + 0xde2d7c3, + 0x220583, + 0x205e03, + 0x6df83, + 0x22ebc2, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x6df83, + 0x23cf83, + 0xa842, + 0x2001c2, + 0x1445d45, + 0x12dac5, + 0x20b342, + 0xa14c8, + 0x2782, + 0x234f42, + 0x202282, + 0x201c42, + 0x205d42, + 0x24fd42, + 0x45585, + 0x201fc2, + 0x201642, + 0x21a682, + 0x202b82, + 0x202142, + 0x3a1602, + 0x203842, + 0x295a82, + 0xef0b404, + 0x142, + 0x14c47, + 0x1a108d, + 0xe3509, + 0xaea4b, + 0xe80c8, + 0x71f49, + 0x10f346, + 0x220583, + 0xa14c8, + 0x109744, + 0x3283, + 0x131905, + 0xa14c8, + 0xdffc7, + 0x59706, + 0x131949, + 0x14a0e, + 0x137987, + 0x2000c2, + 0x241844, + 0x202782, + 0x22d7c3, + 0x203dc2, + 0x233743, + 0x19d03, + 0x200382, + 0x2dd2c4, + 0x219e43, + 0x24ab82, + 0x206b43, + 0x2003c2, + 0x23cf83, + 0x239606, + 0x3343cf, + 0x602, + 0x7094c3, + 0xa14c8, + 0x202782, + 0x228843, + 0x220583, + 0x205e03, + 0x13c3, + 0x14a08, + 0x14d5b8b, + 0x153f50a, + 0x148e24a, + 0x14726c7, + 0xa3bcb, + 0x15e1c5, + 0x11a7c9, + 0x12dac5, + 0x14c47, + 0xf5744, + 0x202782, + 0x22d7c3, + 0x220583, + 0x206b43, + 0x2000c2, + 0x201cc2, + 0x33b5c2, + 0x1222d7c3, + 0x23c842, + 0x233743, + 0x203582, + 0x20a1c2, + 0x220583, + 0x2068c2, + 0x272142, + 0x2ab1c2, + 0x202082, + 0x291a82, + 0x200802, + 0x2012c2, + 0x207102, + 0x27a482, + 0x201d02, + 0x18c3cc, + 0x2b1402, + 0x2efdc2, + 0x21d882, + 0x241442, + 0x205e03, + 0x200c02, + 0x206b43, + 0x209b42, + 0x2d43c2, + 0x23cf83, + 0x23ea82, + 0x202002, + 0x200ec2, + 0x201282, + 0x215042, + 0x2e9d02, + 0x219f82, + 0x25b8c2, + 0x220d02, + 0x323aca, + 0x3660ca, + 0x39858a, + 0x3dce42, + 0x218b42, + 0x3b4cc2, + 0x12644509, + 0x12b63a0a, + 0x142e5c7, + 0x12e04d82, + 0x140abc3, + 0x2e82, + 0x163a0a, + 0x1878ce, + 0x24ec04, + 0x5bd85, + 0x1362d7c3, + 0x3d4c3, + 0x233743, + 0x251184, + 0x1c1f46, + 0x220583, + 0x222884, + 0x219e43, + 0x13ee09, + 0x157646, + 0x205e03, + 0xe9644, + 0x10a4c3, + 0x206b43, + 0xfc85, + 0x2013c3, + 0x23cf83, + 0x14e60c4, + 0x25b583, + 0x6a04, + 0x207b83, + 0xa14c8, + 0x109406, + 0x15089c4, + 0x132605, + 0x13774a, + 0x12b382, + 0x1a7b46, + 0x48fd1, + 0x13e44509, + 0x132688, + 0x50308, + 0x1c6547, + 0x2442, + 0xe834e, + 0x12dacb, + 0x132e0b, + 0x19018a, + 0x89a4a, + 0x2afc7, + 0xa14c8, + 0x11d0c8, + 0x7947, + 0x1a81414b, + 0x1b047, + 0x1c742, + 0x7dc87, + 0xd4b8a, + 0x48a4f, + 0x4604f, + 0xd5e42, + 0x2782, + 0xa5f48, + 0xe1f0a, + 0xdfaca, + 0x54a4a, + 0x6ba48, + 0xe188, + 0x5d448, + 0xdff88, + 0x173088, + 0x2942, + 0x45dcf, + 0xa0d8b, + 0x6c648, + 0x3fbc7, + 0x374a, + 0x19ee0b, + 0x80b89, + 0x4aac7, + 0xe088, + 0x19dc4c, + 0x1a0047, + 0x6644a, + 0x18b08, + 0x29f4e, + 0x2a70e, + 0x2ae0b, + 0x3850b, + 0xde14b, + 0xe4b09, + 0xe518b, + 0xebb0d, + 0x10138b, + 0x110d0d, + 0x11108d, + 0x103c8a, + 0x315cb, + 0x3d54b, + 0x18af05, + 0x1ac24b50, + 0x168cf, + 0x10b5cf, + 0xe558d, + 0x13efd0, + 0x758c2, + 0x1b21e488, + 0x5d88, + 0x6e4d0, + 0x11e60e, + 0x1b7675c5, + 0x5010b, + 0x13df10, + 0x57d48, + 0xe28a, + 0x386c9, + 0x64b87, + 0x64ec7, + 0x65087, + 0x659c7, + 0x66b87, + 0x67107, + 0x67807, + 0x67d47, + 0x68287, + 0x68607, + 0x68cc7, + 0x68e87, + 0x69047, + 0x69207, + 0x69947, + 0x69cc7, + 0x6a787, + 0x6ab47, + 0x6b107, + 0x6b3c7, + 0x6b587, + 0x6c8c7, + 0x6cd87, + 0x6cf87, + 0x6d347, + 0x6d507, + 0x6d6c7, + 0x6ee07, + 0x70247, + 0x70647, + 0x70e07, + 0x710c7, + 0x71447, + 0x71607, + 0x71a07, + 0x72f87, + 0x739c7, + 0x73f47, + 0x74107, + 0x742c7, + 0x75b07, + 0x76587, + 0x76ac7, + 0x770c7, + 0x77287, + 0x77607, + 0x77b47, + 0x37482, + 0x5d54a, + 0xe9787, + 0x8b705, + 0x9a3d1, + 0x1d21c6, + 0xf2f0a, + 0xa5dca, + 0x59706, + 0x15578b, + 0x642, + 0x2fad1, + 0xb3dc9, + 0x967c9, + 0x7102, + 0x8898a, + 0xa8549, + 0xa8c8f, + 0xa928e, + 0xaa8c8, + 0x373c2, + 0x108f09, + 0x19774e, + 0x1c848c, + 0xeaa8f, + 0x1b174e, + 0x8284c, + 0xe4e09, + 0xe6711, + 0xe6cc8, + 0x19e052, + 0x19f60d, + 0x6eacd, + 0x16f00b, + 0x4da95, + 0x504c9, + 0x5c44a, + 0x73109, + 0x82c50, + 0x8700b, + 0x16e18f, + 0x1ca50b, + 0x916cc, + 0x93b50, + 0xa4cca, + 0xa620d, + 0xac4ce, + 0xae70a, + 0xaf0cc, + 0x150094, + 0xb3a51, + 0xb7f0b, + 0xb8f0f, + 0xb9d0d, + 0xba58e, + 0xbed8c, + 0xc1d8c, + 0xc304b, + 0xc3a0e, + 0xc42d0, + 0xc548b, + 0x134c0d, + 0x14288f, + 0xcfc0c, + 0xd0dce, + 0xd2d11, + 0xda08c, + 0xf5587, + 0xfc78d, + 0x11274c, + 0x1cf090, + 0x102dcd, + 0x11ac07, + 0x15c2d0, + 0x16f588, + 0x184ccb, + 0xb018f, + 0x17f8c8, + 0xf310d, + 0x107d10, + 0x175889, + 0x1bab22c6, + 0xb3143, + 0xba245, + 0x53a42, + 0x3bc9, + 0x5a34a, + 0x1bf9e506, + 0x1c27de84, + 0x5acc6, + 0x1d3ca, + 0xe5d0d, + 0x1c5313c9, + 0x19a03, + 0x114e0a, + 0xde5d1, + 0xdea09, + 0xdfa47, + 0xe0808, + 0xe0e07, + 0xe9848, + 0x45ecb, + 0x12d8c9, + 0xe9fd0, + 0xea48c, + 0xeaf48, + 0xeb3c5, + 0x1b9288, + 0x1bcd8a, + 0x19ac7, + 0x12e547, + 0x13c2, + 0x13ec0a, + 0x147488, + 0x1c3689, + 0x78505, + 0x11a90a, + 0x8f40f, + 0x12a2cb, + 0x1b4dcc, + 0x15c812, + 0x78845, + 0xed2c8, + 0x51c0a, + 0x1caf7605, + 0x17770c, + 0x13b403, + 0x1a1602, + 0x10004a, + 0x15003cc, + 0x1a03c8, + 0x110ec8, + 0x1cf47506, + 0x18c8c7, + 0x16f82, + 0x9482, + 0x4ecd0, + 0x72847, + 0x2f0cf, + 0x5bac6, + 0x7c64e, + 0x1592cb, + 0x49f88, + 0x80f49, + 0x1991d2, + 0x11570d, + 0x115f88, + 0xae909, + 0xd8f4d, + 0x18be89, + 0x19628b, + 0x1d1c08, + 0x7c988, + 0x7ec48, + 0x7f089, + 0x7f28a, + 0x7ff4c, + 0xea74a, + 0x1c20c7, + 0x55c8d, + 0xe6fd1, + 0x1d2ba886, + 0x1b068b, + 0x12bf0c, + 0x10448, + 0x48589, + 0x17c5cd, + 0x1a7d50, + 0xd2c2, + 0x14500d, + 0x7d82, + 0x1a6c2, + 0x1c200a, + 0x10c20a, + 0xf2e0a, + 0xf3c8b, + 0x2a98c, + 0x11c8cc, + 0x11cbca, + 0x11ce4e, + 0x1dc80d, + 0x1d5dcd05, + 0x136288, + 0xa842, + 0x1430c68e, + 0x14a0750e, + 0x152046ca, + 0x15b322ce, + 0x16202f4e, + 0x16b7350c, + 0x142e5c7, + 0x142e5c9, + 0x140abc3, + 0x173cd68c, + 0x17a758c9, + 0x18329b09, + 0x18b37549, + 0x2e82, + 0x10c5d1, + 0x7451, + 0x460d, + 0x132211, + 0x2e91, + 0x17344f, + 0x1cd5cf, + 0x7580c, + 0x129a4c, + 0x13748c, + 0x14364d, + 0x202d5, + 0x581cc, + 0x6964c, + 0x133510, + 0x17910c, + 0x18954c, + 0x199c99, + 0x1a9299, + 0x1b2559, + 0x1c0f94, + 0x1c3c94, + 0x7ad4, + 0x8554, + 0x8ad4, + 0x19258289, + 0x19807d89, + 0x1a269709, + 0x146e6ec9, + 0x2e82, + 0x14ee6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x156e6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x15ee6ec9, + 0x2e82, + 0x166e6ec9, + 0x2e82, + 0x16ee6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x176e6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x17ee6ec9, + 0x2e82, + 0x186e6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x18ee6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x196e6ec9, + 0x2e82, + 0x19ee6ec9, + 0x2e82, + 0x1a6e6ec9, + 0x2e82, + 0x7aca, + 0x2e82, + 0x48fc5, + 0x190184, + 0x10c68e, + 0x750e, + 0x79d4e, + 0x46ca, + 0x1322ce, + 0x2f4e, + 0x17350c, + 0x1cd68c, + 0x758c9, + 0x129b09, + 0x137549, + 0x58289, + 0x7d89, + 0x69709, + 0x204cd, + 0x8809, + 0x8d89, + 0x141e44, + 0x1d5f44, + 0x18d184, + 0x149c84, + 0xa3e84, + 0x2c684, + 0x36a04, + 0x52644, + 0x103a04, + 0x159da03, + 0x31b07, + 0x3484c, + 0x20c3, + 0x758c2, + 0x1dc803, + 0x20c3, + 0x35e03, + 0x148702, + 0x1da608, + 0x12d947, + 0x2942, + 0x2000c2, + 0x202782, + 0x203dc2, + 0x219d02, + 0x200382, + 0x2003c2, + 0x209482, + 0x22d7c3, + 0x233743, + 0x220583, + 0x219c83, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x206b43, + 0x23cf83, + 0xb243, + 0x220583, + 0x22884, + 0x2000c2, + 0x24ce83, + 0x1fa2d7c3, + 0x38abc7, + 0x220583, + 0x214903, + 0x205184, + 0x206b43, + 0x23cf83, + 0x21d60a, + 0x239605, + 0x213c43, + 0x21be02, + 0xa14c8, + 0xa14c8, + 0x2782, + 0x1392c2, + 0x2033114b, + 0x2062da44, + 0x7ddc5, + 0x5f85, + 0x1d9c46, + 0x20a05f85, + 0x57243, + 0x1080c3, + 0x109744, + 0x3283, + 0x131905, + 0x12dac5, + 0xa14c8, + 0x1b047, + 0x2d7c3, + 0x2123a4c7, + 0x3686, + 0x21573345, + 0x3a5c7, + 0xbb4a, + 0xba08, + 0xea47, + 0x679ca, + 0x183548, + 0x33c87, + 0x1a618f, + 0x3e047, + 0x52446, + 0x13df10, + 0xf43cf, + 0x12789, + 0x5ad44, + 0x2183a68e, + 0x50949, + 0x69346, + 0x1071c9, + 0x18bb06, + 0x1c4d06, + 0x6c40c, + 0x19f00a, + 0x80d07, + 0x1cd10a, + 0x160a49, + 0xef0cc, + 0x1b4a8a, + 0x60c0a, + 0x131949, + 0x5acc6, + 0x80dca, + 0x11658a, + 0x9cf0a, + 0x11a349, + 0xdce88, + 0xdd106, + 0xe3a0d, + 0xbacc5, + 0x21f4df8c, + 0x137987, + 0x1051c9, + 0xb4147, + 0x10cad4, + 0x10cfcb, + 0x3fa0a, + 0x19904a, + 0xa65cd, + 0x14f3e89, + 0x1154cc, + 0x115d8b, + 0x18b03, + 0x18b03, + 0x29f46, + 0x18b03, + 0x1d9c48, + 0x1cd543, + 0x150c443, + 0x54389, + 0x14cfe83, + 0x82ec7, + 0x22dc6409, + 0x12a06, + 0x1081c9, + 0x4ce83, + 0xa14c8, + 0x2782, + 0x51184, + 0x88dc3, + 0x1da885, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x20a683, + 0x22d7c3, + 0x233743, + 0x228843, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x296983, + 0x207b83, + 0x20a683, + 0x241844, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x204f03, + 0x249c6505, + 0x142c183, + 0x22d7c3, + 0x233743, + 0x219d03, + 0x228843, + 0x220583, + 0x222884, + 0x37fa83, + 0x22a243, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x2561dac3, + 0x15c709, + 0x2782, + 0x2097c3, + 0x2622d7c3, + 0x233743, + 0x24adc3, + 0x220583, + 0x217343, + 0x22a243, + 0x23cf83, + 0x21c3c3, + 0x369444, + 0xa14c8, + 0x26a2d7c3, + 0x233743, + 0x2aa983, + 0x220583, + 0x205e03, + 0x205184, + 0x206b43, + 0x23cf83, + 0x22ec43, + 0xa14c8, + 0x2722d7c3, + 0x233743, + 0x228843, + 0x2013c3, + 0x23cf83, + 0xa14c8, + 0x142e5c7, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x205184, + 0x206b43, + 0x23cf83, + 0x12dac5, + 0x14c47, + 0x10cd0b, + 0xdee04, + 0xbacc5, + 0x144b148, + 0xaafcd, + 0x286e75c5, + 0x9a544, + 0x2782, + 0x1083, + 0x175785, + 0x2ebc2, + 0x2b82, + 0x3cc145, + 0xa14c8, + 0x18b02, + 0x1d003, + 0x16240f, + 0x2782, + 0xfd346, + 0x2ebc2, + 0x32c608, + 0x241844, + 0x340cc6, + 0x343506, + 0xa14c8, + 0x301983, + 0x2c6689, + 0x359a95, + 0x159a9f, + 0x22d7c3, + 0x3c0b52, + 0x16ed46, + 0x17fe05, + 0xe28a, + 0x386c9, + 0x3c090f, + 0x2dd2c4, + 0x25e605, + 0x30e590, + 0x2449c7, + 0x2013c3, + 0x2fb908, + 0x10b906, + 0x27ee0a, + 0x206f84, + 0x2f7043, + 0x21be02, + 0x2f060b, + 0x13c3, + 0x19c3c4, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x2fe843, + 0x202782, + 0xe16c3, + 0xf984, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x214903, + 0x226243, + 0x23cf83, + 0x4ce83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x2000c2, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x5f85, + 0x241844, + 0x22d7c3, + 0x233743, + 0x3216c4, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x6df83, + 0x23cf83, + 0x137249, + 0x22d7c3, + 0x233743, + 0x228843, + 0x209a03, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x32ef44, + 0x222884, + 0x206b43, + 0x23cf83, + 0x207b83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x6df83, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x2067c3, + 0x44b03, + 0x14903, + 0x206b43, + 0x23cf83, + 0x323aca, + 0x345349, + 0x35c04b, + 0x35d44a, + 0x3660ca, + 0x376b8b, + 0x38b8ca, + 0x391f8a, + 0x39858a, + 0x39880b, + 0x3bcac9, + 0x3c94ca, + 0x3c9c8b, + 0x3d680b, + 0x3db74a, + 0x22d7c3, + 0x233743, + 0x228843, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x17830b, + 0x5e148, + 0xd9084, + 0x46006, + 0xec149, + 0xa14c8, + 0x22d7c3, + 0xe284, + 0x264b84, + 0x20d142, + 0x205184, + 0x331e45, + 0x20a683, + 0x241844, + 0x22d7c3, + 0x236204, + 0x233743, + 0x251184, + 0x2dd2c4, + 0x222884, + 0x22a243, + 0x206b43, + 0x23cf83, + 0x3451c5, + 0x204f03, + 0x213c43, + 0x210f43, + 0x23d804, + 0x309384, + 0x308485, + 0xa14c8, + 0x2010c4, + 0x3c4e86, + 0x331a84, + 0x202782, + 0x35cc07, + 0x249587, + 0x24e444, + 0x25bec5, + 0x302fc5, + 0x22e1c5, + 0x222884, + 0x3883c8, + 0x239006, + 0x34c488, + 0x27a4c5, + 0x2e43c5, + 0x235fc4, + 0x23cf83, + 0x2f7dc4, + 0x3751c6, + 0x239703, + 0x23d804, + 0x243185, + 0x203b44, + 0x255ac4, + 0x21be02, + 0x39f906, + 0x3aec06, + 0x313d05, + 0x2000c2, + 0x24ce83, + 0x30a02782, + 0x21e604, + 0x200382, + 0x205e03, + 0x245ec2, + 0x206b43, + 0x2003c2, + 0x2f4786, + 0x202003, + 0x207b83, + 0xab204, + 0xa14c8, + 0xa14c8, + 0x220583, + 0x6df83, + 0x2000c2, + 0x31602782, + 0x220583, + 0x268fc3, + 0x37fa83, + 0x22da44, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x2000c2, + 0x31e02782, + 0x22d7c3, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x682, + 0x2062c2, + 0x2195c2, + 0x214903, + 0x2ef083, + 0x2000c2, + 0x12dac5, + 0xa14c8, + 0x14c47, + 0x202782, + 0x233743, + 0x251184, + 0x204183, + 0x220583, + 0x209a03, + 0x205e03, + 0x206b43, + 0x212203, + 0x23cf83, + 0x234703, + 0x1cb6d3, + 0x127714, + 0x12dac5, + 0x14c47, + 0x114486, + 0x111b4b, + 0x29f46, + 0x58587, + 0x5bec6, + 0x649, + 0x10408a, + 0x8af4d, + 0x1a0d8c, + 0x116f0a, + 0xf9708, + 0x45585, + 0xbb88, + 0x5bac6, + 0x1be646, + 0xec046, + 0x602, + 0x2758c2, + 0x7844, + 0x9b106, + 0x178050, + 0x83a0e, + 0x49c6, + 0x177e0c, + 0x336488cb, + 0x12dac5, + 0x1407cb, + 0x33bbe584, + 0x190347, + 0x23ed1, + 0x10388a, + 0x22d7c3, + 0x67945, + 0x160308, + 0x16f44, + 0x5a545, + 0x33d10886, + 0x9a3c6, + 0xbc406, + 0x91d4a, + 0x198ac3, + 0x34242584, + 0x54389, + 0x1784a, + 0x14cea89, + 0x605, + 0x110c83, + 0x3479e587, + 0xfc85, + 0x1563046, + 0x15584c, + 0xfac48, + 0xf084b, + 0xdf44b, + 0x34a4b78c, + 0x140c0c3, + 0xbbf88, + 0xf0ac5, + 0xa0c09, + 0xf3f88, + 0x141d306, + 0x89947, + 0x34f7c5c9, + 0x12b3c7, + 0x15e1ca, + 0x115a4d, + 0x140fc8, + 0x20c3, + 0x108943, + 0x1d9c48, + 0x103a04, + 0x129285, + 0xe8507, + 0x35245dc3, + 0x3575fec6, + 0x35af8644, + 0x35f00207, + 0x1d9c44, + 0x1d9c44, + 0x1d9c44, + 0x1d9c44, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x2000c2, + 0x202782, + 0x220583, + 0x2067c2, + 0x206b43, + 0x23cf83, + 0x202003, + 0x38054f, + 0x38090e, + 0xa14c8, + 0x22d7c3, + 0x43447, + 0x233743, + 0x220583, + 0x219e43, + 0x206b43, + 0x23cf83, + 0x4904, + 0x33c4, + 0xa04, + 0x21cd03, + 0x30a807, + 0x201842, + 0x2c9689, + 0x200b02, + 0x24efcb, + 0x2a52ca, + 0x2e2689, + 0x200542, + 0x2750c6, + 0x3ac995, + 0x24f115, + 0x230313, + 0x24f693, + 0x220f02, + 0x220f05, + 0x360e4c, + 0x27680b, + 0x296e05, + 0x2020c2, + 0x2ffe82, + 0x38f886, + 0x202442, + 0x260646, + 0x20e50d, + 0x20fa0c, + 0x224bc4, + 0x200882, + 0x20c882, + 0x39e408, + 0x200202, + 0x30f9c6, + 0x30f9cf, + 0x393e90, + 0x3a39c4, + 0x3acb55, + 0x230493, + 0x204dc3, + 0x34320a, + 0x20ee07, + 0x35f709, + 0x217707, + 0x225a42, + 0x200282, + 0x3b2246, + 0x207942, + 0xa14c8, + 0x201a42, + 0x2010c2, + 0x209247, + 0x341247, + 0x341251, + 0x218105, + 0x21810e, + 0x21860f, + 0x21c742, + 0x394547, + 0x21cd48, + 0x207c02, + 0x325802, + 0x2a9746, + 0x3418cf, + 0x2a9750, + 0x22b882, + 0x205cc2, + 0x32f488, + 0x212283, + 0x288f88, + 0x30bd8d, + 0x23af03, + 0x3723c8, + 0x23af0f, + 0x23b2ce, + 0x398d0a, + 0x226e51, + 0x2272d0, + 0x2bd68d, + 0x2bd9cc, + 0x3c2447, + 0x343387, + 0x340d89, + 0x224cc2, + 0x201942, + 0x259e0c, + 0x25a10b, + 0x2014c2, + 0x2c3206, + 0x22ec82, + 0x200482, + 0x2d5e42, + 0x202782, + 0x22dbc4, + 0x23a187, + 0x22bdc2, + 0x23e4c7, + 0x240787, + 0x220282, + 0x22eec2, + 0x243305, + 0x237982, + 0x2e920e, + 0x38288d, + 0x233743, + 0x397d0e, + 0x2b628d, + 0x341643, + 0x201602, + 0x286d04, + 0x265582, + 0x2029c2, + 0x39b945, + 0x39d087, + 0x24a442, + 0x219d02, + 0x250d87, + 0x254708, + 0x2b06c2, + 0x2788c6, + 0x259c8c, + 0x259fcb, + 0x20e282, + 0x260e8f, + 0x261250, + 0x26164f, + 0x261a15, + 0x261f54, + 0x26244e, + 0x2627ce, + 0x262b4f, + 0x262f0e, + 0x263294, + 0x263793, + 0x263c4d, + 0x277d09, + 0x28cc43, + 0x204182, + 0x28dc85, + 0x3c70c6, + 0x200382, + 0x367207, + 0x220583, + 0x200642, + 0x232548, + 0x227091, + 0x2274d0, + 0x200bc2, + 0x28ba87, + 0x201b82, + 0x309a07, + 0x253a42, + 0x37ed89, + 0x38f847, + 0x318008, + 0x3106c6, + 0x2eef83, + 0x3cbdc5, + 0x2339c2, + 0x2004c2, + 0x3d5e45, + 0x377b85, + 0x200f82, + 0x21c583, + 0x340b47, + 0x218447, + 0x204042, + 0x204044, + 0x218983, + 0x348009, + 0x218988, + 0x200b42, + 0x208002, + 0x22cec7, + 0x235d05, + 0x363388, + 0x246a07, + 0x209b83, + 0x29af86, + 0x2bd50d, + 0x2bd88c, + 0x2da786, + 0x202282, + 0x2df302, + 0x2024c2, + 0x23ad8f, + 0x23b18e, + 0x303047, + 0x205e02, + 0x3200c5, + 0x3200c6, + 0x202dc2, + 0x200c02, + 0x29f506, + 0x210203, + 0x309946, + 0x2ccec5, + 0x2ccecd, + 0x2cd515, + 0x2cdf4c, + 0x2ce2cd, + 0x2ce612, + 0x200e82, + 0x26cec2, + 0x201342, + 0x329906, + 0x3c8346, + 0x2013c2, + 0x3c7146, + 0x21a682, + 0x2c71c5, + 0x200d42, + 0x2e9349, + 0x222ecc, + 0x22320b, + 0x2003c2, + 0x2550c8, + 0x2039c2, + 0x201002, + 0x271746, + 0x2e6e45, + 0x309807, + 0x226ac5, + 0x25bc05, + 0x2434c2, + 0x20bc42, + 0x202142, + 0x2ead87, + 0x2f484d, + 0x2f4bcc, + 0x3abf47, + 0x278842, + 0x203d42, + 0x20cb48, + 0x203d48, + 0x2e7c08, + 0x2f30c4, + 0x2c3c87, + 0x27df03, + 0x223802, + 0x204f02, + 0x2f5849, + 0x22a347, + 0x213c42, + 0x271b45, + 0x241f42, + 0x21f4c2, + 0x3bfe83, + 0x3bfe86, + 0x2fe542, + 0x2ffa82, + 0x200402, + 0x27ea46, + 0x2ddb07, + 0x213a42, + 0x200902, + 0x288dcf, + 0x397b4d, + 0x3d364e, + 0x2b610c, + 0x202342, + 0x204482, + 0x310505, + 0x3220c6, + 0x202482, + 0x206382, + 0x200682, + 0x246984, + 0x2fee04, + 0x355686, + 0x209482, + 0x27b0c7, + 0x233ec3, + 0x233ec8, + 0x23ba08, + 0x36ee87, + 0x253cc6, + 0x2037c2, + 0x2398c3, + 0x2b7387, + 0x287c86, + 0x2e3705, + 0x2f3448, + 0x203002, + 0x274e87, + 0x236082, + 0x308102, + 0x21bac2, + 0x218789, + 0x241542, + 0xc2148, + 0x201182, + 0x24fac3, + 0x331fc7, + 0x201202, + 0x22304c, + 0x22334b, + 0x2da806, + 0x310bc5, + 0x243982, + 0x202b42, + 0x2be3c6, + 0x267343, + 0x32ecc7, + 0x288782, + 0x2008c2, + 0x3ac815, + 0x24f2d5, + 0x2301d3, + 0x24f813, + 0x38a2c7, + 0x25fad1, + 0x266d10, + 0x276c52, + 0x27b891, + 0x29a7c8, + 0x29a7d0, + 0x2a168f, + 0x2a5093, + 0x384f52, + 0x3bc3d0, + 0x2b240f, + 0x2c0dd2, + 0x3a2291, + 0x2cca13, + 0x2d7212, + 0x2db24f, + 0x2dc04e, + 0x2e0392, + 0x2e2491, + 0x2ec80f, + 0x2fe1ce, + 0x2f0fd1, + 0x2fae10, + 0x2fbc92, + 0x2fe8d1, + 0x33c390, + 0x354d0f, + 0x3bd1d1, + 0x3c9890, + 0x31b8c6, + 0x33bf87, + 0x215907, + 0x203b02, + 0x2847c5, + 0x30e307, + 0x2195c2, + 0x206042, + 0x227d45, + 0x202243, + 0x308e06, + 0x2f4a0d, + 0x2f4d4c, + 0x206842, + 0x360ccb, + 0x2766ca, + 0x220dca, + 0x2bce09, + 0x2f284b, + 0x246b4d, + 0x30ea0c, + 0x27250a, + 0x2707cc, + 0x27778b, + 0x296c4c, + 0x2b464e, + 0x3560cb, + 0x2b588c, + 0x2e4083, + 0x38bd86, + 0x3bf082, + 0x2fc182, + 0x20f203, + 0x214f82, + 0x21e4c3, + 0x32ae06, + 0x261bc7, + 0x2d3b06, + 0x2e20c8, + 0x3409c8, + 0x31e8c6, + 0x20a342, + 0x3136cd, + 0x313a0c, + 0x2df607, + 0x316d47, + 0x2351c2, + 0x213e42, + 0x276c02, + 0x279b42, + 0x3388d6, + 0x33d315, + 0x340296, + 0x343993, + 0x344052, + 0x353a93, + 0x354012, + 0x3adb0f, + 0x3bdfd8, + 0x3beb57, + 0x3c0019, + 0x3c1498, + 0x3c2e18, + 0x3c4197, + 0x3c5a17, + 0x3c6816, + 0x3ce1d3, + 0x3ce8d5, + 0x3cf792, + 0x3cfc13, + 0x202782, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x205184, + 0x206b43, + 0x23cf83, + 0x202003, + 0x2000c2, + 0x206702, + 0x37e938c5, + 0x3828a305, + 0x3867e706, + 0xa14c8, + 0x38ab2985, + 0x202782, + 0x203dc2, + 0x38f2f1c5, + 0x39282b45, + 0x39683f47, + 0x39a84c49, + 0x39e37284, + 0x200382, + 0x200642, + 0x3a24d8c5, + 0x3a698349, + 0x3ab37f88, + 0x3aeaef45, + 0x3b317887, + 0x3b613148, + 0x3baed185, + 0x3be45a86, + 0x3c2496c9, + 0x3c6d3388, + 0x3cac3848, + 0x3ce9898a, + 0x3d2e1804, + 0x3d60d685, + 0x3dabf848, + 0x3de03945, + 0x212302, + 0x3e237f83, + 0x3e6a5746, + 0x3eae6548, + 0x3efb8806, + 0x3f209388, + 0x3f727d86, + 0x3fa3dbc4, + 0x3fe02642, + 0x40301b47, + 0x406ab6c4, + 0x40a7a1c7, + 0x40f2f7c7, + 0x2003c2, + 0x4129dbc5, + 0x41644704, + 0x41ad29c7, + 0x41e31c87, + 0x42286b46, + 0x42683785, + 0x42a98447, + 0x42ed3208, + 0x4328e007, + 0x437cf549, + 0x43ad6385, + 0x43f125c7, + 0x44292f06, + 0x9a54b, + 0x44606548, + 0x22824d, + 0x27e1c9, + 0x2a874b, + 0x2aaa8b, + 0x3199cb, + 0x31758b, + 0x3222cb, + 0x32258b, + 0x322ac9, + 0x323d4b, + 0x32400b, + 0x3245cb, + 0x3256ca, + 0x325c0a, + 0x32620c, + 0x32a58b, + 0x32b18a, + 0x34240a, + 0x34ad8e, + 0x34bece, + 0x34c24a, + 0x34dd4a, + 0x34eb0b, + 0x34edcb, + 0x34fa4b, + 0x36bc8b, + 0x36c28a, + 0x36cf4b, + 0x36d20a, + 0x36d48a, + 0x36d70a, + 0x38d78b, + 0x392f8b, + 0x39588e, + 0x395c0b, + 0x39d24b, + 0x3a198b, + 0x3a51ca, + 0x3a5449, + 0x3a568a, + 0x3a764a, + 0x3bd9cb, + 0x3c9f4b, + 0x3ca7ca, + 0x3cdc0b, + 0x3d39cb, + 0x3db18b, + 0x44a854c8, + 0x44e8a6c9, + 0x452a0a89, + 0x456e7748, + 0x355405, + 0x2017c3, + 0x27fac4, + 0x2be185, + 0x236fc6, + 0x245805, + 0x289d84, + 0x367108, + 0x31c2c5, + 0x294c44, + 0x3c2887, + 0x2a000a, + 0x381e0a, + 0x303147, + 0x21a647, + 0x2e0947, + 0x27cfc7, + 0x35b445, + 0x211d46, + 0x39f487, + 0x360704, + 0x2b5186, + 0x2f1b86, + 0x3bf885, + 0x34a344, + 0x2999c6, + 0x29ecc7, + 0x238186, + 0x301747, + 0x228883, + 0x3d3c86, + 0x2ff6c5, + 0x284047, + 0x269e8a, + 0x232644, + 0x212508, + 0x312a09, + 0x2cd2c7, + 0x393846, + 0x255348, + 0x3b8f49, + 0x32af04, + 0x3a8c84, + 0x2d8045, + 0x2823c8, + 0x2ca0c7, + 0x2c4949, + 0x229a08, + 0x318dc6, + 0x2e6006, + 0x29ae08, + 0x370586, + 0x28a305, + 0x286c06, + 0x27aa48, + 0x3a8d06, + 0x23eacb, + 0x2b1046, + 0x29c80d, + 0x3bf405, + 0x2ab586, + 0x213205, + 0x349189, + 0x247e07, + 0x3badc8, + 0x3666c6, + 0x29b949, + 0x3cb146, + 0x269e05, + 0x2a2dc6, + 0x2704c6, + 0x2cf6c9, + 0x2bb246, + 0x29fd07, + 0x2a3445, + 0x21b203, + 0x223885, + 0x29cac7, + 0x3614c6, + 0x3bf309, + 0x27e706, + 0x286e46, + 0x211a09, + 0x286609, + 0x2a39c7, + 0x384748, + 0x29a209, + 0x284448, + 0x36bb06, + 0x2dcc45, + 0x31ef0a, + 0x286ec6, + 0x204c46, + 0x2d3e45, + 0x256488, + 0x357487, + 0x22f8ca, + 0x251a06, + 0x2f36c5, + 0x2ffd46, + 0x2d5607, + 0x393707, + 0x21b385, + 0x269fc5, + 0x2a95c6, + 0x2b6806, + 0x2d4686, + 0x2bfd04, + 0x285b89, + 0x28b846, + 0x2d03ca, + 0x225c88, + 0x3122c8, + 0x381e0a, + 0x223a45, + 0x29ec05, + 0x2311c8, + 0x2baf48, + 0x239f47, + 0x2b7dc6, + 0x33af48, + 0x218d07, + 0x2838c8, + 0x2b9bc6, + 0x287608, + 0x297986, + 0x27a647, + 0x36fe46, + 0x2999c6, + 0x281f8a, + 0x2da906, + 0x2dcc49, + 0x368146, + 0x371d8a, + 0x23dbc9, + 0x2f5206, + 0x2bba04, + 0x28dd4d, + 0x28a947, + 0x28e8c6, + 0x2c3705, + 0x3cb1c5, + 0x38ef06, + 0x2d2809, + 0x2eda47, + 0x27bfc6, + 0x2cbcc6, + 0x289e09, + 0x28a244, + 0x241304, + 0x201688, + 0x35fb86, + 0x2a2ec8, + 0x2fd948, + 0x3b9d47, + 0x3b8209, + 0x3b44c7, + 0x2b284a, + 0x2f630f, + 0x2ec3ca, + 0x310305, + 0x27ac85, + 0x2108c5, + 0x3b7807, + 0x23f643, + 0x384948, + 0x27d606, + 0x27d709, + 0x2eb646, + 0x2cf507, + 0x29b709, + 0x3bacc8, + 0x2d3f07, + 0x31fe43, + 0x355485, + 0x2d5145, + 0x2bfb4b, + 0x203a04, + 0x306384, + 0x278ec6, + 0x3204c7, + 0x39aeca, + 0x238007, + 0x209887, + 0x282b45, + 0x3c0645, + 0x292189, + 0x2999c6, + 0x237e8d, + 0x3632c5, + 0x2b5dc3, + 0x226783, + 0x21e685, + 0x35b0c5, + 0x255348, + 0x27cc87, + 0x241086, + 0x2a0706, + 0x2288c5, + 0x233a07, + 0x3b9847, + 0x238ec7, + 0x20d70a, + 0x3d3d48, + 0x2bfd04, + 0x280887, + 0x2805c7, + 0x34f046, + 0x297007, + 0x2c8608, + 0x304248, + 0x247d06, + 0x21a888, + 0x2bb2c4, + 0x39f486, + 0x2656c6, + 0x390946, + 0x201b06, + 0x21bb44, + 0x27d086, + 0x2c2346, + 0x299d86, + 0x20fd86, + 0x3c7586, + 0x244446, + 0x240f88, + 0x2b5008, + 0x2d9608, + 0x245a08, + 0x231146, + 0x20c245, + 0x223846, + 0x2aefc5, + 0x391647, + 0x229ac5, + 0x20c503, + 0x3c4785, + 0x22ccc4, + 0x3c76c5, + 0x2039c3, + 0x3a3547, + 0x3426c8, + 0x301806, + 0x36694d, + 0x27ac46, + 0x299345, + 0x218783, + 0x2bf209, + 0x28a3c6, + 0x295746, + 0x288904, + 0x2ec347, + 0x39fec6, + 0x2edd05, + 0x20fd43, + 0x3d1ac4, + 0x280786, + 0x211e44, + 0x2657c8, + 0x3bb109, + 0x306d89, + 0x2a2cca, + 0x29270d, + 0x2329c7, + 0x3c4bc6, + 0x20bc84, + 0x284c49, + 0x289388, + 0x28a546, + 0x235606, + 0x297007, + 0x2bc186, + 0x2266c6, + 0x336886, + 0x32f84a, + 0x213148, + 0x2a9e45, + 0x372a49, + 0x2ca84a, + 0x3029c8, + 0x29e408, + 0x2956c8, + 0x2a034c, + 0x34ff85, + 0x2a0988, + 0x2b7b46, + 0x344ec6, + 0x3a1c07, + 0x237f05, + 0x286d85, + 0x306c49, + 0x3dc3c7, + 0x27d6c5, + 0x228707, + 0x226783, + 0x2cad05, + 0x21ea48, + 0x285907, + 0x29e2c9, + 0x2dcb05, + 0x3b0b44, + 0x2a4248, + 0x301c87, + 0x2d40c8, + 0x3b5c08, + 0x2ac3c5, + 0x3b7bc6, + 0x248186, + 0x2d8409, + 0x2b1847, + 0x2af786, + 0x21e147, + 0x202183, + 0x237284, + 0x2d0a85, + 0x280b04, + 0x24ba44, + 0x25e7c7, + 0x268747, + 0x27c184, + 0x29e110, + 0x372c47, + 0x3c0645, + 0x3308cc, + 0x20f384, + 0x35d248, + 0x27a549, + 0x383dc6, + 0x2f40c8, + 0x246544, + 0x2791c8, + 0x302346, + 0x281e08, + 0x29cd86, + 0x39800b, + 0x32cd85, + 0x2d0908, + 0x211444, + 0x3bb54a, + 0x29e2c9, + 0x36fd46, + 0x319348, + 0x2a6105, + 0x2be9c4, + 0x35d146, + 0x238d88, + 0x2854c8, + 0x33b7c6, + 0x21fe04, + 0x31ee86, + 0x3b4547, + 0x27a0c7, + 0x29700f, + 0x32de07, + 0x2f52c7, + 0x31ff85, + 0x374345, + 0x2a3689, + 0x2e8ac6, + 0x26b885, + 0x286907, + 0x3a1e88, + 0x2fca45, + 0x36fe46, + 0x225ac8, + 0x3b880a, + 0x238a88, + 0x28fa87, + 0x2f6746, + 0x372a06, + 0x2003c3, + 0x20ecc3, + 0x2caa09, + 0x29a089, + 0x35d046, + 0x2dcb05, + 0x21ab08, + 0x319348, + 0x370708, + 0x33690b, + 0x366b87, + 0x2fb749, + 0x297288, + 0x35e8c4, + 0x390588, + 0x291209, + 0x2afa85, + 0x3b7707, + 0x237305, + 0x2853c8, + 0x29374b, + 0x298190, + 0x2ab305, + 0x21138c, + 0x241245, + 0x282bc3, + 0x2b4446, + 0x2c1244, + 0x370106, + 0x29ecc7, + 0x225b44, + 0x241fc8, + 0x38480d, + 0x319205, + 0x232a04, + 0x2a2544, + 0x2a2549, + 0x2acbc8, + 0x32d247, + 0x3023c8, + 0x285c48, + 0x27c2c5, + 0x205987, + 0x27c247, + 0x2c6447, + 0x269fc9, + 0x3365c9, + 0x20b646, + 0x2bdbc6, + 0x2869c6, + 0x34d6c5, + 0x3a83c4, + 0x3ba3c6, + 0x3bf0c6, + 0x27c308, + 0x2d52cb, + 0x267287, + 0x20bc84, + 0x39fe06, + 0x2c8947, + 0x244045, + 0x244f45, + 0x2ae104, + 0x336546, + 0x3ba448, + 0x284c49, + 0x25f446, + 0x289188, + 0x2eddc6, + 0x35a6c8, + 0x2b340c, + 0x27c186, + 0x29900d, + 0x29948b, + 0x29fdc5, + 0x3b9987, + 0x2bb346, + 0x3935c8, + 0x20b6c9, + 0x3057c8, + 0x3c0645, + 0x360447, + 0x284548, + 0x2ff109, + 0x39fb46, + 0x25f34a, + 0x393348, + 0x30560b, + 0x2133cc, + 0x2792c8, + 0x27fd46, + 0x205388, + 0x3b8487, + 0x209509, + 0x3179cd, + 0x2998c6, + 0x23f608, + 0x2b4ec9, + 0x2bfe08, + 0x287708, + 0x2c2d8c, + 0x2c3e47, + 0x2c4f47, + 0x269e05, + 0x2b89c7, + 0x3a1d48, + 0x35d1c6, + 0x36b18c, + 0x2cb288, + 0x2d1f48, + 0x2ff406, + 0x2d4ec7, + 0x20b844, + 0x245a08, + 0x31e9cc, + 0x28b28c, + 0x310385, + 0x3bf907, + 0x21fd86, + 0x2d4e46, + 0x349348, + 0x21cfc4, + 0x23818b, + 0x27b20b, + 0x2f6746, + 0x384687, + 0x3ccdc5, + 0x271205, + 0x2382c6, + 0x2a60c5, + 0x2039c5, + 0x2cdd87, + 0x3bfcc9, + 0x2b69c4, + 0x25ca05, + 0x3ac2c5, + 0x3b7f88, + 0x28d3c5, + 0x26e249, + 0x375e47, + 0x375e4b, + 0x2f4f46, + 0x240cc9, + 0x34a288, + 0x288405, + 0x2c6548, + 0x336608, + 0x273547, + 0x302147, + 0x25e849, + 0x281d47, + 0x295309, + 0x334f0c, + 0x3cf448, + 0x2b84c9, + 0x2ba407, + 0x285d09, + 0x3617c7, + 0x2134c8, + 0x3b83c5, + 0x39f406, + 0x2c3748, + 0x2f6848, + 0x2ca709, + 0x203a07, + 0x271c05, + 0x256089, + 0x2d8746, + 0x292f04, + 0x31bd06, + 0x2e63c8, + 0x2ff8c7, + 0x2d54c8, + 0x21a949, + 0x3286c7, + 0x2a01c6, + 0x3b9a44, + 0x3c4809, + 0x205808, + 0x2ff2c7, + 0x237c86, + 0x2d5206, + 0x204bc4, + 0x36a2c6, + 0x23a303, + 0x32c909, + 0x32cd46, + 0x2ab805, + 0x2a0706, + 0x2cfa85, + 0x2849c8, + 0x368547, + 0x2ddcc6, + 0x32f206, + 0x3122c8, + 0x2a3807, + 0x299905, + 0x29df08, + 0x3ca348, + 0x393348, + 0x241105, + 0x39f486, + 0x306b49, + 0x2d8284, + 0x2cf90b, + 0x2263cb, + 0x2a9d49, + 0x226783, + 0x25aac5, + 0x301606, + 0x241c88, + 0x2b6cc4, + 0x301806, + 0x20d849, + 0x31e385, + 0x2cdcc6, + 0x301c86, + 0x210984, + 0x29e58a, + 0x2ab748, + 0x2f6846, + 0x243e85, + 0x3ccc47, + 0x35b307, + 0x3b7bc4, + 0x226607, + 0x229a84, + 0x229a86, + 0x205dc3, + 0x269fc5, + 0x2b0445, + 0x368788, + 0x280a45, + 0x27bec9, + 0x245847, + 0x24584b, + 0x2a554c, + 0x2a5b4a, + 0x317887, + 0x201303, + 0x26bd48, + 0x2412c5, + 0x2fcac5, + 0x355544, + 0x2133c6, + 0x27a546, + 0x36a307, + 0x25560b, + 0x21bb44, + 0x3008c4, + 0x2c9284, + 0x2cf386, + 0x225b44, + 0x2824c8, + 0x355345, + 0x21b205, + 0x370647, + 0x3b9a89, + 0x35b0c5, + 0x38ef0a, + 0x2a3349, + 0x2a82ca, + 0x32f989, + 0x338e44, + 0x2cbd85, + 0x2bc288, + 0x2d2a8b, + 0x2d8045, + 0x2fdac6, + 0x240844, + 0x27c406, + 0x328549, + 0x2c8a47, + 0x27e8c8, + 0x292a86, + 0x3b44c7, + 0x2854c8, + 0x38f486, + 0x3b9544, + 0x380c47, + 0x36e085, + 0x382447, + 0x245a84, + 0x2bb2c6, + 0x3026c8, + 0x299648, + 0x2fa2c7, + 0x3294c8, + 0x297a45, + 0x226504, + 0x381d08, + 0x3201c4, + 0x210845, + 0x3028c4, + 0x218e07, + 0x28b907, + 0x285e48, + 0x2d4246, + 0x2809c5, + 0x27bcc8, + 0x24bb48, + 0x2a2c09, + 0x2266c6, + 0x22f948, + 0x3bb3ca, + 0x2440c8, + 0x2ed185, + 0x215686, + 0x2a3208, + 0x36050a, + 0x357887, + 0x2897c5, + 0x293108, + 0x2dd904, + 0x256506, + 0x2c52c8, + 0x3c7586, + 0x30a648, + 0x2d6947, + 0x3c2786, + 0x2bba04, + 0x281487, + 0x2b5484, + 0x328507, + 0x36fa8d, + 0x239fc5, + 0x2d260b, + 0x28b506, + 0x2551c8, + 0x241f84, + 0x231346, + 0x280786, + 0x2056c7, + 0x298ccd, + 0x2fc607, + 0x2b5d08, + 0x284e05, + 0x36a448, + 0x2ca046, + 0x297ac8, + 0x39df06, + 0x330647, + 0x2861c9, + 0x36a9c7, + 0x28a808, + 0x275c45, + 0x228948, + 0x2d4d85, + 0x22a4c5, + 0x32fc05, + 0x251e03, + 0x201b84, + 0x244185, + 0x2496c9, + 0x36a0c6, + 0x2c8708, + 0x301f05, + 0x2b8887, + 0x344a4a, + 0x2cdc09, + 0x2703ca, + 0x2d9688, + 0x22854c, + 0x28698d, + 0x30d243, + 0x30a548, + 0x3d1a85, + 0x3b85c6, + 0x3bab46, + 0x359205, + 0x21e249, + 0x361605, + 0x27bcc8, + 0x2590c6, + 0x35dbc6, + 0x2a4109, + 0x3aae47, + 0x293a06, + 0x3449c8, + 0x390848, + 0x2e7947, + 0x2c24ce, + 0x2ca285, + 0x2ff005, + 0x3c7488, + 0x2e9a87, + 0x204c42, + 0x2c2904, + 0x37000a, + 0x2ff388, + 0x336746, + 0x29b848, + 0x248186, + 0x361108, + 0x2af788, + 0x22a484, + 0x2b8c45, + 0x731a84, + 0x731a84, + 0x731a84, + 0x2094c3, + 0x2d5086, + 0x27c186, + 0x29fa8c, + 0x20d8c3, + 0x246446, + 0x2133c4, + 0x28a348, + 0x20d685, + 0x370106, + 0x2bf948, + 0x2daf86, + 0x2ddc46, + 0x3a88c8, + 0x2d0b07, + 0x281b09, + 0x3114ca, + 0x20d6c4, + 0x229ac5, + 0x2c4905, + 0x2d65c6, + 0x232a06, + 0x29f406, + 0x3cef46, + 0x281c44, + 0x281c4b, + 0x229884, + 0x240e45, + 0x2ae605, + 0x3b9e06, + 0x3c2c08, + 0x286847, + 0x32ccc4, + 0x25dfc3, + 0x2dd405, + 0x31bbc7, + 0x28674b, + 0x368687, + 0x2bf848, + 0x2b8d87, + 0x26b246, + 0x27e488, + 0x25364b, + 0x2be0c6, + 0x20c249, + 0x2537c5, + 0x31fe43, + 0x2cdcc6, + 0x2d6848, + 0x20d2c3, + 0x2ad643, + 0x2854c6, + 0x248186, + 0x37654a, + 0x27fd85, + 0x2805cb, + 0x2a064b, + 0x244e03, + 0x202603, + 0x2b27c4, + 0x247f47, + 0x2792c4, + 0x28a344, + 0x2b79c4, + 0x2443c8, + 0x243dc8, + 0x20ec49, + 0x2d6408, + 0x32fe87, + 0x20fd86, + 0x2c834f, + 0x2ca3c6, + 0x2d8b84, + 0x243c0a, + 0x31bac7, + 0x2b5586, + 0x292f49, + 0x20ebc5, + 0x3688c5, + 0x20ed06, + 0x228a83, + 0x2dd949, + 0x2132c6, + 0x21a709, + 0x39aec6, + 0x269fc5, + 0x310785, + 0x201b83, + 0x248088, + 0x32d407, + 0x27d604, + 0x28a1c8, + 0x344c44, + 0x304b46, + 0x2b4446, + 0x23cb46, + 0x2d07c9, + 0x2fca45, + 0x2999c6, + 0x22fec9, + 0x2c8e86, + 0x244446, + 0x3a3946, + 0x22b5c5, + 0x3028c6, + 0x330644, + 0x3b83c5, + 0x2c3744, + 0x2b78c6, + 0x363284, + 0x203b03, + 0x289445, + 0x2346c8, + 0x2e4947, + 0x2b6d49, + 0x2896c8, + 0x29abd1, + 0x301d0a, + 0x2f6687, + 0x304586, + 0x2133c4, + 0x2c3848, + 0x3698c8, + 0x29ad8a, + 0x26e00d, + 0x2a2dc6, + 0x3a89c6, + 0x281546, + 0x21b207, + 0x2b5dc5, + 0x275187, + 0x28a285, + 0x375f84, + 0x2aa746, + 0x39f2c7, + 0x2dd64d, + 0x2a3147, + 0x367008, + 0x27bfc9, + 0x215586, + 0x39fac5, + 0x231a84, + 0x2e64c6, + 0x3b7ac6, + 0x2ff506, + 0x29c0c8, + 0x222e43, + 0x2056c3, + 0x37f685, + 0x251386, + 0x2af745, + 0x292c88, + 0x29ee8a, + 0x3b7cc4, + 0x28a348, + 0x2956c8, + 0x3b9c47, + 0x301fc9, + 0x2bf548, + 0x284cc7, + 0x2b7c46, + 0x3c758a, + 0x2e6548, + 0x30d849, + 0x2acc88, + 0x21ae09, + 0x304447, + 0x2f9505, + 0x336b06, + 0x35d048, + 0x3885c8, + 0x39ea08, + 0x210988, + 0x240e45, + 0x201484, + 0x233088, + 0x21f304, + 0x32f784, + 0x269fc5, + 0x294c87, + 0x3b9849, + 0x2054c7, + 0x211a85, + 0x2790c6, + 0x367dc6, + 0x20c384, + 0x2a4446, + 0x27f8c4, + 0x28c286, + 0x3b9606, + 0x20d106, + 0x3c0645, + 0x292b47, + 0x201303, + 0x272d49, + 0x3120c8, + 0x284b44, + 0x284b4d, + 0x299748, + 0x2efe48, + 0x30d7c6, + 0x2862c9, + 0x2cdc09, + 0x328245, + 0x29ef8a, + 0x26e88a, + 0x24e50c, + 0x24e686, + 0x2799c6, + 0x2cac46, + 0x26b6c9, + 0x3b8806, + 0x213546, + 0x3616c6, + 0x245a08, + 0x238a86, + 0x2d7b4b, + 0x294e05, + 0x21b205, + 0x27a1c5, + 0x201406, + 0x226543, + 0x23cac6, + 0x2a30c7, + 0x2c3705, + 0x25c345, + 0x3cb1c5, + 0x37a286, + 0x328304, + 0x337e86, + 0x2a4a09, + 0x20128c, + 0x375cc8, + 0x238d04, + 0x3025c6, + 0x28b606, + 0x2d6848, + 0x319348, + 0x201189, + 0x3ccc47, + 0x35f8c9, + 0x2712c6, + 0x22b984, + 0x208044, + 0x2842c4, + 0x2854c8, + 0x3b968a, + 0x35b046, + 0x369f87, + 0x3826c7, + 0x240dc5, + 0x2c48c4, + 0x2911c6, + 0x2b5e06, + 0x21d003, + 0x311f07, + 0x3b5b08, + 0x32838a, + 0x22b688, + 0x209388, + 0x3632c5, + 0x29fec5, + 0x267385, + 0x241186, + 0x38b006, + 0x398bc5, + 0x32cb49, + 0x2c46cc, + 0x267447, + 0x29ae08, + 0x2b1185, + 0x731a84, + 0x22c344, + 0x285a44, + 0x21a506, + 0x2a1e0e, + 0x368947, + 0x21b405, + 0x2d820c, + 0x30e047, + 0x39f247, + 0x235a09, + 0x2125c9, + 0x2897c5, + 0x3120c8, + 0x306b49, + 0x393205, + 0x2c3648, + 0x2b8706, + 0x381f86, + 0x23dbc4, + 0x290008, + 0x215743, + 0x378384, + 0x2dd485, + 0x394c07, + 0x2de485, + 0x3bb289, + 0x29608d, + 0x2adc06, + 0x3c2344, + 0x2b7d48, + 0x3bfb0a, + 0x224887, + 0x3cc385, + 0x280a03, + 0x2a080e, + 0x24818c, + 0x302ac7, + 0x2a1fc7, + 0x109d86, + 0x205643, + 0x3b8845, + 0x285a45, + 0x29bc08, + 0x2987c9, + 0x238c06, + 0x2792c4, + 0x2f65c6, + 0x23f3cb, + 0x2bd28c, + 0x251ec7, + 0x2d7e05, + 0x3ca248, + 0x2e7705, + 0x243c07, + 0x301b47, + 0x39e885, + 0x226543, + 0x2193c4, + 0x2e6285, + 0x2b68c5, + 0x2b68c6, + 0x29c608, + 0x39f2c7, + 0x3bae46, + 0x204ac6, + 0x32fb46, + 0x23f789, + 0x205a87, + 0x27f9c6, + 0x2bd406, + 0x2e1706, + 0x2ab685, + 0x20a7c6, + 0x377645, + 0x28d448, + 0x29458b, + 0x290f06, + 0x382704, + 0x2da549, + 0x245844, + 0x2b8688, + 0x31be07, + 0x287604, + 0x2bebc8, + 0x2c4d44, + 0x2ab6c4, + 0x28a105, + 0x319246, + 0x244307, + 0x2166c3, + 0x2a0285, + 0x2f4344, + 0x2ff046, + 0x3282c8, + 0x3293c5, + 0x294249, + 0x256285, + 0x246448, + 0x358447, + 0x32ce48, + 0x2be807, + 0x2f5389, + 0x27cf06, + 0x334ac6, + 0x29a344, + 0x300805, + 0x312f4c, + 0x27a1c7, + 0x27ab47, + 0x232648, + 0x2adc06, + 0x2a3004, + 0x37af04, + 0x25e6c9, + 0x2cad46, + 0x292207, + 0x205304, + 0x2a4546, + 0x348c85, + 0x2d3d87, + 0x2d7ac6, + 0x25f209, + 0x2e8cc7, + 0x297007, + 0x2a3f86, + 0x237bc5, + 0x283748, + 0x213148, + 0x20ff86, + 0x329405, + 0x2c5e86, + 0x203883, + 0x29ba89, + 0x29f18e, + 0x2be548, + 0x344d48, + 0x20fd8b, + 0x294486, + 0x327d84, + 0x286584, + 0x29f28a, + 0x211287, + 0x27fa85, + 0x20c249, + 0x2c2405, + 0x32f7c7, + 0x2310c4, + 0x291547, + 0x2fd848, + 0x2cd386, + 0x2bb449, + 0x2bf64a, + 0x211206, + 0x299286, + 0x2ae585, + 0x3961c5, + 0x38cc47, + 0x2479c8, + 0x348bc8, + 0x22a486, + 0x310805, + 0x23278e, + 0x2bfd04, + 0x20ff05, + 0x278a49, + 0x2e88c8, + 0x28f9c6, + 0x29da0c, + 0x29ea90, + 0x2a1a4f, + 0x2a3588, + 0x317887, + 0x3c0645, + 0x244185, + 0x244189, + 0x293309, + 0x31ef86, + 0x2d80c7, + 0x300705, + 0x239f49, + 0x34f0c6, + 0x3b864d, + 0x284189, + 0x28a344, + 0x2be2c8, + 0x233149, + 0x35b206, + 0x26bf45, + 0x334ac6, + 0x27e789, + 0x2063c8, + 0x20c245, + 0x290004, + 0x29dbcb, + 0x35b0c5, + 0x241d06, + 0x286cc6, + 0x206dc6, + 0x2a294b, + 0x294349, + 0x2096c5, + 0x391547, + 0x301c86, + 0x3a8ac6, + 0x2857c8, + 0x282649, + 0x366dcc, + 0x31b9c8, + 0x31b4c6, + 0x33b7c3, + 0x37cd86, + 0x2a2785, + 0x281188, + 0x310206, + 0x2d3fc8, + 0x238085, + 0x3882c5, + 0x358588, + 0x390707, + 0x3baa87, + 0x36a307, + 0x2f40c8, + 0x2d66c8, + 0x2d1886, + 0x2b7707, + 0x237147, + 0x2a264a, + 0x246603, + 0x201406, + 0x232705, + 0x244704, + 0x27bfc9, + 0x2f5304, + 0x2b9f84, + 0x29ce04, + 0x2a1fcb, + 0x32d347, + 0x2329c5, + 0x297748, + 0x2790c6, + 0x2790c8, + 0x27fcc6, + 0x28ff45, + 0x290205, + 0x291bc6, + 0x292548, + 0x292e88, + 0x27c186, + 0x29758f, + 0x29b550, + 0x3bf405, + 0x201303, + 0x22ba45, + 0x2fb688, + 0x293209, + 0x393348, + 0x2d7ec8, + 0x2506c8, + 0x32d407, + 0x278d89, + 0x2d41c8, + 0x2fcf84, + 0x29cc88, + 0x3b8049, + 0x2b81c7, + 0x29cc04, + 0x205588, + 0x29290a, + 0x2cc046, + 0x2a2dc6, + 0x226589, + 0x29ecc7, + 0x2d0648, + 0x20a408, + 0x205188, + 0x38a405, + 0x396f85, + 0x21b205, + 0x285a05, + 0x2b4d07, + 0x226545, + 0x2c3705, + 0x3c2646, + 0x393287, + 0x2d29c7, + 0x292c06, + 0x2d9bc5, + 0x241d06, + 0x26be05, + 0x2badc8, + 0x300684, + 0x2c8f06, + 0x348ac4, + 0x2be9c8, + 0x2c900a, + 0x27cc8c, + 0x255805, + 0x21b2c6, + 0x366f86, + 0x37f546, + 0x2fb884, + 0x3693c5, + 0x27f607, + 0x29ed49, + 0x2cf7c7, + 0x731a84, + 0x731a84, + 0x32d1c5, + 0x2177c4, + 0x29d3ca, + 0x278f46, + 0x306944, + 0x3bf885, + 0x2b3945, + 0x2b5d04, + 0x286907, + 0x256207, + 0x2cf388, + 0x2c5f88, + 0x3c8009, + 0x3201c8, + 0x29d58b, + 0x2442c4, + 0x3a8bc5, + 0x26b905, + 0x36a289, + 0x282649, + 0x2da448, + 0x229888, + 0x2dea44, + 0x28b645, + 0x2017c3, + 0x2d6585, + 0x299a46, + 0x29860c, + 0x2131c6, + 0x26be46, + 0x28fc45, + 0x37a308, + 0x3194c6, + 0x304706, + 0x2a2dc6, + 0x22b40c, + 0x26b9c4, + 0x32fc8a, + 0x28fb88, + 0x298447, + 0x2f4246, + 0x238cc7, + 0x2f61c5, + 0x237c86, + 0x365e46, + 0x374207, + 0x2bf344, + 0x218f05, + 0x278a44, + 0x376007, + 0x278c88, + 0x27984a, + 0x2843c7, + 0x2ab8c7, + 0x317807, + 0x2e7849, + 0x29860a, + 0x20ff83, + 0x2e4905, + 0x20d143, + 0x2b7a09, + 0x2d6a88, + 0x31ff87, + 0x393449, + 0x213246, + 0x32df48, + 0x3a34c5, + 0x24bc4a, + 0x384ac9, + 0x247bc9, + 0x3a1c07, + 0x3699c9, + 0x20d008, + 0x361306, + 0x21b488, + 0x3c1c47, + 0x281d47, + 0x2a3347, + 0x2d3208, + 0x3d02c6, + 0x2926c5, + 0x27f607, + 0x298d88, + 0x348a44, + 0x2d0284, + 0x293907, + 0x2afb07, + 0x3069ca, + 0x361286, + 0x3696ca, + 0x2c2847, + 0x2bfac7, + 0x218fc4, + 0x2953c4, + 0x2d3c86, + 0x3a0144, + 0x3a014c, + 0x306885, + 0x2107c9, + 0x2465c4, + 0x2b5dc5, + 0x3bfa88, + 0x28ea85, + 0x38ef06, + 0x293444, + 0x2a6c8a, + 0x2b1746, + 0x23ed0a, + 0x28e007, + 0x2d5605, + 0x228a85, + 0x240e0a, + 0x39e945, + 0x244146, + 0x21f304, + 0x2b2946, + 0x38cd05, + 0x3102c6, + 0x2fa2cc, + 0x2db94a, + 0x26e984, + 0x20fd86, + 0x29ecc7, + 0x2d7a44, + 0x245a08, + 0x2e37c6, + 0x382549, + 0x2c1b89, + 0x3cf549, + 0x2cfac6, + 0x3c1d46, + 0x21b5c7, + 0x32ca88, + 0x3c1b49, + 0x32d347, + 0x2978c6, + 0x3b4547, + 0x281405, + 0x2bfd04, + 0x21b187, + 0x237305, + 0x28a045, + 0x2f9e47, + 0x39e748, + 0x3ca1c6, + 0x299bcd, + 0x29be0f, + 0x2a064d, + 0x20d884, + 0x2347c6, + 0x2dbd08, + 0x361685, + 0x2a2808, + 0x27340a, + 0x28a344, + 0x2f1c86, + 0x2d8c07, + 0x21bb47, + 0x2d0bc9, + 0x21b445, + 0x2b5d04, + 0x2b8b8a, + 0x2bf109, + 0x369ac7, + 0x299e86, + 0x35b206, + 0x28b586, + 0x380d06, + 0x2db60f, + 0x2dbbc9, + 0x238a86, + 0x388206, + 0x32c149, + 0x2b7807, + 0x21a003, + 0x22b586, + 0x20ecc3, + 0x3590c8, + 0x2d4747, + 0x2a3789, + 0x2b42c8, + 0x3babc8, + 0x361906, + 0x30c049, + 0x37c885, + 0x2b78c4, + 0x2f95c7, + 0x26b745, + 0x20d884, + 0x232a88, + 0x211544, + 0x2b7547, + 0x342646, + 0x2a9685, + 0x2acc88, + 0x35b0cb, + 0x3125c7, + 0x241086, + 0x2ca444, + 0x327d06, + 0x269fc5, + 0x237305, + 0x2834c9, + 0x286509, + 0x281d84, + 0x281dc5, + 0x20fdc5, + 0x24bac6, + 0x3121c8, + 0x2c1646, + 0x3b594b, + 0x383c4a, + 0x2be905, + 0x290286, + 0x27d305, + 0x3c2585, + 0x295847, + 0x201688, + 0x2925c4, + 0x265cc6, + 0x292f06, + 0x20d1c7, + 0x31fe04, + 0x280786, + 0x3b7905, + 0x3b7909, + 0x2dc984, + 0x2c4a49, + 0x27c186, + 0x2c3f08, + 0x20fdc5, + 0x3827c5, + 0x3102c6, + 0x366cc9, + 0x2125c9, + 0x26bec6, + 0x2e89c8, + 0x2961c8, + 0x27d2c4, + 0x2b99c4, + 0x2b99c8, + 0x28e9c8, + 0x35f9c9, + 0x2999c6, + 0x2a2dc6, + 0x33ae0d, + 0x301806, + 0x2b32c9, + 0x223945, + 0x20ed06, + 0x206548, + 0x337dc5, + 0x237184, + 0x269fc5, + 0x286048, + 0x29d189, + 0x278b04, + 0x2bb2c6, + 0x30da0a, + 0x3029c8, + 0x306b49, + 0x26a8ca, + 0x3933c6, + 0x29bfc8, + 0x2439c5, + 0x29f608, + 0x2f6245, + 0x213109, + 0x33d7c9, + 0x219482, + 0x2537c5, + 0x270f46, + 0x27c0c7, + 0x244705, + 0x2f35c6, + 0x316b48, + 0x2adc06, + 0x2bc149, + 0x27ac46, + 0x285648, + 0x26c285, + 0x34b8c6, + 0x330748, + 0x2854c8, + 0x304348, + 0x318e48, + 0x20a7c4, + 0x250c83, + 0x2bc384, + 0x2845c6, + 0x281444, + 0x344c87, + 0x304609, + 0x2c9285, + 0x20a406, + 0x22b586, + 0x29c44b, + 0x2b54c6, + 0x363506, + 0x2cda88, + 0x2e6006, + 0x26e303, + 0x3da583, + 0x2bfd04, + 0x22f845, + 0x2edc07, + 0x278c88, + 0x278c8f, + 0x27f50b, + 0x311fc8, + 0x2bb346, + 0x3122ce, + 0x241243, + 0x2edb84, + 0x2b5445, + 0x2b5b86, + 0x2912cb, + 0x294d46, + 0x225b49, + 0x2a9685, + 0x253dc8, + 0x3c7cc8, + 0x21248c, + 0x2a2006, + 0x2d65c6, + 0x2dcb05, + 0x28a5c8, + 0x27cc85, + 0x35e8c8, + 0x29dd8a, + 0x2a0a89, + 0x731a84, + 0x2000c2, + 0x45e02782, + 0x200382, + 0x222884, + 0x2024c2, + 0x3216c4, + 0x202642, + 0x13c3, + 0x2003c2, + 0x202002, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x206b43, + 0x23cf83, + 0x240b03, + 0x241844, + 0x22d7c3, + 0x236204, + 0x233743, + 0x2dd2c4, + 0x220583, + 0x2449c7, + 0x205e03, + 0x2013c3, + 0x2fb908, + 0x23cf83, + 0x27ee0b, + 0x2f7043, + 0x239606, + 0x21be02, + 0x2f060b, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x23cf83, + 0x206a03, + 0x217583, + 0x2000c2, + 0xa14c8, + 0x216685, + 0x237388, + 0x300ec8, + 0x202782, + 0x32ee85, + 0x3b4687, + 0x201242, + 0x2421c7, + 0x200382, + 0x25d047, + 0x308789, + 0x2c99c8, + 0x205009, + 0x20b2c2, + 0x3c7e87, + 0x36b004, + 0x3b4747, + 0x383b47, + 0x25d602, + 0x205e03, + 0x200e82, + 0x202642, + 0x2003c2, + 0x202142, + 0x200902, + 0x202002, + 0x2abec5, + 0x2a9785, + 0x2782, + 0x33743, + 0x22d7c3, + 0x233743, + 0x2053c3, + 0x220583, + 0x209a03, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x6df83, + 0x23cf83, + 0xaec3, + 0x101, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x219e43, + 0x206b43, + 0x6df83, + 0x23cf83, + 0x214703, + 0x490726c6, + 0x45dc3, + 0xca685, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x6df83, + 0x23cf83, + 0x6942, + 0xa14c8, + 0x12bd03, + 0x13c3, + 0x6df83, + 0x47984, + 0x1421d04, + 0xe7b05, + 0x2000c2, + 0x391904, + 0x22d7c3, + 0x233743, + 0x220583, + 0x23d9c3, + 0x22e1c5, + 0x219e43, + 0x214903, + 0x206b43, + 0x251ac3, + 0x23cf83, + 0x202003, + 0x2418c3, + 0x207b83, + 0x5c2, + 0x2ebc2, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x2000c2, + 0x24ce83, + 0x202782, + 0x233743, + 0x220583, + 0x222884, + 0x206b43, + 0x23cf83, + 0x202002, + 0xa14c8, + 0x220583, + 0x6df83, + 0xa14c8, + 0x6df83, + 0x26f283, + 0x22d7c3, + 0x230944, + 0x233743, + 0x220583, + 0x2067c2, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x2067c2, + 0x22a243, + 0x206b43, + 0x23cf83, + 0x2ef083, + 0x202003, + 0x2000c2, + 0x202782, + 0x220583, + 0x206b43, + 0x23cf83, + 0x239605, + 0x11a406, + 0x241844, + 0x21be02, + 0xa14c8, + 0x2000c2, + 0x12dac5, + 0x1cb48, + 0x161c03, + 0x202782, + 0x4d8947c6, + 0xe184, + 0x10cd0b, + 0x35246, + 0x5f07, + 0x233743, + 0x4c108, + 0x4c10b, + 0x4c58b, + 0x4cc0b, + 0x4cf4b, + 0x4d20b, + 0x4d64b, + 0x9d86, + 0x220583, + 0x1b8e85, + 0x131844, + 0x218dc3, + 0x118c87, + 0xe1284, + 0x6d0c4, + 0x206b43, + 0x6bfc6, + 0xb2bc4, + 0x6df83, + 0x23cf83, + 0x2f7dc4, + 0x12d947, + 0x11a009, + 0x10cac8, + 0x14a504, + 0xec046, + 0x140fc8, + 0x141185, + 0x1da6c9, + 0x2fe03, + 0x12dac5, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x2013c3, + 0x23cf83, + 0x2f7043, + 0x21be02, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x219c83, + 0x205184, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x2dd2c4, + 0x220583, + 0x206b43, + 0x23cf83, + 0x239606, + 0x233743, + 0x220583, + 0x3d443, + 0x6df83, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x12dac5, + 0x5f07, + 0xe9c3, + 0x2fe03, + 0xa14c8, + 0x220583, + 0x22d7c3, + 0x233743, + 0x220583, + 0x89003, + 0x206b43, + 0x23cf83, + 0x50e2d7c3, + 0x233743, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x2000c2, + 0x202782, + 0x22d7c3, + 0x220583, + 0x206b43, + 0x2003c2, + 0x23cf83, + 0x33dd07, + 0x2c67cb, + 0x2165c3, + 0x31ec48, + 0x32c807, + 0x20f286, + 0x215b85, + 0x32efc9, + 0x205b88, + 0x37ab89, + 0x3a5d10, + 0x37ab8b, + 0x2e1d89, + 0x20e9c3, + 0x2f0cc9, + 0x232006, + 0x23200c, + 0x216748, + 0x3d8588, + 0x308c49, + 0x2b948e, + 0x30854b, + 0x336d4c, + 0x20a683, + 0x2802cc, + 0x3c6089, + 0x306487, + 0x23368c, + 0x2b0cca, + 0x24ec04, + 0x305a8d, + 0x280188, + 0x3c544d, + 0x287b86, + 0x24184b, + 0x31a189, + 0x388487, + 0x372586, + 0x274c09, + 0x327eca, + 0x3243c8, + 0x2f6c44, + 0x38dc07, + 0x231447, + 0x201c84, + 0x217444, + 0x200ac9, + 0x371bc9, + 0x28da08, + 0x20ab05, + 0x20b205, + 0x3dc286, + 0x305949, + 0x27368d, + 0x2fdbc8, + 0x3dc187, + 0x215c08, + 0x250a06, + 0x22e3c4, + 0x2850c5, + 0x3c1a46, + 0x3c33c4, + 0x3c5f87, + 0x3d10ca, + 0x20c184, + 0x211146, + 0x212109, + 0x21210f, + 0x212e0d, + 0x2136c6, + 0x21c750, + 0x21cb46, + 0x21d247, + 0x21da87, + 0x21da8f, + 0x21ec49, + 0x224a46, + 0x225087, + 0x225088, + 0x225e89, + 0x3d2008, + 0x2ece07, + 0x216683, + 0x22d646, + 0x3c3ac8, + 0x2b974a, + 0x3785c9, + 0x205cc3, + 0x32ed86, + 0x265b0a, + 0x2f2087, + 0x3062ca, + 0x21f60e, + 0x21ed86, + 0x2df347, + 0x2aa086, + 0x242d46, + 0x396d8b, + 0x21608a, + 0x2c6e0d, + 0x3c1e07, + 0x268908, + 0x268909, + 0x26890f, + 0x2b6ecc, + 0x2729c9, + 0x2e454e, + 0x244aca, + 0x2d5a86, + 0x3d9b86, + 0x3264cc, + 0x33934c, + 0x34b0c8, + 0x36a8c7, + 0x235905, + 0x294b44, + 0x20278e, + 0x2663c4, + 0x329007, + 0x3d6d0a, + 0x22c794, + 0x22d08f, + 0x21dc48, + 0x22d508, + 0x351a8d, + 0x351a8e, + 0x22d989, + 0x22e808, + 0x22e80f, + 0x23338c, + 0x23338f, + 0x234507, + 0x236b0a, + 0x24748b, + 0x239c48, + 0x23ac47, + 0x26014d, + 0x336146, + 0x305c46, + 0x23c949, + 0x25b608, + 0x242b48, + 0x242b4e, + 0x2c68c7, + 0x2fc1c5, + 0x247745, + 0x200f04, + 0x20f546, + 0x28d908, + 0x30ae43, + 0x2cb98e, + 0x260508, + 0x2a688b, + 0x26f447, + 0x22a2c5, + 0x26ec06, + 0x2ad3c7, + 0x347a08, + 0x38ca49, + 0x3cee45, + 0x289488, + 0x221746, + 0x3a7a4a, + 0x202689, + 0x233749, + 0x23374b, + 0x30a308, + 0x201b49, + 0x20abc6, + 0x24998a, + 0x35660a, + 0x236d0c, + 0x335f07, + 0x2c97ca, + 0x346ecb, + 0x346ed9, + 0x32ab08, + 0x239685, + 0x260306, + 0x26aec9, + 0x2c9ec6, + 0x378d0a, + 0x205d86, + 0x202404, + 0x2cc70d, + 0x202407, + 0x221b09, + 0x24adc5, + 0x24b648, + 0x24bec9, + 0x24e444, + 0x24eb07, + 0x24eb08, + 0x24fcc7, + 0x267e88, + 0x254907, + 0x39fd05, + 0x25b10c, + 0x25b809, + 0x2e0b8a, + 0x3aacc9, + 0x2f0dc9, + 0x387fcc, + 0x25de8b, + 0x25f048, + 0x260908, + 0x264044, + 0x2872c8, + 0x288c09, + 0x2b0d87, + 0x212346, + 0x29cfc7, + 0x29b1c9, + 0x3cbb0b, + 0x327b87, + 0x38b307, + 0x28e147, + 0x3c53c4, + 0x3c53c5, + 0x2dcfc5, + 0x354a0b, + 0x3b6784, + 0x3a1308, + 0x2cb60a, + 0x221807, + 0x3d81c7, + 0x290a92, + 0x28c186, + 0x22fac6, + 0x37f0ce, + 0x317f46, + 0x295548, + 0x295b8f, + 0x3c5808, + 0x3979c8, + 0x342b4a, + 0x342b51, + 0x2a46ce, + 0x20434a, + 0x20434c, + 0x22ea07, + 0x22ea10, + 0x3bf148, + 0x2a48c5, + 0x2ad9ca, + 0x3c340c, + 0x297c0d, + 0x209a06, + 0x3c8207, + 0x3c820c, + 0x209a0c, + 0x21c44c, + 0x2af28b, + 0x38a844, + 0x226704, + 0x2b0589, + 0x37af87, + 0x39c749, + 0x356449, + 0x2b0987, + 0x2b0b46, + 0x2b0b49, + 0x2b0f43, + 0x2add0a, + 0x31f807, + 0x372e0b, + 0x2c6c8a, + 0x36b084, + 0x3997c6, + 0x284649, + 0x39ffc4, + 0x2f378a, + 0x241385, + 0x2c03c5, + 0x2c03cd, + 0x2c070e, + 0x2bc4c5, + 0x33c9c6, + 0x239207, + 0x25b38a, + 0x2666c6, + 0x2ee984, + 0x305e07, + 0x2d934b, + 0x267b87, + 0x2503c4, + 0x2b1a46, + 0x2b1a4d, + 0x2dfc0c, + 0x212a06, + 0x2fddca, + 0x2a9b06, + 0x2f7888, + 0x23aa87, + 0x24b30a, + 0x249bc6, + 0x2066c3, + 0x2066c6, + 0x3c3948, + 0x2b070a, + 0x287887, + 0x287888, + 0x2d4344, + 0x291007, + 0x2d87c8, + 0x29f788, + 0x292348, + 0x2d198a, + 0x2e43c5, + 0x30bc87, + 0x3a8e13, + 0x2588c6, + 0x21a048, + 0x222049, + 0x242088, + 0x36198b, + 0x3baf48, + 0x26a304, + 0x358686, + 0x322146, + 0x319089, + 0x3d8747, + 0x25b208, + 0x29f906, + 0x2f9d44, + 0x3a4dc5, + 0x2d00c8, + 0x203e4a, + 0x2cc388, + 0x2d1406, + 0x29c1ca, + 0x2b6a48, + 0x2d7848, + 0x2d8dc8, + 0x2d9886, + 0x2dbf06, + 0x3aa78c, + 0x2dc3d0, + 0x2a6345, + 0x31dfc8, + 0x31dfd0, + 0x3c5610, + 0x3a5b8e, + 0x3aa40e, + 0x3aa414, + 0x3b008f, + 0x3b0446, + 0x204211, + 0x201d53, + 0x2021c8, + 0x360c45, + 0x31f188, + 0x37e385, + 0x33304c, + 0x227989, + 0x294989, + 0x227e07, + 0x235fc9, + 0x3788c7, + 0x35b4c6, + 0x284ec7, + 0x2075c5, + 0x20af03, + 0x30b009, + 0x24c8c9, + 0x23d443, + 0x2192c4, + 0x21ff8d, + 0x38ce0f, + 0x2f9d85, + 0x332f46, + 0x217c47, + 0x2164c7, + 0x3da906, + 0x3da90b, + 0x2a5d05, + 0x25c706, + 0x303647, + 0x254e09, + 0x224446, + 0x384245, + 0x3cc78b, + 0x3b5086, + 0x3c7a05, + 0x23da48, + 0x28bf48, + 0x2a100c, + 0x2a1010, + 0x2a7a49, + 0x2b1e87, + 0x324c8b, + 0x2eb106, + 0x2eccca, + 0x206a8b, + 0x2ee08a, + 0x2ee306, + 0x2eef45, + 0x32c706, + 0x27ae08, + 0x227eca, + 0x35171c, + 0x2f710c, + 0x2f7408, + 0x239605, + 0x38a147, + 0x21f4c6, + 0x3494c5, + 0x215f46, + 0x3daac8, + 0x2bf387, + 0x2b9388, + 0x25898a, + 0x217d4c, + 0x2c7289, + 0x20a587, + 0x246984, + 0x247806, + 0x39754a, + 0x356545, + 0x2170cc, + 0x21bf48, + 0x2aa388, + 0x2d49cc, + 0x3587cc, + 0x36abc9, + 0x36ae07, + 0x24a14c, + 0x228184, + 0x24a60a, + 0x314a4c, + 0x25690b, + 0x256f8b, + 0x259b06, + 0x25ee87, + 0x22ec47, + 0x22ec4f, + 0x307851, + 0x2e2e12, + 0x2641cd, + 0x2641ce, + 0x26450e, + 0x3b0248, + 0x3b0252, + 0x269ac8, + 0x222687, + 0x2528ca, + 0x2a8108, + 0x317f05, + 0x2b4b4a, + 0x21cec7, + 0x2e8684, + 0x203843, + 0x236745, + 0x342dc7, + 0x34e287, + 0x297e0e, + 0x31d5cd, + 0x326a89, + 0x255c85, + 0x352a03, + 0x337986, + 0x25cd05, + 0x2a6ac8, + 0x2bcf89, + 0x260345, + 0x26034f, + 0x2dadc7, + 0x215a05, + 0x26fe0a, + 0x3bf6c6, + 0x2f9889, + 0x37b50c, + 0x3bcfc9, + 0x3d1b06, + 0x2cb40c, + 0x33b8c6, + 0x304fc8, + 0x305fc6, + 0x33f806, + 0x2b5644, + 0x31ddc3, + 0x32358a, + 0x28e451, + 0x2818ca, + 0x27d185, + 0x355ac7, + 0x258d07, + 0x2d88c4, + 0x2d88cb, + 0x204e88, + 0x2be3c6, + 0x2326c5, + 0x32a284, + 0x243089, + 0x2008c4, + 0x242987, + 0x380385, + 0x380387, + 0x37f305, + 0x2535c3, + 0x222548, + 0x31f38a, + 0x2166c3, + 0x2166ca, + 0x27eb06, + 0x2600cf, + 0x3d3489, + 0x2cb910, + 0x2fd448, + 0x2d2049, + 0x298b07, + 0x2b19cf, + 0x393804, + 0x2dd344, + 0x21c9c6, + 0x3ac106, + 0x2ed80a, + 0x2574c6, + 0x394fc7, + 0x3152c8, + 0x3154c7, + 0x316907, + 0x31820a, + 0x31720b, + 0x328805, + 0x2e2a48, + 0x21b2c3, + 0x3ba74c, + 0x351e0f, + 0x23570d, + 0x259307, + 0x326bc9, + 0x225547, + 0x23be88, + 0x22c98c, + 0x26a208, + 0x23d708, + 0x33290e, + 0x345b14, + 0x346024, + 0x35d98a, + 0x37b14b, + 0x378984, + 0x378989, + 0x2f1d08, + 0x2484c5, + 0x30a94a, + 0x260747, + 0x21e744, + 0x24ce83, + 0x22d7c3, + 0x236204, + 0x233743, + 0x220583, + 0x222884, + 0x219e43, + 0x205e03, + 0x2dc3c6, + 0x205184, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x2000c2, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x236204, + 0x233743, + 0x220583, + 0x219e43, + 0x2dc3c6, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x228843, + 0x206b43, + 0x6df83, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x205184, + 0x206b43, + 0x23cf83, + 0x2000c2, + 0x24de03, + 0x202782, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x205cc2, + 0x235d82, + 0x202782, + 0x22d7c3, + 0x206742, + 0x2005c2, + 0x222884, + 0x3216c4, + 0x228d42, + 0x205184, + 0x2003c2, + 0x23cf83, + 0x213c43, + 0x259b06, + 0x2195c2, + 0x207d82, + 0x223f82, + 0x5361f043, + 0x53a04343, + 0x59646, + 0x59646, + 0x241844, + 0x2013c3, + 0x8d78a, + 0x1721cc, + 0x1dca0c, + 0xca48d, + 0x12dac5, + 0x8cf0c, + 0x2afc7, + 0xc946, + 0x13848, + 0x1b047, + 0x20a08, + 0x18930a, + 0x1142c7, + 0x5468d145, + 0xdee89, + 0x34f8b, + 0x17830b, + 0x1c6408, + 0x5f89, + 0x18c58a, + 0x17598e, + 0x8f68d, + 0x1441e8b, + 0xdfaca, + 0xe184, + 0x5c846, + 0x160308, + 0x6c648, + 0x3fbc7, + 0xbb45, + 0x19447, + 0x80b89, + 0x1a0047, + 0x18b08, + 0x29009, + 0x4aec4, + 0x4fe45, + 0x16364e, + 0x6c2cd, + 0x5d88, + 0x54a6e4c6, + 0x55571a08, + 0x76248, + 0x13df10, + 0x5784c, + 0x65247, + 0x66287, + 0x6a407, + 0x70c47, + 0x37482, + 0x13be07, + 0x1c1f46, + 0x1624c, + 0x198c85, + 0x1cc607, + 0xa7906, + 0xa8549, + 0xaa8c8, + 0x373c2, + 0x5c2, + 0x18bb06, + 0x1c4a0b, + 0x1c4d06, + 0x1091c4, + 0x45647, + 0xe4e09, + 0x504c9, + 0x17f8c8, + 0x4d442, + 0x191789, + 0xc548, + 0xed64a, + 0x6d06, + 0xcea89, + 0xdfa47, + 0xe0189, + 0xe22c8, + 0xe32c7, + 0xe4349, + 0xe9c45, + 0xe9fd0, + 0x178f46, + 0x45585, + 0x1667c7, + 0xebccd, + 0x409c5, + 0xf0bc6, + 0xf1407, + 0xf7dd8, + 0x1a03c8, + 0x10ba8a, + 0x16f82, + 0x56d4a, + 0x6ca4d, + 0x1bc2, + 0x5bac6, + 0x51488, + 0x49f88, + 0x6d8c9, + 0x115f88, + 0x7b54e, + 0x6db08, + 0x137987, + 0x55b08104, + 0x10ec4d, + 0x100185, + 0x109f48, + 0x1abcc8, + 0x10f346, + 0xd2c2, + 0x53844, + 0x33d86, + 0xec046, + 0xa842, + 0x401, + 0x5ed07, + 0x117c83, + 0x54ef8644, + 0x55296943, + 0xc1, + 0x11746, + 0xc1, + 0x201, + 0x11746, + 0x117c83, + 0x418c3, + 0x9a544, + 0x147da45, + 0x52184, + 0x65387, + 0x2782, + 0x24ec04, + 0x22d7c3, + 0x251184, + 0x222884, + 0x206b43, + 0x221f05, + 0x214703, + 0x25b583, + 0x3da885, + 0x207b83, + 0xe583, + 0x56a2d7c3, + 0x233743, + 0x4183, + 0x220583, + 0x200181, + 0x14903, + 0x205e03, + 0x3216c4, + 0x205184, + 0x206b43, + 0x23cf83, + 0x202003, + 0xa14c8, + 0x2000c2, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x228843, + 0x2005c2, + 0x222884, + 0x219e43, + 0x205e03, + 0x206b43, + 0x2013c3, + 0x23cf83, + 0x207b83, + 0xa14c8, + 0x1213c7, + 0x2782, + 0x1a4d45, + 0x5798f, + 0xdac46, + 0x144b148, + 0x11630e, + 0x57a0f9c2, + 0x32bd88, + 0x310446, + 0x252306, + 0x30fdc7, + 0x57e01cc2, + 0x583d3308, + 0x21538a, + 0x264cc8, + 0x200b02, + 0x31f649, + 0x328847, + 0x2122c6, + 0x222289, + 0x30bdc4, + 0x20f186, + 0x2c5bc4, + 0x2072c4, + 0x25ab09, + 0x314786, + 0x22c345, + 0x2684c5, + 0x22df07, + 0x2c2ac7, + 0x28c3c4, + 0x310006, + 0x2f9045, + 0x218c85, + 0x27d245, + 0x2af587, + 0x26f285, + 0x24c349, + 0x3ccec5, + 0x347b44, + 0x266607, + 0x330b8e, + 0x360849, + 0x37ef89, + 0x335d46, + 0x23e788, + 0x24378b, + 0x367ecc, + 0x34d746, + 0x336c07, + 0x2b2a45, + 0x21744a, + 0x28db09, + 0x203489, + 0x3d5546, + 0x303405, + 0x247ac5, + 0x34a009, + 0x27d3cb, + 0x2e1886, + 0x350706, + 0x202c44, + 0x290746, + 0x2fc248, + 0x3b7506, + 0x357086, + 0x3c6d48, + 0x3d1907, + 0x3d5309, + 0x3d7485, + 0xa14c8, + 0x3cedc4, + 0x316e84, + 0x20b085, + 0x343e09, + 0x2214c7, + 0x2214cb, + 0x2245ca, + 0x2278c5, + 0x586022c2, + 0x2c6b47, + 0x58a27bc8, + 0x3d5787, + 0x2bdf05, + 0x35cd4a, + 0x2782, + 0x279acb, + 0x27f74a, + 0x24c7c6, + 0x22a2c3, + 0x36f7cd, + 0x3a864c, + 0x3b568d, + 0x231085, + 0x27a785, + 0x30ae87, + 0x3dac89, + 0x215286, + 0x257345, + 0x2eed48, + 0x290643, + 0x3011c8, + 0x290648, + 0x2c7d47, + 0x32af88, + 0x3a8449, + 0x2cbec7, + 0x2c6347, + 0x27d8c8, + 0x31ad44, + 0x31ad47, + 0x287a88, + 0x35e006, + 0x39990f, + 0x2e5007, + 0x358d86, + 0x36af45, + 0x224103, + 0x249d47, + 0x387183, + 0x24ff86, + 0x252086, + 0x252f86, + 0x294045, + 0x267e83, + 0x391408, + 0x388d49, + 0x39a54b, + 0x253108, + 0x2545c5, + 0x2563c5, + 0x58eb06c2, + 0x284f89, + 0x222907, + 0x25c785, + 0x25aa07, + 0x25c046, + 0x380bc5, + 0x25cb4b, + 0x25f044, + 0x264885, + 0x2649c7, + 0x277f46, + 0x278385, + 0x2874c7, + 0x287e07, + 0x2d2944, + 0x28cd0a, + 0x28ee48, + 0x243a49, + 0x368a85, + 0x2b2dc6, + 0x2fc40a, + 0x2683c6, + 0x22cd47, + 0x2c9b4d, + 0x2a5849, + 0x341d45, + 0x202d07, + 0x330f88, + 0x330508, + 0x21fa47, + 0x32e906, + 0x222c87, + 0x251b03, + 0x314704, + 0x37d145, + 0x3a9b07, + 0x3ae709, + 0x22ac48, + 0x22cc45, + 0x24b544, + 0x24cac5, + 0x2532cd, + 0x202082, + 0x2c1346, + 0x25ba06, + 0x2fe5ca, + 0x390dc6, + 0x397485, + 0x2c6085, + 0x2c6087, + 0x3a788c, + 0x2760ca, + 0x290406, + 0x2dbe05, + 0x290586, + 0x2908c7, + 0x292046, + 0x293f4c, + 0x2223c9, + 0x59211bc7, + 0x295f45, + 0x295f46, + 0x2963c8, + 0x2bca45, + 0x2a6545, + 0x2a6f08, + 0x2a710a, + 0x5967a482, + 0x59a08402, + 0x300945, + 0x281443, + 0x229d88, + 0x20b443, + 0x2a7384, + 0x2f99cb, + 0x3c72c8, + 0x2b1588, + 0x59fcc049, + 0x2abbc9, + 0x2ac306, + 0x2ad048, + 0x2ad249, + 0x2ae3c6, + 0x2ae545, + 0x24a8c6, + 0x2aed09, + 0x2ba987, + 0x34b786, + 0x21d087, + 0x3731c7, + 0x21f1c4, + 0x5a3a06c9, + 0x349708, + 0x3d3208, + 0x23fd07, + 0x2caf06, + 0x3c7789, + 0x2522c7, + 0x348f8a, + 0x369508, + 0x212c47, + 0x224f06, + 0x2ad5ca, + 0x231808, + 0x2e8745, + 0x2269c5, + 0x351147, + 0x31c689, + 0x3208cb, + 0x355d88, + 0x3ccf49, + 0x253a47, + 0x2bbd8c, + 0x2bc60c, + 0x2bc90a, + 0x2bcb8c, + 0x2c5748, + 0x2c5948, + 0x2c5b44, + 0x2c74c9, + 0x2c7709, + 0x2c794a, + 0x2c7bc9, + 0x2c7f07, + 0x3d5b4c, + 0x20ca46, + 0x2c9508, + 0x268486, + 0x3a3386, + 0x341c47, + 0x21fbc8, + 0x20f74b, + 0x3d5647, + 0x25a7c9, + 0x285189, + 0x355c07, + 0x2c5e04, + 0x2fa147, + 0x20a286, + 0x20ddc6, + 0x2fdf85, + 0x2cec48, + 0x294884, + 0x294886, + 0x275f8b, + 0x2ae009, + 0x250ac6, + 0x357289, + 0x20b146, + 0x204048, + 0x218983, + 0x303585, + 0x222a89, + 0x224805, + 0x37e504, + 0x277486, + 0x23c705, + 0x257bc6, + 0x31a607, + 0x346dc6, + 0x22bb0b, + 0x249887, + 0x2554c6, + 0x210046, + 0x22dfc6, + 0x28c389, + 0x2fa54a, + 0x2be6c5, + 0x3b518d, + 0x2a7206, + 0x38fac6, + 0x2cb806, + 0x2f7805, + 0x2ea2c7, + 0x22a587, + 0x273bce, + 0x205e03, + 0x2caec9, + 0x245009, + 0x22dc47, + 0x226247, + 0x237d85, + 0x210205, + 0x5a600c0f, + 0x2d2287, + 0x2d2448, + 0x2d3144, + 0x2d3586, + 0x5aa477c2, + 0x2d9b06, + 0x2dc3c6, + 0x2451ce, + 0x30100a, + 0x2b6546, + 0x21ba0a, + 0x3c2989, + 0x234045, + 0x305488, + 0x31d886, + 0x29d808, + 0x329788, + 0x27958b, + 0x30fec5, + 0x26f308, + 0x3c6e8c, + 0x2bddc7, + 0x252806, + 0x2e5888, + 0x20f408, + 0x5ae4fd42, + 0x20ef4b, + 0x3d7689, + 0x28d5c9, + 0x21b707, + 0x3c4f88, + 0x5b397048, + 0x20e7cb, + 0x37f749, + 0x25db4d, + 0x3295c8, + 0x2ad7c8, + 0x5b601642, + 0x3cbec4, + 0x5ba2ebc2, + 0x3b0a06, + 0x5be01102, + 0x2f500a, + 0x2ab406, + 0x238348, + 0x3be948, + 0x248ec6, + 0x337106, + 0x2fd1c6, + 0x2a6a45, + 0x23a1c4, + 0x5c238884, + 0x355586, + 0x296e47, + 0x5c60c687, + 0x26c08b, + 0x3d5989, + 0x27a7ca, + 0x206944, + 0x2c61c8, + 0x34b54d, + 0x2f5b89, + 0x2f5dc8, + 0x2f6049, + 0x2f7dc4, + 0x247344, + 0x25ebc5, + 0x36824b, + 0x3c7246, + 0x3553c5, + 0x2eb909, + 0x3100c8, + 0x238a04, + 0x2175c9, + 0x237605, + 0x2c2b08, + 0x2c6a07, + 0x37f388, + 0x284846, + 0x3d1ec7, + 0x2e1049, + 0x3cc909, + 0x3c7a85, + 0x36ff45, + 0x5ca12cc2, + 0x347904, + 0x217fc5, + 0x30fcc6, + 0x37a1c5, + 0x2edec7, + 0x299f85, + 0x277f84, + 0x335e06, + 0x2573c7, + 0x2ff786, + 0x321d85, + 0x210608, + 0x310645, + 0x214887, + 0x221109, + 0x2ae14a, + 0x22b147, + 0x22b14c, + 0x22c306, + 0x23ce09, + 0x37ff05, + 0x38ad48, + 0x209f43, + 0x20ab85, + 0x209f45, + 0x303b07, + 0x5ce03542, + 0x2f0187, + 0x2e7f46, + 0x3ce746, + 0x2eb246, + 0x20f346, + 0x2ddf88, + 0x31f2c5, + 0x358e47, + 0x358e4d, + 0x203843, + 0x20cf05, + 0x26fbc7, + 0x2f04c8, + 0x26f785, + 0x213e88, + 0x39c646, + 0x2df047, + 0x2c9445, + 0x30ff46, + 0x391985, + 0x21504a, + 0x2f9406, + 0x282187, + 0x31e445, + 0x3a6707, + 0x305d84, + 0x37e486, + 0x3053c5, + 0x216bcb, + 0x20a109, + 0x24df0a, + 0x3c7b08, + 0x348348, + 0x30d40c, + 0x30ef47, + 0x311dc8, + 0x313f88, + 0x314d05, + 0x350f0a, + 0x352a09, + 0x5d202702, + 0x3c0806, + 0x246dc4, + 0x246dc9, + 0x270a09, + 0x277987, + 0x2b4907, + 0x3562c9, + 0x2d1b88, + 0x2d1b8f, + 0x223686, + 0x2deb4b, + 0x2669c5, + 0x2669c7, + 0x374c49, + 0x217546, + 0x217547, + 0x2e3185, + 0x230f84, + 0x267586, + 0x221684, + 0x2b5287, + 0x2b3688, + 0x5d703308, + 0x304885, + 0x3049c7, + 0x32ac89, + 0x20ed04, + 0x240588, + 0x5da72b88, + 0x2d88c4, + 0x347e48, + 0x372644, + 0x3b5489, + 0x219f85, + 0x5de1be02, + 0x2236c5, + 0x2e38c5, + 0x202b48, + 0x234347, + 0x5e2008c2, + 0x2389c5, + 0x2d76c6, + 0x232e06, + 0x3478c8, + 0x34ab88, + 0x37a186, + 0x37ae06, + 0x321489, + 0x3ce686, + 0x2195cb, + 0x31f585, + 0x2a8046, + 0x2755c8, + 0x3333c6, + 0x39ec86, + 0x21434a, + 0x2abf8a, + 0x273305, + 0x30dcc7, + 0x2f33c6, + 0x5e606842, + 0x26fd07, + 0x25e345, + 0x2fc384, + 0x2fc385, + 0x206846, + 0x271847, + 0x21c9c5, + 0x21fc44, + 0x2d39c8, + 0x39ed45, + 0x3c9707, + 0x3d4145, + 0x214f85, + 0x2ae9c4, + 0x2e6ac9, + 0x2f8e88, + 0x23a946, + 0x3b7ec6, + 0x3cae86, + 0x5eb0f4c8, + 0x30f6c7, + 0x31174d, + 0x312c4c, + 0x313249, + 0x313489, + 0x5ef73c82, + 0x3d2fc3, + 0x20a343, + 0x20a345, + 0x3a9c0a, + 0x33fbc6, + 0x24e305, + 0x31af04, + 0x31af0b, + 0x3340cc, + 0x33534c, + 0x335655, + 0x337b4d, + 0x33964f, + 0x339a12, + 0x339e8f, + 0x33a252, + 0x33a6d3, + 0x33ab8d, + 0x33b14d, + 0x33b4ce, + 0x33ba4e, + 0x33c78c, + 0x33cb4c, + 0x33cf8b, + 0x33da0e, + 0x33e312, + 0x33f98c, + 0x33fe90, + 0x34ba52, + 0x34c6cc, + 0x34cd8d, + 0x34d0cc, + 0x34f611, + 0x35088d, + 0x352c4d, + 0x35324a, + 0x3534cc, + 0x3547cc, + 0x3550cc, + 0x35688c, + 0x35a253, + 0x35a8d0, + 0x35acd0, + 0x35b64d, + 0x35bc4c, + 0x35d6c9, + 0x35ef4d, + 0x35f293, + 0x361fd1, + 0x3627d3, + 0x363c8f, + 0x36404c, + 0x36434f, + 0x36470d, + 0x364d0f, + 0x3650d0, + 0x365b4e, + 0x369c8e, + 0x36b490, + 0x36bf4d, + 0x36c8ce, + 0x36cc4c, + 0x36dc13, + 0x37028e, + 0x370910, + 0x370d11, + 0x37114f, + 0x371513, + 0x37380d, + 0x373b4f, + 0x373f0e, + 0x374490, + 0x374889, + 0x3761d0, + 0x3767cf, + 0x376e4f, + 0x377212, + 0x37940e, + 0x379e0d, + 0x37a54d, + 0x37a88d, + 0x37b80d, + 0x37bb4d, + 0x37be90, + 0x37c28b, + 0x37cf0c, + 0x37d28c, + 0x37d88c, + 0x37db8e, + 0x38b4d0, + 0x38ddd2, + 0x38e24b, + 0x38e58e, + 0x38e90e, + 0x38f18e, + 0x38f60b, + 0x5f38fc56, + 0x390acd, + 0x390f54, + 0x391c4d, + 0x3939d5, + 0x39554d, + 0x395ecf, + 0x39654f, + 0x39a80f, + 0x39abce, + 0x39b14d, + 0x39cc91, + 0x3a2b4c, + 0x3a2e4c, + 0x3a314b, + 0x3a370c, + 0x3a3d8f, + 0x3a4152, + 0x3a480d, + 0x3a590c, + 0x3a68cc, + 0x3a6bcd, + 0x3a6f0f, + 0x3a72ce, + 0x3a98cc, + 0x3a9e8d, + 0x3aa1cb, + 0x3aaa8c, + 0x3ab38d, + 0x3ab6ce, + 0x3aba49, + 0x3ad093, + 0x3ad7cd, + 0x3adecd, + 0x3ae4cc, + 0x3ae94e, + 0x3af04f, + 0x3af40c, + 0x3af70d, + 0x3afa4f, + 0x3afe0c, + 0x3b0c4c, + 0x3b110c, + 0x3b140c, + 0x3b1acd, + 0x3b1e12, + 0x3b2b8c, + 0x3b2e8c, + 0x3b3191, + 0x3b35cf, + 0x3b398f, + 0x3b3d53, + 0x3b5e0e, + 0x3b618f, + 0x3b654c, + 0x5f7b688e, + 0x3b6c0f, + 0x3b6fd6, + 0x3b9f92, + 0x3bc7cc, + 0x3bd60f, + 0x3bdc8d, + 0x3c878f, + 0x3c8b4c, + 0x3c8e4d, + 0x3c918d, + 0x3caa4e, + 0x3cdecc, + 0x3d044c, + 0x3d0750, + 0x3d2351, + 0x3d278b, + 0x3d2bcc, + 0x3d2ece, + 0x3d4591, + 0x3d49ce, + 0x3d4d4d, + 0x3d894b, + 0x3d924f, + 0x3d9e54, + 0x2068c2, + 0x2068c2, + 0x202e03, + 0x2068c2, + 0x202e03, + 0x2068c2, + 0x20c682, + 0x24a905, + 0x3d428c, + 0x2068c2, + 0x2068c2, + 0x20c682, + 0x2068c2, + 0x296a45, + 0x2ae145, + 0x2068c2, + 0x2068c2, + 0x2010c2, + 0x296a45, + 0x338309, + 0x361ccc, + 0x2068c2, + 0x2068c2, + 0x2068c2, + 0x2068c2, + 0x24a905, + 0x2068c2, + 0x2068c2, + 0x2068c2, + 0x2068c2, + 0x2010c2, + 0x338309, + 0x2068c2, + 0x2068c2, + 0x2068c2, + 0x2ae145, + 0x2068c2, + 0x2ae145, + 0x361ccc, + 0x3d428c, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x206b43, + 0x23cf83, + 0x60314887, + 0x1c618f, + 0x24c8, + 0x7b684, + 0x13c3, + 0x1a20c8, + 0x7c44, + 0x2000c2, + 0x60a02782, + 0x23fec3, + 0x250604, + 0x204183, + 0x3dc504, + 0x22fac6, + 0x20ad83, + 0x30e184, + 0x24d985, + 0x205e03, + 0x206b43, + 0x6df83, + 0x23cf83, + 0x21d60a, + 0x259b06, + 0x38ec8c, + 0xa14c8, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x22a243, + 0x2dc3c6, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x2fe03, + 0xa7c88, + 0x6157eac5, + 0x4b8c7, + 0x12dac5, + 0x178449, + 0xdcc2, + 0x6237e2c5, + 0x12dac5, + 0x2afc7, + 0x6da08, + 0x820e, + 0x8abd2, + 0x11f94b, + 0x1143c6, + 0x6268d145, + 0x62a8d14c, + 0x5e4c7, + 0x14c47, + 0x1a0eca, + 0x3b650, + 0x173345, + 0x10cd0b, + 0x6c648, + 0x3fbc7, + 0x19ee0b, + 0x80b89, + 0x4aac7, + 0x1a0047, + 0xe1ac7, + 0x35186, + 0x18b08, + 0x63029f46, + 0x49ec7, + 0x15c646, + 0x6c2cd, + 0x1a0890, + 0x634758c2, + 0x5d88, + 0x3c010, + 0x1818cc, + 0x63b89fcd, + 0x5d348, + 0x5d7cb, + 0x6ad07, + 0x16a549, + 0x59706, + 0x965c8, + 0x7102, + 0x8898a, + 0xde307, + 0x1cc607, + 0xa8549, + 0xaa8c8, + 0x1b8e85, + 0x18bb06, + 0x1c4d06, + 0xf6cce, + 0x23b4e, + 0xa9f4f, + 0xe4e09, + 0x504c9, + 0x8850b, + 0xa224f, + 0xc334c, + 0xbb64b, + 0xe0ac8, + 0x144707, + 0x166308, + 0x18da0b, + 0x194d8c, + 0x19bd4c, + 0x1a3a8c, + 0xafccd, + 0x17f8c8, + 0xefdc2, + 0x191789, + 0xf9708, + 0x1921cb, + 0xcb106, + 0xd6f8b, + 0x13de4b, + 0xe28ca, + 0xe3485, + 0xe9fd0, + 0xec646, + 0x12e406, + 0x45585, + 0x1667c7, + 0xfd6c8, + 0xf1407, + 0xf16c7, + 0x1c6647, + 0x1b084a, + 0xa134a, + 0x5bac6, + 0x94ecd, + 0x49f88, + 0x115f88, + 0xae909, + 0xbacc5, + 0x1aed4c, + 0xafecb, + 0x10d704, + 0x10f109, + 0x10f346, + 0x159546, + 0x1b4886, + 0x7d82, + 0xec046, + 0x10b9cb, + 0x11d447, + 0xa842, + 0xcd9c5, + 0x26c44, + 0x101, + 0x568c3, + 0x62e81606, + 0x96943, + 0x382, + 0x29144, + 0xb02, + 0x41844, + 0x882, + 0x2202, + 0x2c42, + 0x25a42, + 0x5cc2, + 0x8d142, + 0x14c2, + 0xd5e42, + 0x36d82, + 0x37982, + 0x2942, + 0x52282, + 0x33743, + 0x942, + 0x1242, + 0x19d02, + 0xe282, + 0x642, + 0x320c2, + 0x373c2, + 0x3d82, + 0x5e42, + 0x5c2, + 0x19e43, + 0x1b82, + 0x6102, + 0x4d442, + 0x53a42, + 0xb42, + 0x8002, + 0xf1c2, + 0xdf302, + 0x24c2, + 0x1582, + 0x6cec2, + 0x45ec2, + 0x6b43, + 0x602, + 0x4fd42, + 0x13c2, + 0xcc82, + 0x1c7a05, + 0x6a82, + 0x41f42, + 0x3c883, + 0x682, + 0x16f82, + 0x1bc2, + 0x37c2, + 0x3842, + 0x8c2, + 0xd2c2, + 0x7d82, + 0x5f85, + 0x63e0c682, + 0x642cfe83, + 0x20c3, + 0x6460c682, + 0x20c3, + 0x83cc7, + 0x20c443, + 0x2000c2, + 0x22d7c3, + 0x233743, + 0x228843, + 0x2005c3, + 0x22a243, + 0x206b43, + 0x2013c3, + 0x23cf83, + 0x296983, + 0xfc105, + 0x1083, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x228843, + 0x205e03, + 0x206b43, + 0x2013c3, + 0x6df83, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x200181, + 0x205e03, + 0x206b43, + 0x251ac3, + 0x23cf83, + 0x10c9c4, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x205d83, + 0x228843, + 0x251383, + 0x22f503, + 0x2ab3c3, + 0x249743, + 0x220583, + 0x222884, + 0x206b43, + 0x23cf83, + 0x207b83, + 0x201844, + 0x2534c3, + 0xa683, + 0x3c38c3, + 0x32a148, + 0x2ad604, + 0x20020a, + 0x250846, + 0x12aa84, + 0x383407, + 0x21dd8a, + 0x223549, + 0x3ad507, + 0x3b41ca, + 0x24ce83, + 0x3009cb, + 0x2d5809, + 0x2d86c5, + 0x3b0f47, + 0x2782, + 0x22d7c3, + 0x237987, + 0x2e5505, + 0x2c5cc9, + 0x233743, + 0x308386, + 0x2c5103, + 0xa1c3, + 0x119746, + 0x10b206, + 0xad07, + 0x221986, + 0x225a85, + 0x3d7547, + 0x316747, + 0x67220583, + 0x34c907, + 0x3b4983, + 0x20be85, + 0x222884, + 0x26ef88, + 0x379b0c, + 0x2b12c5, + 0x2a59c6, + 0x237847, + 0x20a647, + 0x2660c7, + 0x270048, + 0x31868f, + 0x223785, + 0x23ffc7, + 0x20d547, + 0x2a74ca, + 0x2eeb89, + 0x322805, + 0x32484a, + 0x130246, + 0xbb147, + 0x2c5185, + 0x38e484, + 0x248e06, + 0xbdfc6, + 0x381b47, + 0x2efcc7, + 0x3dae88, + 0x21a205, + 0x2e5406, + 0x25388, + 0x357005, + 0x1571c6, + 0x23bd85, + 0x28ca84, + 0x2376c7, + 0x2dddca, + 0x255988, + 0x361386, + 0x2a243, + 0x2e43c5, + 0x3291c6, + 0x3d5d86, + 0x245486, + 0x205e03, + 0x3a4a87, + 0x20d4c5, + 0x206b43, + 0x2e2b8d, + 0x2013c3, + 0x3daf88, + 0x219344, + 0x278245, + 0x2a73c6, + 0x394206, + 0x2a7f47, + 0x25da07, + 0x283385, + 0x23cf83, + 0x2e9987, + 0x344809, + 0x36a6c9, + 0x32e64a, + 0x2434c2, + 0x20be44, + 0x2ecbc4, + 0x2efb87, + 0x2f0048, + 0x2f24c9, + 0x20cdc9, + 0x2f3a07, + 0xffc09, + 0x3720c6, + 0xf6a46, + 0x2f7dc4, + 0x2f83ca, + 0x2fb488, + 0x2fd089, + 0x3ac386, + 0x2b5e85, + 0x255848, + 0x2cc48a, + 0x210f43, + 0x2019c6, + 0x2f3b07, + 0x357785, + 0x390485, + 0x239703, + 0x23d804, + 0x226985, + 0x287f07, + 0x2f8fc5, + 0x2eea46, + 0x13c285, + 0x28a243, + 0x2b6609, + 0x27800c, + 0x2b9f4c, + 0x2d6d88, + 0x2a4b47, + 0x306148, + 0x106787, + 0x306fca, + 0x30768b, + 0x2d5948, + 0x394308, + 0x239106, + 0x3cad45, + 0x30a10a, + 0x2cfec5, + 0x21be02, + 0x2c9307, + 0x251646, + 0x375145, + 0x30de89, + 0x206145, + 0x31fec5, + 0x2752c9, + 0x329106, + 0x3ba5c8, + 0x26a183, + 0x209046, + 0x2773c6, + 0x31c485, + 0x31c489, + 0x2f2c09, + 0x27e387, + 0x11d2c4, + 0x31d2c7, + 0x20ccc9, + 0x21df85, + 0x3a2c8, + 0x340ec5, + 0x274b05, + 0x377a09, + 0x2020c2, + 0x2e4884, + 0x203f42, + 0x201b82, + 0x38c145, + 0x32a808, + 0x2bac05, + 0x2c80c3, + 0x2c80c5, + 0x2d9d03, + 0x209002, + 0x302284, + 0x2b69c3, + 0x201002, + 0x3cb604, + 0x2ed143, + 0x204f02, + 0x2bac83, + 0x303a84, + 0x2fd643, + 0x25cfc4, + 0x209482, + 0x213b43, + 0x21bb03, + 0x203002, + 0x308102, + 0x2f2a49, + 0x219082, + 0x28ba04, + 0x202242, + 0x2556c4, + 0x372084, + 0x206f04, + 0x207d82, + 0x238d42, + 0x36ad83, + 0x307443, + 0x237b44, + 0x248804, + 0x2ba344, + 0x2d1544, + 0x2fb643, + 0x2446c3, + 0x3301c4, + 0x31fdc4, + 0x3203c6, + 0x22c202, + 0x2782, + 0x409c3, + 0x202782, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x2000c2, + 0x24ce83, + 0x22d7c3, + 0x233743, + 0x208903, + 0x220583, + 0x222884, + 0x2f2d04, + 0x205184, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x2f8984, + 0x32bd43, + 0x2a8fc3, + 0x37a0c4, + 0x340cc6, + 0x218a43, + 0x12dac5, + 0x14c47, + 0x2e6e03, + 0x68a4abc8, + 0x2416c3, + 0x2b3883, + 0x20bec3, + 0x22a243, + 0x35ff85, + 0x1b0f03, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x3410c3, + 0x22f0c3, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x219e43, + 0x206b43, + 0x23b484, + 0x6df83, + 0x23cf83, + 0x21f4c4, + 0x12dac5, + 0x2c1745, + 0x14c47, + 0x202782, + 0x203dc2, + 0x200382, + 0x202642, + 0x13c3, + 0x2003c2, + 0x3304, + 0x22d7c3, + 0x236204, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x205184, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x202003, + 0x241844, + 0xa14c8, + 0x22d7c3, + 0x2013c3, + 0x1083, + 0x14d5c4, + 0x24ec04, + 0xa14c8, + 0x22d7c3, + 0x251184, + 0x222884, + 0x2013c3, + 0x201642, + 0x6df83, + 0x23cf83, + 0x25b583, + 0x3d804, + 0x3da885, + 0x21be02, + 0x3094c3, + 0x131949, + 0xdff06, + 0x109548, + 0x2000c2, + 0xa14c8, + 0x202782, + 0x233743, + 0x220583, + 0x2005c2, + 0x13c3, + 0x23cf83, + 0x79c2, + 0x82, + 0x2000c2, + 0x1b4387, + 0x135b49, + 0x7c303, + 0xa14c8, + 0x25a03, + 0x6c356e87, + 0x2d7c3, + 0x1c0708, + 0x233743, + 0x220583, + 0x3d346, + 0x219e43, + 0x95988, + 0xc4108, + 0x11f086, + 0x205e03, + 0xcf188, + 0xedf43, + 0x6c4e3d46, + 0xea9c5, + 0x33947, + 0x6b43, + 0x4e283, + 0x3cf83, + 0x2102, + 0x19c44a, + 0x4cc3, + 0x18c203, + 0x300204, + 0x11848b, + 0x118a48, + 0x91a82, + 0x1457987, + 0x1530e07, + 0x14c8188, + 0x151e703, + 0x1289cb, + 0x12d947, + 0x6a04, + 0x2000c2, + 0x202782, + 0x236204, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x22a243, + 0x206b43, + 0x23cf83, + 0x21f4c3, + 0x202003, + 0x2fe03, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x1083, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x22a243, + 0x206b43, + 0x23cf83, + 0x2195c2, + 0x2000c1, + 0x2000c2, + 0x200201, + 0x339742, + 0xa14c8, + 0x21c745, + 0x200101, + 0x2d7c3, + 0x30944, + 0x200f01, + 0x200501, + 0x202401, + 0x24a882, + 0x387184, + 0x24a883, + 0x200041, + 0x200801, + 0x200181, + 0x200701, + 0x37e6c7, + 0x31d9cf, + 0x319886, + 0x2004c1, + 0x34d606, + 0x200c01, + 0x200581, + 0x3d8b8e, + 0x2003c1, + 0x23cf83, + 0x201001, + 0x2e4d05, + 0x202102, + 0x239605, + 0x200401, + 0x200741, + 0x2007c1, + 0x21be02, + 0x200081, + 0x201ec1, + 0x203301, + 0x201081, + 0x20a781, + 0x54389, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x214703, + 0x22d7c3, + 0x220583, + 0x919c8, + 0x205e03, + 0x206b43, + 0x4e703, + 0x23cf83, + 0x14ee5c8, + 0x140fc8, + 0x12dac5, + 0xa14c8, + 0x13c3, + 0x12dac5, + 0x43fc4, + 0x3c2c8, + 0x47984, + 0x54389, + 0x14ee5ca, + 0xa14c8, + 0x6df83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x206b43, + 0x23cf83, + 0x20a683, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x2dd2c4, + 0x23cf83, + 0x3451c5, + 0x31f384, + 0x22d7c3, + 0x206b43, + 0x23cf83, + 0x2003, + 0xa7d8a, + 0xf3e84, + 0x122c86, + 0x202782, + 0x22d7c3, + 0x230ec9, + 0x233743, + 0x2ab989, + 0x220583, + 0x205e03, + 0x206b43, + 0x6bfc4, + 0x13c3, + 0x23cf83, + 0x2f7bc8, + 0x2319c7, + 0x3da885, + 0x1d29c8, + 0x1b4387, + 0xf02ca, + 0x6f54b, + 0x14d847, + 0x3e648, + 0x1a050a, + 0x11808, + 0x135b49, + 0x26847, + 0x374c7, + 0x14c8, + 0x1c0708, + 0x4028f, + 0x19a45, + 0x18b307, + 0x3d346, + 0x4e1c7, + 0x122946, + 0x95988, + 0x9e786, + 0x128f07, + 0x12ea49, + 0x10ec7, + 0xb2f09, + 0xbb909, + 0xc14c6, + 0xc4108, + 0xc2c45, + 0x7a30a, + 0xcf188, + 0xedf43, + 0xdaa88, + 0x33947, + 0x172945, + 0x5f550, + 0x4e283, + 0x6df83, + 0x128d87, + 0x22d85, + 0xf19c8, + 0x68885, + 0x18c203, + 0x7048, + 0xc0246, + 0x17c949, + 0xad447, + 0x131c0b, + 0x6d144, + 0x10e984, + 0x11848b, + 0x118a48, + 0x119647, + 0x12dac5, + 0x22d7c3, + 0x233743, + 0x228843, + 0x23cf83, + 0x23de43, + 0x220583, + 0x6df83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x8864b, + 0x2000c2, + 0x202782, + 0x23cf83, + 0xa14c8, + 0x2782, + 0x2000c2, + 0x202782, + 0x200382, + 0x2005c2, + 0x205e02, + 0x206b43, + 0x132f46, + 0x2003c2, + 0x3d804, + 0x2000c2, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x200382, + 0x220583, + 0x219e43, + 0x205e03, + 0x205184, + 0x206b43, + 0x212203, + 0x13c3, + 0x23cf83, + 0x300204, + 0x207b83, + 0x220583, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x2013c3, + 0x23cf83, + 0x3bcc87, + 0x22d7c3, + 0x27c507, + 0x366486, + 0x201f83, + 0x219d03, + 0x220583, + 0x209a03, + 0x222884, + 0x3975c4, + 0x2df1c6, + 0x201d43, + 0x206b43, + 0x23cf83, + 0x3451c5, + 0x309e84, + 0x3a13c3, + 0x2c7183, + 0x2c9307, + 0x2c6985, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x52507, + 0x1667c7, + 0x1a2a05, + 0x20c882, + 0x24a0c3, + 0x20ee03, + 0x24ce83, + 0x7622d7c3, + 0x206742, + 0x233743, + 0x204183, + 0x220583, + 0x222884, + 0x37fa83, + 0x223783, + 0x205e03, + 0x205184, + 0x76602a42, + 0x206b43, + 0x23cf83, + 0x204f03, + 0x21c4c3, + 0x212bc3, + 0x2195c2, + 0x207b83, + 0xa14c8, + 0x220583, + 0x1083, + 0x21e744, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x236204, + 0x233743, + 0x220583, + 0x222884, + 0x219e43, + 0x3b7d44, + 0x3216c4, + 0x2dc3c6, + 0x205184, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x251646, + 0x3540b, + 0x29f46, + 0xebe8a, + 0x11c10a, + 0xa14c8, + 0x225344, + 0x77a2d7c3, + 0x329384, + 0x233743, + 0x2aea44, + 0x220583, + 0x2067c3, + 0x205e03, + 0x206b43, + 0x6df83, + 0x23cf83, + 0x4b283, + 0x3487cb, + 0x3c94ca, + 0x3db44c, + 0xe4148, + 0x2000c2, + 0x202782, + 0x200382, + 0x22e1c5, + 0x222884, + 0x2024c2, + 0x205e03, + 0x3216c4, + 0x202642, + 0x2003c2, + 0x202002, + 0x2195c2, + 0x4ce83, + 0x35d82, + 0x2c1f89, + 0x33f688, + 0x2294c9, + 0x21f009, + 0x2b718a, + 0x32324a, + 0x20a602, + 0x2d5e42, + 0x2782, + 0x22d7c3, + 0x22bdc2, + 0x240186, + 0x376cc2, + 0x203742, + 0x26f8ce, + 0x213b8e, + 0x281287, + 0x212ac7, + 0x251bc2, + 0x233743, + 0x220583, + 0x2191c2, + 0x2005c2, + 0x19c83, + 0x23640f, + 0x237542, + 0x355f47, + 0x2b5707, + 0x2c8c47, + 0x2d164c, + 0x2d36cc, + 0x21e404, + 0x25ea0a, + 0x213ac2, + 0x253a42, + 0x2bd1c4, + 0x200702, + 0x2af602, + 0x2d3904, + 0x212302, + 0x200b42, + 0x14903, + 0x29e807, + 0x23f2c5, + 0x20f1c2, + 0x24e144, + 0x201582, + 0x2e3ec8, + 0x206b43, + 0x3754c8, + 0x204082, + 0x21e5c5, + 0x394b06, + 0x23cf83, + 0x206a82, + 0x2f2707, + 0x2102, + 0x3a46c5, + 0x21fe85, + 0x213f82, + 0x202c02, + 0x204d4a, + 0x28320a, + 0x2801c2, + 0x29ce84, + 0x201202, + 0x20bd08, + 0x20a742, + 0x304d48, + 0x314187, + 0x315089, + 0x21ff02, + 0x31a585, + 0x36a1c5, + 0x21a2cb, + 0x2df74c, + 0x22b8c8, + 0x32d788, + 0x22c202, + 0x2a8002, + 0x2000c2, + 0xa14c8, + 0x202782, + 0x22d7c3, + 0x200382, + 0x202642, + 0x13c3, + 0x2003c2, + 0x23cf83, + 0x202002, + 0x2000c2, + 0x12dac5, + 0x78e02782, + 0x79620583, + 0x214903, + 0x2024c2, + 0x206b43, + 0x379083, + 0x79a3cf83, + 0x2ef083, + 0x283dc6, + 0x1602003, + 0x12dac5, + 0x132e0b, + 0xa14c8, + 0x793caf88, + 0x60ac7, + 0x6d807, + 0x45585, + 0xaafcd, + 0x3d142, + 0x119042, + 0xa8a0a, + 0x83047, + 0x256c4, + 0x25703, + 0x1b4904, + 0x7a205342, + 0x7a600b02, + 0x7aa02442, + 0x7ae026c2, + 0x7b20d242, + 0x7b605cc2, + 0x14c47, + 0x7ba02782, + 0x7be2eec2, + 0x7c21ed42, + 0x7c602942, + 0x213b83, + 0x16f44, + 0x2399c3, + 0x7ca0dd82, + 0x5d348, + 0x7ce05282, + 0x71d87, + 0x7d200042, + 0x7d6012c2, + 0x7da00182, + 0x7de067c2, + 0x7e205e42, + 0x7e6005c2, + 0xd8605, + 0x251e03, + 0x39ffc4, + 0x7ea00702, + 0x7ee03942, + 0x7f206ac2, + 0x7af0b, + 0x7f601442, + 0x7fe4ab82, + 0x802024c2, + 0x80605e02, + 0x80a02dc2, + 0x80e00c02, + 0x81200e82, + 0x8166cec2, + 0x81a02a42, + 0x81e09a42, + 0x82202642, + 0x82616202, + 0x82a6ef42, + 0x82e09b42, + 0xb2bc4, + 0x217a43, + 0x8320a302, + 0x836137c2, + 0x83a11b82, + 0x83e006c2, + 0x842003c2, + 0x84601002, + 0x887c7, + 0x84a13c42, + 0x84e04482, + 0x85202002, + 0x85600ec2, + 0x1aed4c, + 0x85a43982, + 0x85e28202, + 0x86203082, + 0x86606842, + 0x86a0a342, + 0x86e76c02, + 0x87205302, + 0x8760adc2, + 0x87a77742, + 0x87e77c82, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x17343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x7fb7fa83, + 0x217343, + 0x360004, + 0x2293c6, + 0x2fe843, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x308b49, + 0x235d82, + 0x3d3c43, + 0x2bbc03, + 0x202ac5, + 0x204183, + 0x37fa83, + 0x217343, + 0x2a6343, + 0x243283, + 0x245b89, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x37fa83, + 0x217343, + 0x235d82, + 0x235d82, + 0x37fa83, + 0x217343, + 0x8862d7c3, + 0x233743, + 0x21f243, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0xa14c8, + 0x202782, + 0x22d7c3, + 0x206b43, + 0x23cf83, + 0x22d7c3, + 0x233743, + 0x220583, + 0x205e03, + 0x206b43, + 0x13c3, + 0x23cf83, + 0x24ec04, + 0x202782, + 0x22d7c3, + 0x309703, + 0x233743, + 0x251184, + 0x228843, + 0x220583, + 0x222884, + 0x219e43, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x25b583, + 0x3da885, + 0x243283, + 0x207b83, + 0x13c3, + 0x202782, + 0x22d7c3, + 0x37fa83, + 0x206b43, + 0x23cf83, + 0x2000c2, + 0x24ce83, + 0xa14c8, + 0x22d7c3, + 0x233743, + 0x220583, + 0x22fac6, + 0x222884, + 0x219e43, + 0x205184, + 0x206b43, + 0x23cf83, + 0x213c43, + 0x22d7c3, + 0x233743, + 0x206b43, + 0x23cf83, + 0x2ebc2, + 0x2b42, + 0x144de07, + 0x492c7, + 0x22d7c3, + 0x29f46, + 0x233743, + 0x220583, + 0xe7e06, + 0x206b43, + 0x23cf83, + 0x329fc8, + 0x32d5c9, + 0x341f49, + 0x34a9c8, + 0x396bc8, + 0x396bc9, + 0x323aca, + 0x35d44a, + 0x391f8a, + 0x39858a, + 0x3c94ca, + 0x3d680b, + 0x24704d, + 0x3676cf, + 0x272190, + 0x35eacd, + 0x37d58c, + 0x3982cb, + 0x6da08, + 0x147d48, + 0xb1005, + 0x1489947, + 0xcd9c5, + 0x2000c2, + 0x2c67c5, + 0x200b03, + 0x8c202782, + 0x233743, + 0x220583, + 0x38d5c7, + 0x20bec3, + 0x205e03, + 0x206b43, + 0x251ac3, + 0x20c243, + 0x2013c3, + 0x23cf83, + 0x259b06, + 0x21be02, + 0x207b83, + 0xa14c8, + 0x2000c2, + 0x24ce83, + 0x202782, + 0x22d7c3, + 0x233743, + 0x220583, + 0x222884, + 0x205e03, + 0x206b43, + 0x23cf83, + 0x202003, + 0x492c7, + 0x131944, + 0x153fd06, + 0x2000c2, + 0x202782, + 0x220583, + 0x205e03, + 0x23cf83, +} + +// children is the list of nodes' children, the parent's wildcard bit and the +// parent's node type. If a node has no children then their children index +// will be in the range [0, 6), depending on the wildcard bit and node type. +// +// The layout within the uint32, from MSB to LSB, is: +// [ 1 bits] unused +// [ 1 bits] wildcard bit +// [ 2 bits] node type +// [14 bits] high nodes index (exclusive) of children +// [14 bits] low nodes index (inclusive) of children +var children = [...]uint32{ + 0x0, + 0x10000000, + 0x20000000, + 0x40000000, + 0x50000000, + 0x60000000, + 0x1824603, + 0x1828609, + 0x182c60a, + 0x185060b, + 0x19ac614, + 0x19c466b, + 0x19d8671, + 0x19f0676, + 0x1a1067c, + 0x1a28684, + 0x1a4068a, + 0x1a58690, + 0x1a5c696, + 0x1a84697, + 0x1a886a1, + 0x1aa06a2, + 0x1aa46a8, + 0x1aa86a9, + 0x1ae46aa, + 0x1ae86b9, + 0x61af06ba, + 0x21af86bc, + 0x1b406be, + 0x1b446d0, + 0x1b646d1, + 0x1b786d9, + 0x1b7c6de, + 0x1bac6df, + 0x1bc86eb, + 0x1bf06f2, + 0x1c006fc, + 0x1c04700, + 0x1c9c701, + 0x1cb0727, + 0x1cc472c, + 0x1cfc731, + 0x1d0c73f, + 0x1d20743, + 0x1d38748, + 0x1ddc74e, + 0x1fe0777, + 0x1fe47f8, + 0x20507f9, + 0x20bc814, + 0x20d482f, + 0x20e8835, + 0x20ec83a, + 0x20f483b, + 0x210883d, + 0x210c842, + 0x2128843, + 0x217884a, + 0x217c85e, + 0x2218085f, + 0x219c860, + 0x21a0867, + 0x21a4868, + 0x21c8869, + 0x2208872, + 0x220c882, + 0x62210883, + 0x2228884, + 0x224888a, + 0x2254892, + 0x2264895, + 0x2318899, + 0x231c8c6, + 0x2232c8c7, + 0x223308cb, + 0x223388cc, + 0x23948ce, + 0x23988e5, + 0x28848e6, + 0x2292ca21, + 0x22930a4b, + 0x22934a4c, + 0x22940a4d, + 0x22944a50, + 0x22950a51, + 0x22954a54, + 0x22958a55, + 0x2295ca56, + 0x22960a57, + 0x22964a58, + 0x22970a59, + 0x22974a5c, + 0x22980a5d, + 0x22984a60, + 0x22988a61, + 0x2298ca62, + 0x22998a63, + 0x2299ca66, + 0x229a8a67, + 0x229aca6a, + 0x229b0a6b, + 0x229b4a6c, + 0x29b8a6d, + 0x229bca6e, + 0x229c8a6f, + 0x229cca72, + 0x29d4a73, + 0x2a18a75, + 0x22a38a86, + 0x22a3ca8e, + 0x22a40a8f, + 0x22a48a90, + 0x22a4ca92, + 0x2a50a93, + 0x22a54a94, + 0x22a58a95, + 0x22a5ca96, + 0x2a64a97, + 0x2a68a99, + 0x2a6ca9a, + 0x2a88a9b, + 0x2aa0aa2, + 0x2aa4aa8, + 0x2ab4aa9, + 0x2ac0aad, + 0x2af4ab0, + 0x2af8abd, + 0x2b10abe, + 0x22b18ac4, + 0x22b1cac6, + 0x22b24ac7, + 0x2c14ac9, + 0x22c18b05, + 0x2c20b06, + 0x2c24b08, + 0x22c28b09, + 0x2c2cb0a, + 0x2c3cb0b, + 0x2c40b0f, + 0x2c44b10, + 0x2c48b11, + 0x2c60b12, + 0x2c74b18, + 0x2c9cb1d, + 0x2cbcb27, + 0x2cc0b2f, + 0x62cc4b30, + 0x2cf4b31, + 0x2cf8b3d, + 0x22cfcb3e, + 0x2d00b3f, + 0x2d28b40, + 0x2d2cb4a, + 0x2d50b4b, + 0x2d54b54, + 0x2d68b55, + 0x2d6cb5a, + 0x2d70b5b, + 0x2d90b5c, + 0x2dacb64, + 0x2db0b6b, + 0x22db4b6c, + 0x2db8b6d, + 0x2dbcb6e, + 0x2dc0b6f, + 0x2dc8b70, + 0x2ddcb72, + 0x2de0b77, + 0x2de4b78, + 0x2de8b79, + 0x2e58b7a, + 0x2e5cb96, + 0x2e60b97, + 0x2e80b98, + 0x2e94ba0, + 0x2ea8ba5, + 0x2ec0baa, + 0x2edcbb0, + 0x2ef4bb7, + 0x2ef8bbd, + 0x2f10bbe, + 0x2f2cbc4, + 0x2f30bcb, + 0x2f50bcc, + 0x2f70bd4, + 0x2f8cbdc, + 0x2fecbe3, + 0x3008bfb, + 0x3018c02, + 0x301cc06, + 0x3034c07, + 0x3078c0d, + 0x30f8c1e, + 0x312cc3e, + 0x3130c4b, + 0x313cc4c, + 0x315cc4f, + 0x3160c57, + 0x3184c58, + 0x318cc61, + 0x31c8c63, + 0x3218c72, + 0x321cc86, + 0x3220c87, + 0x32e4c88, + 0x232e8cb9, + 0x232eccba, + 0x32f0cbb, + 0x232f4cbc, + 0x232f8cbd, + 0x232fccbe, + 0x2330ccbf, + 0x23310cc3, + 0x23314cc4, + 0x23318cc5, + 0x2331ccc6, + 0x3334cc7, + 0x3358ccd, + 0x3378cd6, + 0x39e4cde, + 0x39f0e79, + 0x3a10e7c, + 0x3bd0e84, + 0x3ca0ef4, + 0x3d10f28, + 0x3d68f44, + 0x3e50f5a, + 0x3ea8f94, + 0x3ee4faa, + 0x3fe0fb9, + 0x40acff8, + 0x414502b, + 0x41d5051, + 0x4239075, + 0x447108e, + 0x452911c, + 0x45f514a, + 0x464117d, + 0x46c9190, + 0x47051b2, + 0x47551c1, + 0x47cd1d5, + 0x647d11f3, + 0x647d51f4, + 0x647d91f5, + 0x48551f6, + 0x48b1215, + 0x492d22c, + 0x49a524b, + 0x4a25269, + 0x4a91289, + 0x4bbd2a4, + 0x4c152ef, + 0x64c19305, + 0x4cb1306, + 0x4cb532c, + 0x4d3d32d, + 0x4d8934f, + 0x4df1362, + 0x4e9937c, + 0x4f613a6, + 0x4fc93d8, + 0x50dd3f2, + 0x650e1437, + 0x650e5438, + 0x5141439, + 0x519d450, + 0x522d467, + 0x52a948b, + 0x52ed4aa, + 0x53d14bb, + 0x54054f4, + 0x5465501, + 0x54d9519, + 0x5561536, + 0x55a1558, + 0x5611568, + 0x65615584, + 0x563d585, + 0x564158f, + 0x5659590, + 0x5675596, + 0x56b959d, + 0x56c95ae, + 0x56e15b2, + 0x57595b8, + 0x57615d6, + 0x577d5d8, + 0x57915df, + 0x57ad5e4, + 0x57d95eb, + 0x57dd5f6, + 0x57e55f7, + 0x57f95f9, + 0x58195fe, + 0x5829606, + 0x583560a, + 0x587160d, + 0x587961c, + 0x588d61e, + 0x58b1623, + 0x58bd62c, + 0x58c562f, + 0x58e9631, + 0x590d63a, + 0x5925643, + 0x5929649, + 0x593164a, + 0x593564c, + 0x59d164d, + 0x59d5674, + 0x59d9675, + 0x59dd676, + 0x5a01677, + 0x5a25680, + 0x5a41689, + 0x5a55690, + 0x5a69695, + 0x5a7169a, + 0x5a7969c, + 0x5a8169e, + 0x5a996a0, + 0x5aa96a6, + 0x5aad6aa, + 0x5ac96ab, + 0x63596b2, + 0x63918d6, + 0x63bd8e4, + 0x63d98ef, + 0x63f98f6, + 0x64198fe, + 0x645d906, + 0x6465917, + 0x26469919, + 0x2646d91a, + 0x647591b, + 0x663d91d, + 0x2664198f, + 0x26651990, + 0x26659994, + 0x26665996, + 0x6669999, + 0x2667199a, + 0x668199c, + 0x66a99a0, + 0x66dd9aa, + 0x66e19b7, + 0x67199b8, + 0x67399c6, + 0x72919ce, + 0x7295ca4, + 0x7299ca5, + 0x2729dca6, + 0x72a1ca7, + 0x272a5ca8, + 0x72a9ca9, + 0x272b5caa, + 0x72b9cad, + 0x72bdcae, + 0x272c1caf, + 0x72c5cb0, + 0x272cdcb1, + 0x72d1cb3, + 0x72d5cb4, + 0x272e5cb5, + 0x72e9cb9, + 0x72edcba, + 0x72f1cbb, + 0x72f5cbc, + 0x272f9cbd, + 0x72fdcbe, + 0x7301cbf, + 0x7305cc0, + 0x7309cc1, + 0x27311cc2, + 0x7315cc4, + 0x7319cc5, + 0x731dcc6, + 0x27321cc7, + 0x7325cc8, + 0x2732dcc9, + 0x27331ccb, + 0x734dccc, + 0x7365cd3, + 0x27369cd9, + 0x73adcda, + 0x73b1ceb, + 0x73d5cec, + 0x73e1cf5, + 0x73e5cf8, + 0x73e9cf9, + 0x759dcfa, + 0x275a1d67, + 0x275a9d68, + 0x275add6a, + 0x275b1d6b, + 0x75b9d6c, + 0x7695d6e, + 0x276a1da5, + 0x276a5da8, + 0x276a9da9, + 0x276addaa, + 0x76b1dab, + 0x76dddac, + 0x76e1db7, + 0x76e5db8, + 0x7709db9, + 0x7715dc2, + 0x7735dc5, + 0x7739dcd, + 0x7771dce, + 0x7a21ddc, + 0x7adde88, + 0x7ae1eb7, + 0x7ae5eb8, + 0x7af9eb9, + 0x7b2debe, + 0x7b65ecb, + 0x27b69ed9, + 0x7b85eda, + 0x7badee1, + 0x7bb1eeb, + 0x7bd5eec, + 0x7bf1ef5, + 0x7c19efc, + 0x7c29f06, + 0x7c2df0a, + 0x7c31f0b, + 0x7c69f0c, + 0x7c75f1a, + 0x7c9df1d, + 0x7d1df27, + 0x27d21f47, + 0x7d31f48, + 0x7d3df4c, + 0x7d59f4f, + 0x7d79f56, + 0x7d7df5e, + 0x7d91f5f, + 0x7da5f64, + 0x7da9f69, + 0x7dc9f6a, + 0x7e71f72, + 0x7e75f9c, + 0x7e91f9d, + 0x7eb5fa4, + 0x7eb9fad, + 0x7ec1fae, + 0x7ed9fb0, + 0x7ee1fb6, + 0x7ef5fb8, + 0x7f15fbd, + 0x7f25fc5, + 0x7f31fc9, + 0x7f69fcc, + 0x803dfda, + 0x804200f, + 0x8056010, + 0x805e015, + 0x8076017, + 0x807a01d, + 0x808601e, + 0x808a021, + 0x808e022, + 0x80b2023, + 0x80f202c, + 0x80f603c, + 0x811603d, + 0x8166045, + 0x8182059, + 0x818a060, + 0x81e2062, + 0x81e6078, + 0x81ea079, + 0x81ee07a, + 0x823207b, + 0x824208c, + 0x8282090, + 0x82860a0, + 0x82b60a1, + 0x83fe0ad, + 0x84260ff, + 0x8456109, + 0x8476115, + 0x2847e11d, + 0x848611f, + 0x8492121, + 0x85a6124, + 0x85b2169, + 0x85be16c, + 0x85ca16f, + 0x85d6172, + 0x85e2175, + 0x85ee178, + 0x85fa17b, + 0x860617e, + 0x8612181, + 0x861e184, + 0x862a187, + 0x863618a, + 0x864218d, + 0x864a190, + 0x8656192, + 0x8662195, + 0x866e198, + 0x867a19b, + 0x868619e, + 0x86921a1, + 0x869e1a4, + 0x86aa1a7, + 0x86b61aa, + 0x86c21ad, + 0x86ce1b0, + 0x86fa1b3, + 0x87061be, + 0x87121c1, + 0x871e1c4, + 0x872a1c7, + 0x87361ca, + 0x873e1cd, + 0x874a1cf, + 0x87561d2, + 0x87621d5, + 0x876e1d8, + 0x877a1db, + 0x87861de, + 0x87921e1, + 0x879e1e4, + 0x87aa1e7, + 0x87b61ea, + 0x87c21ed, + 0x87ce1f0, + 0x87da1f3, + 0x87e21f6, + 0x87ee1f8, + 0x87fa1fb, + 0x88061fe, + 0x8812201, + 0x881e204, + 0x882a207, + 0x883620a, + 0x884220d, + 0x8846210, + 0x8852211, + 0x886e214, + 0x887221b, + 0x888221c, + 0x889e220, + 0x88e2227, + 0x88e6238, + 0x88fa239, + 0x892e23e, + 0x893e24b, + 0x894624f, + 0x896a251, + 0x898225a, + 0x899a260, + 0x89b2266, + 0x89c626c, + 0x28a0a271, + 0x8a0e282, + 0x8a3a283, + 0x8a4628e, + 0x8a5a291, +} + +// max children 563 (capacity 1023) +// max text offset 30521 (capacity 32767) +// max text length 36 (capacity 63) +// max hi 8854 (capacity 16383) +// max lo 8849 (capacity 16383) diff --git a/vendor/golang.org/x/net/publicsuffix/table_test.go b/vendor/golang.org/x/net/publicsuffix/table_test.go new file mode 100755 index 0000000000..8fa1cd1f2c --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/table_test.go @@ -0,0 +1,17632 @@ +// generated by go run gen.go; DO NOT EDIT + +package publicsuffix + +const numICANNRules = 7336 + +var rules = [...]string{ + "ac", + "com.ac", + "edu.ac", + "gov.ac", + "net.ac", + "mil.ac", + "org.ac", + "ad", + "nom.ad", + "ae", + "co.ae", + "net.ae", + "org.ae", + "sch.ae", + "ac.ae", + "gov.ae", + "mil.ae", + "aero", + "accident-investigation.aero", + "accident-prevention.aero", + "aerobatic.aero", + "aeroclub.aero", + "aerodrome.aero", + "agents.aero", + "aircraft.aero", + "airline.aero", + "airport.aero", + "air-surveillance.aero", + "airtraffic.aero", + "air-traffic-control.aero", + "ambulance.aero", + "amusement.aero", + "association.aero", + "author.aero", + "ballooning.aero", + "broker.aero", + "caa.aero", + "cargo.aero", + "catering.aero", + "certification.aero", + "championship.aero", + "charter.aero", + "civilaviation.aero", + "club.aero", + "conference.aero", + "consultant.aero", + "consulting.aero", + "control.aero", + "council.aero", + "crew.aero", + "design.aero", + "dgca.aero", + "educator.aero", + "emergency.aero", + "engine.aero", + "engineer.aero", + "entertainment.aero", + "equipment.aero", + "exchange.aero", + "express.aero", + "federation.aero", + "flight.aero", + "freight.aero", + "fuel.aero", + "gliding.aero", + "government.aero", + "groundhandling.aero", + "group.aero", + "hanggliding.aero", + "homebuilt.aero", + "insurance.aero", + "journal.aero", + "journalist.aero", + "leasing.aero", + "logistics.aero", + "magazine.aero", + "maintenance.aero", + "media.aero", + "microlight.aero", + "modelling.aero", + "navigation.aero", + "parachuting.aero", + "paragliding.aero", + "passenger-association.aero", + "pilot.aero", + "press.aero", + "production.aero", + "recreation.aero", + "repbody.aero", + "res.aero", + "research.aero", + "rotorcraft.aero", + "safety.aero", + "scientist.aero", + "services.aero", + "show.aero", + "skydiving.aero", + "software.aero", + "student.aero", + "trader.aero", + "trading.aero", + "trainer.aero", + "union.aero", + "workinggroup.aero", + "works.aero", + "af", + "gov.af", + "com.af", + "org.af", + "net.af", + "edu.af", + "ag", + "com.ag", + "org.ag", + "net.ag", + "co.ag", + "nom.ag", + "ai", + "off.ai", + "com.ai", + "net.ai", + "org.ai", + "al", + "com.al", + "edu.al", + "gov.al", + "mil.al", + "net.al", + "org.al", + "am", + "co.am", + "com.am", + "commune.am", + "net.am", + "org.am", + "ao", + "ed.ao", + "gv.ao", + "og.ao", + "co.ao", + "pb.ao", + "it.ao", + "aq", + "ar", + "com.ar", + "edu.ar", + "gob.ar", + "gov.ar", + "int.ar", + "mil.ar", + "musica.ar", + "net.ar", + "org.ar", + "tur.ar", + "arpa", + "e164.arpa", + "in-addr.arpa", + "ip6.arpa", + "iris.arpa", + "uri.arpa", + "urn.arpa", + "as", + "gov.as", + "asia", + "at", + "ac.at", + "co.at", + "gv.at", + "or.at", + "au", + "com.au", + "net.au", + "org.au", + "edu.au", + "gov.au", + "asn.au", + "id.au", + "info.au", + "conf.au", + "oz.au", + "act.au", + "nsw.au", + "nt.au", + "qld.au", + "sa.au", + "tas.au", + "vic.au", + "wa.au", + "act.edu.au", + "nsw.edu.au", + "nt.edu.au", + "qld.edu.au", + "sa.edu.au", + "tas.edu.au", + "vic.edu.au", + "wa.edu.au", + "qld.gov.au", + "sa.gov.au", + "tas.gov.au", + "vic.gov.au", + "wa.gov.au", + "aw", + "com.aw", + "ax", + "az", + "com.az", + "net.az", + "int.az", + "gov.az", + "org.az", + "edu.az", + "info.az", + "pp.az", + "mil.az", + "name.az", + "pro.az", + "biz.az", + "ba", + "com.ba", + "edu.ba", + "gov.ba", + "mil.ba", + "net.ba", + "org.ba", + "bb", + "biz.bb", + "co.bb", + "com.bb", + "edu.bb", + "gov.bb", + "info.bb", + "net.bb", + "org.bb", + "store.bb", + "tv.bb", + "*.bd", + "be", + "ac.be", + "bf", + "gov.bf", + "bg", + "a.bg", + "b.bg", + "c.bg", + "d.bg", + "e.bg", + "f.bg", + "g.bg", + "h.bg", + "i.bg", + "j.bg", + "k.bg", + "l.bg", + "m.bg", + "n.bg", + "o.bg", + "p.bg", + "q.bg", + "r.bg", + "s.bg", + "t.bg", + "u.bg", + "v.bg", + "w.bg", + "x.bg", + "y.bg", + "z.bg", + "0.bg", + "1.bg", + "2.bg", + "3.bg", + "4.bg", + "5.bg", + "6.bg", + "7.bg", + "8.bg", + "9.bg", + "bh", + "com.bh", + "edu.bh", + "net.bh", + "org.bh", + "gov.bh", + "bi", + "co.bi", + "com.bi", + "edu.bi", + "or.bi", + "org.bi", + "biz", + "bj", + "asso.bj", + "barreau.bj", + "gouv.bj", + "bm", + "com.bm", + "edu.bm", + "gov.bm", + "net.bm", + "org.bm", + "bn", + "com.bn", + "edu.bn", + "gov.bn", + "net.bn", + "org.bn", + "bo", + "com.bo", + "edu.bo", + "gob.bo", + "int.bo", + "org.bo", + "net.bo", + "mil.bo", + "tv.bo", + "web.bo", + "academia.bo", + "agro.bo", + "arte.bo", + "blog.bo", + "bolivia.bo", + "ciencia.bo", + "cooperativa.bo", + "democracia.bo", + "deporte.bo", + "ecologia.bo", + "economia.bo", + "empresa.bo", + "indigena.bo", + "industria.bo", + "info.bo", + "medicina.bo", + "movimiento.bo", + "musica.bo", + "natural.bo", + "nombre.bo", + "noticias.bo", + "patria.bo", + "politica.bo", + "profesional.bo", + "plurinacional.bo", + "pueblo.bo", + "revista.bo", + "salud.bo", + "tecnologia.bo", + "tksat.bo", + "transporte.bo", + "wiki.bo", + "br", + "9guacu.br", + "abc.br", + "adm.br", + "adv.br", + "agr.br", + "aju.br", + "am.br", + "anani.br", + "aparecida.br", + "arq.br", + "art.br", + "ato.br", + "b.br", + "barueri.br", + "belem.br", + "bhz.br", + "bio.br", + "blog.br", + "bmd.br", + "boavista.br", + "bsb.br", + "campinagrande.br", + "campinas.br", + "caxias.br", + "cim.br", + "cng.br", + "cnt.br", + "com.br", + "contagem.br", + "coop.br", + "cri.br", + "cuiaba.br", + "curitiba.br", + "def.br", + "ecn.br", + "eco.br", + "edu.br", + "emp.br", + "eng.br", + "esp.br", + "etc.br", + "eti.br", + "far.br", + "feira.br", + "flog.br", + "floripa.br", + "fm.br", + "fnd.br", + "fortal.br", + "fot.br", + "foz.br", + "fst.br", + "g12.br", + "ggf.br", + "goiania.br", + "gov.br", + "ac.gov.br", + "al.gov.br", + "am.gov.br", + "ap.gov.br", + "ba.gov.br", + "ce.gov.br", + "df.gov.br", + "es.gov.br", + "go.gov.br", + "ma.gov.br", + "mg.gov.br", + "ms.gov.br", + "mt.gov.br", + "pa.gov.br", + "pb.gov.br", + "pe.gov.br", + "pi.gov.br", + "pr.gov.br", + "rj.gov.br", + "rn.gov.br", + "ro.gov.br", + "rr.gov.br", + "rs.gov.br", + "sc.gov.br", + "se.gov.br", + "sp.gov.br", + "to.gov.br", + "gru.br", + "imb.br", + "ind.br", + "inf.br", + "jab.br", + "jampa.br", + "jdf.br", + "joinville.br", + "jor.br", + "jus.br", + "leg.br", + "lel.br", + "londrina.br", + "macapa.br", + "maceio.br", + "manaus.br", + "maringa.br", + "mat.br", + "med.br", + "mil.br", + "morena.br", + "mp.br", + "mus.br", + "natal.br", + "net.br", + "niteroi.br", + "*.nom.br", + "not.br", + "ntr.br", + "odo.br", + "ong.br", + "org.br", + "osasco.br", + "palmas.br", + "poa.br", + "ppg.br", + "pro.br", + "psc.br", + "psi.br", + "pvh.br", + "qsl.br", + "radio.br", + "rec.br", + "recife.br", + "ribeirao.br", + "rio.br", + "riobranco.br", + "riopreto.br", + "salvador.br", + "sampa.br", + "santamaria.br", + "santoandre.br", + "saobernardo.br", + "saogonca.br", + "sjc.br", + "slg.br", + "slz.br", + "sorocaba.br", + "srv.br", + "taxi.br", + "tc.br", + "teo.br", + "the.br", + "tmp.br", + "trd.br", + "tur.br", + "tv.br", + "udi.br", + "vet.br", + "vix.br", + "vlog.br", + "wiki.br", + "zlg.br", + "bs", + "com.bs", + "net.bs", + "org.bs", + "edu.bs", + "gov.bs", + "bt", + "com.bt", + "edu.bt", + "gov.bt", + "net.bt", + "org.bt", + "bv", + "bw", + "co.bw", + "org.bw", + "by", + "gov.by", + "mil.by", + "com.by", + "of.by", + "bz", + "com.bz", + "net.bz", + "org.bz", + "edu.bz", + "gov.bz", + "ca", + "ab.ca", + "bc.ca", + "mb.ca", + "nb.ca", + "nf.ca", + "nl.ca", + "ns.ca", + "nt.ca", + "nu.ca", + "on.ca", + "pe.ca", + "qc.ca", + "sk.ca", + "yk.ca", + "gc.ca", + "cat", + "cc", + "cd", + "gov.cd", + "cf", + "cg", + "ch", + "ci", + "org.ci", + "or.ci", + "com.ci", + "co.ci", + "edu.ci", + "ed.ci", + "ac.ci", + "net.ci", + "go.ci", + "asso.ci", + "xn--aroport-bya.ci", + "int.ci", + "presse.ci", + "md.ci", + "gouv.ci", + "*.ck", + "!www.ck", + "cl", + "gov.cl", + "gob.cl", + "co.cl", + "mil.cl", + "cm", + "co.cm", + "com.cm", + "gov.cm", + "net.cm", + "cn", + "ac.cn", + "com.cn", + "edu.cn", + "gov.cn", + "net.cn", + "org.cn", + "mil.cn", + "xn--55qx5d.cn", + "xn--io0a7i.cn", + "xn--od0alg.cn", + "ah.cn", + "bj.cn", + "cq.cn", + "fj.cn", + "gd.cn", + "gs.cn", + "gz.cn", + "gx.cn", + "ha.cn", + "hb.cn", + "he.cn", + "hi.cn", + "hl.cn", + "hn.cn", + "jl.cn", + "js.cn", + "jx.cn", + "ln.cn", + "nm.cn", + "nx.cn", + "qh.cn", + "sc.cn", + "sd.cn", + "sh.cn", + "sn.cn", + "sx.cn", + "tj.cn", + "xj.cn", + "xz.cn", + "yn.cn", + "zj.cn", + "hk.cn", + "mo.cn", + "tw.cn", + "co", + "arts.co", + "com.co", + "edu.co", + "firm.co", + "gov.co", + "info.co", + "int.co", + "mil.co", + "net.co", + "nom.co", + "org.co", + "rec.co", + "web.co", + "com", + "coop", + "cr", + "ac.cr", + "co.cr", + "ed.cr", + "fi.cr", + "go.cr", + "or.cr", + "sa.cr", + "cu", + "com.cu", + "edu.cu", + "org.cu", + "net.cu", + "gov.cu", + "inf.cu", + "cv", + "cw", + "com.cw", + "edu.cw", + "net.cw", + "org.cw", + "cx", + "gov.cx", + "cy", + "ac.cy", + "biz.cy", + "com.cy", + "ekloges.cy", + "gov.cy", + "ltd.cy", + "name.cy", + "net.cy", + "org.cy", + "parliament.cy", + "press.cy", + "pro.cy", + "tm.cy", + "cz", + "de", + "dj", + "dk", + "dm", + "com.dm", + "net.dm", + "org.dm", + "edu.dm", + "gov.dm", + "do", + "art.do", + "com.do", + "edu.do", + "gob.do", + "gov.do", + "mil.do", + "net.do", + "org.do", + "sld.do", + "web.do", + "dz", + "com.dz", + "org.dz", + "net.dz", + "gov.dz", + "edu.dz", + "asso.dz", + "pol.dz", + "art.dz", + "ec", + "com.ec", + "info.ec", + "net.ec", + "fin.ec", + "k12.ec", + "med.ec", + "pro.ec", + "org.ec", + "edu.ec", + "gov.ec", + "gob.ec", + "mil.ec", + "edu", + "ee", + "edu.ee", + "gov.ee", + "riik.ee", + "lib.ee", + "med.ee", + "com.ee", + "pri.ee", + "aip.ee", + "org.ee", + "fie.ee", + "eg", + "com.eg", + "edu.eg", + "eun.eg", + "gov.eg", + "mil.eg", + "name.eg", + "net.eg", + "org.eg", + "sci.eg", + "*.er", + "es", + "com.es", + "nom.es", + "org.es", + "gob.es", + "edu.es", + "et", + "com.et", + "gov.et", + "org.et", + "edu.et", + "biz.et", + "name.et", + "info.et", + "net.et", + "eu", + "fi", + "aland.fi", + "*.fj", + "*.fk", + "fm", + "fo", + "fr", + "asso.fr", + "com.fr", + "gouv.fr", + "nom.fr", + "prd.fr", + "tm.fr", + "aeroport.fr", + "avocat.fr", + "avoues.fr", + "cci.fr", + "chambagri.fr", + "chirurgiens-dentistes.fr", + "experts-comptables.fr", + "geometre-expert.fr", + "greta.fr", + "huissier-justice.fr", + "medecin.fr", + "notaires.fr", + "pharmacien.fr", + "port.fr", + "veterinaire.fr", + "ga", + "gb", + "gd", + "ge", + "com.ge", + "edu.ge", + "gov.ge", + "org.ge", + "mil.ge", + "net.ge", + "pvt.ge", + "gf", + "gg", + "co.gg", + "net.gg", + "org.gg", + "gh", + "com.gh", + "edu.gh", + "gov.gh", + "org.gh", + "mil.gh", + "gi", + "com.gi", + "ltd.gi", + "gov.gi", + "mod.gi", + "edu.gi", + "org.gi", + "gl", + "co.gl", + "com.gl", + "edu.gl", + "net.gl", + "org.gl", + "gm", + "gn", + "ac.gn", + "com.gn", + "edu.gn", + "gov.gn", + "org.gn", + "net.gn", + "gov", + "gp", + "com.gp", + "net.gp", + "mobi.gp", + "edu.gp", + "org.gp", + "asso.gp", + "gq", + "gr", + "com.gr", + "edu.gr", + "net.gr", + "org.gr", + "gov.gr", + "gs", + "gt", + "com.gt", + "edu.gt", + "gob.gt", + "ind.gt", + "mil.gt", + "net.gt", + "org.gt", + "gu", + "com.gu", + "edu.gu", + "gov.gu", + "guam.gu", + "info.gu", + "net.gu", + "org.gu", + "web.gu", + "gw", + "gy", + "co.gy", + "com.gy", + "edu.gy", + "gov.gy", + "net.gy", + "org.gy", + "hk", + "com.hk", + "edu.hk", + "gov.hk", + "idv.hk", + "net.hk", + "org.hk", + "xn--55qx5d.hk", + "xn--wcvs22d.hk", + "xn--lcvr32d.hk", + "xn--mxtq1m.hk", + "xn--gmqw5a.hk", + "xn--ciqpn.hk", + "xn--gmq050i.hk", + "xn--zf0avx.hk", + "xn--io0a7i.hk", + "xn--mk0axi.hk", + "xn--od0alg.hk", + "xn--od0aq3b.hk", + "xn--tn0ag.hk", + "xn--uc0atv.hk", + "xn--uc0ay4a.hk", + "hm", + "hn", + "com.hn", + "edu.hn", + "org.hn", + "net.hn", + "mil.hn", + "gob.hn", + "hr", + "iz.hr", + "from.hr", + "name.hr", + "com.hr", + "ht", + "com.ht", + "shop.ht", + "firm.ht", + "info.ht", + "adult.ht", + "net.ht", + "pro.ht", + "org.ht", + "med.ht", + "art.ht", + "coop.ht", + "pol.ht", + "asso.ht", + "edu.ht", + "rel.ht", + "gouv.ht", + "perso.ht", + "hu", + "co.hu", + "info.hu", + "org.hu", + "priv.hu", + "sport.hu", + "tm.hu", + "2000.hu", + "agrar.hu", + "bolt.hu", + "casino.hu", + "city.hu", + "erotica.hu", + "erotika.hu", + "film.hu", + "forum.hu", + "games.hu", + "hotel.hu", + "ingatlan.hu", + "jogasz.hu", + "konyvelo.hu", + "lakas.hu", + "media.hu", + "news.hu", + "reklam.hu", + "sex.hu", + "shop.hu", + "suli.hu", + "szex.hu", + "tozsde.hu", + "utazas.hu", + "video.hu", + "id", + "ac.id", + "biz.id", + "co.id", + "desa.id", + "go.id", + "mil.id", + "my.id", + "net.id", + "or.id", + "ponpes.id", + "sch.id", + "web.id", + "ie", + "gov.ie", + "il", + "ac.il", + "co.il", + "gov.il", + "idf.il", + "k12.il", + "muni.il", + "net.il", + "org.il", + "im", + "ac.im", + "co.im", + "com.im", + "ltd.co.im", + "net.im", + "org.im", + "plc.co.im", + "tt.im", + "tv.im", + "in", + "co.in", + "firm.in", + "net.in", + "org.in", + "gen.in", + "ind.in", + "nic.in", + "ac.in", + "edu.in", + "res.in", + "gov.in", + "mil.in", + "info", + "int", + "eu.int", + "io", + "com.io", + "iq", + "gov.iq", + "edu.iq", + "mil.iq", + "com.iq", + "org.iq", + "net.iq", + "ir", + "ac.ir", + "co.ir", + "gov.ir", + "id.ir", + "net.ir", + "org.ir", + "sch.ir", + "xn--mgba3a4f16a.ir", + "xn--mgba3a4fra.ir", + "is", + "net.is", + "com.is", + "edu.is", + "gov.is", + "org.is", + "int.is", + "it", + "gov.it", + "edu.it", + "abr.it", + "abruzzo.it", + "aosta-valley.it", + "aostavalley.it", + "bas.it", + "basilicata.it", + "cal.it", + "calabria.it", + "cam.it", + "campania.it", + "emilia-romagna.it", + "emiliaromagna.it", + "emr.it", + "friuli-v-giulia.it", + "friuli-ve-giulia.it", + "friuli-vegiulia.it", + "friuli-venezia-giulia.it", + "friuli-veneziagiulia.it", + "friuli-vgiulia.it", + "friuliv-giulia.it", + "friulive-giulia.it", + "friulivegiulia.it", + "friulivenezia-giulia.it", + "friuliveneziagiulia.it", + "friulivgiulia.it", + "fvg.it", + "laz.it", + "lazio.it", + "lig.it", + "liguria.it", + "lom.it", + "lombardia.it", + "lombardy.it", + "lucania.it", + "mar.it", + "marche.it", + "mol.it", + "molise.it", + "piedmont.it", + "piemonte.it", + "pmn.it", + "pug.it", + "puglia.it", + "sar.it", + "sardegna.it", + "sardinia.it", + "sic.it", + "sicilia.it", + "sicily.it", + "taa.it", + "tos.it", + "toscana.it", + "trentin-sud-tirol.it", + "xn--trentin-sd-tirol-rzb.it", + "trentin-sudtirol.it", + "xn--trentin-sdtirol-7vb.it", + "trentin-sued-tirol.it", + "trentin-suedtirol.it", + "trentino-a-adige.it", + "trentino-aadige.it", + "trentino-alto-adige.it", + "trentino-altoadige.it", + "trentino-s-tirol.it", + "trentino-stirol.it", + "trentino-sud-tirol.it", + "xn--trentino-sd-tirol-c3b.it", + "trentino-sudtirol.it", + "xn--trentino-sdtirol-szb.it", + "trentino-sued-tirol.it", + "trentino-suedtirol.it", + "trentino.it", + "trentinoa-adige.it", + "trentinoaadige.it", + "trentinoalto-adige.it", + "trentinoaltoadige.it", + "trentinos-tirol.it", + "trentinostirol.it", + "trentinosud-tirol.it", + "xn--trentinosd-tirol-rzb.it", + "trentinosudtirol.it", + "xn--trentinosdtirol-7vb.it", + "trentinosued-tirol.it", + "trentinosuedtirol.it", + "trentinsud-tirol.it", + "xn--trentinsd-tirol-6vb.it", + "trentinsudtirol.it", + "xn--trentinsdtirol-nsb.it", + "trentinsued-tirol.it", + "trentinsuedtirol.it", + "tuscany.it", + "umb.it", + "umbria.it", + "val-d-aosta.it", + "val-daosta.it", + "vald-aosta.it", + "valdaosta.it", + "valle-aosta.it", + "valle-d-aosta.it", + "valle-daosta.it", + "valleaosta.it", + "valled-aosta.it", + "valledaosta.it", + "vallee-aoste.it", + "xn--valle-aoste-ebb.it", + "vallee-d-aoste.it", + "xn--valle-d-aoste-ehb.it", + "valleeaoste.it", + "xn--valleaoste-e7a.it", + "valleedaoste.it", + "xn--valledaoste-ebb.it", + "vao.it", + "vda.it", + "ven.it", + "veneto.it", + "ag.it", + "agrigento.it", + "al.it", + "alessandria.it", + "alto-adige.it", + "altoadige.it", + "an.it", + "ancona.it", + "andria-barletta-trani.it", + "andria-trani-barletta.it", + "andriabarlettatrani.it", + "andriatranibarletta.it", + "ao.it", + "aosta.it", + "aoste.it", + "ap.it", + "aq.it", + "aquila.it", + "ar.it", + "arezzo.it", + "ascoli-piceno.it", + "ascolipiceno.it", + "asti.it", + "at.it", + "av.it", + "avellino.it", + "ba.it", + "balsan-sudtirol.it", + "xn--balsan-sdtirol-nsb.it", + "balsan-suedtirol.it", + "balsan.it", + "bari.it", + "barletta-trani-andria.it", + "barlettatraniandria.it", + "belluno.it", + "benevento.it", + "bergamo.it", + "bg.it", + "bi.it", + "biella.it", + "bl.it", + "bn.it", + "bo.it", + "bologna.it", + "bolzano-altoadige.it", + "bolzano.it", + "bozen-sudtirol.it", + "xn--bozen-sdtirol-2ob.it", + "bozen-suedtirol.it", + "bozen.it", + "br.it", + "brescia.it", + "brindisi.it", + "bs.it", + "bt.it", + "bulsan-sudtirol.it", + "xn--bulsan-sdtirol-nsb.it", + "bulsan-suedtirol.it", + "bulsan.it", + "bz.it", + "ca.it", + "cagliari.it", + "caltanissetta.it", + "campidano-medio.it", + "campidanomedio.it", + "campobasso.it", + "carbonia-iglesias.it", + "carboniaiglesias.it", + "carrara-massa.it", + "carraramassa.it", + "caserta.it", + "catania.it", + "catanzaro.it", + "cb.it", + "ce.it", + "cesena-forli.it", + "xn--cesena-forl-mcb.it", + "cesenaforli.it", + "xn--cesenaforl-i8a.it", + "ch.it", + "chieti.it", + "ci.it", + "cl.it", + "cn.it", + "co.it", + "como.it", + "cosenza.it", + "cr.it", + "cremona.it", + "crotone.it", + "cs.it", + "ct.it", + "cuneo.it", + "cz.it", + "dell-ogliastra.it", + "dellogliastra.it", + "en.it", + "enna.it", + "fc.it", + "fe.it", + "fermo.it", + "ferrara.it", + "fg.it", + "fi.it", + "firenze.it", + "florence.it", + "fm.it", + "foggia.it", + "forli-cesena.it", + "xn--forl-cesena-fcb.it", + "forlicesena.it", + "xn--forlcesena-c8a.it", + "fr.it", + "frosinone.it", + "ge.it", + "genoa.it", + "genova.it", + "go.it", + "gorizia.it", + "gr.it", + "grosseto.it", + "iglesias-carbonia.it", + "iglesiascarbonia.it", + "im.it", + "imperia.it", + "is.it", + "isernia.it", + "kr.it", + "la-spezia.it", + "laquila.it", + "laspezia.it", + "latina.it", + "lc.it", + "le.it", + "lecce.it", + "lecco.it", + "li.it", + "livorno.it", + "lo.it", + "lodi.it", + "lt.it", + "lu.it", + "lucca.it", + "macerata.it", + "mantova.it", + "massa-carrara.it", + "massacarrara.it", + "matera.it", + "mb.it", + "mc.it", + "me.it", + "medio-campidano.it", + "mediocampidano.it", + "messina.it", + "mi.it", + "milan.it", + "milano.it", + "mn.it", + "mo.it", + "modena.it", + "monza-brianza.it", + "monza-e-della-brianza.it", + "monza.it", + "monzabrianza.it", + "monzaebrianza.it", + "monzaedellabrianza.it", + "ms.it", + "mt.it", + "na.it", + "naples.it", + "napoli.it", + "no.it", + "novara.it", + "nu.it", + "nuoro.it", + "og.it", + "ogliastra.it", + "olbia-tempio.it", + "olbiatempio.it", + "or.it", + "oristano.it", + "ot.it", + "pa.it", + "padova.it", + "padua.it", + "palermo.it", + "parma.it", + "pavia.it", + "pc.it", + "pd.it", + "pe.it", + "perugia.it", + "pesaro-urbino.it", + "pesarourbino.it", + "pescara.it", + "pg.it", + "pi.it", + "piacenza.it", + "pisa.it", + "pistoia.it", + "pn.it", + "po.it", + "pordenone.it", + "potenza.it", + "pr.it", + "prato.it", + "pt.it", + "pu.it", + "pv.it", + "pz.it", + "ra.it", + "ragusa.it", + "ravenna.it", + "rc.it", + "re.it", + "reggio-calabria.it", + "reggio-emilia.it", + "reggiocalabria.it", + "reggioemilia.it", + "rg.it", + "ri.it", + "rieti.it", + "rimini.it", + "rm.it", + "rn.it", + "ro.it", + "roma.it", + "rome.it", + "rovigo.it", + "sa.it", + "salerno.it", + "sassari.it", + "savona.it", + "si.it", + "siena.it", + "siracusa.it", + "so.it", + "sondrio.it", + "sp.it", + "sr.it", + "ss.it", + "suedtirol.it", + "xn--sdtirol-n2a.it", + "sv.it", + "ta.it", + "taranto.it", + "te.it", + "tempio-olbia.it", + "tempioolbia.it", + "teramo.it", + "terni.it", + "tn.it", + "to.it", + "torino.it", + "tp.it", + "tr.it", + "trani-andria-barletta.it", + "trani-barletta-andria.it", + "traniandriabarletta.it", + "tranibarlettaandria.it", + "trapani.it", + "trento.it", + "treviso.it", + "trieste.it", + "ts.it", + "turin.it", + "tv.it", + "ud.it", + "udine.it", + "urbino-pesaro.it", + "urbinopesaro.it", + "va.it", + "varese.it", + "vb.it", + "vc.it", + "ve.it", + "venezia.it", + "venice.it", + "verbania.it", + "vercelli.it", + "verona.it", + "vi.it", + "vibo-valentia.it", + "vibovalentia.it", + "vicenza.it", + "viterbo.it", + "vr.it", + "vs.it", + "vt.it", + "vv.it", + "je", + "co.je", + "net.je", + "org.je", + "*.jm", + "jo", + "com.jo", + "org.jo", + "net.jo", + "edu.jo", + "sch.jo", + "gov.jo", + "mil.jo", + "name.jo", + "jobs", + "jp", + "ac.jp", + "ad.jp", + "co.jp", + "ed.jp", + "go.jp", + "gr.jp", + "lg.jp", + "ne.jp", + "or.jp", + "aichi.jp", + "akita.jp", + "aomori.jp", + "chiba.jp", + "ehime.jp", + "fukui.jp", + "fukuoka.jp", + "fukushima.jp", + "gifu.jp", + "gunma.jp", + "hiroshima.jp", + "hokkaido.jp", + "hyogo.jp", + "ibaraki.jp", + "ishikawa.jp", + "iwate.jp", + "kagawa.jp", + "kagoshima.jp", + "kanagawa.jp", + "kochi.jp", + "kumamoto.jp", + "kyoto.jp", + "mie.jp", + "miyagi.jp", + "miyazaki.jp", + "nagano.jp", + "nagasaki.jp", + "nara.jp", + "niigata.jp", + "oita.jp", + "okayama.jp", + "okinawa.jp", + "osaka.jp", + "saga.jp", + "saitama.jp", + "shiga.jp", + "shimane.jp", + "shizuoka.jp", + "tochigi.jp", + "tokushima.jp", + "tokyo.jp", + "tottori.jp", + "toyama.jp", + "wakayama.jp", + "yamagata.jp", + "yamaguchi.jp", + "yamanashi.jp", + "xn--4pvxs.jp", + "xn--vgu402c.jp", + "xn--c3s14m.jp", + "xn--f6qx53a.jp", + "xn--8pvr4u.jp", + "xn--uist22h.jp", + "xn--djrs72d6uy.jp", + "xn--mkru45i.jp", + "xn--0trq7p7nn.jp", + "xn--8ltr62k.jp", + "xn--2m4a15e.jp", + "xn--efvn9s.jp", + "xn--32vp30h.jp", + "xn--4it797k.jp", + "xn--1lqs71d.jp", + "xn--5rtp49c.jp", + "xn--5js045d.jp", + "xn--ehqz56n.jp", + "xn--1lqs03n.jp", + "xn--qqqt11m.jp", + "xn--kbrq7o.jp", + "xn--pssu33l.jp", + "xn--ntsq17g.jp", + "xn--uisz3g.jp", + "xn--6btw5a.jp", + "xn--1ctwo.jp", + "xn--6orx2r.jp", + "xn--rht61e.jp", + "xn--rht27z.jp", + "xn--djty4k.jp", + "xn--nit225k.jp", + "xn--rht3d.jp", + "xn--klty5x.jp", + "xn--kltx9a.jp", + "xn--kltp7d.jp", + "xn--uuwu58a.jp", + "xn--zbx025d.jp", + "xn--ntso0iqx3a.jp", + "xn--elqq16h.jp", + "xn--4it168d.jp", + "xn--klt787d.jp", + "xn--rny31h.jp", + "xn--7t0a264c.jp", + "xn--5rtq34k.jp", + "xn--k7yn95e.jp", + "xn--tor131o.jp", + "xn--d5qv7z876c.jp", + "*.kawasaki.jp", + "*.kitakyushu.jp", + "*.kobe.jp", + "*.nagoya.jp", + "*.sapporo.jp", + "*.sendai.jp", + "*.yokohama.jp", + "!city.kawasaki.jp", + "!city.kitakyushu.jp", + "!city.kobe.jp", + "!city.nagoya.jp", + "!city.sapporo.jp", + "!city.sendai.jp", + "!city.yokohama.jp", + "aisai.aichi.jp", + "ama.aichi.jp", + "anjo.aichi.jp", + "asuke.aichi.jp", + "chiryu.aichi.jp", + "chita.aichi.jp", + "fuso.aichi.jp", + "gamagori.aichi.jp", + "handa.aichi.jp", + "hazu.aichi.jp", + "hekinan.aichi.jp", + "higashiura.aichi.jp", + "ichinomiya.aichi.jp", + "inazawa.aichi.jp", + "inuyama.aichi.jp", + "isshiki.aichi.jp", + "iwakura.aichi.jp", + "kanie.aichi.jp", + "kariya.aichi.jp", + "kasugai.aichi.jp", + "kira.aichi.jp", + "kiyosu.aichi.jp", + "komaki.aichi.jp", + "konan.aichi.jp", + "kota.aichi.jp", + "mihama.aichi.jp", + "miyoshi.aichi.jp", + "nishio.aichi.jp", + "nisshin.aichi.jp", + "obu.aichi.jp", + "oguchi.aichi.jp", + "oharu.aichi.jp", + "okazaki.aichi.jp", + "owariasahi.aichi.jp", + "seto.aichi.jp", + "shikatsu.aichi.jp", + "shinshiro.aichi.jp", + "shitara.aichi.jp", + "tahara.aichi.jp", + "takahama.aichi.jp", + "tobishima.aichi.jp", + "toei.aichi.jp", + "togo.aichi.jp", + "tokai.aichi.jp", + "tokoname.aichi.jp", + "toyoake.aichi.jp", + "toyohashi.aichi.jp", + "toyokawa.aichi.jp", + "toyone.aichi.jp", + "toyota.aichi.jp", + "tsushima.aichi.jp", + "yatomi.aichi.jp", + "akita.akita.jp", + "daisen.akita.jp", + "fujisato.akita.jp", + "gojome.akita.jp", + "hachirogata.akita.jp", + "happou.akita.jp", + "higashinaruse.akita.jp", + "honjo.akita.jp", + "honjyo.akita.jp", + "ikawa.akita.jp", + "kamikoani.akita.jp", + "kamioka.akita.jp", + "katagami.akita.jp", + "kazuno.akita.jp", + "kitaakita.akita.jp", + "kosaka.akita.jp", + "kyowa.akita.jp", + "misato.akita.jp", + "mitane.akita.jp", + "moriyoshi.akita.jp", + "nikaho.akita.jp", + "noshiro.akita.jp", + "odate.akita.jp", + "oga.akita.jp", + "ogata.akita.jp", + "semboku.akita.jp", + "yokote.akita.jp", + "yurihonjo.akita.jp", + "aomori.aomori.jp", + "gonohe.aomori.jp", + "hachinohe.aomori.jp", + "hashikami.aomori.jp", + "hiranai.aomori.jp", + "hirosaki.aomori.jp", + "itayanagi.aomori.jp", + "kuroishi.aomori.jp", + "misawa.aomori.jp", + "mutsu.aomori.jp", + "nakadomari.aomori.jp", + "noheji.aomori.jp", + "oirase.aomori.jp", + "owani.aomori.jp", + "rokunohe.aomori.jp", + "sannohe.aomori.jp", + "shichinohe.aomori.jp", + "shingo.aomori.jp", + "takko.aomori.jp", + "towada.aomori.jp", + "tsugaru.aomori.jp", + "tsuruta.aomori.jp", + "abiko.chiba.jp", + "asahi.chiba.jp", + "chonan.chiba.jp", + "chosei.chiba.jp", + "choshi.chiba.jp", + "chuo.chiba.jp", + "funabashi.chiba.jp", + "futtsu.chiba.jp", + "hanamigawa.chiba.jp", + "ichihara.chiba.jp", + "ichikawa.chiba.jp", + "ichinomiya.chiba.jp", + "inzai.chiba.jp", + "isumi.chiba.jp", + "kamagaya.chiba.jp", + "kamogawa.chiba.jp", + "kashiwa.chiba.jp", + "katori.chiba.jp", + "katsuura.chiba.jp", + "kimitsu.chiba.jp", + "kisarazu.chiba.jp", + "kozaki.chiba.jp", + "kujukuri.chiba.jp", + "kyonan.chiba.jp", + "matsudo.chiba.jp", + "midori.chiba.jp", + "mihama.chiba.jp", + "minamiboso.chiba.jp", + "mobara.chiba.jp", + "mutsuzawa.chiba.jp", + "nagara.chiba.jp", + "nagareyama.chiba.jp", + "narashino.chiba.jp", + "narita.chiba.jp", + "noda.chiba.jp", + "oamishirasato.chiba.jp", + "omigawa.chiba.jp", + "onjuku.chiba.jp", + "otaki.chiba.jp", + "sakae.chiba.jp", + "sakura.chiba.jp", + "shimofusa.chiba.jp", + "shirako.chiba.jp", + "shiroi.chiba.jp", + "shisui.chiba.jp", + "sodegaura.chiba.jp", + "sosa.chiba.jp", + "tako.chiba.jp", + "tateyama.chiba.jp", + "togane.chiba.jp", + "tohnosho.chiba.jp", + "tomisato.chiba.jp", + "urayasu.chiba.jp", + "yachimata.chiba.jp", + "yachiyo.chiba.jp", + "yokaichiba.chiba.jp", + "yokoshibahikari.chiba.jp", + "yotsukaido.chiba.jp", + "ainan.ehime.jp", + "honai.ehime.jp", + "ikata.ehime.jp", + "imabari.ehime.jp", + "iyo.ehime.jp", + "kamijima.ehime.jp", + "kihoku.ehime.jp", + "kumakogen.ehime.jp", + "masaki.ehime.jp", + "matsuno.ehime.jp", + "matsuyama.ehime.jp", + "namikata.ehime.jp", + "niihama.ehime.jp", + "ozu.ehime.jp", + "saijo.ehime.jp", + "seiyo.ehime.jp", + "shikokuchuo.ehime.jp", + "tobe.ehime.jp", + "toon.ehime.jp", + "uchiko.ehime.jp", + "uwajima.ehime.jp", + "yawatahama.ehime.jp", + "echizen.fukui.jp", + "eiheiji.fukui.jp", + "fukui.fukui.jp", + "ikeda.fukui.jp", + "katsuyama.fukui.jp", + "mihama.fukui.jp", + "minamiechizen.fukui.jp", + "obama.fukui.jp", + "ohi.fukui.jp", + "ono.fukui.jp", + "sabae.fukui.jp", + "sakai.fukui.jp", + "takahama.fukui.jp", + "tsuruga.fukui.jp", + "wakasa.fukui.jp", + "ashiya.fukuoka.jp", + "buzen.fukuoka.jp", + "chikugo.fukuoka.jp", + "chikuho.fukuoka.jp", + "chikujo.fukuoka.jp", + "chikushino.fukuoka.jp", + "chikuzen.fukuoka.jp", + "chuo.fukuoka.jp", + "dazaifu.fukuoka.jp", + "fukuchi.fukuoka.jp", + "hakata.fukuoka.jp", + "higashi.fukuoka.jp", + "hirokawa.fukuoka.jp", + "hisayama.fukuoka.jp", + "iizuka.fukuoka.jp", + "inatsuki.fukuoka.jp", + "kaho.fukuoka.jp", + "kasuga.fukuoka.jp", + "kasuya.fukuoka.jp", + "kawara.fukuoka.jp", + "keisen.fukuoka.jp", + "koga.fukuoka.jp", + "kurate.fukuoka.jp", + "kurogi.fukuoka.jp", + "kurume.fukuoka.jp", + "minami.fukuoka.jp", + "miyako.fukuoka.jp", + "miyama.fukuoka.jp", + "miyawaka.fukuoka.jp", + "mizumaki.fukuoka.jp", + "munakata.fukuoka.jp", + "nakagawa.fukuoka.jp", + "nakama.fukuoka.jp", + "nishi.fukuoka.jp", + "nogata.fukuoka.jp", + "ogori.fukuoka.jp", + "okagaki.fukuoka.jp", + "okawa.fukuoka.jp", + "oki.fukuoka.jp", + "omuta.fukuoka.jp", + "onga.fukuoka.jp", + "onojo.fukuoka.jp", + "oto.fukuoka.jp", + "saigawa.fukuoka.jp", + "sasaguri.fukuoka.jp", + "shingu.fukuoka.jp", + "shinyoshitomi.fukuoka.jp", + "shonai.fukuoka.jp", + "soeda.fukuoka.jp", + "sue.fukuoka.jp", + "tachiarai.fukuoka.jp", + "tagawa.fukuoka.jp", + "takata.fukuoka.jp", + "toho.fukuoka.jp", + "toyotsu.fukuoka.jp", + "tsuiki.fukuoka.jp", + "ukiha.fukuoka.jp", + "umi.fukuoka.jp", + "usui.fukuoka.jp", + "yamada.fukuoka.jp", + "yame.fukuoka.jp", + "yanagawa.fukuoka.jp", + "yukuhashi.fukuoka.jp", + "aizubange.fukushima.jp", + "aizumisato.fukushima.jp", + "aizuwakamatsu.fukushima.jp", + "asakawa.fukushima.jp", + "bandai.fukushima.jp", + "date.fukushima.jp", + "fukushima.fukushima.jp", + "furudono.fukushima.jp", + "futaba.fukushima.jp", + "hanawa.fukushima.jp", + "higashi.fukushima.jp", + "hirata.fukushima.jp", + "hirono.fukushima.jp", + "iitate.fukushima.jp", + "inawashiro.fukushima.jp", + "ishikawa.fukushima.jp", + "iwaki.fukushima.jp", + "izumizaki.fukushima.jp", + "kagamiishi.fukushima.jp", + "kaneyama.fukushima.jp", + "kawamata.fukushima.jp", + "kitakata.fukushima.jp", + "kitashiobara.fukushima.jp", + "koori.fukushima.jp", + "koriyama.fukushima.jp", + "kunimi.fukushima.jp", + "miharu.fukushima.jp", + "mishima.fukushima.jp", + "namie.fukushima.jp", + "nango.fukushima.jp", + "nishiaizu.fukushima.jp", + "nishigo.fukushima.jp", + "okuma.fukushima.jp", + "omotego.fukushima.jp", + "ono.fukushima.jp", + "otama.fukushima.jp", + "samegawa.fukushima.jp", + "shimogo.fukushima.jp", + "shirakawa.fukushima.jp", + "showa.fukushima.jp", + "soma.fukushima.jp", + "sukagawa.fukushima.jp", + "taishin.fukushima.jp", + "tamakawa.fukushima.jp", + "tanagura.fukushima.jp", + "tenei.fukushima.jp", + "yabuki.fukushima.jp", + "yamato.fukushima.jp", + "yamatsuri.fukushima.jp", + "yanaizu.fukushima.jp", + "yugawa.fukushima.jp", + "anpachi.gifu.jp", + "ena.gifu.jp", + "gifu.gifu.jp", + "ginan.gifu.jp", + "godo.gifu.jp", + "gujo.gifu.jp", + "hashima.gifu.jp", + "hichiso.gifu.jp", + "hida.gifu.jp", + "higashishirakawa.gifu.jp", + "ibigawa.gifu.jp", + "ikeda.gifu.jp", + "kakamigahara.gifu.jp", + "kani.gifu.jp", + "kasahara.gifu.jp", + "kasamatsu.gifu.jp", + "kawaue.gifu.jp", + "kitagata.gifu.jp", + "mino.gifu.jp", + "minokamo.gifu.jp", + "mitake.gifu.jp", + "mizunami.gifu.jp", + "motosu.gifu.jp", + "nakatsugawa.gifu.jp", + "ogaki.gifu.jp", + "sakahogi.gifu.jp", + "seki.gifu.jp", + "sekigahara.gifu.jp", + "shirakawa.gifu.jp", + "tajimi.gifu.jp", + "takayama.gifu.jp", + "tarui.gifu.jp", + "toki.gifu.jp", + "tomika.gifu.jp", + "wanouchi.gifu.jp", + "yamagata.gifu.jp", + "yaotsu.gifu.jp", + "yoro.gifu.jp", + "annaka.gunma.jp", + "chiyoda.gunma.jp", + "fujioka.gunma.jp", + "higashiagatsuma.gunma.jp", + "isesaki.gunma.jp", + "itakura.gunma.jp", + "kanna.gunma.jp", + "kanra.gunma.jp", + "katashina.gunma.jp", + "kawaba.gunma.jp", + "kiryu.gunma.jp", + "kusatsu.gunma.jp", + "maebashi.gunma.jp", + "meiwa.gunma.jp", + "midori.gunma.jp", + "minakami.gunma.jp", + "naganohara.gunma.jp", + "nakanojo.gunma.jp", + "nanmoku.gunma.jp", + "numata.gunma.jp", + "oizumi.gunma.jp", + "ora.gunma.jp", + "ota.gunma.jp", + "shibukawa.gunma.jp", + "shimonita.gunma.jp", + "shinto.gunma.jp", + "showa.gunma.jp", + "takasaki.gunma.jp", + "takayama.gunma.jp", + "tamamura.gunma.jp", + "tatebayashi.gunma.jp", + "tomioka.gunma.jp", + "tsukiyono.gunma.jp", + "tsumagoi.gunma.jp", + "ueno.gunma.jp", + "yoshioka.gunma.jp", + "asaminami.hiroshima.jp", + "daiwa.hiroshima.jp", + "etajima.hiroshima.jp", + "fuchu.hiroshima.jp", + "fukuyama.hiroshima.jp", + "hatsukaichi.hiroshima.jp", + "higashihiroshima.hiroshima.jp", + "hongo.hiroshima.jp", + "jinsekikogen.hiroshima.jp", + "kaita.hiroshima.jp", + "kui.hiroshima.jp", + "kumano.hiroshima.jp", + "kure.hiroshima.jp", + "mihara.hiroshima.jp", + "miyoshi.hiroshima.jp", + "naka.hiroshima.jp", + "onomichi.hiroshima.jp", + "osakikamijima.hiroshima.jp", + "otake.hiroshima.jp", + "saka.hiroshima.jp", + "sera.hiroshima.jp", + "seranishi.hiroshima.jp", + "shinichi.hiroshima.jp", + "shobara.hiroshima.jp", + "takehara.hiroshima.jp", + "abashiri.hokkaido.jp", + "abira.hokkaido.jp", + "aibetsu.hokkaido.jp", + "akabira.hokkaido.jp", + "akkeshi.hokkaido.jp", + "asahikawa.hokkaido.jp", + "ashibetsu.hokkaido.jp", + "ashoro.hokkaido.jp", + "assabu.hokkaido.jp", + "atsuma.hokkaido.jp", + "bibai.hokkaido.jp", + "biei.hokkaido.jp", + "bifuka.hokkaido.jp", + "bihoro.hokkaido.jp", + "biratori.hokkaido.jp", + "chippubetsu.hokkaido.jp", + "chitose.hokkaido.jp", + "date.hokkaido.jp", + "ebetsu.hokkaido.jp", + "embetsu.hokkaido.jp", + "eniwa.hokkaido.jp", + "erimo.hokkaido.jp", + "esan.hokkaido.jp", + "esashi.hokkaido.jp", + "fukagawa.hokkaido.jp", + "fukushima.hokkaido.jp", + "furano.hokkaido.jp", + "furubira.hokkaido.jp", + "haboro.hokkaido.jp", + "hakodate.hokkaido.jp", + "hamatonbetsu.hokkaido.jp", + "hidaka.hokkaido.jp", + "higashikagura.hokkaido.jp", + "higashikawa.hokkaido.jp", + "hiroo.hokkaido.jp", + "hokuryu.hokkaido.jp", + "hokuto.hokkaido.jp", + "honbetsu.hokkaido.jp", + "horokanai.hokkaido.jp", + "horonobe.hokkaido.jp", + "ikeda.hokkaido.jp", + "imakane.hokkaido.jp", + "ishikari.hokkaido.jp", + "iwamizawa.hokkaido.jp", + "iwanai.hokkaido.jp", + "kamifurano.hokkaido.jp", + "kamikawa.hokkaido.jp", + "kamishihoro.hokkaido.jp", + "kamisunagawa.hokkaido.jp", + "kamoenai.hokkaido.jp", + "kayabe.hokkaido.jp", + "kembuchi.hokkaido.jp", + "kikonai.hokkaido.jp", + "kimobetsu.hokkaido.jp", + "kitahiroshima.hokkaido.jp", + "kitami.hokkaido.jp", + "kiyosato.hokkaido.jp", + "koshimizu.hokkaido.jp", + "kunneppu.hokkaido.jp", + "kuriyama.hokkaido.jp", + "kuromatsunai.hokkaido.jp", + "kushiro.hokkaido.jp", + "kutchan.hokkaido.jp", + "kyowa.hokkaido.jp", + "mashike.hokkaido.jp", + "matsumae.hokkaido.jp", + "mikasa.hokkaido.jp", + "minamifurano.hokkaido.jp", + "mombetsu.hokkaido.jp", + "moseushi.hokkaido.jp", + "mukawa.hokkaido.jp", + "muroran.hokkaido.jp", + "naie.hokkaido.jp", + "nakagawa.hokkaido.jp", + "nakasatsunai.hokkaido.jp", + "nakatombetsu.hokkaido.jp", + "nanae.hokkaido.jp", + "nanporo.hokkaido.jp", + "nayoro.hokkaido.jp", + "nemuro.hokkaido.jp", + "niikappu.hokkaido.jp", + "niki.hokkaido.jp", + "nishiokoppe.hokkaido.jp", + "noboribetsu.hokkaido.jp", + "numata.hokkaido.jp", + "obihiro.hokkaido.jp", + "obira.hokkaido.jp", + "oketo.hokkaido.jp", + "okoppe.hokkaido.jp", + "otaru.hokkaido.jp", + "otobe.hokkaido.jp", + "otofuke.hokkaido.jp", + "otoineppu.hokkaido.jp", + "oumu.hokkaido.jp", + "ozora.hokkaido.jp", + "pippu.hokkaido.jp", + "rankoshi.hokkaido.jp", + "rebun.hokkaido.jp", + "rikubetsu.hokkaido.jp", + "rishiri.hokkaido.jp", + "rishirifuji.hokkaido.jp", + "saroma.hokkaido.jp", + "sarufutsu.hokkaido.jp", + "shakotan.hokkaido.jp", + "shari.hokkaido.jp", + "shibecha.hokkaido.jp", + "shibetsu.hokkaido.jp", + "shikabe.hokkaido.jp", + "shikaoi.hokkaido.jp", + "shimamaki.hokkaido.jp", + "shimizu.hokkaido.jp", + "shimokawa.hokkaido.jp", + "shinshinotsu.hokkaido.jp", + "shintoku.hokkaido.jp", + "shiranuka.hokkaido.jp", + "shiraoi.hokkaido.jp", + "shiriuchi.hokkaido.jp", + "sobetsu.hokkaido.jp", + "sunagawa.hokkaido.jp", + "taiki.hokkaido.jp", + "takasu.hokkaido.jp", + "takikawa.hokkaido.jp", + "takinoue.hokkaido.jp", + "teshikaga.hokkaido.jp", + "tobetsu.hokkaido.jp", + "tohma.hokkaido.jp", + "tomakomai.hokkaido.jp", + "tomari.hokkaido.jp", + "toya.hokkaido.jp", + "toyako.hokkaido.jp", + "toyotomi.hokkaido.jp", + "toyoura.hokkaido.jp", + "tsubetsu.hokkaido.jp", + "tsukigata.hokkaido.jp", + "urakawa.hokkaido.jp", + "urausu.hokkaido.jp", + "uryu.hokkaido.jp", + "utashinai.hokkaido.jp", + "wakkanai.hokkaido.jp", + "wassamu.hokkaido.jp", + "yakumo.hokkaido.jp", + "yoichi.hokkaido.jp", + "aioi.hyogo.jp", + "akashi.hyogo.jp", + "ako.hyogo.jp", + "amagasaki.hyogo.jp", + "aogaki.hyogo.jp", + "asago.hyogo.jp", + "ashiya.hyogo.jp", + "awaji.hyogo.jp", + "fukusaki.hyogo.jp", + "goshiki.hyogo.jp", + "harima.hyogo.jp", + "himeji.hyogo.jp", + "ichikawa.hyogo.jp", + "inagawa.hyogo.jp", + "itami.hyogo.jp", + "kakogawa.hyogo.jp", + "kamigori.hyogo.jp", + "kamikawa.hyogo.jp", + "kasai.hyogo.jp", + "kasuga.hyogo.jp", + "kawanishi.hyogo.jp", + "miki.hyogo.jp", + "minamiawaji.hyogo.jp", + "nishinomiya.hyogo.jp", + "nishiwaki.hyogo.jp", + "ono.hyogo.jp", + "sanda.hyogo.jp", + "sannan.hyogo.jp", + "sasayama.hyogo.jp", + "sayo.hyogo.jp", + "shingu.hyogo.jp", + "shinonsen.hyogo.jp", + "shiso.hyogo.jp", + "sumoto.hyogo.jp", + "taishi.hyogo.jp", + "taka.hyogo.jp", + "takarazuka.hyogo.jp", + "takasago.hyogo.jp", + "takino.hyogo.jp", + "tamba.hyogo.jp", + "tatsuno.hyogo.jp", + "toyooka.hyogo.jp", + "yabu.hyogo.jp", + "yashiro.hyogo.jp", + "yoka.hyogo.jp", + "yokawa.hyogo.jp", + "ami.ibaraki.jp", + "asahi.ibaraki.jp", + "bando.ibaraki.jp", + "chikusei.ibaraki.jp", + "daigo.ibaraki.jp", + "fujishiro.ibaraki.jp", + "hitachi.ibaraki.jp", + "hitachinaka.ibaraki.jp", + "hitachiomiya.ibaraki.jp", + "hitachiota.ibaraki.jp", + "ibaraki.ibaraki.jp", + "ina.ibaraki.jp", + "inashiki.ibaraki.jp", + "itako.ibaraki.jp", + "iwama.ibaraki.jp", + "joso.ibaraki.jp", + "kamisu.ibaraki.jp", + "kasama.ibaraki.jp", + "kashima.ibaraki.jp", + "kasumigaura.ibaraki.jp", + "koga.ibaraki.jp", + "miho.ibaraki.jp", + "mito.ibaraki.jp", + "moriya.ibaraki.jp", + "naka.ibaraki.jp", + "namegata.ibaraki.jp", + "oarai.ibaraki.jp", + "ogawa.ibaraki.jp", + "omitama.ibaraki.jp", + "ryugasaki.ibaraki.jp", + "sakai.ibaraki.jp", + "sakuragawa.ibaraki.jp", + "shimodate.ibaraki.jp", + "shimotsuma.ibaraki.jp", + "shirosato.ibaraki.jp", + "sowa.ibaraki.jp", + "suifu.ibaraki.jp", + "takahagi.ibaraki.jp", + "tamatsukuri.ibaraki.jp", + "tokai.ibaraki.jp", + "tomobe.ibaraki.jp", + "tone.ibaraki.jp", + "toride.ibaraki.jp", + "tsuchiura.ibaraki.jp", + "tsukuba.ibaraki.jp", + "uchihara.ibaraki.jp", + "ushiku.ibaraki.jp", + "yachiyo.ibaraki.jp", + "yamagata.ibaraki.jp", + "yawara.ibaraki.jp", + "yuki.ibaraki.jp", + "anamizu.ishikawa.jp", + "hakui.ishikawa.jp", + "hakusan.ishikawa.jp", + "kaga.ishikawa.jp", + "kahoku.ishikawa.jp", + "kanazawa.ishikawa.jp", + "kawakita.ishikawa.jp", + "komatsu.ishikawa.jp", + "nakanoto.ishikawa.jp", + "nanao.ishikawa.jp", + "nomi.ishikawa.jp", + "nonoichi.ishikawa.jp", + "noto.ishikawa.jp", + "shika.ishikawa.jp", + "suzu.ishikawa.jp", + "tsubata.ishikawa.jp", + "tsurugi.ishikawa.jp", + "uchinada.ishikawa.jp", + "wajima.ishikawa.jp", + "fudai.iwate.jp", + "fujisawa.iwate.jp", + "hanamaki.iwate.jp", + "hiraizumi.iwate.jp", + "hirono.iwate.jp", + "ichinohe.iwate.jp", + "ichinoseki.iwate.jp", + "iwaizumi.iwate.jp", + "iwate.iwate.jp", + "joboji.iwate.jp", + "kamaishi.iwate.jp", + "kanegasaki.iwate.jp", + "karumai.iwate.jp", + "kawai.iwate.jp", + "kitakami.iwate.jp", + "kuji.iwate.jp", + "kunohe.iwate.jp", + "kuzumaki.iwate.jp", + "miyako.iwate.jp", + "mizusawa.iwate.jp", + "morioka.iwate.jp", + "ninohe.iwate.jp", + "noda.iwate.jp", + "ofunato.iwate.jp", + "oshu.iwate.jp", + "otsuchi.iwate.jp", + "rikuzentakata.iwate.jp", + "shiwa.iwate.jp", + "shizukuishi.iwate.jp", + "sumita.iwate.jp", + "tanohata.iwate.jp", + "tono.iwate.jp", + "yahaba.iwate.jp", + "yamada.iwate.jp", + "ayagawa.kagawa.jp", + "higashikagawa.kagawa.jp", + "kanonji.kagawa.jp", + "kotohira.kagawa.jp", + "manno.kagawa.jp", + "marugame.kagawa.jp", + "mitoyo.kagawa.jp", + "naoshima.kagawa.jp", + "sanuki.kagawa.jp", + "tadotsu.kagawa.jp", + "takamatsu.kagawa.jp", + "tonosho.kagawa.jp", + "uchinomi.kagawa.jp", + "utazu.kagawa.jp", + "zentsuji.kagawa.jp", + "akune.kagoshima.jp", + "amami.kagoshima.jp", + "hioki.kagoshima.jp", + "isa.kagoshima.jp", + "isen.kagoshima.jp", + "izumi.kagoshima.jp", + "kagoshima.kagoshima.jp", + "kanoya.kagoshima.jp", + "kawanabe.kagoshima.jp", + "kinko.kagoshima.jp", + "kouyama.kagoshima.jp", + "makurazaki.kagoshima.jp", + "matsumoto.kagoshima.jp", + "minamitane.kagoshima.jp", + "nakatane.kagoshima.jp", + "nishinoomote.kagoshima.jp", + "satsumasendai.kagoshima.jp", + "soo.kagoshima.jp", + "tarumizu.kagoshima.jp", + "yusui.kagoshima.jp", + "aikawa.kanagawa.jp", + "atsugi.kanagawa.jp", + "ayase.kanagawa.jp", + "chigasaki.kanagawa.jp", + "ebina.kanagawa.jp", + "fujisawa.kanagawa.jp", + "hadano.kanagawa.jp", + "hakone.kanagawa.jp", + "hiratsuka.kanagawa.jp", + "isehara.kanagawa.jp", + "kaisei.kanagawa.jp", + "kamakura.kanagawa.jp", + "kiyokawa.kanagawa.jp", + "matsuda.kanagawa.jp", + "minamiashigara.kanagawa.jp", + "miura.kanagawa.jp", + "nakai.kanagawa.jp", + "ninomiya.kanagawa.jp", + "odawara.kanagawa.jp", + "oi.kanagawa.jp", + "oiso.kanagawa.jp", + "sagamihara.kanagawa.jp", + "samukawa.kanagawa.jp", + "tsukui.kanagawa.jp", + "yamakita.kanagawa.jp", + "yamato.kanagawa.jp", + "yokosuka.kanagawa.jp", + "yugawara.kanagawa.jp", + "zama.kanagawa.jp", + "zushi.kanagawa.jp", + "aki.kochi.jp", + "geisei.kochi.jp", + "hidaka.kochi.jp", + "higashitsuno.kochi.jp", + "ino.kochi.jp", + "kagami.kochi.jp", + "kami.kochi.jp", + "kitagawa.kochi.jp", + "kochi.kochi.jp", + "mihara.kochi.jp", + "motoyama.kochi.jp", + "muroto.kochi.jp", + "nahari.kochi.jp", + "nakamura.kochi.jp", + "nankoku.kochi.jp", + "nishitosa.kochi.jp", + "niyodogawa.kochi.jp", + "ochi.kochi.jp", + "okawa.kochi.jp", + "otoyo.kochi.jp", + "otsuki.kochi.jp", + "sakawa.kochi.jp", + "sukumo.kochi.jp", + "susaki.kochi.jp", + "tosa.kochi.jp", + "tosashimizu.kochi.jp", + "toyo.kochi.jp", + "tsuno.kochi.jp", + "umaji.kochi.jp", + "yasuda.kochi.jp", + "yusuhara.kochi.jp", + "amakusa.kumamoto.jp", + "arao.kumamoto.jp", + "aso.kumamoto.jp", + "choyo.kumamoto.jp", + "gyokuto.kumamoto.jp", + "kamiamakusa.kumamoto.jp", + "kikuchi.kumamoto.jp", + "kumamoto.kumamoto.jp", + "mashiki.kumamoto.jp", + "mifune.kumamoto.jp", + "minamata.kumamoto.jp", + "minamioguni.kumamoto.jp", + "nagasu.kumamoto.jp", + "nishihara.kumamoto.jp", + "oguni.kumamoto.jp", + "ozu.kumamoto.jp", + "sumoto.kumamoto.jp", + "takamori.kumamoto.jp", + "uki.kumamoto.jp", + "uto.kumamoto.jp", + "yamaga.kumamoto.jp", + "yamato.kumamoto.jp", + "yatsushiro.kumamoto.jp", + "ayabe.kyoto.jp", + "fukuchiyama.kyoto.jp", + "higashiyama.kyoto.jp", + "ide.kyoto.jp", + "ine.kyoto.jp", + "joyo.kyoto.jp", + "kameoka.kyoto.jp", + "kamo.kyoto.jp", + "kita.kyoto.jp", + "kizu.kyoto.jp", + "kumiyama.kyoto.jp", + "kyotamba.kyoto.jp", + "kyotanabe.kyoto.jp", + "kyotango.kyoto.jp", + "maizuru.kyoto.jp", + "minami.kyoto.jp", + "minamiyamashiro.kyoto.jp", + "miyazu.kyoto.jp", + "muko.kyoto.jp", + "nagaokakyo.kyoto.jp", + "nakagyo.kyoto.jp", + "nantan.kyoto.jp", + "oyamazaki.kyoto.jp", + "sakyo.kyoto.jp", + "seika.kyoto.jp", + "tanabe.kyoto.jp", + "uji.kyoto.jp", + "ujitawara.kyoto.jp", + "wazuka.kyoto.jp", + "yamashina.kyoto.jp", + "yawata.kyoto.jp", + "asahi.mie.jp", + "inabe.mie.jp", + "ise.mie.jp", + "kameyama.mie.jp", + "kawagoe.mie.jp", + "kiho.mie.jp", + "kisosaki.mie.jp", + "kiwa.mie.jp", + "komono.mie.jp", + "kumano.mie.jp", + "kuwana.mie.jp", + "matsusaka.mie.jp", + "meiwa.mie.jp", + "mihama.mie.jp", + "minamiise.mie.jp", + "misugi.mie.jp", + "miyama.mie.jp", + "nabari.mie.jp", + "shima.mie.jp", + "suzuka.mie.jp", + "tado.mie.jp", + "taiki.mie.jp", + "taki.mie.jp", + "tamaki.mie.jp", + "toba.mie.jp", + "tsu.mie.jp", + "udono.mie.jp", + "ureshino.mie.jp", + "watarai.mie.jp", + "yokkaichi.mie.jp", + "furukawa.miyagi.jp", + "higashimatsushima.miyagi.jp", + "ishinomaki.miyagi.jp", + "iwanuma.miyagi.jp", + "kakuda.miyagi.jp", + "kami.miyagi.jp", + "kawasaki.miyagi.jp", + "marumori.miyagi.jp", + "matsushima.miyagi.jp", + "minamisanriku.miyagi.jp", + "misato.miyagi.jp", + "murata.miyagi.jp", + "natori.miyagi.jp", + "ogawara.miyagi.jp", + "ohira.miyagi.jp", + "onagawa.miyagi.jp", + "osaki.miyagi.jp", + "rifu.miyagi.jp", + "semine.miyagi.jp", + "shibata.miyagi.jp", + "shichikashuku.miyagi.jp", + "shikama.miyagi.jp", + "shiogama.miyagi.jp", + "shiroishi.miyagi.jp", + "tagajo.miyagi.jp", + "taiwa.miyagi.jp", + "tome.miyagi.jp", + "tomiya.miyagi.jp", + "wakuya.miyagi.jp", + "watari.miyagi.jp", + "yamamoto.miyagi.jp", + "zao.miyagi.jp", + "aya.miyazaki.jp", + "ebino.miyazaki.jp", + "gokase.miyazaki.jp", + "hyuga.miyazaki.jp", + "kadogawa.miyazaki.jp", + "kawaminami.miyazaki.jp", + "kijo.miyazaki.jp", + "kitagawa.miyazaki.jp", + "kitakata.miyazaki.jp", + "kitaura.miyazaki.jp", + "kobayashi.miyazaki.jp", + "kunitomi.miyazaki.jp", + "kushima.miyazaki.jp", + "mimata.miyazaki.jp", + "miyakonojo.miyazaki.jp", + "miyazaki.miyazaki.jp", + "morotsuka.miyazaki.jp", + "nichinan.miyazaki.jp", + "nishimera.miyazaki.jp", + "nobeoka.miyazaki.jp", + "saito.miyazaki.jp", + "shiiba.miyazaki.jp", + "shintomi.miyazaki.jp", + "takaharu.miyazaki.jp", + "takanabe.miyazaki.jp", + "takazaki.miyazaki.jp", + "tsuno.miyazaki.jp", + "achi.nagano.jp", + "agematsu.nagano.jp", + "anan.nagano.jp", + "aoki.nagano.jp", + "asahi.nagano.jp", + "azumino.nagano.jp", + "chikuhoku.nagano.jp", + "chikuma.nagano.jp", + "chino.nagano.jp", + "fujimi.nagano.jp", + "hakuba.nagano.jp", + "hara.nagano.jp", + "hiraya.nagano.jp", + "iida.nagano.jp", + "iijima.nagano.jp", + "iiyama.nagano.jp", + "iizuna.nagano.jp", + "ikeda.nagano.jp", + "ikusaka.nagano.jp", + "ina.nagano.jp", + "karuizawa.nagano.jp", + "kawakami.nagano.jp", + "kiso.nagano.jp", + "kisofukushima.nagano.jp", + "kitaaiki.nagano.jp", + "komagane.nagano.jp", + "komoro.nagano.jp", + "matsukawa.nagano.jp", + "matsumoto.nagano.jp", + "miasa.nagano.jp", + "minamiaiki.nagano.jp", + "minamimaki.nagano.jp", + "minamiminowa.nagano.jp", + "minowa.nagano.jp", + "miyada.nagano.jp", + "miyota.nagano.jp", + "mochizuki.nagano.jp", + "nagano.nagano.jp", + "nagawa.nagano.jp", + "nagiso.nagano.jp", + "nakagawa.nagano.jp", + "nakano.nagano.jp", + "nozawaonsen.nagano.jp", + "obuse.nagano.jp", + "ogawa.nagano.jp", + "okaya.nagano.jp", + "omachi.nagano.jp", + "omi.nagano.jp", + "ookuwa.nagano.jp", + "ooshika.nagano.jp", + "otaki.nagano.jp", + "otari.nagano.jp", + "sakae.nagano.jp", + "sakaki.nagano.jp", + "saku.nagano.jp", + "sakuho.nagano.jp", + "shimosuwa.nagano.jp", + "shinanomachi.nagano.jp", + "shiojiri.nagano.jp", + "suwa.nagano.jp", + "suzaka.nagano.jp", + "takagi.nagano.jp", + "takamori.nagano.jp", + "takayama.nagano.jp", + "tateshina.nagano.jp", + "tatsuno.nagano.jp", + "togakushi.nagano.jp", + "togura.nagano.jp", + "tomi.nagano.jp", + "ueda.nagano.jp", + "wada.nagano.jp", + "yamagata.nagano.jp", + "yamanouchi.nagano.jp", + "yasaka.nagano.jp", + "yasuoka.nagano.jp", + "chijiwa.nagasaki.jp", + "futsu.nagasaki.jp", + "goto.nagasaki.jp", + "hasami.nagasaki.jp", + "hirado.nagasaki.jp", + "iki.nagasaki.jp", + "isahaya.nagasaki.jp", + "kawatana.nagasaki.jp", + "kuchinotsu.nagasaki.jp", + "matsuura.nagasaki.jp", + "nagasaki.nagasaki.jp", + "obama.nagasaki.jp", + "omura.nagasaki.jp", + "oseto.nagasaki.jp", + "saikai.nagasaki.jp", + "sasebo.nagasaki.jp", + "seihi.nagasaki.jp", + "shimabara.nagasaki.jp", + "shinkamigoto.nagasaki.jp", + "togitsu.nagasaki.jp", + "tsushima.nagasaki.jp", + "unzen.nagasaki.jp", + "ando.nara.jp", + "gose.nara.jp", + "heguri.nara.jp", + "higashiyoshino.nara.jp", + "ikaruga.nara.jp", + "ikoma.nara.jp", + "kamikitayama.nara.jp", + "kanmaki.nara.jp", + "kashiba.nara.jp", + "kashihara.nara.jp", + "katsuragi.nara.jp", + "kawai.nara.jp", + "kawakami.nara.jp", + "kawanishi.nara.jp", + "koryo.nara.jp", + "kurotaki.nara.jp", + "mitsue.nara.jp", + "miyake.nara.jp", + "nara.nara.jp", + "nosegawa.nara.jp", + "oji.nara.jp", + "ouda.nara.jp", + "oyodo.nara.jp", + "sakurai.nara.jp", + "sango.nara.jp", + "shimoichi.nara.jp", + "shimokitayama.nara.jp", + "shinjo.nara.jp", + "soni.nara.jp", + "takatori.nara.jp", + "tawaramoto.nara.jp", + "tenkawa.nara.jp", + "tenri.nara.jp", + "uda.nara.jp", + "yamatokoriyama.nara.jp", + "yamatotakada.nara.jp", + "yamazoe.nara.jp", + "yoshino.nara.jp", + "aga.niigata.jp", + "agano.niigata.jp", + "gosen.niigata.jp", + "itoigawa.niigata.jp", + "izumozaki.niigata.jp", + "joetsu.niigata.jp", + "kamo.niigata.jp", + "kariwa.niigata.jp", + "kashiwazaki.niigata.jp", + "minamiuonuma.niigata.jp", + "mitsuke.niigata.jp", + "muika.niigata.jp", + "murakami.niigata.jp", + "myoko.niigata.jp", + "nagaoka.niigata.jp", + "niigata.niigata.jp", + "ojiya.niigata.jp", + "omi.niigata.jp", + "sado.niigata.jp", + "sanjo.niigata.jp", + "seiro.niigata.jp", + "seirou.niigata.jp", + "sekikawa.niigata.jp", + "shibata.niigata.jp", + "tagami.niigata.jp", + "tainai.niigata.jp", + "tochio.niigata.jp", + "tokamachi.niigata.jp", + "tsubame.niigata.jp", + "tsunan.niigata.jp", + "uonuma.niigata.jp", + "yahiko.niigata.jp", + "yoita.niigata.jp", + "yuzawa.niigata.jp", + "beppu.oita.jp", + "bungoono.oita.jp", + "bungotakada.oita.jp", + "hasama.oita.jp", + "hiji.oita.jp", + "himeshima.oita.jp", + "hita.oita.jp", + "kamitsue.oita.jp", + "kokonoe.oita.jp", + "kuju.oita.jp", + "kunisaki.oita.jp", + "kusu.oita.jp", + "oita.oita.jp", + "saiki.oita.jp", + "taketa.oita.jp", + "tsukumi.oita.jp", + "usa.oita.jp", + "usuki.oita.jp", + "yufu.oita.jp", + "akaiwa.okayama.jp", + "asakuchi.okayama.jp", + "bizen.okayama.jp", + "hayashima.okayama.jp", + "ibara.okayama.jp", + "kagamino.okayama.jp", + "kasaoka.okayama.jp", + "kibichuo.okayama.jp", + "kumenan.okayama.jp", + "kurashiki.okayama.jp", + "maniwa.okayama.jp", + "misaki.okayama.jp", + "nagi.okayama.jp", + "niimi.okayama.jp", + "nishiawakura.okayama.jp", + "okayama.okayama.jp", + "satosho.okayama.jp", + "setouchi.okayama.jp", + "shinjo.okayama.jp", + "shoo.okayama.jp", + "soja.okayama.jp", + "takahashi.okayama.jp", + "tamano.okayama.jp", + "tsuyama.okayama.jp", + "wake.okayama.jp", + "yakage.okayama.jp", + "aguni.okinawa.jp", + "ginowan.okinawa.jp", + "ginoza.okinawa.jp", + "gushikami.okinawa.jp", + "haebaru.okinawa.jp", + "higashi.okinawa.jp", + "hirara.okinawa.jp", + "iheya.okinawa.jp", + "ishigaki.okinawa.jp", + "ishikawa.okinawa.jp", + "itoman.okinawa.jp", + "izena.okinawa.jp", + "kadena.okinawa.jp", + "kin.okinawa.jp", + "kitadaito.okinawa.jp", + "kitanakagusuku.okinawa.jp", + "kumejima.okinawa.jp", + "kunigami.okinawa.jp", + "minamidaito.okinawa.jp", + "motobu.okinawa.jp", + "nago.okinawa.jp", + "naha.okinawa.jp", + "nakagusuku.okinawa.jp", + "nakijin.okinawa.jp", + "nanjo.okinawa.jp", + "nishihara.okinawa.jp", + "ogimi.okinawa.jp", + "okinawa.okinawa.jp", + "onna.okinawa.jp", + "shimoji.okinawa.jp", + "taketomi.okinawa.jp", + "tarama.okinawa.jp", + "tokashiki.okinawa.jp", + "tomigusuku.okinawa.jp", + "tonaki.okinawa.jp", + "urasoe.okinawa.jp", + "uruma.okinawa.jp", + "yaese.okinawa.jp", + "yomitan.okinawa.jp", + "yonabaru.okinawa.jp", + "yonaguni.okinawa.jp", + "zamami.okinawa.jp", + "abeno.osaka.jp", + "chihayaakasaka.osaka.jp", + "chuo.osaka.jp", + "daito.osaka.jp", + "fujiidera.osaka.jp", + "habikino.osaka.jp", + "hannan.osaka.jp", + "higashiosaka.osaka.jp", + "higashisumiyoshi.osaka.jp", + "higashiyodogawa.osaka.jp", + "hirakata.osaka.jp", + "ibaraki.osaka.jp", + "ikeda.osaka.jp", + "izumi.osaka.jp", + "izumiotsu.osaka.jp", + "izumisano.osaka.jp", + "kadoma.osaka.jp", + "kaizuka.osaka.jp", + "kanan.osaka.jp", + "kashiwara.osaka.jp", + "katano.osaka.jp", + "kawachinagano.osaka.jp", + "kishiwada.osaka.jp", + "kita.osaka.jp", + "kumatori.osaka.jp", + "matsubara.osaka.jp", + "minato.osaka.jp", + "minoh.osaka.jp", + "misaki.osaka.jp", + "moriguchi.osaka.jp", + "neyagawa.osaka.jp", + "nishi.osaka.jp", + "nose.osaka.jp", + "osakasayama.osaka.jp", + "sakai.osaka.jp", + "sayama.osaka.jp", + "sennan.osaka.jp", + "settsu.osaka.jp", + "shijonawate.osaka.jp", + "shimamoto.osaka.jp", + "suita.osaka.jp", + "tadaoka.osaka.jp", + "taishi.osaka.jp", + "tajiri.osaka.jp", + "takaishi.osaka.jp", + "takatsuki.osaka.jp", + "tondabayashi.osaka.jp", + "toyonaka.osaka.jp", + "toyono.osaka.jp", + "yao.osaka.jp", + "ariake.saga.jp", + "arita.saga.jp", + "fukudomi.saga.jp", + "genkai.saga.jp", + "hamatama.saga.jp", + "hizen.saga.jp", + "imari.saga.jp", + "kamimine.saga.jp", + "kanzaki.saga.jp", + "karatsu.saga.jp", + "kashima.saga.jp", + "kitagata.saga.jp", + "kitahata.saga.jp", + "kiyama.saga.jp", + "kouhoku.saga.jp", + "kyuragi.saga.jp", + "nishiarita.saga.jp", + "ogi.saga.jp", + "omachi.saga.jp", + "ouchi.saga.jp", + "saga.saga.jp", + "shiroishi.saga.jp", + "taku.saga.jp", + "tara.saga.jp", + "tosu.saga.jp", + "yoshinogari.saga.jp", + "arakawa.saitama.jp", + "asaka.saitama.jp", + "chichibu.saitama.jp", + "fujimi.saitama.jp", + "fujimino.saitama.jp", + "fukaya.saitama.jp", + "hanno.saitama.jp", + "hanyu.saitama.jp", + "hasuda.saitama.jp", + "hatogaya.saitama.jp", + "hatoyama.saitama.jp", + "hidaka.saitama.jp", + "higashichichibu.saitama.jp", + "higashimatsuyama.saitama.jp", + "honjo.saitama.jp", + "ina.saitama.jp", + "iruma.saitama.jp", + "iwatsuki.saitama.jp", + "kamiizumi.saitama.jp", + "kamikawa.saitama.jp", + "kamisato.saitama.jp", + "kasukabe.saitama.jp", + "kawagoe.saitama.jp", + "kawaguchi.saitama.jp", + "kawajima.saitama.jp", + "kazo.saitama.jp", + "kitamoto.saitama.jp", + "koshigaya.saitama.jp", + "kounosu.saitama.jp", + "kuki.saitama.jp", + "kumagaya.saitama.jp", + "matsubushi.saitama.jp", + "minano.saitama.jp", + "misato.saitama.jp", + "miyashiro.saitama.jp", + "miyoshi.saitama.jp", + "moroyama.saitama.jp", + "nagatoro.saitama.jp", + "namegawa.saitama.jp", + "niiza.saitama.jp", + "ogano.saitama.jp", + "ogawa.saitama.jp", + "ogose.saitama.jp", + "okegawa.saitama.jp", + "omiya.saitama.jp", + "otaki.saitama.jp", + "ranzan.saitama.jp", + "ryokami.saitama.jp", + "saitama.saitama.jp", + "sakado.saitama.jp", + "satte.saitama.jp", + "sayama.saitama.jp", + "shiki.saitama.jp", + "shiraoka.saitama.jp", + "soka.saitama.jp", + "sugito.saitama.jp", + "toda.saitama.jp", + "tokigawa.saitama.jp", + "tokorozawa.saitama.jp", + "tsurugashima.saitama.jp", + "urawa.saitama.jp", + "warabi.saitama.jp", + "yashio.saitama.jp", + "yokoze.saitama.jp", + "yono.saitama.jp", + "yorii.saitama.jp", + "yoshida.saitama.jp", + "yoshikawa.saitama.jp", + "yoshimi.saitama.jp", + "aisho.shiga.jp", + "gamo.shiga.jp", + "higashiomi.shiga.jp", + "hikone.shiga.jp", + "koka.shiga.jp", + "konan.shiga.jp", + "kosei.shiga.jp", + "koto.shiga.jp", + "kusatsu.shiga.jp", + "maibara.shiga.jp", + "moriyama.shiga.jp", + "nagahama.shiga.jp", + "nishiazai.shiga.jp", + "notogawa.shiga.jp", + "omihachiman.shiga.jp", + "otsu.shiga.jp", + "ritto.shiga.jp", + "ryuoh.shiga.jp", + "takashima.shiga.jp", + "takatsuki.shiga.jp", + "torahime.shiga.jp", + "toyosato.shiga.jp", + "yasu.shiga.jp", + "akagi.shimane.jp", + "ama.shimane.jp", + "gotsu.shimane.jp", + "hamada.shimane.jp", + "higashiizumo.shimane.jp", + "hikawa.shimane.jp", + "hikimi.shimane.jp", + "izumo.shimane.jp", + "kakinoki.shimane.jp", + "masuda.shimane.jp", + "matsue.shimane.jp", + "misato.shimane.jp", + "nishinoshima.shimane.jp", + "ohda.shimane.jp", + "okinoshima.shimane.jp", + "okuizumo.shimane.jp", + "shimane.shimane.jp", + "tamayu.shimane.jp", + "tsuwano.shimane.jp", + "unnan.shimane.jp", + "yakumo.shimane.jp", + "yasugi.shimane.jp", + "yatsuka.shimane.jp", + "arai.shizuoka.jp", + "atami.shizuoka.jp", + "fuji.shizuoka.jp", + "fujieda.shizuoka.jp", + "fujikawa.shizuoka.jp", + "fujinomiya.shizuoka.jp", + "fukuroi.shizuoka.jp", + "gotemba.shizuoka.jp", + "haibara.shizuoka.jp", + "hamamatsu.shizuoka.jp", + "higashiizu.shizuoka.jp", + "ito.shizuoka.jp", + "iwata.shizuoka.jp", + "izu.shizuoka.jp", + "izunokuni.shizuoka.jp", + "kakegawa.shizuoka.jp", + "kannami.shizuoka.jp", + "kawanehon.shizuoka.jp", + "kawazu.shizuoka.jp", + "kikugawa.shizuoka.jp", + "kosai.shizuoka.jp", + "makinohara.shizuoka.jp", + "matsuzaki.shizuoka.jp", + "minamiizu.shizuoka.jp", + "mishima.shizuoka.jp", + "morimachi.shizuoka.jp", + "nishiizu.shizuoka.jp", + "numazu.shizuoka.jp", + "omaezaki.shizuoka.jp", + "shimada.shizuoka.jp", + "shimizu.shizuoka.jp", + "shimoda.shizuoka.jp", + "shizuoka.shizuoka.jp", + "susono.shizuoka.jp", + "yaizu.shizuoka.jp", + "yoshida.shizuoka.jp", + "ashikaga.tochigi.jp", + "bato.tochigi.jp", + "haga.tochigi.jp", + "ichikai.tochigi.jp", + "iwafune.tochigi.jp", + "kaminokawa.tochigi.jp", + "kanuma.tochigi.jp", + "karasuyama.tochigi.jp", + "kuroiso.tochigi.jp", + "mashiko.tochigi.jp", + "mibu.tochigi.jp", + "moka.tochigi.jp", + "motegi.tochigi.jp", + "nasu.tochigi.jp", + "nasushiobara.tochigi.jp", + "nikko.tochigi.jp", + "nishikata.tochigi.jp", + "nogi.tochigi.jp", + "ohira.tochigi.jp", + "ohtawara.tochigi.jp", + "oyama.tochigi.jp", + "sakura.tochigi.jp", + "sano.tochigi.jp", + "shimotsuke.tochigi.jp", + "shioya.tochigi.jp", + "takanezawa.tochigi.jp", + "tochigi.tochigi.jp", + "tsuga.tochigi.jp", + "ujiie.tochigi.jp", + "utsunomiya.tochigi.jp", + "yaita.tochigi.jp", + "aizumi.tokushima.jp", + "anan.tokushima.jp", + "ichiba.tokushima.jp", + "itano.tokushima.jp", + "kainan.tokushima.jp", + "komatsushima.tokushima.jp", + "matsushige.tokushima.jp", + "mima.tokushima.jp", + "minami.tokushima.jp", + "miyoshi.tokushima.jp", + "mugi.tokushima.jp", + "nakagawa.tokushima.jp", + "naruto.tokushima.jp", + "sanagochi.tokushima.jp", + "shishikui.tokushima.jp", + "tokushima.tokushima.jp", + "wajiki.tokushima.jp", + "adachi.tokyo.jp", + "akiruno.tokyo.jp", + "akishima.tokyo.jp", + "aogashima.tokyo.jp", + "arakawa.tokyo.jp", + "bunkyo.tokyo.jp", + "chiyoda.tokyo.jp", + "chofu.tokyo.jp", + "chuo.tokyo.jp", + "edogawa.tokyo.jp", + "fuchu.tokyo.jp", + "fussa.tokyo.jp", + "hachijo.tokyo.jp", + "hachioji.tokyo.jp", + "hamura.tokyo.jp", + "higashikurume.tokyo.jp", + "higashimurayama.tokyo.jp", + "higashiyamato.tokyo.jp", + "hino.tokyo.jp", + "hinode.tokyo.jp", + "hinohara.tokyo.jp", + "inagi.tokyo.jp", + "itabashi.tokyo.jp", + "katsushika.tokyo.jp", + "kita.tokyo.jp", + "kiyose.tokyo.jp", + "kodaira.tokyo.jp", + "koganei.tokyo.jp", + "kokubunji.tokyo.jp", + "komae.tokyo.jp", + "koto.tokyo.jp", + "kouzushima.tokyo.jp", + "kunitachi.tokyo.jp", + "machida.tokyo.jp", + "meguro.tokyo.jp", + "minato.tokyo.jp", + "mitaka.tokyo.jp", + "mizuho.tokyo.jp", + "musashimurayama.tokyo.jp", + "musashino.tokyo.jp", + "nakano.tokyo.jp", + "nerima.tokyo.jp", + "ogasawara.tokyo.jp", + "okutama.tokyo.jp", + "ome.tokyo.jp", + "oshima.tokyo.jp", + "ota.tokyo.jp", + "setagaya.tokyo.jp", + "shibuya.tokyo.jp", + "shinagawa.tokyo.jp", + "shinjuku.tokyo.jp", + "suginami.tokyo.jp", + "sumida.tokyo.jp", + "tachikawa.tokyo.jp", + "taito.tokyo.jp", + "tama.tokyo.jp", + "toshima.tokyo.jp", + "chizu.tottori.jp", + "hino.tottori.jp", + "kawahara.tottori.jp", + "koge.tottori.jp", + "kotoura.tottori.jp", + "misasa.tottori.jp", + "nanbu.tottori.jp", + "nichinan.tottori.jp", + "sakaiminato.tottori.jp", + "tottori.tottori.jp", + "wakasa.tottori.jp", + "yazu.tottori.jp", + "yonago.tottori.jp", + "asahi.toyama.jp", + "fuchu.toyama.jp", + "fukumitsu.toyama.jp", + "funahashi.toyama.jp", + "himi.toyama.jp", + "imizu.toyama.jp", + "inami.toyama.jp", + "johana.toyama.jp", + "kamiichi.toyama.jp", + "kurobe.toyama.jp", + "nakaniikawa.toyama.jp", + "namerikawa.toyama.jp", + "nanto.toyama.jp", + "nyuzen.toyama.jp", + "oyabe.toyama.jp", + "taira.toyama.jp", + "takaoka.toyama.jp", + "tateyama.toyama.jp", + "toga.toyama.jp", + "tonami.toyama.jp", + "toyama.toyama.jp", + "unazuki.toyama.jp", + "uozu.toyama.jp", + "yamada.toyama.jp", + "arida.wakayama.jp", + "aridagawa.wakayama.jp", + "gobo.wakayama.jp", + "hashimoto.wakayama.jp", + "hidaka.wakayama.jp", + "hirogawa.wakayama.jp", + "inami.wakayama.jp", + "iwade.wakayama.jp", + "kainan.wakayama.jp", + "kamitonda.wakayama.jp", + "katsuragi.wakayama.jp", + "kimino.wakayama.jp", + "kinokawa.wakayama.jp", + "kitayama.wakayama.jp", + "koya.wakayama.jp", + "koza.wakayama.jp", + "kozagawa.wakayama.jp", + "kudoyama.wakayama.jp", + "kushimoto.wakayama.jp", + "mihama.wakayama.jp", + "misato.wakayama.jp", + "nachikatsuura.wakayama.jp", + "shingu.wakayama.jp", + "shirahama.wakayama.jp", + "taiji.wakayama.jp", + "tanabe.wakayama.jp", + "wakayama.wakayama.jp", + "yuasa.wakayama.jp", + "yura.wakayama.jp", + "asahi.yamagata.jp", + "funagata.yamagata.jp", + "higashine.yamagata.jp", + "iide.yamagata.jp", + "kahoku.yamagata.jp", + "kaminoyama.yamagata.jp", + "kaneyama.yamagata.jp", + "kawanishi.yamagata.jp", + "mamurogawa.yamagata.jp", + "mikawa.yamagata.jp", + "murayama.yamagata.jp", + "nagai.yamagata.jp", + "nakayama.yamagata.jp", + "nanyo.yamagata.jp", + "nishikawa.yamagata.jp", + "obanazawa.yamagata.jp", + "oe.yamagata.jp", + "oguni.yamagata.jp", + "ohkura.yamagata.jp", + "oishida.yamagata.jp", + "sagae.yamagata.jp", + "sakata.yamagata.jp", + "sakegawa.yamagata.jp", + "shinjo.yamagata.jp", + "shirataka.yamagata.jp", + "shonai.yamagata.jp", + "takahata.yamagata.jp", + "tendo.yamagata.jp", + "tozawa.yamagata.jp", + "tsuruoka.yamagata.jp", + "yamagata.yamagata.jp", + "yamanobe.yamagata.jp", + "yonezawa.yamagata.jp", + "yuza.yamagata.jp", + "abu.yamaguchi.jp", + "hagi.yamaguchi.jp", + "hikari.yamaguchi.jp", + "hofu.yamaguchi.jp", + "iwakuni.yamaguchi.jp", + "kudamatsu.yamaguchi.jp", + "mitou.yamaguchi.jp", + "nagato.yamaguchi.jp", + "oshima.yamaguchi.jp", + "shimonoseki.yamaguchi.jp", + "shunan.yamaguchi.jp", + "tabuse.yamaguchi.jp", + "tokuyama.yamaguchi.jp", + "toyota.yamaguchi.jp", + "ube.yamaguchi.jp", + "yuu.yamaguchi.jp", + "chuo.yamanashi.jp", + "doshi.yamanashi.jp", + "fuefuki.yamanashi.jp", + "fujikawa.yamanashi.jp", + "fujikawaguchiko.yamanashi.jp", + "fujiyoshida.yamanashi.jp", + "hayakawa.yamanashi.jp", + "hokuto.yamanashi.jp", + "ichikawamisato.yamanashi.jp", + "kai.yamanashi.jp", + "kofu.yamanashi.jp", + "koshu.yamanashi.jp", + "kosuge.yamanashi.jp", + "minami-alps.yamanashi.jp", + "minobu.yamanashi.jp", + "nakamichi.yamanashi.jp", + "nanbu.yamanashi.jp", + "narusawa.yamanashi.jp", + "nirasaki.yamanashi.jp", + "nishikatsura.yamanashi.jp", + "oshino.yamanashi.jp", + "otsuki.yamanashi.jp", + "showa.yamanashi.jp", + "tabayama.yamanashi.jp", + "tsuru.yamanashi.jp", + "uenohara.yamanashi.jp", + "yamanakako.yamanashi.jp", + "yamanashi.yamanashi.jp", + "ke", + "ac.ke", + "co.ke", + "go.ke", + "info.ke", + "me.ke", + "mobi.ke", + "ne.ke", + "or.ke", + "sc.ke", + "kg", + "org.kg", + "net.kg", + "com.kg", + "edu.kg", + "gov.kg", + "mil.kg", + "*.kh", + "ki", + "edu.ki", + "biz.ki", + "net.ki", + "org.ki", + "gov.ki", + "info.ki", + "com.ki", + "km", + "org.km", + "nom.km", + "gov.km", + "prd.km", + "tm.km", + "edu.km", + "mil.km", + "ass.km", + "com.km", + "coop.km", + "asso.km", + "presse.km", + "medecin.km", + "notaires.km", + "pharmaciens.km", + "veterinaire.km", + "gouv.km", + "kn", + "net.kn", + "org.kn", + "edu.kn", + "gov.kn", + "kp", + "com.kp", + "edu.kp", + "gov.kp", + "org.kp", + "rep.kp", + "tra.kp", + "kr", + "ac.kr", + "co.kr", + "es.kr", + "go.kr", + "hs.kr", + "kg.kr", + "mil.kr", + "ms.kr", + "ne.kr", + "or.kr", + "pe.kr", + "re.kr", + "sc.kr", + "busan.kr", + "chungbuk.kr", + "chungnam.kr", + "daegu.kr", + "daejeon.kr", + "gangwon.kr", + "gwangju.kr", + "gyeongbuk.kr", + "gyeonggi.kr", + "gyeongnam.kr", + "incheon.kr", + "jeju.kr", + "jeonbuk.kr", + "jeonnam.kr", + "seoul.kr", + "ulsan.kr", + "kw", + "com.kw", + "edu.kw", + "emb.kw", + "gov.kw", + "ind.kw", + "net.kw", + "org.kw", + "ky", + "edu.ky", + "gov.ky", + "com.ky", + "org.ky", + "net.ky", + "kz", + "org.kz", + "edu.kz", + "net.kz", + "gov.kz", + "mil.kz", + "com.kz", + "la", + "int.la", + "net.la", + "info.la", + "edu.la", + "gov.la", + "per.la", + "com.la", + "org.la", + "lb", + "com.lb", + "edu.lb", + "gov.lb", + "net.lb", + "org.lb", + "lc", + "com.lc", + "net.lc", + "co.lc", + "org.lc", + "edu.lc", + "gov.lc", + "li", + "lk", + "gov.lk", + "sch.lk", + "net.lk", + "int.lk", + "com.lk", + "org.lk", + "edu.lk", + "ngo.lk", + "soc.lk", + "web.lk", + "ltd.lk", + "assn.lk", + "grp.lk", + "hotel.lk", + "ac.lk", + "lr", + "com.lr", + "edu.lr", + "gov.lr", + "org.lr", + "net.lr", + "ls", + "ac.ls", + "biz.ls", + "co.ls", + "edu.ls", + "gov.ls", + "info.ls", + "net.ls", + "org.ls", + "sc.ls", + "lt", + "gov.lt", + "lu", + "lv", + "com.lv", + "edu.lv", + "gov.lv", + "org.lv", + "mil.lv", + "id.lv", + "net.lv", + "asn.lv", + "conf.lv", + "ly", + "com.ly", + "net.ly", + "gov.ly", + "plc.ly", + "edu.ly", + "sch.ly", + "med.ly", + "org.ly", + "id.ly", + "ma", + "co.ma", + "net.ma", + "gov.ma", + "org.ma", + "ac.ma", + "press.ma", + "mc", + "tm.mc", + "asso.mc", + "md", + "me", + "co.me", + "net.me", + "org.me", + "edu.me", + "ac.me", + "gov.me", + "its.me", + "priv.me", + "mg", + "org.mg", + "nom.mg", + "gov.mg", + "prd.mg", + "tm.mg", + "edu.mg", + "mil.mg", + "com.mg", + "co.mg", + "mh", + "mil", + "mk", + "com.mk", + "org.mk", + "net.mk", + "edu.mk", + "gov.mk", + "inf.mk", + "name.mk", + "ml", + "com.ml", + "edu.ml", + "gouv.ml", + "gov.ml", + "net.ml", + "org.ml", + "presse.ml", + "*.mm", + "mn", + "gov.mn", + "edu.mn", + "org.mn", + "mo", + "com.mo", + "net.mo", + "org.mo", + "edu.mo", + "gov.mo", + "mobi", + "mp", + "mq", + "mr", + "gov.mr", + "ms", + "com.ms", + "edu.ms", + "gov.ms", + "net.ms", + "org.ms", + "mt", + "com.mt", + "edu.mt", + "net.mt", + "org.mt", + "mu", + "com.mu", + "net.mu", + "org.mu", + "gov.mu", + "ac.mu", + "co.mu", + "or.mu", + "museum", + "academy.museum", + "agriculture.museum", + "air.museum", + "airguard.museum", + "alabama.museum", + "alaska.museum", + "amber.museum", + "ambulance.museum", + "american.museum", + "americana.museum", + "americanantiques.museum", + "americanart.museum", + "amsterdam.museum", + "and.museum", + "annefrank.museum", + "anthro.museum", + "anthropology.museum", + "antiques.museum", + "aquarium.museum", + "arboretum.museum", + "archaeological.museum", + "archaeology.museum", + "architecture.museum", + "art.museum", + "artanddesign.museum", + "artcenter.museum", + "artdeco.museum", + "arteducation.museum", + "artgallery.museum", + "arts.museum", + "artsandcrafts.museum", + "asmatart.museum", + "assassination.museum", + "assisi.museum", + "association.museum", + "astronomy.museum", + "atlanta.museum", + "austin.museum", + "australia.museum", + "automotive.museum", + "aviation.museum", + "axis.museum", + "badajoz.museum", + "baghdad.museum", + "bahn.museum", + "bale.museum", + "baltimore.museum", + "barcelona.museum", + "baseball.museum", + "basel.museum", + "baths.museum", + "bauern.museum", + "beauxarts.museum", + "beeldengeluid.museum", + "bellevue.museum", + "bergbau.museum", + "berkeley.museum", + "berlin.museum", + "bern.museum", + "bible.museum", + "bilbao.museum", + "bill.museum", + "birdart.museum", + "birthplace.museum", + "bonn.museum", + "boston.museum", + "botanical.museum", + "botanicalgarden.museum", + "botanicgarden.museum", + "botany.museum", + "brandywinevalley.museum", + "brasil.museum", + "bristol.museum", + "british.museum", + "britishcolumbia.museum", + "broadcast.museum", + "brunel.museum", + "brussel.museum", + "brussels.museum", + "bruxelles.museum", + "building.museum", + "burghof.museum", + "bus.museum", + "bushey.museum", + "cadaques.museum", + "california.museum", + "cambridge.museum", + "can.museum", + "canada.museum", + "capebreton.museum", + "carrier.museum", + "cartoonart.museum", + "casadelamoneda.museum", + "castle.museum", + "castres.museum", + "celtic.museum", + "center.museum", + "chattanooga.museum", + "cheltenham.museum", + "chesapeakebay.museum", + "chicago.museum", + "children.museum", + "childrens.museum", + "childrensgarden.museum", + "chiropractic.museum", + "chocolate.museum", + "christiansburg.museum", + "cincinnati.museum", + "cinema.museum", + "circus.museum", + "civilisation.museum", + "civilization.museum", + "civilwar.museum", + "clinton.museum", + "clock.museum", + "coal.museum", + "coastaldefence.museum", + "cody.museum", + "coldwar.museum", + "collection.museum", + "colonialwilliamsburg.museum", + "coloradoplateau.museum", + "columbia.museum", + "columbus.museum", + "communication.museum", + "communications.museum", + "community.museum", + "computer.museum", + "computerhistory.museum", + "xn--comunicaes-v6a2o.museum", + "contemporary.museum", + "contemporaryart.museum", + "convent.museum", + "copenhagen.museum", + "corporation.museum", + "xn--correios-e-telecomunicaes-ghc29a.museum", + "corvette.museum", + "costume.museum", + "countryestate.museum", + "county.museum", + "crafts.museum", + "cranbrook.museum", + "creation.museum", + "cultural.museum", + "culturalcenter.museum", + "culture.museum", + "cyber.museum", + "cymru.museum", + "dali.museum", + "dallas.museum", + "database.museum", + "ddr.museum", + "decorativearts.museum", + "delaware.museum", + "delmenhorst.museum", + "denmark.museum", + "depot.museum", + "design.museum", + "detroit.museum", + "dinosaur.museum", + "discovery.museum", + "dolls.museum", + "donostia.museum", + "durham.museum", + "eastafrica.museum", + "eastcoast.museum", + "education.museum", + "educational.museum", + "egyptian.museum", + "eisenbahn.museum", + "elburg.museum", + "elvendrell.museum", + "embroidery.museum", + "encyclopedic.museum", + "england.museum", + "entomology.museum", + "environment.museum", + "environmentalconservation.museum", + "epilepsy.museum", + "essex.museum", + "estate.museum", + "ethnology.museum", + "exeter.museum", + "exhibition.museum", + "family.museum", + "farm.museum", + "farmequipment.museum", + "farmers.museum", + "farmstead.museum", + "field.museum", + "figueres.museum", + "filatelia.museum", + "film.museum", + "fineart.museum", + "finearts.museum", + "finland.museum", + "flanders.museum", + "florida.museum", + "force.museum", + "fortmissoula.museum", + "fortworth.museum", + "foundation.museum", + "francaise.museum", + "frankfurt.museum", + "franziskaner.museum", + "freemasonry.museum", + "freiburg.museum", + "fribourg.museum", + "frog.museum", + "fundacio.museum", + "furniture.museum", + "gallery.museum", + "garden.museum", + "gateway.museum", + "geelvinck.museum", + "gemological.museum", + "geology.museum", + "georgia.museum", + "giessen.museum", + "glas.museum", + "glass.museum", + "gorge.museum", + "grandrapids.museum", + "graz.museum", + "guernsey.museum", + "halloffame.museum", + "hamburg.museum", + "handson.museum", + "harvestcelebration.museum", + "hawaii.museum", + "health.museum", + "heimatunduhren.museum", + "hellas.museum", + "helsinki.museum", + "hembygdsforbund.museum", + "heritage.museum", + "histoire.museum", + "historical.museum", + "historicalsociety.museum", + "historichouses.museum", + "historisch.museum", + "historisches.museum", + "history.museum", + "historyofscience.museum", + "horology.museum", + "house.museum", + "humanities.museum", + "illustration.museum", + "imageandsound.museum", + "indian.museum", + "indiana.museum", + "indianapolis.museum", + "indianmarket.museum", + "intelligence.museum", + "interactive.museum", + "iraq.museum", + "iron.museum", + "isleofman.museum", + "jamison.museum", + "jefferson.museum", + "jerusalem.museum", + "jewelry.museum", + "jewish.museum", + "jewishart.museum", + "jfk.museum", + "journalism.museum", + "judaica.museum", + "judygarland.museum", + "juedisches.museum", + "juif.museum", + "karate.museum", + "karikatur.museum", + "kids.museum", + "koebenhavn.museum", + "koeln.museum", + "kunst.museum", + "kunstsammlung.museum", + "kunstunddesign.museum", + "labor.museum", + "labour.museum", + "lajolla.museum", + "lancashire.museum", + "landes.museum", + "lans.museum", + "xn--lns-qla.museum", + "larsson.museum", + "lewismiller.museum", + "lincoln.museum", + "linz.museum", + "living.museum", + "livinghistory.museum", + "localhistory.museum", + "london.museum", + "losangeles.museum", + "louvre.museum", + "loyalist.museum", + "lucerne.museum", + "luxembourg.museum", + "luzern.museum", + "mad.museum", + "madrid.museum", + "mallorca.museum", + "manchester.museum", + "mansion.museum", + "mansions.museum", + "manx.museum", + "marburg.museum", + "maritime.museum", + "maritimo.museum", + "maryland.museum", + "marylhurst.museum", + "media.museum", + "medical.museum", + "medizinhistorisches.museum", + "meeres.museum", + "memorial.museum", + "mesaverde.museum", + "michigan.museum", + "midatlantic.museum", + "military.museum", + "mill.museum", + "miners.museum", + "mining.museum", + "minnesota.museum", + "missile.museum", + "missoula.museum", + "modern.museum", + "moma.museum", + "money.museum", + "monmouth.museum", + "monticello.museum", + "montreal.museum", + "moscow.museum", + "motorcycle.museum", + "muenchen.museum", + "muenster.museum", + "mulhouse.museum", + "muncie.museum", + "museet.museum", + "museumcenter.museum", + "museumvereniging.museum", + "music.museum", + "national.museum", + "nationalfirearms.museum", + "nationalheritage.museum", + "nativeamerican.museum", + "naturalhistory.museum", + "naturalhistorymuseum.museum", + "naturalsciences.museum", + "nature.museum", + "naturhistorisches.museum", + "natuurwetenschappen.museum", + "naumburg.museum", + "naval.museum", + "nebraska.museum", + "neues.museum", + "newhampshire.museum", + "newjersey.museum", + "newmexico.museum", + "newport.museum", + "newspaper.museum", + "newyork.museum", + "niepce.museum", + "norfolk.museum", + "north.museum", + "nrw.museum", + "nuernberg.museum", + "nuremberg.museum", + "nyc.museum", + "nyny.museum", + "oceanographic.museum", + "oceanographique.museum", + "omaha.museum", + "online.museum", + "ontario.museum", + "openair.museum", + "oregon.museum", + "oregontrail.museum", + "otago.museum", + "oxford.museum", + "pacific.museum", + "paderborn.museum", + "palace.museum", + "paleo.museum", + "palmsprings.museum", + "panama.museum", + "paris.museum", + "pasadena.museum", + "pharmacy.museum", + "philadelphia.museum", + "philadelphiaarea.museum", + "philately.museum", + "phoenix.museum", + "photography.museum", + "pilots.museum", + "pittsburgh.museum", + "planetarium.museum", + "plantation.museum", + "plants.museum", + "plaza.museum", + "portal.museum", + "portland.museum", + "portlligat.museum", + "posts-and-telecommunications.museum", + "preservation.museum", + "presidio.museum", + "press.museum", + "project.museum", + "public.museum", + "pubol.museum", + "quebec.museum", + "railroad.museum", + "railway.museum", + "research.museum", + "resistance.museum", + "riodejaneiro.museum", + "rochester.museum", + "rockart.museum", + "roma.museum", + "russia.museum", + "saintlouis.museum", + "salem.museum", + "salvadordali.museum", + "salzburg.museum", + "sandiego.museum", + "sanfrancisco.museum", + "santabarbara.museum", + "santacruz.museum", + "santafe.museum", + "saskatchewan.museum", + "satx.museum", + "savannahga.museum", + "schlesisches.museum", + "schoenbrunn.museum", + "schokoladen.museum", + "school.museum", + "schweiz.museum", + "science.museum", + "scienceandhistory.museum", + "scienceandindustry.museum", + "sciencecenter.museum", + "sciencecenters.museum", + "science-fiction.museum", + "sciencehistory.museum", + "sciences.museum", + "sciencesnaturelles.museum", + "scotland.museum", + "seaport.museum", + "settlement.museum", + "settlers.museum", + "shell.museum", + "sherbrooke.museum", + "sibenik.museum", + "silk.museum", + "ski.museum", + "skole.museum", + "society.museum", + "sologne.museum", + "soundandvision.museum", + "southcarolina.museum", + "southwest.museum", + "space.museum", + "spy.museum", + "square.museum", + "stadt.museum", + "stalbans.museum", + "starnberg.museum", + "state.museum", + "stateofdelaware.museum", + "station.museum", + "steam.museum", + "steiermark.museum", + "stjohn.museum", + "stockholm.museum", + "stpetersburg.museum", + "stuttgart.museum", + "suisse.museum", + "surgeonshall.museum", + "surrey.museum", + "svizzera.museum", + "sweden.museum", + "sydney.museum", + "tank.museum", + "tcm.museum", + "technology.museum", + "telekommunikation.museum", + "television.museum", + "texas.museum", + "textile.museum", + "theater.museum", + "time.museum", + "timekeeping.museum", + "topology.museum", + "torino.museum", + "touch.museum", + "town.museum", + "transport.museum", + "tree.museum", + "trolley.museum", + "trust.museum", + "trustee.museum", + "uhren.museum", + "ulm.museum", + "undersea.museum", + "university.museum", + "usa.museum", + "usantiques.museum", + "usarts.museum", + "uscountryestate.museum", + "usculture.museum", + "usdecorativearts.museum", + "usgarden.museum", + "ushistory.museum", + "ushuaia.museum", + "uslivinghistory.museum", + "utah.museum", + "uvic.museum", + "valley.museum", + "vantaa.museum", + "versailles.museum", + "viking.museum", + "village.museum", + "virginia.museum", + "virtual.museum", + "virtuel.museum", + "vlaanderen.museum", + "volkenkunde.museum", + "wales.museum", + "wallonie.museum", + "war.museum", + "washingtondc.museum", + "watchandclock.museum", + "watch-and-clock.museum", + "western.museum", + "westfalen.museum", + "whaling.museum", + "wildlife.museum", + "williamsburg.museum", + "windmill.museum", + "workshop.museum", + "york.museum", + "yorkshire.museum", + "yosemite.museum", + "youth.museum", + "zoological.museum", + "zoology.museum", + "xn--9dbhblg6di.museum", + "xn--h1aegh.museum", + "mv", + "aero.mv", + "biz.mv", + "com.mv", + "coop.mv", + "edu.mv", + "gov.mv", + "info.mv", + "int.mv", + "mil.mv", + "museum.mv", + "name.mv", + "net.mv", + "org.mv", + "pro.mv", + "mw", + "ac.mw", + "biz.mw", + "co.mw", + "com.mw", + "coop.mw", + "edu.mw", + "gov.mw", + "int.mw", + "museum.mw", + "net.mw", + "org.mw", + "mx", + "com.mx", + "org.mx", + "gob.mx", + "edu.mx", + "net.mx", + "my", + "com.my", + "net.my", + "org.my", + "gov.my", + "edu.my", + "mil.my", + "name.my", + "mz", + "ac.mz", + "adv.mz", + "co.mz", + "edu.mz", + "gov.mz", + "mil.mz", + "net.mz", + "org.mz", + "na", + "info.na", + "pro.na", + "name.na", + "school.na", + "or.na", + "dr.na", + "us.na", + "mx.na", + "ca.na", + "in.na", + "cc.na", + "tv.na", + "ws.na", + "mobi.na", + "co.na", + "com.na", + "org.na", + "name", + "nc", + "asso.nc", + "nom.nc", + "ne", + "net", + "nf", + "com.nf", + "net.nf", + "per.nf", + "rec.nf", + "web.nf", + "arts.nf", + "firm.nf", + "info.nf", + "other.nf", + "store.nf", + "ng", + "com.ng", + "edu.ng", + "gov.ng", + "i.ng", + "mil.ng", + "mobi.ng", + "name.ng", + "net.ng", + "org.ng", + "sch.ng", + "ni", + "ac.ni", + "biz.ni", + "co.ni", + "com.ni", + "edu.ni", + "gob.ni", + "in.ni", + "info.ni", + "int.ni", + "mil.ni", + "net.ni", + "nom.ni", + "org.ni", + "web.ni", + "nl", + "no", + "fhs.no", + "vgs.no", + "fylkesbibl.no", + "folkebibl.no", + "museum.no", + "idrett.no", + "priv.no", + "mil.no", + "stat.no", + "dep.no", + "kommune.no", + "herad.no", + "aa.no", + "ah.no", + "bu.no", + "fm.no", + "hl.no", + "hm.no", + "jan-mayen.no", + "mr.no", + "nl.no", + "nt.no", + "of.no", + "ol.no", + "oslo.no", + "rl.no", + "sf.no", + "st.no", + "svalbard.no", + "tm.no", + "tr.no", + "va.no", + "vf.no", + "gs.aa.no", + "gs.ah.no", + "gs.bu.no", + "gs.fm.no", + "gs.hl.no", + "gs.hm.no", + "gs.jan-mayen.no", + "gs.mr.no", + "gs.nl.no", + "gs.nt.no", + "gs.of.no", + "gs.ol.no", + "gs.oslo.no", + "gs.rl.no", + "gs.sf.no", + "gs.st.no", + "gs.svalbard.no", + "gs.tm.no", + "gs.tr.no", + "gs.va.no", + "gs.vf.no", + "akrehamn.no", + "xn--krehamn-dxa.no", + "algard.no", + "xn--lgrd-poac.no", + "arna.no", + "brumunddal.no", + "bryne.no", + "bronnoysund.no", + "xn--brnnysund-m8ac.no", + "drobak.no", + "xn--drbak-wua.no", + "egersund.no", + "fetsund.no", + "floro.no", + "xn--flor-jra.no", + "fredrikstad.no", + "hokksund.no", + "honefoss.no", + "xn--hnefoss-q1a.no", + "jessheim.no", + "jorpeland.no", + "xn--jrpeland-54a.no", + "kirkenes.no", + "kopervik.no", + "krokstadelva.no", + "langevag.no", + "xn--langevg-jxa.no", + "leirvik.no", + "mjondalen.no", + "xn--mjndalen-64a.no", + "mo-i-rana.no", + "mosjoen.no", + "xn--mosjen-eya.no", + "nesoddtangen.no", + "orkanger.no", + "osoyro.no", + "xn--osyro-wua.no", + "raholt.no", + "xn--rholt-mra.no", + "sandnessjoen.no", + "xn--sandnessjen-ogb.no", + "skedsmokorset.no", + "slattum.no", + "spjelkavik.no", + "stathelle.no", + "stavern.no", + "stjordalshalsen.no", + "xn--stjrdalshalsen-sqb.no", + "tananger.no", + "tranby.no", + "vossevangen.no", + "afjord.no", + "xn--fjord-lra.no", + "agdenes.no", + "al.no", + "xn--l-1fa.no", + "alesund.no", + "xn--lesund-hua.no", + "alstahaug.no", + "alta.no", + "xn--lt-liac.no", + "alaheadju.no", + "xn--laheadju-7ya.no", + "alvdal.no", + "amli.no", + "xn--mli-tla.no", + "amot.no", + "xn--mot-tla.no", + "andebu.no", + "andoy.no", + "xn--andy-ira.no", + "andasuolo.no", + "ardal.no", + "xn--rdal-poa.no", + "aremark.no", + "arendal.no", + "xn--s-1fa.no", + "aseral.no", + "xn--seral-lra.no", + "asker.no", + "askim.no", + "askvoll.no", + "askoy.no", + "xn--asky-ira.no", + "asnes.no", + "xn--snes-poa.no", + "audnedaln.no", + "aukra.no", + "aure.no", + "aurland.no", + "aurskog-holand.no", + "xn--aurskog-hland-jnb.no", + "austevoll.no", + "austrheim.no", + "averoy.no", + "xn--avery-yua.no", + "balestrand.no", + "ballangen.no", + "balat.no", + "xn--blt-elab.no", + "balsfjord.no", + "bahccavuotna.no", + "xn--bhccavuotna-k7a.no", + "bamble.no", + "bardu.no", + "beardu.no", + "beiarn.no", + "bajddar.no", + "xn--bjddar-pta.no", + "baidar.no", + "xn--bidr-5nac.no", + "berg.no", + "bergen.no", + "berlevag.no", + "xn--berlevg-jxa.no", + "bearalvahki.no", + "xn--bearalvhki-y4a.no", + "bindal.no", + "birkenes.no", + "bjarkoy.no", + "xn--bjarky-fya.no", + "bjerkreim.no", + "bjugn.no", + "bodo.no", + "xn--bod-2na.no", + "badaddja.no", + "xn--bdddj-mrabd.no", + "budejju.no", + "bokn.no", + "bremanger.no", + "bronnoy.no", + "xn--brnny-wuac.no", + "bygland.no", + "bykle.no", + "barum.no", + "xn--brum-voa.no", + "bo.telemark.no", + "xn--b-5ga.telemark.no", + "bo.nordland.no", + "xn--b-5ga.nordland.no", + "bievat.no", + "xn--bievt-0qa.no", + "bomlo.no", + "xn--bmlo-gra.no", + "batsfjord.no", + "xn--btsfjord-9za.no", + "bahcavuotna.no", + "xn--bhcavuotna-s4a.no", + "dovre.no", + "drammen.no", + "drangedal.no", + "dyroy.no", + "xn--dyry-ira.no", + "donna.no", + "xn--dnna-gra.no", + "eid.no", + "eidfjord.no", + "eidsberg.no", + "eidskog.no", + "eidsvoll.no", + "eigersund.no", + "elverum.no", + "enebakk.no", + "engerdal.no", + "etne.no", + "etnedal.no", + "evenes.no", + "evenassi.no", + "xn--eveni-0qa01ga.no", + "evje-og-hornnes.no", + "farsund.no", + "fauske.no", + "fuossko.no", + "fuoisku.no", + "fedje.no", + "fet.no", + "finnoy.no", + "xn--finny-yua.no", + "fitjar.no", + "fjaler.no", + "fjell.no", + "flakstad.no", + "flatanger.no", + "flekkefjord.no", + "flesberg.no", + "flora.no", + "fla.no", + "xn--fl-zia.no", + "folldal.no", + "forsand.no", + "fosnes.no", + "frei.no", + "frogn.no", + "froland.no", + "frosta.no", + "frana.no", + "xn--frna-woa.no", + "froya.no", + "xn--frya-hra.no", + "fusa.no", + "fyresdal.no", + "forde.no", + "xn--frde-gra.no", + "gamvik.no", + "gangaviika.no", + "xn--ggaviika-8ya47h.no", + "gaular.no", + "gausdal.no", + "gildeskal.no", + "xn--gildeskl-g0a.no", + "giske.no", + "gjemnes.no", + "gjerdrum.no", + "gjerstad.no", + "gjesdal.no", + "gjovik.no", + "xn--gjvik-wua.no", + "gloppen.no", + "gol.no", + "gran.no", + "grane.no", + "granvin.no", + "gratangen.no", + "grimstad.no", + "grong.no", + "kraanghke.no", + "xn--kranghke-b0a.no", + "grue.no", + "gulen.no", + "hadsel.no", + "halden.no", + "halsa.no", + "hamar.no", + "hamaroy.no", + "habmer.no", + "xn--hbmer-xqa.no", + "hapmir.no", + "xn--hpmir-xqa.no", + "hammerfest.no", + "hammarfeasta.no", + "xn--hmmrfeasta-s4ac.no", + "haram.no", + "hareid.no", + "harstad.no", + "hasvik.no", + "aknoluokta.no", + "xn--koluokta-7ya57h.no", + "hattfjelldal.no", + "aarborte.no", + "haugesund.no", + "hemne.no", + "hemnes.no", + "hemsedal.no", + "heroy.more-og-romsdal.no", + "xn--hery-ira.xn--mre-og-romsdal-qqb.no", + "heroy.nordland.no", + "xn--hery-ira.nordland.no", + "hitra.no", + "hjartdal.no", + "hjelmeland.no", + "hobol.no", + "xn--hobl-ira.no", + "hof.no", + "hol.no", + "hole.no", + "holmestrand.no", + "holtalen.no", + "xn--holtlen-hxa.no", + "hornindal.no", + "horten.no", + "hurdal.no", + "hurum.no", + "hvaler.no", + "hyllestad.no", + "hagebostad.no", + "xn--hgebostad-g3a.no", + "hoyanger.no", + "xn--hyanger-q1a.no", + "hoylandet.no", + "xn--hylandet-54a.no", + "ha.no", + "xn--h-2fa.no", + "ibestad.no", + "inderoy.no", + "xn--indery-fya.no", + "iveland.no", + "jevnaker.no", + "jondal.no", + "jolster.no", + "xn--jlster-bya.no", + "karasjok.no", + "karasjohka.no", + "xn--krjohka-hwab49j.no", + "karlsoy.no", + "galsa.no", + "xn--gls-elac.no", + "karmoy.no", + "xn--karmy-yua.no", + "kautokeino.no", + "guovdageaidnu.no", + "klepp.no", + "klabu.no", + "xn--klbu-woa.no", + "kongsberg.no", + "kongsvinger.no", + "kragero.no", + "xn--krager-gya.no", + "kristiansand.no", + "kristiansund.no", + "krodsherad.no", + "xn--krdsherad-m8a.no", + "kvalsund.no", + "rahkkeravju.no", + "xn--rhkkervju-01af.no", + "kvam.no", + "kvinesdal.no", + "kvinnherad.no", + "kviteseid.no", + "kvitsoy.no", + "xn--kvitsy-fya.no", + "kvafjord.no", + "xn--kvfjord-nxa.no", + "giehtavuoatna.no", + "kvanangen.no", + "xn--kvnangen-k0a.no", + "navuotna.no", + "xn--nvuotna-hwa.no", + "kafjord.no", + "xn--kfjord-iua.no", + "gaivuotna.no", + "xn--givuotna-8ya.no", + "larvik.no", + "lavangen.no", + "lavagis.no", + "loabat.no", + "xn--loabt-0qa.no", + "lebesby.no", + "davvesiida.no", + "leikanger.no", + "leirfjord.no", + "leka.no", + "leksvik.no", + "lenvik.no", + "leangaviika.no", + "xn--leagaviika-52b.no", + "lesja.no", + "levanger.no", + "lier.no", + "lierne.no", + "lillehammer.no", + "lillesand.no", + "lindesnes.no", + "lindas.no", + "xn--linds-pra.no", + "lom.no", + "loppa.no", + "lahppi.no", + "xn--lhppi-xqa.no", + "lund.no", + "lunner.no", + "luroy.no", + "xn--lury-ira.no", + "luster.no", + "lyngdal.no", + "lyngen.no", + "ivgu.no", + "lardal.no", + "lerdal.no", + "xn--lrdal-sra.no", + "lodingen.no", + "xn--ldingen-q1a.no", + "lorenskog.no", + "xn--lrenskog-54a.no", + "loten.no", + "xn--lten-gra.no", + "malvik.no", + "masoy.no", + "xn--msy-ula0h.no", + "muosat.no", + "xn--muost-0qa.no", + "mandal.no", + "marker.no", + "marnardal.no", + "masfjorden.no", + "meland.no", + "meldal.no", + "melhus.no", + "meloy.no", + "xn--mely-ira.no", + "meraker.no", + "xn--merker-kua.no", + "moareke.no", + "xn--moreke-jua.no", + "midsund.no", + "midtre-gauldal.no", + "modalen.no", + "modum.no", + "molde.no", + "moskenes.no", + "moss.no", + "mosvik.no", + "malselv.no", + "xn--mlselv-iua.no", + "malatvuopmi.no", + "xn--mlatvuopmi-s4a.no", + "namdalseid.no", + "aejrie.no", + "namsos.no", + "namsskogan.no", + "naamesjevuemie.no", + "xn--nmesjevuemie-tcba.no", + "laakesvuemie.no", + "nannestad.no", + "narvik.no", + "narviika.no", + "naustdal.no", + "nedre-eiker.no", + "nes.akershus.no", + "nes.buskerud.no", + "nesna.no", + "nesodden.no", + "nesseby.no", + "unjarga.no", + "xn--unjrga-rta.no", + "nesset.no", + "nissedal.no", + "nittedal.no", + "nord-aurdal.no", + "nord-fron.no", + "nord-odal.no", + "norddal.no", + "nordkapp.no", + "davvenjarga.no", + "xn--davvenjrga-y4a.no", + "nordre-land.no", + "nordreisa.no", + "raisa.no", + "xn--risa-5na.no", + "nore-og-uvdal.no", + "notodden.no", + "naroy.no", + "xn--nry-yla5g.no", + "notteroy.no", + "xn--nttery-byae.no", + "odda.no", + "oksnes.no", + "xn--ksnes-uua.no", + "oppdal.no", + "oppegard.no", + "xn--oppegrd-ixa.no", + "orkdal.no", + "orland.no", + "xn--rland-uua.no", + "orskog.no", + "xn--rskog-uua.no", + "orsta.no", + "xn--rsta-fra.no", + "os.hedmark.no", + "os.hordaland.no", + "osen.no", + "osteroy.no", + "xn--ostery-fya.no", + "ostre-toten.no", + "xn--stre-toten-zcb.no", + "overhalla.no", + "ovre-eiker.no", + "xn--vre-eiker-k8a.no", + "oyer.no", + "xn--yer-zna.no", + "oygarden.no", + "xn--ygarden-p1a.no", + "oystre-slidre.no", + "xn--ystre-slidre-ujb.no", + "porsanger.no", + "porsangu.no", + "xn--porsgu-sta26f.no", + "porsgrunn.no", + "radoy.no", + "xn--rady-ira.no", + "rakkestad.no", + "rana.no", + "ruovat.no", + "randaberg.no", + "rauma.no", + "rendalen.no", + "rennebu.no", + "rennesoy.no", + "xn--rennesy-v1a.no", + "rindal.no", + "ringebu.no", + "ringerike.no", + "ringsaker.no", + "rissa.no", + "risor.no", + "xn--risr-ira.no", + "roan.no", + "rollag.no", + "rygge.no", + "ralingen.no", + "xn--rlingen-mxa.no", + "rodoy.no", + "xn--rdy-0nab.no", + "romskog.no", + "xn--rmskog-bya.no", + "roros.no", + "xn--rros-gra.no", + "rost.no", + "xn--rst-0na.no", + "royken.no", + "xn--ryken-vua.no", + "royrvik.no", + "xn--ryrvik-bya.no", + "rade.no", + "xn--rde-ula.no", + "salangen.no", + "siellak.no", + "saltdal.no", + "salat.no", + "xn--slt-elab.no", + "xn--slat-5na.no", + "samnanger.no", + "sande.more-og-romsdal.no", + "sande.xn--mre-og-romsdal-qqb.no", + "sande.vestfold.no", + "sandefjord.no", + "sandnes.no", + "sandoy.no", + "xn--sandy-yua.no", + "sarpsborg.no", + "sauda.no", + "sauherad.no", + "sel.no", + "selbu.no", + "selje.no", + "seljord.no", + "sigdal.no", + "siljan.no", + "sirdal.no", + "skaun.no", + "skedsmo.no", + "ski.no", + "skien.no", + "skiptvet.no", + "skjervoy.no", + "xn--skjervy-v1a.no", + "skierva.no", + "xn--skierv-uta.no", + "skjak.no", + "xn--skjk-soa.no", + "skodje.no", + "skanland.no", + "xn--sknland-fxa.no", + "skanit.no", + "xn--sknit-yqa.no", + "smola.no", + "xn--smla-hra.no", + "snillfjord.no", + "snasa.no", + "xn--snsa-roa.no", + "snoasa.no", + "snaase.no", + "xn--snase-nra.no", + "sogndal.no", + "sokndal.no", + "sola.no", + "solund.no", + "songdalen.no", + "sortland.no", + "spydeberg.no", + "stange.no", + "stavanger.no", + "steigen.no", + "steinkjer.no", + "stjordal.no", + "xn--stjrdal-s1a.no", + "stokke.no", + "stor-elvdal.no", + "stord.no", + "stordal.no", + "storfjord.no", + "omasvuotna.no", + "strand.no", + "stranda.no", + "stryn.no", + "sula.no", + "suldal.no", + "sund.no", + "sunndal.no", + "surnadal.no", + "sveio.no", + "svelvik.no", + "sykkylven.no", + "sogne.no", + "xn--sgne-gra.no", + "somna.no", + "xn--smna-gra.no", + "sondre-land.no", + "xn--sndre-land-0cb.no", + "sor-aurdal.no", + "xn--sr-aurdal-l8a.no", + "sor-fron.no", + "xn--sr-fron-q1a.no", + "sor-odal.no", + "xn--sr-odal-q1a.no", + "sor-varanger.no", + "xn--sr-varanger-ggb.no", + "matta-varjjat.no", + "xn--mtta-vrjjat-k7af.no", + "sorfold.no", + "xn--srfold-bya.no", + "sorreisa.no", + "xn--srreisa-q1a.no", + "sorum.no", + "xn--srum-gra.no", + "tana.no", + "deatnu.no", + "time.no", + "tingvoll.no", + "tinn.no", + "tjeldsund.no", + "dielddanuorri.no", + "tjome.no", + "xn--tjme-hra.no", + "tokke.no", + "tolga.no", + "torsken.no", + "tranoy.no", + "xn--trany-yua.no", + "tromso.no", + "xn--troms-zua.no", + "tromsa.no", + "romsa.no", + "trondheim.no", + "troandin.no", + "trysil.no", + "trana.no", + "xn--trna-woa.no", + "trogstad.no", + "xn--trgstad-r1a.no", + "tvedestrand.no", + "tydal.no", + "tynset.no", + "tysfjord.no", + "divtasvuodna.no", + "divttasvuotna.no", + "tysnes.no", + "tysvar.no", + "xn--tysvr-vra.no", + "tonsberg.no", + "xn--tnsberg-q1a.no", + "ullensaker.no", + "ullensvang.no", + "ulvik.no", + "utsira.no", + "vadso.no", + "xn--vads-jra.no", + "cahcesuolo.no", + "xn--hcesuolo-7ya35b.no", + "vaksdal.no", + "valle.no", + "vang.no", + "vanylven.no", + "vardo.no", + "xn--vard-jra.no", + "varggat.no", + "xn--vrggt-xqad.no", + "vefsn.no", + "vaapste.no", + "vega.no", + "vegarshei.no", + "xn--vegrshei-c0a.no", + "vennesla.no", + "verdal.no", + "verran.no", + "vestby.no", + "vestnes.no", + "vestre-slidre.no", + "vestre-toten.no", + "vestvagoy.no", + "xn--vestvgy-ixa6o.no", + "vevelstad.no", + "vik.no", + "vikna.no", + "vindafjord.no", + "volda.no", + "voss.no", + "varoy.no", + "xn--vry-yla5g.no", + "vagan.no", + "xn--vgan-qoa.no", + "voagat.no", + "vagsoy.no", + "xn--vgsy-qoa0j.no", + "vaga.no", + "xn--vg-yiab.no", + "valer.ostfold.no", + "xn--vler-qoa.xn--stfold-9xa.no", + "valer.hedmark.no", + "xn--vler-qoa.hedmark.no", + "*.np", + "nr", + "biz.nr", + "info.nr", + "gov.nr", + "edu.nr", + "org.nr", + "net.nr", + "com.nr", + "nu", + "nz", + "ac.nz", + "co.nz", + "cri.nz", + "geek.nz", + "gen.nz", + "govt.nz", + "health.nz", + "iwi.nz", + "kiwi.nz", + "maori.nz", + "mil.nz", + "xn--mori-qsa.nz", + "net.nz", + "org.nz", + "parliament.nz", + "school.nz", + "om", + "co.om", + "com.om", + "edu.om", + "gov.om", + "med.om", + "museum.om", + "net.om", + "org.om", + "pro.om", + "onion", + "org", + "pa", + "ac.pa", + "gob.pa", + "com.pa", + "org.pa", + "sld.pa", + "edu.pa", + "net.pa", + "ing.pa", + "abo.pa", + "med.pa", + "nom.pa", + "pe", + "edu.pe", + "gob.pe", + "nom.pe", + "mil.pe", + "org.pe", + "com.pe", + "net.pe", + "pf", + "com.pf", + "org.pf", + "edu.pf", + "*.pg", + "ph", + "com.ph", + "net.ph", + "org.ph", + "gov.ph", + "edu.ph", + "ngo.ph", + "mil.ph", + "i.ph", + "pk", + "com.pk", + "net.pk", + "edu.pk", + "org.pk", + "fam.pk", + "biz.pk", + "web.pk", + "gov.pk", + "gob.pk", + "gok.pk", + "gon.pk", + "gop.pk", + "gos.pk", + "info.pk", + "pl", + "com.pl", + "net.pl", + "org.pl", + "aid.pl", + "agro.pl", + "atm.pl", + "auto.pl", + "biz.pl", + "edu.pl", + "gmina.pl", + "gsm.pl", + "info.pl", + "mail.pl", + "miasta.pl", + "media.pl", + "mil.pl", + "nieruchomosci.pl", + "nom.pl", + "pc.pl", + "powiat.pl", + "priv.pl", + "realestate.pl", + "rel.pl", + "sex.pl", + "shop.pl", + "sklep.pl", + "sos.pl", + "szkola.pl", + "targi.pl", + "tm.pl", + "tourism.pl", + "travel.pl", + "turystyka.pl", + "gov.pl", + "ap.gov.pl", + "ic.gov.pl", + "is.gov.pl", + "us.gov.pl", + "kmpsp.gov.pl", + "kppsp.gov.pl", + "kwpsp.gov.pl", + "psp.gov.pl", + "wskr.gov.pl", + "kwp.gov.pl", + "mw.gov.pl", + "ug.gov.pl", + "um.gov.pl", + "umig.gov.pl", + "ugim.gov.pl", + "upow.gov.pl", + "uw.gov.pl", + "starostwo.gov.pl", + "pa.gov.pl", + "po.gov.pl", + "psse.gov.pl", + "pup.gov.pl", + "rzgw.gov.pl", + "sa.gov.pl", + "so.gov.pl", + "sr.gov.pl", + "wsa.gov.pl", + "sko.gov.pl", + "uzs.gov.pl", + "wiih.gov.pl", + "winb.gov.pl", + "pinb.gov.pl", + "wios.gov.pl", + "witd.gov.pl", + "wzmiuw.gov.pl", + "piw.gov.pl", + "wiw.gov.pl", + "griw.gov.pl", + "wif.gov.pl", + "oum.gov.pl", + "sdn.gov.pl", + "zp.gov.pl", + "uppo.gov.pl", + "mup.gov.pl", + "wuoz.gov.pl", + "konsulat.gov.pl", + "oirm.gov.pl", + "augustow.pl", + "babia-gora.pl", + "bedzin.pl", + "beskidy.pl", + "bialowieza.pl", + "bialystok.pl", + "bielawa.pl", + "bieszczady.pl", + "boleslawiec.pl", + "bydgoszcz.pl", + "bytom.pl", + "cieszyn.pl", + "czeladz.pl", + "czest.pl", + "dlugoleka.pl", + "elblag.pl", + "elk.pl", + "glogow.pl", + "gniezno.pl", + "gorlice.pl", + "grajewo.pl", + "ilawa.pl", + "jaworzno.pl", + "jelenia-gora.pl", + "jgora.pl", + "kalisz.pl", + "kazimierz-dolny.pl", + "karpacz.pl", + "kartuzy.pl", + "kaszuby.pl", + "katowice.pl", + "kepno.pl", + "ketrzyn.pl", + "klodzko.pl", + "kobierzyce.pl", + "kolobrzeg.pl", + "konin.pl", + "konskowola.pl", + "kutno.pl", + "lapy.pl", + "lebork.pl", + "legnica.pl", + "lezajsk.pl", + "limanowa.pl", + "lomza.pl", + "lowicz.pl", + "lubin.pl", + "lukow.pl", + "malbork.pl", + "malopolska.pl", + "mazowsze.pl", + "mazury.pl", + "mielec.pl", + "mielno.pl", + "mragowo.pl", + "naklo.pl", + "nowaruda.pl", + "nysa.pl", + "olawa.pl", + "olecko.pl", + "olkusz.pl", + "olsztyn.pl", + "opoczno.pl", + "opole.pl", + "ostroda.pl", + "ostroleka.pl", + "ostrowiec.pl", + "ostrowwlkp.pl", + "pila.pl", + "pisz.pl", + "podhale.pl", + "podlasie.pl", + "polkowice.pl", + "pomorze.pl", + "pomorskie.pl", + "prochowice.pl", + "pruszkow.pl", + "przeworsk.pl", + "pulawy.pl", + "radom.pl", + "rawa-maz.pl", + "rybnik.pl", + "rzeszow.pl", + "sanok.pl", + "sejny.pl", + "slask.pl", + "slupsk.pl", + "sosnowiec.pl", + "stalowa-wola.pl", + "skoczow.pl", + "starachowice.pl", + "stargard.pl", + "suwalki.pl", + "swidnica.pl", + "swiebodzin.pl", + "swinoujscie.pl", + "szczecin.pl", + "szczytno.pl", + "tarnobrzeg.pl", + "tgory.pl", + "turek.pl", + "tychy.pl", + "ustka.pl", + "walbrzych.pl", + "warmia.pl", + "warszawa.pl", + "waw.pl", + "wegrow.pl", + "wielun.pl", + "wlocl.pl", + "wloclawek.pl", + "wodzislaw.pl", + "wolomin.pl", + "wroclaw.pl", + "zachpomor.pl", + "zagan.pl", + "zarow.pl", + "zgora.pl", + "zgorzelec.pl", + "pm", + "pn", + "gov.pn", + "co.pn", + "org.pn", + "edu.pn", + "net.pn", + "post", + "pr", + "com.pr", + "net.pr", + "org.pr", + "gov.pr", + "edu.pr", + "isla.pr", + "pro.pr", + "biz.pr", + "info.pr", + "name.pr", + "est.pr", + "prof.pr", + "ac.pr", + "pro", + "aaa.pro", + "aca.pro", + "acct.pro", + "avocat.pro", + "bar.pro", + "cpa.pro", + "eng.pro", + "jur.pro", + "law.pro", + "med.pro", + "recht.pro", + "ps", + "edu.ps", + "gov.ps", + "sec.ps", + "plo.ps", + "com.ps", + "org.ps", + "net.ps", + "pt", + "net.pt", + "gov.pt", + "org.pt", + "edu.pt", + "int.pt", + "publ.pt", + "com.pt", + "nome.pt", + "pw", + "co.pw", + "ne.pw", + "or.pw", + "ed.pw", + "go.pw", + "belau.pw", + "py", + "com.py", + "coop.py", + "edu.py", + "gov.py", + "mil.py", + "net.py", + "org.py", + "qa", + "com.qa", + "edu.qa", + "gov.qa", + "mil.qa", + "name.qa", + "net.qa", + "org.qa", + "sch.qa", + "re", + "asso.re", + "com.re", + "nom.re", + "ro", + "arts.ro", + "com.ro", + "firm.ro", + "info.ro", + "nom.ro", + "nt.ro", + "org.ro", + "rec.ro", + "store.ro", + "tm.ro", + "www.ro", + "rs", + "ac.rs", + "co.rs", + "edu.rs", + "gov.rs", + "in.rs", + "org.rs", + "ru", + "ac.ru", + "edu.ru", + "gov.ru", + "int.ru", + "mil.ru", + "test.ru", + "rw", + "ac.rw", + "co.rw", + "coop.rw", + "gov.rw", + "mil.rw", + "net.rw", + "org.rw", + "sa", + "com.sa", + "net.sa", + "org.sa", + "gov.sa", + "med.sa", + "pub.sa", + "edu.sa", + "sch.sa", + "sb", + "com.sb", + "edu.sb", + "gov.sb", + "net.sb", + "org.sb", + "sc", + "com.sc", + "gov.sc", + "net.sc", + "org.sc", + "edu.sc", + "sd", + "com.sd", + "net.sd", + "org.sd", + "edu.sd", + "med.sd", + "tv.sd", + "gov.sd", + "info.sd", + "se", + "a.se", + "ac.se", + "b.se", + "bd.se", + "brand.se", + "c.se", + "d.se", + "e.se", + "f.se", + "fh.se", + "fhsk.se", + "fhv.se", + "g.se", + "h.se", + "i.se", + "k.se", + "komforb.se", + "kommunalforbund.se", + "komvux.se", + "l.se", + "lanbib.se", + "m.se", + "n.se", + "naturbruksgymn.se", + "o.se", + "org.se", + "p.se", + "parti.se", + "pp.se", + "press.se", + "r.se", + "s.se", + "t.se", + "tm.se", + "u.se", + "w.se", + "x.se", + "y.se", + "z.se", + "sg", + "com.sg", + "net.sg", + "org.sg", + "gov.sg", + "edu.sg", + "per.sg", + "sh", + "com.sh", + "net.sh", + "gov.sh", + "org.sh", + "mil.sh", + "si", + "sj", + "sk", + "sl", + "com.sl", + "net.sl", + "edu.sl", + "gov.sl", + "org.sl", + "sm", + "sn", + "art.sn", + "com.sn", + "edu.sn", + "gouv.sn", + "org.sn", + "perso.sn", + "univ.sn", + "so", + "com.so", + "net.so", + "org.so", + "sr", + "st", + "co.st", + "com.st", + "consulado.st", + "edu.st", + "embaixada.st", + "gov.st", + "mil.st", + "net.st", + "org.st", + "principe.st", + "saotome.st", + "store.st", + "su", + "sv", + "com.sv", + "edu.sv", + "gob.sv", + "org.sv", + "red.sv", + "sx", + "gov.sx", + "sy", + "edu.sy", + "gov.sy", + "net.sy", + "mil.sy", + "com.sy", + "org.sy", + "sz", + "co.sz", + "ac.sz", + "org.sz", + "tc", + "td", + "tel", + "tf", + "tg", + "th", + "ac.th", + "co.th", + "go.th", + "in.th", + "mi.th", + "net.th", + "or.th", + "tj", + "ac.tj", + "biz.tj", + "co.tj", + "com.tj", + "edu.tj", + "go.tj", + "gov.tj", + "int.tj", + "mil.tj", + "name.tj", + "net.tj", + "nic.tj", + "org.tj", + "test.tj", + "web.tj", + "tk", + "tl", + "gov.tl", + "tm", + "com.tm", + "co.tm", + "org.tm", + "net.tm", + "nom.tm", + "gov.tm", + "mil.tm", + "edu.tm", + "tn", + "com.tn", + "ens.tn", + "fin.tn", + "gov.tn", + "ind.tn", + "intl.tn", + "nat.tn", + "net.tn", + "org.tn", + "info.tn", + "perso.tn", + "tourism.tn", + "edunet.tn", + "rnrt.tn", + "rns.tn", + "rnu.tn", + "mincom.tn", + "agrinet.tn", + "defense.tn", + "turen.tn", + "to", + "com.to", + "gov.to", + "net.to", + "org.to", + "edu.to", + "mil.to", + "tr", + "av.tr", + "bbs.tr", + "bel.tr", + "biz.tr", + "com.tr", + "dr.tr", + "edu.tr", + "gen.tr", + "gov.tr", + "info.tr", + "mil.tr", + "k12.tr", + "kep.tr", + "name.tr", + "net.tr", + "org.tr", + "pol.tr", + "tel.tr", + "tsk.tr", + "tv.tr", + "web.tr", + "nc.tr", + "gov.nc.tr", + "tt", + "co.tt", + "com.tt", + "org.tt", + "net.tt", + "biz.tt", + "info.tt", + "pro.tt", + "int.tt", + "coop.tt", + "jobs.tt", + "mobi.tt", + "travel.tt", + "museum.tt", + "aero.tt", + "name.tt", + "gov.tt", + "edu.tt", + "tv", + "tw", + "edu.tw", + "gov.tw", + "mil.tw", + "com.tw", + "net.tw", + "org.tw", + "idv.tw", + "game.tw", + "ebiz.tw", + "club.tw", + "xn--zf0ao64a.tw", + "xn--uc0atv.tw", + "xn--czrw28b.tw", + "tz", + "ac.tz", + "co.tz", + "go.tz", + "hotel.tz", + "info.tz", + "me.tz", + "mil.tz", + "mobi.tz", + "ne.tz", + "or.tz", + "sc.tz", + "tv.tz", + "ua", + "com.ua", + "edu.ua", + "gov.ua", + "in.ua", + "net.ua", + "org.ua", + "cherkassy.ua", + "cherkasy.ua", + "chernigov.ua", + "chernihiv.ua", + "chernivtsi.ua", + "chernovtsy.ua", + "ck.ua", + "cn.ua", + "cr.ua", + "crimea.ua", + "cv.ua", + "dn.ua", + "dnepropetrovsk.ua", + "dnipropetrovsk.ua", + "dominic.ua", + "donetsk.ua", + "dp.ua", + "if.ua", + "ivano-frankivsk.ua", + "kh.ua", + "kharkiv.ua", + "kharkov.ua", + "kherson.ua", + "khmelnitskiy.ua", + "khmelnytskyi.ua", + "kiev.ua", + "kirovograd.ua", + "km.ua", + "kr.ua", + "krym.ua", + "ks.ua", + "kv.ua", + "kyiv.ua", + "lg.ua", + "lt.ua", + "lugansk.ua", + "lutsk.ua", + "lv.ua", + "lviv.ua", + "mk.ua", + "mykolaiv.ua", + "nikolaev.ua", + "od.ua", + "odesa.ua", + "odessa.ua", + "pl.ua", + "poltava.ua", + "rivne.ua", + "rovno.ua", + "rv.ua", + "sb.ua", + "sebastopol.ua", + "sevastopol.ua", + "sm.ua", + "sumy.ua", + "te.ua", + "ternopil.ua", + "uz.ua", + "uzhgorod.ua", + "vinnica.ua", + "vinnytsia.ua", + "vn.ua", + "volyn.ua", + "yalta.ua", + "zaporizhzhe.ua", + "zaporizhzhia.ua", + "zhitomir.ua", + "zhytomyr.ua", + "zp.ua", + "zt.ua", + "ug", + "co.ug", + "or.ug", + "ac.ug", + "sc.ug", + "go.ug", + "ne.ug", + "com.ug", + "org.ug", + "uk", + "ac.uk", + "co.uk", + "gov.uk", + "ltd.uk", + "me.uk", + "net.uk", + "nhs.uk", + "org.uk", + "plc.uk", + "police.uk", + "*.sch.uk", + "us", + "dni.us", + "fed.us", + "isa.us", + "kids.us", + "nsn.us", + "ak.us", + "al.us", + "ar.us", + "as.us", + "az.us", + "ca.us", + "co.us", + "ct.us", + "dc.us", + "de.us", + "fl.us", + "ga.us", + "gu.us", + "hi.us", + "ia.us", + "id.us", + "il.us", + "in.us", + "ks.us", + "ky.us", + "la.us", + "ma.us", + "md.us", + "me.us", + "mi.us", + "mn.us", + "mo.us", + "ms.us", + "mt.us", + "nc.us", + "nd.us", + "ne.us", + "nh.us", + "nj.us", + "nm.us", + "nv.us", + "ny.us", + "oh.us", + "ok.us", + "or.us", + "pa.us", + "pr.us", + "ri.us", + "sc.us", + "sd.us", + "tn.us", + "tx.us", + "ut.us", + "vi.us", + "vt.us", + "va.us", + "wa.us", + "wi.us", + "wv.us", + "wy.us", + "k12.ak.us", + "k12.al.us", + "k12.ar.us", + "k12.as.us", + "k12.az.us", + "k12.ca.us", + "k12.co.us", + "k12.ct.us", + "k12.dc.us", + "k12.de.us", + "k12.fl.us", + "k12.ga.us", + "k12.gu.us", + "k12.ia.us", + "k12.id.us", + "k12.il.us", + "k12.in.us", + "k12.ks.us", + "k12.ky.us", + "k12.la.us", + "k12.ma.us", + "k12.md.us", + "k12.me.us", + "k12.mi.us", + "k12.mn.us", + "k12.mo.us", + "k12.ms.us", + "k12.mt.us", + "k12.nc.us", + "k12.ne.us", + "k12.nh.us", + "k12.nj.us", + "k12.nm.us", + "k12.nv.us", + "k12.ny.us", + "k12.oh.us", + "k12.ok.us", + "k12.or.us", + "k12.pa.us", + "k12.pr.us", + "k12.ri.us", + "k12.sc.us", + "k12.tn.us", + "k12.tx.us", + "k12.ut.us", + "k12.vi.us", + "k12.vt.us", + "k12.va.us", + "k12.wa.us", + "k12.wi.us", + "k12.wy.us", + "cc.ak.us", + "cc.al.us", + "cc.ar.us", + "cc.as.us", + "cc.az.us", + "cc.ca.us", + "cc.co.us", + "cc.ct.us", + "cc.dc.us", + "cc.de.us", + "cc.fl.us", + "cc.ga.us", + "cc.gu.us", + "cc.hi.us", + "cc.ia.us", + "cc.id.us", + "cc.il.us", + "cc.in.us", + "cc.ks.us", + "cc.ky.us", + "cc.la.us", + "cc.ma.us", + "cc.md.us", + "cc.me.us", + "cc.mi.us", + "cc.mn.us", + "cc.mo.us", + "cc.ms.us", + "cc.mt.us", + "cc.nc.us", + "cc.nd.us", + "cc.ne.us", + "cc.nh.us", + "cc.nj.us", + "cc.nm.us", + "cc.nv.us", + "cc.ny.us", + "cc.oh.us", + "cc.ok.us", + "cc.or.us", + "cc.pa.us", + "cc.pr.us", + "cc.ri.us", + "cc.sc.us", + "cc.sd.us", + "cc.tn.us", + "cc.tx.us", + "cc.ut.us", + "cc.vi.us", + "cc.vt.us", + "cc.va.us", + "cc.wa.us", + "cc.wi.us", + "cc.wv.us", + "cc.wy.us", + "lib.ak.us", + "lib.al.us", + "lib.ar.us", + "lib.as.us", + "lib.az.us", + "lib.ca.us", + "lib.co.us", + "lib.ct.us", + "lib.dc.us", + "lib.fl.us", + "lib.ga.us", + "lib.gu.us", + "lib.hi.us", + "lib.ia.us", + "lib.id.us", + "lib.il.us", + "lib.in.us", + "lib.ks.us", + "lib.ky.us", + "lib.la.us", + "lib.ma.us", + "lib.md.us", + "lib.me.us", + "lib.mi.us", + "lib.mn.us", + "lib.mo.us", + "lib.ms.us", + "lib.mt.us", + "lib.nc.us", + "lib.nd.us", + "lib.ne.us", + "lib.nh.us", + "lib.nj.us", + "lib.nm.us", + "lib.nv.us", + "lib.ny.us", + "lib.oh.us", + "lib.ok.us", + "lib.or.us", + "lib.pa.us", + "lib.pr.us", + "lib.ri.us", + "lib.sc.us", + "lib.sd.us", + "lib.tn.us", + "lib.tx.us", + "lib.ut.us", + "lib.vi.us", + "lib.vt.us", + "lib.va.us", + "lib.wa.us", + "lib.wi.us", + "lib.wy.us", + "pvt.k12.ma.us", + "chtr.k12.ma.us", + "paroch.k12.ma.us", + "ann-arbor.mi.us", + "cog.mi.us", + "dst.mi.us", + "eaton.mi.us", + "gen.mi.us", + "mus.mi.us", + "tec.mi.us", + "washtenaw.mi.us", + "uy", + "com.uy", + "edu.uy", + "gub.uy", + "mil.uy", + "net.uy", + "org.uy", + "uz", + "co.uz", + "com.uz", + "net.uz", + "org.uz", + "va", + "vc", + "com.vc", + "net.vc", + "org.vc", + "gov.vc", + "mil.vc", + "edu.vc", + "ve", + "arts.ve", + "co.ve", + "com.ve", + "e12.ve", + "edu.ve", + "firm.ve", + "gob.ve", + "gov.ve", + "info.ve", + "int.ve", + "mil.ve", + "net.ve", + "org.ve", + "rec.ve", + "store.ve", + "tec.ve", + "web.ve", + "vg", + "vi", + "co.vi", + "com.vi", + "k12.vi", + "net.vi", + "org.vi", + "vn", + "com.vn", + "net.vn", + "org.vn", + "edu.vn", + "gov.vn", + "int.vn", + "ac.vn", + "biz.vn", + "info.vn", + "name.vn", + "pro.vn", + "health.vn", + "vu", + "com.vu", + "edu.vu", + "net.vu", + "org.vu", + "wf", + "ws", + "com.ws", + "net.ws", + "org.ws", + "gov.ws", + "edu.ws", + "yt", + "xn--mgbaam7a8h", + "xn--y9a3aq", + "xn--54b7fta0cc", + "xn--90ae", + "xn--90ais", + "xn--fiqs8s", + "xn--fiqz9s", + "xn--lgbbat1ad8j", + "xn--wgbh1c", + "xn--e1a4c", + "xn--node", + "xn--qxam", + "xn--j6w193g", + "xn--55qx5d.xn--j6w193g", + "xn--wcvs22d.xn--j6w193g", + "xn--mxtq1m.xn--j6w193g", + "xn--gmqw5a.xn--j6w193g", + "xn--od0alg.xn--j6w193g", + "xn--uc0atv.xn--j6w193g", + "xn--2scrj9c", + "xn--3hcrj9c", + "xn--45br5cyl", + "xn--h2breg3eve", + "xn--h2brj9c8c", + "xn--mgbgu82a", + "xn--rvc1e0am3e", + "xn--h2brj9c", + "xn--mgbbh1a", + "xn--mgbbh1a71e", + "xn--fpcrj9c3d", + "xn--gecrj9c", + "xn--s9brj9c", + "xn--45brj9c", + "xn--xkc2dl3a5ee0h", + "xn--mgba3a4f16a", + "xn--mgba3a4fra", + "xn--mgbtx2b", + "xn--mgbayh7gpa", + "xn--3e0b707e", + "xn--80ao21a", + "xn--fzc2c9e2c", + "xn--xkc2al3hye2a", + "xn--mgbc0a9azcg", + "xn--d1alf", + "xn--l1acc", + "xn--mix891f", + "xn--mix082f", + "xn--mgbx4cd0ab", + "xn--mgb9awbf", + "xn--mgbai9azgqp6j", + "xn--mgbai9a5eva00b", + "xn--ygbi2ammx", + "xn--90a3ac", + "xn--o1ac.xn--90a3ac", + "xn--c1avg.xn--90a3ac", + "xn--90azh.xn--90a3ac", + "xn--d1at.xn--90a3ac", + "xn--o1ach.xn--90a3ac", + "xn--80au.xn--90a3ac", + "xn--p1ai", + "xn--wgbl6a", + "xn--mgberp4a5d4ar", + "xn--mgberp4a5d4a87g", + "xn--mgbqly7c0a67fbc", + "xn--mgbqly7cvafr", + "xn--mgbpl2fh", + "xn--yfro4i67o", + "xn--clchc0ea0b2g2a9gcd", + "xn--ogbpf8fl", + "xn--mgbtf8fl", + "xn--o3cw4h", + "xn--12c1fe0br.xn--o3cw4h", + "xn--12co0c3b4eva.xn--o3cw4h", + "xn--h3cuzk1di.xn--o3cw4h", + "xn--o3cyx2a.xn--o3cw4h", + "xn--m3ch0j3a.xn--o3cw4h", + "xn--12cfi8ixb8l.xn--o3cw4h", + "xn--pgbs0dh", + "xn--kpry57d", + "xn--kprw13d", + "xn--nnx388a", + "xn--j1amh", + "xn--mgb2ddes", + "xxx", + "*.ye", + "ac.za", + "agric.za", + "alt.za", + "co.za", + "edu.za", + "gov.za", + "grondar.za", + "law.za", + "mil.za", + "net.za", + "ngo.za", + "nis.za", + "nom.za", + "org.za", + "school.za", + "tm.za", + "web.za", + "zm", + "ac.zm", + "biz.zm", + "co.zm", + "com.zm", + "edu.zm", + "gov.zm", + "info.zm", + "mil.zm", + "net.zm", + "org.zm", + "sch.zm", + "zw", + "ac.zw", + "co.zw", + "gov.zw", + "mil.zw", + "org.zw", + "aaa", + "aarp", + "abarth", + "abb", + "abbott", + "abbvie", + "abc", + "able", + "abogado", + "abudhabi", + "academy", + "accenture", + "accountant", + "accountants", + "aco", + "actor", + "adac", + "ads", + "adult", + "aeg", + "aetna", + "afamilycompany", + "afl", + "africa", + "agakhan", + "agency", + "aig", + "aigo", + "airbus", + "airforce", + "airtel", + "akdn", + "alfaromeo", + "alibaba", + "alipay", + "allfinanz", + "allstate", + "ally", + "alsace", + "alstom", + "americanexpress", + "americanfamily", + "amex", + "amfam", + "amica", + "amsterdam", + "analytics", + "android", + "anquan", + "anz", + "aol", + "apartments", + "app", + "apple", + "aquarelle", + "arab", + "aramco", + "archi", + "army", + "art", + "arte", + "asda", + "associates", + "athleta", + "attorney", + "auction", + "audi", + "audible", + "audio", + "auspost", + "author", + "auto", + "autos", + "avianca", + "aws", + "axa", + "azure", + "baby", + "baidu", + "banamex", + "bananarepublic", + "band", + "bank", + "bar", + "barcelona", + "barclaycard", + "barclays", + "barefoot", + "bargains", + "baseball", + "basketball", + "bauhaus", + "bayern", + "bbc", + "bbt", + "bbva", + "bcg", + "bcn", + "beats", + "beauty", + "beer", + "bentley", + "berlin", + "best", + "bestbuy", + "bet", + "bharti", + "bible", + "bid", + "bike", + "bing", + "bingo", + "bio", + "black", + "blackfriday", + "blockbuster", + "blog", + "bloomberg", + "blue", + "bms", + "bmw", + "bnl", + "bnpparibas", + "boats", + "boehringer", + "bofa", + "bom", + "bond", + "boo", + "book", + "booking", + "bosch", + "bostik", + "boston", + "bot", + "boutique", + "box", + "bradesco", + "bridgestone", + "broadway", + "broker", + "brother", + "brussels", + "budapest", + "bugatti", + "build", + "builders", + "business", + "buy", + "buzz", + "bzh", + "cab", + "cafe", + "cal", + "call", + "calvinklein", + "cam", + "camera", + "camp", + "cancerresearch", + "canon", + "capetown", + "capital", + "capitalone", + "car", + "caravan", + "cards", + "care", + "career", + "careers", + "cars", + "cartier", + "casa", + "case", + "caseih", + "cash", + "casino", + "catering", + "catholic", + "cba", + "cbn", + "cbre", + "cbs", + "ceb", + "center", + "ceo", + "cern", + "cfa", + "cfd", + "chanel", + "channel", + "charity", + "chase", + "chat", + "cheap", + "chintai", + "christmas", + "chrome", + "chrysler", + "church", + "cipriani", + "circle", + "cisco", + "citadel", + "citi", + "citic", + "city", + "cityeats", + "claims", + "cleaning", + "click", + "clinic", + "clinique", + "clothing", + "cloud", + "club", + "clubmed", + "coach", + "codes", + "coffee", + "college", + "cologne", + "comcast", + "commbank", + "community", + "company", + "compare", + "computer", + "comsec", + "condos", + "construction", + "consulting", + "contact", + "contractors", + "cooking", + "cookingchannel", + "cool", + "corsica", + "country", + "coupon", + "coupons", + "courses", + "credit", + "creditcard", + "creditunion", + "cricket", + "crown", + "crs", + "cruise", + "cruises", + "csc", + "cuisinella", + "cymru", + "cyou", + "dabur", + "dad", + "dance", + "data", + "date", + "dating", + "datsun", + "day", + "dclk", + "dds", + "deal", + "dealer", + "deals", + "degree", + "delivery", + "dell", + "deloitte", + "delta", + "democrat", + "dental", + "dentist", + "desi", + "design", + "dev", + "dhl", + "diamonds", + "diet", + "digital", + "direct", + "directory", + "discount", + "discover", + "dish", + "diy", + "dnp", + "docs", + "doctor", + "dodge", + "dog", + "domains", + "dot", + "download", + "drive", + "dtv", + "dubai", + "duck", + "dunlop", + "duns", + "dupont", + "durban", + "dvag", + "dvr", + "earth", + "eat", + "eco", + "edeka", + "education", + "email", + "emerck", + "energy", + "engineer", + "engineering", + "enterprises", + "epson", + "equipment", + "ericsson", + "erni", + "esq", + "estate", + "esurance", + "etisalat", + "eurovision", + "eus", + "events", + "everbank", + "exchange", + "expert", + "exposed", + "express", + "extraspace", + "fage", + "fail", + "fairwinds", + "faith", + "family", + "fan", + "fans", + "farm", + "farmers", + "fashion", + "fast", + "fedex", + "feedback", + "ferrari", + "ferrero", + "fiat", + "fidelity", + "fido", + "film", + "final", + "finance", + "financial", + "fire", + "firestone", + "firmdale", + "fish", + "fishing", + "fit", + "fitness", + "flickr", + "flights", + "flir", + "florist", + "flowers", + "fly", + "foo", + "food", + "foodnetwork", + "football", + "ford", + "forex", + "forsale", + "forum", + "foundation", + "fox", + "free", + "fresenius", + "frl", + "frogans", + "frontdoor", + "frontier", + "ftr", + "fujitsu", + "fujixerox", + "fun", + "fund", + "furniture", + "futbol", + "fyi", + "gal", + "gallery", + "gallo", + "gallup", + "game", + "games", + "gap", + "garden", + "gbiz", + "gdn", + "gea", + "gent", + "genting", + "george", + "ggee", + "gift", + "gifts", + "gives", + "giving", + "glade", + "glass", + "gle", + "global", + "globo", + "gmail", + "gmbh", + "gmo", + "gmx", + "godaddy", + "gold", + "goldpoint", + "golf", + "goo", + "goodyear", + "goog", + "google", + "gop", + "got", + "grainger", + "graphics", + "gratis", + "green", + "gripe", + "grocery", + "group", + "guardian", + "gucci", + "guge", + "guide", + "guitars", + "guru", + "hair", + "hamburg", + "hangout", + "haus", + "hbo", + "hdfc", + "hdfcbank", + "health", + "healthcare", + "help", + "helsinki", + "here", + "hermes", + "hgtv", + "hiphop", + "hisamitsu", + "hitachi", + "hiv", + "hkt", + "hockey", + "holdings", + "holiday", + "homedepot", + "homegoods", + "homes", + "homesense", + "honda", + "honeywell", + "horse", + "hospital", + "host", + "hosting", + "hot", + "hoteles", + "hotels", + "hotmail", + "house", + "how", + "hsbc", + "hughes", + "hyatt", + "hyundai", + "ibm", + "icbc", + "ice", + "icu", + "ieee", + "ifm", + "ikano", + "imamat", + "imdb", + "immo", + "immobilien", + "inc", + "industries", + "infiniti", + "ing", + "ink", + "institute", + "insurance", + "insure", + "intel", + "international", + "intuit", + "investments", + "ipiranga", + "irish", + "iselect", + "ismaili", + "ist", + "istanbul", + "itau", + "itv", + "iveco", + "jaguar", + "java", + "jcb", + "jcp", + "jeep", + "jetzt", + "jewelry", + "jio", + "jll", + "jmp", + "jnj", + "joburg", + "jot", + "joy", + "jpmorgan", + "jprs", + "juegos", + "juniper", + "kaufen", + "kddi", + "kerryhotels", + "kerrylogistics", + "kerryproperties", + "kfh", + "kia", + "kim", + "kinder", + "kindle", + "kitchen", + "kiwi", + "koeln", + "komatsu", + "kosher", + "kpmg", + "kpn", + "krd", + "kred", + "kuokgroup", + "kyoto", + "lacaixa", + "ladbrokes", + "lamborghini", + "lamer", + "lancaster", + "lancia", + "lancome", + "land", + "landrover", + "lanxess", + "lasalle", + "lat", + "latino", + "latrobe", + "law", + "lawyer", + "lds", + "lease", + "leclerc", + "lefrak", + "legal", + "lego", + "lexus", + "lgbt", + "liaison", + "lidl", + "life", + "lifeinsurance", + "lifestyle", + "lighting", + "like", + "lilly", + "limited", + "limo", + "lincoln", + "linde", + "link", + "lipsy", + "live", + "living", + "lixil", + "llc", + "loan", + "loans", + "locker", + "locus", + "loft", + "lol", + "london", + "lotte", + "lotto", + "love", + "lpl", + "lplfinancial", + "ltd", + "ltda", + "lundbeck", + "lupin", + "luxe", + "luxury", + "macys", + "madrid", + "maif", + "maison", + "makeup", + "man", + "management", + "mango", + "map", + "market", + "marketing", + "markets", + "marriott", + "marshalls", + "maserati", + "mattel", + "mba", + "mckinsey", + "med", + "media", + "meet", + "melbourne", + "meme", + "memorial", + "men", + "menu", + "merckmsd", + "metlife", + "miami", + "microsoft", + "mini", + "mint", + "mit", + "mitsubishi", + "mlb", + "mls", + "mma", + "mobile", + "mobily", + "moda", + "moe", + "moi", + "mom", + "monash", + "money", + "monster", + "mopar", + "mormon", + "mortgage", + "moscow", + "moto", + "motorcycles", + "mov", + "movie", + "movistar", + "msd", + "mtn", + "mtr", + "mutual", + "nab", + "nadex", + "nagoya", + "nationwide", + "natura", + "navy", + "nba", + "nec", + "netbank", + "netflix", + "network", + "neustar", + "new", + "newholland", + "news", + "next", + "nextdirect", + "nexus", + "nfl", + "ngo", + "nhk", + "nico", + "nike", + "nikon", + "ninja", + "nissan", + "nissay", + "nokia", + "northwesternmutual", + "norton", + "now", + "nowruz", + "nowtv", + "nra", + "nrw", + "ntt", + "nyc", + "obi", + "observer", + "off", + "office", + "okinawa", + "olayan", + "olayangroup", + "oldnavy", + "ollo", + "omega", + "one", + "ong", + "onl", + "online", + "onyourside", + "ooo", + "open", + "oracle", + "orange", + "organic", + "origins", + "osaka", + "otsuka", + "ott", + "ovh", + "page", + "panasonic", + "paris", + "pars", + "partners", + "parts", + "party", + "passagens", + "pay", + "pccw", + "pet", + "pfizer", + "pharmacy", + "phd", + "philips", + "phone", + "photo", + "photography", + "photos", + "physio", + "piaget", + "pics", + "pictet", + "pictures", + "pid", + "pin", + "ping", + "pink", + "pioneer", + "pizza", + "place", + "play", + "playstation", + "plumbing", + "plus", + "pnc", + "pohl", + "poker", + "politie", + "porn", + "pramerica", + "praxi", + "press", + "prime", + "prod", + "productions", + "prof", + "progressive", + "promo", + "properties", + "property", + "protection", + "pru", + "prudential", + "pub", + "pwc", + "qpon", + "quebec", + "quest", + "qvc", + "racing", + "radio", + "raid", + "read", + "realestate", + "realtor", + "realty", + "recipes", + "red", + "redstone", + "redumbrella", + "rehab", + "reise", + "reisen", + "reit", + "reliance", + "ren", + "rent", + "rentals", + "repair", + "report", + "republican", + "rest", + "restaurant", + "review", + "reviews", + "rexroth", + "rich", + "richardli", + "ricoh", + "rightathome", + "ril", + "rio", + "rip", + "rmit", + "rocher", + "rocks", + "rodeo", + "rogers", + "room", + "rsvp", + "rugby", + "ruhr", + "run", + "rwe", + "ryukyu", + "saarland", + "safe", + "safety", + "sakura", + "sale", + "salon", + "samsclub", + "samsung", + "sandvik", + "sandvikcoromant", + "sanofi", + "sap", + "sarl", + "sas", + "save", + "saxo", + "sbi", + "sbs", + "sca", + "scb", + "schaeffler", + "schmidt", + "scholarships", + "school", + "schule", + "schwarz", + "science", + "scjohnson", + "scor", + "scot", + "search", + "seat", + "secure", + "security", + "seek", + "select", + "sener", + "services", + "ses", + "seven", + "sew", + "sex", + "sexy", + "sfr", + "shangrila", + "sharp", + "shaw", + "shell", + "shia", + "shiksha", + "shoes", + "shop", + "shopping", + "shouji", + "show", + "showtime", + "shriram", + "silk", + "sina", + "singles", + "site", + "ski", + "skin", + "sky", + "skype", + "sling", + "smart", + "smile", + "sncf", + "soccer", + "social", + "softbank", + "software", + "sohu", + "solar", + "solutions", + "song", + "sony", + "soy", + "space", + "sport", + "spot", + "spreadbetting", + "srl", + "srt", + "stada", + "staples", + "star", + "starhub", + "statebank", + "statefarm", + "stc", + "stcgroup", + "stockholm", + "storage", + "store", + "stream", + "studio", + "study", + "style", + "sucks", + "supplies", + "supply", + "support", + "surf", + "surgery", + "suzuki", + "swatch", + "swiftcover", + "swiss", + "sydney", + "symantec", + "systems", + "tab", + "taipei", + "talk", + "taobao", + "target", + "tatamotors", + "tatar", + "tattoo", + "tax", + "taxi", + "tci", + "tdk", + "team", + "tech", + "technology", + "telefonica", + "temasek", + "tennis", + "teva", + "thd", + "theater", + "theatre", + "tiaa", + "tickets", + "tienda", + "tiffany", + "tips", + "tires", + "tirol", + "tjmaxx", + "tjx", + "tkmaxx", + "tmall", + "today", + "tokyo", + "tools", + "top", + "toray", + "toshiba", + "total", + "tours", + "town", + "toyota", + "toys", + "trade", + "trading", + "training", + "travel", + "travelchannel", + "travelers", + "travelersinsurance", + "trust", + "trv", + "tube", + "tui", + "tunes", + "tushu", + "tvs", + "ubank", + "ubs", + "uconnect", + "unicom", + "university", + "uno", + "uol", + "ups", + "vacations", + "vana", + "vanguard", + "vegas", + "ventures", + "verisign", + "versicherung", + "vet", + "viajes", + "video", + "vig", + "viking", + "villas", + "vin", + "vip", + "virgin", + "visa", + "vision", + "vistaprint", + "viva", + "vivo", + "vlaanderen", + "vodka", + "volkswagen", + "volvo", + "vote", + "voting", + "voto", + "voyage", + "vuelos", + "wales", + "walmart", + "walter", + "wang", + "wanggou", + "warman", + "watch", + "watches", + "weather", + "weatherchannel", + "webcam", + "weber", + "website", + "wed", + "wedding", + "weibo", + "weir", + "whoswho", + "wien", + "wiki", + "williamhill", + "win", + "windows", + "wine", + "winners", + "wme", + "wolterskluwer", + "woodside", + "work", + "works", + "world", + "wow", + "wtc", + "wtf", + "xbox", + "xerox", + "xfinity", + "xihuan", + "xin", + "xn--11b4c3d", + "xn--1ck2e1b", + "xn--1qqw23a", + "xn--30rr7y", + "xn--3bst00m", + "xn--3ds443g", + "xn--3oq18vl8pn36a", + "xn--3pxu8k", + "xn--42c2d9a", + "xn--45q11c", + "xn--4gbrim", + "xn--55qw42g", + "xn--55qx5d", + "xn--5su34j936bgsg", + "xn--5tzm5g", + "xn--6frz82g", + "xn--6qq986b3xl", + "xn--80adxhks", + "xn--80aqecdr1a", + "xn--80asehdb", + "xn--80aswg", + "xn--8y0a063a", + "xn--9dbq2a", + "xn--9et52u", + "xn--9krt00a", + "xn--b4w605ferd", + "xn--bck1b9a5dre4c", + "xn--c1avg", + "xn--c2br7g", + "xn--cck2b3b", + "xn--cg4bki", + "xn--czr694b", + "xn--czrs0t", + "xn--czru2d", + "xn--d1acj3b", + "xn--eckvdtc9d", + "xn--efvy88h", + "xn--estv75g", + "xn--fct429k", + "xn--fhbei", + "xn--fiq228c5hs", + "xn--fiq64b", + "xn--fjq720a", + "xn--flw351e", + "xn--fzys8d69uvgm", + "xn--g2xx48c", + "xn--gckr3f0f", + "xn--gk3at1e", + "xn--hxt814e", + "xn--i1b6b1a6a2e", + "xn--imr513n", + "xn--io0a7i", + "xn--j1aef", + "xn--jlq61u9w7b", + "xn--jvr189m", + "xn--kcrx77d1x4a", + "xn--kpu716f", + "xn--kput3i", + "xn--mgba3a3ejt", + "xn--mgba7c0bbn0a", + "xn--mgbaakc7dvf", + "xn--mgbab2bd", + "xn--mgbb9fbpob", + "xn--mgbca7dzdo", + "xn--mgbi4ecexp", + "xn--mgbt3dhd", + "xn--mk1bu44c", + "xn--mxtq1m", + "xn--ngbc5azd", + "xn--ngbe9e0a", + "xn--ngbrx", + "xn--nqv7f", + "xn--nqv7fs00ema", + "xn--nyqy26a", + "xn--otu796d", + "xn--p1acf", + "xn--pbt977c", + "xn--pssy2u", + "xn--q9jyb4c", + "xn--qcka1pmc", + "xn--rhqv96g", + "xn--rovu88b", + "xn--ses554g", + "xn--t60b56a", + "xn--tckwe", + "xn--tiq49xqyj", + "xn--unup4y", + "xn--vermgensberater-ctb", + "xn--vermgensberatung-pwb", + "xn--vhquv", + "xn--vuq861b", + "xn--w4r85el8fhu5dnra", + "xn--w4rs40l", + "xn--xhq521b", + "xn--zfr164b", + "xyz", + "yachts", + "yahoo", + "yamaxun", + "yandex", + "yodobashi", + "yoga", + "yokohama", + "you", + "youtube", + "yun", + "zappos", + "zara", + "zero", + "zip", + "zone", + "zuerich", + "cc.ua", + "inf.ua", + "ltd.ua", + "beep.pl", + "barsy.ca", + "*.compute.estate", + "*.alces.network", + "alwaysdata.net", + "cloudfront.net", + "*.compute.amazonaws.com", + "*.compute-1.amazonaws.com", + "*.compute.amazonaws.com.cn", + "us-east-1.amazonaws.com", + "cn-north-1.eb.amazonaws.com.cn", + "cn-northwest-1.eb.amazonaws.com.cn", + "elasticbeanstalk.com", + "ap-northeast-1.elasticbeanstalk.com", + "ap-northeast-2.elasticbeanstalk.com", + "ap-northeast-3.elasticbeanstalk.com", + "ap-south-1.elasticbeanstalk.com", + "ap-southeast-1.elasticbeanstalk.com", + "ap-southeast-2.elasticbeanstalk.com", + "ca-central-1.elasticbeanstalk.com", + "eu-central-1.elasticbeanstalk.com", + "eu-west-1.elasticbeanstalk.com", + "eu-west-2.elasticbeanstalk.com", + "eu-west-3.elasticbeanstalk.com", + "sa-east-1.elasticbeanstalk.com", + "us-east-1.elasticbeanstalk.com", + "us-east-2.elasticbeanstalk.com", + "us-gov-west-1.elasticbeanstalk.com", + "us-west-1.elasticbeanstalk.com", + "us-west-2.elasticbeanstalk.com", + "*.elb.amazonaws.com", + "*.elb.amazonaws.com.cn", + "s3.amazonaws.com", + "s3-ap-northeast-1.amazonaws.com", + "s3-ap-northeast-2.amazonaws.com", + "s3-ap-south-1.amazonaws.com", + "s3-ap-southeast-1.amazonaws.com", + "s3-ap-southeast-2.amazonaws.com", + "s3-ca-central-1.amazonaws.com", + "s3-eu-central-1.amazonaws.com", + "s3-eu-west-1.amazonaws.com", + "s3-eu-west-2.amazonaws.com", + "s3-eu-west-3.amazonaws.com", + "s3-external-1.amazonaws.com", + "s3-fips-us-gov-west-1.amazonaws.com", + "s3-sa-east-1.amazonaws.com", + "s3-us-gov-west-1.amazonaws.com", + "s3-us-east-2.amazonaws.com", + "s3-us-west-1.amazonaws.com", + "s3-us-west-2.amazonaws.com", + "s3.ap-northeast-2.amazonaws.com", + "s3.ap-south-1.amazonaws.com", + "s3.cn-north-1.amazonaws.com.cn", + "s3.ca-central-1.amazonaws.com", + "s3.eu-central-1.amazonaws.com", + "s3.eu-west-2.amazonaws.com", + "s3.eu-west-3.amazonaws.com", + "s3.us-east-2.amazonaws.com", + "s3.dualstack.ap-northeast-1.amazonaws.com", + "s3.dualstack.ap-northeast-2.amazonaws.com", + "s3.dualstack.ap-south-1.amazonaws.com", + "s3.dualstack.ap-southeast-1.amazonaws.com", + "s3.dualstack.ap-southeast-2.amazonaws.com", + "s3.dualstack.ca-central-1.amazonaws.com", + "s3.dualstack.eu-central-1.amazonaws.com", + "s3.dualstack.eu-west-1.amazonaws.com", + "s3.dualstack.eu-west-2.amazonaws.com", + "s3.dualstack.eu-west-3.amazonaws.com", + "s3.dualstack.sa-east-1.amazonaws.com", + "s3.dualstack.us-east-1.amazonaws.com", + "s3.dualstack.us-east-2.amazonaws.com", + "s3-website-us-east-1.amazonaws.com", + "s3-website-us-west-1.amazonaws.com", + "s3-website-us-west-2.amazonaws.com", + "s3-website-ap-northeast-1.amazonaws.com", + "s3-website-ap-southeast-1.amazonaws.com", + "s3-website-ap-southeast-2.amazonaws.com", + "s3-website-eu-west-1.amazonaws.com", + "s3-website-sa-east-1.amazonaws.com", + "s3-website.ap-northeast-2.amazonaws.com", + "s3-website.ap-south-1.amazonaws.com", + "s3-website.ca-central-1.amazonaws.com", + "s3-website.eu-central-1.amazonaws.com", + "s3-website.eu-west-2.amazonaws.com", + "s3-website.eu-west-3.amazonaws.com", + "s3-website.us-east-2.amazonaws.com", + "t3l3p0rt.net", + "tele.amune.org", + "apigee.io", + "on-aptible.com", + "user.party.eus", + "pimienta.org", + "poivron.org", + "potager.org", + "sweetpepper.org", + "myasustor.com", + "go-vip.co", + "go-vip.net", + "wpcomstaging.com", + "myfritz.net", + "*.awdev.ca", + "*.advisor.ws", + "b-data.io", + "backplaneapp.io", + "balena-devices.com", + "app.banzaicloud.io", + "betainabox.com", + "bnr.la", + "blackbaudcdn.net", + "boomla.net", + "boxfuse.io", + "square7.ch", + "bplaced.com", + "bplaced.de", + "square7.de", + "bplaced.net", + "square7.net", + "browsersafetymark.io", + "uk0.bigv.io", + "dh.bytemark.co.uk", + "vm.bytemark.co.uk", + "mycd.eu", + "carrd.co", + "crd.co", + "uwu.ai", + "ae.org", + "ar.com", + "br.com", + "cn.com", + "com.de", + "com.se", + "de.com", + "eu.com", + "gb.com", + "gb.net", + "hu.com", + "hu.net", + "jp.net", + "jpn.com", + "kr.com", + "mex.com", + "no.com", + "qc.com", + "ru.com", + "sa.com", + "se.net", + "uk.com", + "uk.net", + "us.com", + "uy.com", + "za.bz", + "za.com", + "africa.com", + "gr.com", + "in.net", + "us.org", + "co.com", + "c.la", + "certmgr.org", + "xenapponazure.com", + "discourse.group", + "virtueeldomein.nl", + "cleverapps.io", + "*.lcl.dev", + "*.stg.dev", + "c66.me", + "cloud66.ws", + "cloud66.zone", + "jdevcloud.com", + "wpdevcloud.com", + "cloudaccess.host", + "freesite.host", + "cloudaccess.net", + "cloudcontrolled.com", + "cloudcontrolapp.com", + "cloudera.site", + "workers.dev", + "wnext.app", + "co.ca", + "*.otap.co", + "co.cz", + "c.cdn77.org", + "cdn77-ssl.net", + "r.cdn77.net", + "rsc.cdn77.org", + "ssl.origin.cdn77-secure.org", + "cloudns.asia", + "cloudns.biz", + "cloudns.club", + "cloudns.cc", + "cloudns.eu", + "cloudns.in", + "cloudns.info", + "cloudns.org", + "cloudns.pro", + "cloudns.pw", + "cloudns.us", + "cloudeity.net", + "cnpy.gdn", + "co.nl", + "co.no", + "webhosting.be", + "hosting-cluster.nl", + "dyn.cosidns.de", + "dynamisches-dns.de", + "dnsupdater.de", + "internet-dns.de", + "l-o-g-i-n.de", + "dynamic-dns.info", + "feste-ip.net", + "knx-server.net", + "static-access.net", + "realm.cz", + "*.cryptonomic.net", + "cupcake.is", + "cyon.link", + "cyon.site", + "daplie.me", + "localhost.daplie.me", + "dattolocal.com", + "dattorelay.com", + "dattoweb.com", + "mydatto.com", + "dattolocal.net", + "mydatto.net", + "biz.dk", + "co.dk", + "firm.dk", + "reg.dk", + "store.dk", + "*.dapps.earth", + "*.bzz.dapps.earth", + "debian.net", + "dedyn.io", + "dnshome.de", + "online.th", + "shop.th", + "drayddns.com", + "dreamhosters.com", + "mydrobo.com", + "drud.io", + "drud.us", + "duckdns.org", + "dy.fi", + "tunk.org", + "dyndns-at-home.com", + "dyndns-at-work.com", + "dyndns-blog.com", + "dyndns-free.com", + "dyndns-home.com", + "dyndns-ip.com", + "dyndns-mail.com", + "dyndns-office.com", + "dyndns-pics.com", + "dyndns-remote.com", + "dyndns-server.com", + "dyndns-web.com", + "dyndns-wiki.com", + "dyndns-work.com", + "dyndns.biz", + "dyndns.info", + "dyndns.org", + "dyndns.tv", + "at-band-camp.net", + "ath.cx", + "barrel-of-knowledge.info", + "barrell-of-knowledge.info", + "better-than.tv", + "blogdns.com", + "blogdns.net", + "blogdns.org", + "blogsite.org", + "boldlygoingnowhere.org", + "broke-it.net", + "buyshouses.net", + "cechire.com", + "dnsalias.com", + "dnsalias.net", + "dnsalias.org", + "dnsdojo.com", + "dnsdojo.net", + "dnsdojo.org", + "does-it.net", + "doesntexist.com", + "doesntexist.org", + "dontexist.com", + "dontexist.net", + "dontexist.org", + "doomdns.com", + "doomdns.org", + "dvrdns.org", + "dyn-o-saur.com", + "dynalias.com", + "dynalias.net", + "dynalias.org", + "dynathome.net", + "dyndns.ws", + "endofinternet.net", + "endofinternet.org", + "endoftheinternet.org", + "est-a-la-maison.com", + "est-a-la-masion.com", + "est-le-patron.com", + "est-mon-blogueur.com", + "for-better.biz", + "for-more.biz", + "for-our.info", + "for-some.biz", + "for-the.biz", + "forgot.her.name", + "forgot.his.name", + "from-ak.com", + "from-al.com", + "from-ar.com", + "from-az.net", + "from-ca.com", + "from-co.net", + "from-ct.com", + "from-dc.com", + "from-de.com", + "from-fl.com", + "from-ga.com", + "from-hi.com", + "from-ia.com", + "from-id.com", + "from-il.com", + "from-in.com", + "from-ks.com", + "from-ky.com", + "from-la.net", + "from-ma.com", + "from-md.com", + "from-me.org", + "from-mi.com", + "from-mn.com", + "from-mo.com", + "from-ms.com", + "from-mt.com", + "from-nc.com", + "from-nd.com", + "from-ne.com", + "from-nh.com", + "from-nj.com", + "from-nm.com", + "from-nv.com", + "from-ny.net", + "from-oh.com", + "from-ok.com", + "from-or.com", + "from-pa.com", + "from-pr.com", + "from-ri.com", + "from-sc.com", + "from-sd.com", + "from-tn.com", + "from-tx.com", + "from-ut.com", + "from-va.com", + "from-vt.com", + "from-wa.com", + "from-wi.com", + "from-wv.com", + "from-wy.com", + "ftpaccess.cc", + "fuettertdasnetz.de", + "game-host.org", + "game-server.cc", + "getmyip.com", + "gets-it.net", + "go.dyndns.org", + "gotdns.com", + "gotdns.org", + "groks-the.info", + "groks-this.info", + "ham-radio-op.net", + "here-for-more.info", + "hobby-site.com", + "hobby-site.org", + "home.dyndns.org", + "homedns.org", + "homeftp.net", + "homeftp.org", + "homeip.net", + "homelinux.com", + "homelinux.net", + "homelinux.org", + "homeunix.com", + "homeunix.net", + "homeunix.org", + "iamallama.com", + "in-the-band.net", + "is-a-anarchist.com", + "is-a-blogger.com", + "is-a-bookkeeper.com", + "is-a-bruinsfan.org", + "is-a-bulls-fan.com", + "is-a-candidate.org", + "is-a-caterer.com", + "is-a-celticsfan.org", + "is-a-chef.com", + "is-a-chef.net", + "is-a-chef.org", + "is-a-conservative.com", + "is-a-cpa.com", + "is-a-cubicle-slave.com", + "is-a-democrat.com", + "is-a-designer.com", + "is-a-doctor.com", + "is-a-financialadvisor.com", + "is-a-geek.com", + "is-a-geek.net", + "is-a-geek.org", + "is-a-green.com", + "is-a-guru.com", + "is-a-hard-worker.com", + "is-a-hunter.com", + "is-a-knight.org", + "is-a-landscaper.com", + "is-a-lawyer.com", + "is-a-liberal.com", + "is-a-libertarian.com", + "is-a-linux-user.org", + "is-a-llama.com", + "is-a-musician.com", + "is-a-nascarfan.com", + "is-a-nurse.com", + "is-a-painter.com", + "is-a-patsfan.org", + "is-a-personaltrainer.com", + "is-a-photographer.com", + "is-a-player.com", + "is-a-republican.com", + "is-a-rockstar.com", + "is-a-socialist.com", + "is-a-soxfan.org", + "is-a-student.com", + "is-a-teacher.com", + "is-a-techie.com", + "is-a-therapist.com", + "is-an-accountant.com", + "is-an-actor.com", + "is-an-actress.com", + "is-an-anarchist.com", + "is-an-artist.com", + "is-an-engineer.com", + "is-an-entertainer.com", + "is-by.us", + "is-certified.com", + "is-found.org", + "is-gone.com", + "is-into-anime.com", + "is-into-cars.com", + "is-into-cartoons.com", + "is-into-games.com", + "is-leet.com", + "is-lost.org", + "is-not-certified.com", + "is-saved.org", + "is-slick.com", + "is-uberleet.com", + "is-very-bad.org", + "is-very-evil.org", + "is-very-good.org", + "is-very-nice.org", + "is-very-sweet.org", + "is-with-theband.com", + "isa-geek.com", + "isa-geek.net", + "isa-geek.org", + "isa-hockeynut.com", + "issmarterthanyou.com", + "isteingeek.de", + "istmein.de", + "kicks-ass.net", + "kicks-ass.org", + "knowsitall.info", + "land-4-sale.us", + "lebtimnetz.de", + "leitungsen.de", + "likes-pie.com", + "likescandy.com", + "merseine.nu", + "mine.nu", + "misconfused.org", + "mypets.ws", + "myphotos.cc", + "neat-url.com", + "office-on-the.net", + "on-the-web.tv", + "podzone.net", + "podzone.org", + "readmyblog.org", + "saves-the-whales.com", + "scrapper-site.net", + "scrapping.cc", + "selfip.biz", + "selfip.com", + "selfip.info", + "selfip.net", + "selfip.org", + "sells-for-less.com", + "sells-for-u.com", + "sells-it.net", + "sellsyourhome.org", + "servebbs.com", + "servebbs.net", + "servebbs.org", + "serveftp.net", + "serveftp.org", + "servegame.org", + "shacknet.nu", + "simple-url.com", + "space-to-rent.com", + "stuff-4-sale.org", + "stuff-4-sale.us", + "teaches-yoga.com", + "thruhere.net", + "traeumtgerade.de", + "webhop.biz", + "webhop.info", + "webhop.net", + "webhop.org", + "worse-than.tv", + "writesthisblog.com", + "ddnss.de", + "dyn.ddnss.de", + "dyndns.ddnss.de", + "dyndns1.de", + "dyn-ip24.de", + "home-webserver.de", + "dyn.home-webserver.de", + "myhome-server.de", + "ddnss.org", + "definima.net", + "definima.io", + "bci.dnstrace.pro", + "ddnsfree.com", + "ddnsgeek.com", + "giize.com", + "gleeze.com", + "kozow.com", + "loseyourip.com", + "ooguy.com", + "theworkpc.com", + "casacam.net", + "dynu.net", + "accesscam.org", + "camdvr.org", + "freeddns.org", + "mywire.org", + "webredirect.org", + "myddns.rocks", + "blogsite.xyz", + "dynv6.net", + "e4.cz", + "mytuleap.com", + "onred.one", + "staging.onred.one", + "enonic.io", + "customer.enonic.io", + "eu.org", + "al.eu.org", + "asso.eu.org", + "at.eu.org", + "au.eu.org", + "be.eu.org", + "bg.eu.org", + "ca.eu.org", + "cd.eu.org", + "ch.eu.org", + "cn.eu.org", + "cy.eu.org", + "cz.eu.org", + "de.eu.org", + "dk.eu.org", + "edu.eu.org", + "ee.eu.org", + "es.eu.org", + "fi.eu.org", + "fr.eu.org", + "gr.eu.org", + "hr.eu.org", + "hu.eu.org", + "ie.eu.org", + "il.eu.org", + "in.eu.org", + "int.eu.org", + "is.eu.org", + "it.eu.org", + "jp.eu.org", + "kr.eu.org", + "lt.eu.org", + "lu.eu.org", + "lv.eu.org", + "mc.eu.org", + "me.eu.org", + "mk.eu.org", + "mt.eu.org", + "my.eu.org", + "net.eu.org", + "ng.eu.org", + "nl.eu.org", + "no.eu.org", + "nz.eu.org", + "paris.eu.org", + "pl.eu.org", + "pt.eu.org", + "q-a.eu.org", + "ro.eu.org", + "ru.eu.org", + "se.eu.org", + "si.eu.org", + "sk.eu.org", + "tr.eu.org", + "uk.eu.org", + "us.eu.org", + "eu-1.evennode.com", + "eu-2.evennode.com", + "eu-3.evennode.com", + "eu-4.evennode.com", + "us-1.evennode.com", + "us-2.evennode.com", + "us-3.evennode.com", + "us-4.evennode.com", + "twmail.cc", + "twmail.net", + "twmail.org", + "mymailer.com.tw", + "url.tw", + "apps.fbsbx.com", + "ru.net", + "adygeya.ru", + "bashkiria.ru", + "bir.ru", + "cbg.ru", + "com.ru", + "dagestan.ru", + "grozny.ru", + "kalmykia.ru", + "kustanai.ru", + "marine.ru", + "mordovia.ru", + "msk.ru", + "mytis.ru", + "nalchik.ru", + "nov.ru", + "pyatigorsk.ru", + "spb.ru", + "vladikavkaz.ru", + "vladimir.ru", + "abkhazia.su", + "adygeya.su", + "aktyubinsk.su", + "arkhangelsk.su", + "armenia.su", + "ashgabad.su", + "azerbaijan.su", + "balashov.su", + "bashkiria.su", + "bryansk.su", + "bukhara.su", + "chimkent.su", + "dagestan.su", + "east-kazakhstan.su", + "exnet.su", + "georgia.su", + "grozny.su", + "ivanovo.su", + "jambyl.su", + "kalmykia.su", + "kaluga.su", + "karacol.su", + "karaganda.su", + "karelia.su", + "khakassia.su", + "krasnodar.su", + "kurgan.su", + "kustanai.su", + "lenug.su", + "mangyshlak.su", + "mordovia.su", + "msk.su", + "murmansk.su", + "nalchik.su", + "navoi.su", + "north-kazakhstan.su", + "nov.su", + "obninsk.su", + "penza.su", + "pokrovsk.su", + "sochi.su", + "spb.su", + "tashkent.su", + "termez.su", + "togliatti.su", + "troitsk.su", + "tselinograd.su", + "tula.su", + "tuva.su", + "vladikavkaz.su", + "vladimir.su", + "vologda.su", + "channelsdvr.net", + "fastly-terrarium.com", + "fastlylb.net", + "map.fastlylb.net", + "freetls.fastly.net", + "map.fastly.net", + "a.prod.fastly.net", + "global.prod.fastly.net", + "a.ssl.fastly.net", + "b.ssl.fastly.net", + "global.ssl.fastly.net", + "fastpanel.direct", + "fastvps-server.com", + "fhapp.xyz", + "fedorainfracloud.org", + "fedorapeople.org", + "cloud.fedoraproject.org", + "app.os.fedoraproject.org", + "app.os.stg.fedoraproject.org", + "mydobiss.com", + "filegear.me", + "filegear-au.me", + "filegear-de.me", + "filegear-gb.me", + "filegear-ie.me", + "filegear-jp.me", + "filegear-sg.me", + "firebaseapp.com", + "flynnhub.com", + "flynnhosting.net", + "freebox-os.com", + "freeboxos.com", + "fbx-os.fr", + "fbxos.fr", + "freebox-os.fr", + "freeboxos.fr", + "freedesktop.org", + "*.futurecms.at", + "*.ex.futurecms.at", + "*.in.futurecms.at", + "futurehosting.at", + "futuremailing.at", + "*.ex.ortsinfo.at", + "*.kunden.ortsinfo.at", + "*.statics.cloud", + "service.gov.uk", + "gehirn.ne.jp", + "usercontent.jp", + "lab.ms", + "github.io", + "githubusercontent.com", + "gitlab.io", + "glitch.me", + "cloudapps.digital", + "london.cloudapps.digital", + "homeoffice.gov.uk", + "ro.im", + "shop.ro", + "goip.de", + "run.app", + "a.run.app", + "web.app", + "*.0emm.com", + "appspot.com", + "blogspot.ae", + "blogspot.al", + "blogspot.am", + "blogspot.ba", + "blogspot.be", + "blogspot.bg", + "blogspot.bj", + "blogspot.ca", + "blogspot.cf", + "blogspot.ch", + "blogspot.cl", + "blogspot.co.at", + "blogspot.co.id", + "blogspot.co.il", + "blogspot.co.ke", + "blogspot.co.nz", + "blogspot.co.uk", + "blogspot.co.za", + "blogspot.com", + "blogspot.com.ar", + "blogspot.com.au", + "blogspot.com.br", + "blogspot.com.by", + "blogspot.com.co", + "blogspot.com.cy", + "blogspot.com.ee", + "blogspot.com.eg", + "blogspot.com.es", + "blogspot.com.mt", + "blogspot.com.ng", + "blogspot.com.tr", + "blogspot.com.uy", + "blogspot.cv", + "blogspot.cz", + "blogspot.de", + "blogspot.dk", + "blogspot.fi", + "blogspot.fr", + "blogspot.gr", + "blogspot.hk", + "blogspot.hr", + "blogspot.hu", + "blogspot.ie", + "blogspot.in", + "blogspot.is", + "blogspot.it", + "blogspot.jp", + "blogspot.kr", + "blogspot.li", + "blogspot.lt", + "blogspot.lu", + "blogspot.md", + "blogspot.mk", + "blogspot.mr", + "blogspot.mx", + "blogspot.my", + "blogspot.nl", + "blogspot.no", + "blogspot.pe", + "blogspot.pt", + "blogspot.qa", + "blogspot.re", + "blogspot.ro", + "blogspot.rs", + "blogspot.ru", + "blogspot.se", + "blogspot.sg", + "blogspot.si", + "blogspot.sk", + "blogspot.sn", + "blogspot.td", + "blogspot.tw", + "blogspot.ug", + "blogspot.vn", + "cloudfunctions.net", + "cloud.goog", + "codespot.com", + "googleapis.com", + "googlecode.com", + "pagespeedmobilizer.com", + "publishproxy.com", + "withgoogle.com", + "withyoutube.com", + "fin.ci", + "free.hr", + "caa.li", + "ua.rs", + "conf.se", + "hashbang.sh", + "hasura.app", + "hasura-app.io", + "hepforge.org", + "herokuapp.com", + "herokussl.com", + "myravendb.com", + "ravendb.community", + "ravendb.me", + "development.run", + "ravendb.run", + "bpl.biz", + "orx.biz", + "ng.city", + "ng.ink", + "biz.gl", + "col.ng", + "gen.ng", + "ltd.ng", + "sch.so", + "xn--hkkinen-5wa.fi", + "*.moonscale.io", + "moonscale.net", + "iki.fi", + "dyn-berlin.de", + "in-berlin.de", + "in-brb.de", + "in-butter.de", + "in-dsl.de", + "in-dsl.net", + "in-dsl.org", + "in-vpn.de", + "in-vpn.net", + "in-vpn.org", + "biz.at", + "info.at", + "info.cx", + "ac.leg.br", + "al.leg.br", + "am.leg.br", + "ap.leg.br", + "ba.leg.br", + "ce.leg.br", + "df.leg.br", + "es.leg.br", + "go.leg.br", + "ma.leg.br", + "mg.leg.br", + "ms.leg.br", + "mt.leg.br", + "pa.leg.br", + "pb.leg.br", + "pe.leg.br", + "pi.leg.br", + "pr.leg.br", + "rj.leg.br", + "rn.leg.br", + "ro.leg.br", + "rr.leg.br", + "rs.leg.br", + "sc.leg.br", + "se.leg.br", + "sp.leg.br", + "to.leg.br", + "pixolino.com", + "ipifony.net", + "mein-iserv.de", + "test-iserv.de", + "iobb.net", + "myjino.ru", + "*.hosting.myjino.ru", + "*.landing.myjino.ru", + "*.spectrum.myjino.ru", + "*.vps.myjino.ru", + "*.triton.zone", + "*.cns.joyent.com", + "js.org", + "kaas.gg", + "khplay.nl", + "keymachine.de", + "kinghost.net", + "uni5.net", + "knightpoint.systems", + "co.krd", + "edu.krd", + "git-repos.de", + "lcube-server.de", + "svn-repos.de", + "leadpages.co", + "lpages.co", + "lpusercontent.com", + "co.business", + "co.education", + "co.events", + "co.financial", + "co.network", + "co.place", + "co.technology", + "app.lmpm.com", + "linkitools.space", + "linkyard.cloud", + "linkyard-cloud.ch", + "members.linode.com", + "nodebalancer.linode.com", + "we.bs", + "loginline.app", + "loginline.dev", + "loginline.io", + "loginline.services", + "loginline.site", + "krasnik.pl", + "leczna.pl", + "lubartow.pl", + "lublin.pl", + "poniatowa.pl", + "swidnik.pl", + "uklugs.org", + "glug.org.uk", + "lug.org.uk", + "lugs.org.uk", + "barsy.bg", + "barsy.co.uk", + "barsyonline.co.uk", + "barsycenter.com", + "barsyonline.com", + "barsy.club", + "barsy.de", + "barsy.eu", + "barsy.in", + "barsy.info", + "barsy.io", + "barsy.me", + "barsy.menu", + "barsy.mobi", + "barsy.net", + "barsy.online", + "barsy.org", + "barsy.pro", + "barsy.pub", + "barsy.shop", + "barsy.site", + "barsy.support", + "barsy.uk", + "*.magentosite.cloud", + "mayfirst.info", + "mayfirst.org", + "hb.cldmail.ru", + "miniserver.com", + "memset.net", + "cloud.metacentrum.cz", + "custom.metacentrum.cz", + "flt.cloud.muni.cz", + "usr.cloud.muni.cz", + "meteorapp.com", + "eu.meteorapp.com", + "co.pl", + "azurecontainer.io", + "azurewebsites.net", + "azure-mobile.net", + "cloudapp.net", + "mozilla-iot.org", + "bmoattachments.org", + "net.ru", + "org.ru", + "pp.ru", + "ui.nabu.casa", + "pony.club", + "of.fashion", + "on.fashion", + "of.football", + "in.london", + "of.london", + "for.men", + "and.mom", + "for.mom", + "for.one", + "for.sale", + "of.work", + "to.work", + "nctu.me", + "bitballoon.com", + "netlify.com", + "4u.com", + "ngrok.io", + "nh-serv.co.uk", + "nfshost.com", + "dnsking.ch", + "mypi.co", + "n4t.co", + "001www.com", + "ddnslive.com", + "myiphost.com", + "forumz.info", + "16-b.it", + "32-b.it", + "64-b.it", + "soundcast.me", + "tcp4.me", + "dnsup.net", + "hicam.net", + "now-dns.net", + "ownip.net", + "vpndns.net", + "dynserv.org", + "now-dns.org", + "x443.pw", + "now-dns.top", + "ntdll.top", + "freeddns.us", + "crafting.xyz", + "zapto.xyz", + "nsupdate.info", + "nerdpol.ovh", + "blogsyte.com", + "brasilia.me", + "cable-modem.org", + "ciscofreak.com", + "collegefan.org", + "couchpotatofries.org", + "damnserver.com", + "ddns.me", + "ditchyourip.com", + "dnsfor.me", + "dnsiskinky.com", + "dvrcam.info", + "dynns.com", + "eating-organic.net", + "fantasyleague.cc", + "geekgalaxy.com", + "golffan.us", + "health-carereform.com", + "homesecuritymac.com", + "homesecuritypc.com", + "hopto.me", + "ilovecollege.info", + "loginto.me", + "mlbfan.org", + "mmafan.biz", + "myactivedirectory.com", + "mydissent.net", + "myeffect.net", + "mymediapc.net", + "mypsx.net", + "mysecuritycamera.com", + "mysecuritycamera.net", + "mysecuritycamera.org", + "net-freaks.com", + "nflfan.org", + "nhlfan.net", + "no-ip.ca", + "no-ip.co.uk", + "no-ip.net", + "noip.us", + "onthewifi.com", + "pgafan.net", + "point2this.com", + "pointto.us", + "privatizehealthinsurance.net", + "quicksytes.com", + "read-books.org", + "securitytactics.com", + "serveexchange.com", + "servehumour.com", + "servep2p.com", + "servesarcasm.com", + "stufftoread.com", + "ufcfan.org", + "unusualperson.com", + "workisboring.com", + "3utilities.com", + "bounceme.net", + "ddns.net", + "ddnsking.com", + "gotdns.ch", + "hopto.org", + "myftp.biz", + "myftp.org", + "myvnc.com", + "no-ip.biz", + "no-ip.info", + "no-ip.org", + "noip.me", + "redirectme.net", + "servebeer.com", + "serveblog.net", + "servecounterstrike.com", + "serveftp.com", + "servegame.com", + "servehalflife.com", + "servehttp.com", + "serveirc.com", + "serveminecraft.net", + "servemp3.com", + "servepics.com", + "servequake.com", + "sytes.net", + "webhop.me", + "zapto.org", + "stage.nodeart.io", + "nodum.co", + "nodum.io", + "pcloud.host", + "nyc.mn", + "nom.ae", + "nom.af", + "nom.ai", + "nom.al", + "nym.by", + "nym.bz", + "nom.cl", + "nom.gd", + "nom.ge", + "nom.gl", + "nym.gr", + "nom.gt", + "nym.gy", + "nom.hn", + "nym.ie", + "nom.im", + "nom.ke", + "nym.kz", + "nym.la", + "nym.lc", + "nom.li", + "nym.li", + "nym.lt", + "nym.lu", + "nym.me", + "nom.mk", + "nym.mn", + "nym.mx", + "nom.nu", + "nym.nz", + "nym.pe", + "nym.pt", + "nom.pw", + "nom.qa", + "nym.ro", + "nom.rs", + "nom.si", + "nym.sk", + "nom.st", + "nym.su", + "nym.sx", + "nom.tj", + "nym.tw", + "nom.ug", + "nom.uy", + "nom.vc", + "nom.vg", + "cya.gg", + "cloudycluster.net", + "nid.io", + "opencraft.hosting", + "operaunite.com", + "outsystemscloud.com", + "ownprovider.com", + "own.pm", + "ox.rs", + "oy.lc", + "pgfog.com", + "pagefrontapp.com", + "art.pl", + "gliwice.pl", + "krakow.pl", + "poznan.pl", + "wroc.pl", + "zakopane.pl", + "pantheonsite.io", + "gotpantheon.com", + "mypep.link", + "on-web.fr", + "*.platform.sh", + "*.platformsh.site", + "dyn53.io", + "co.bn", + "xen.prgmr.com", + "priv.at", + "prvcy.page", + "*.dweb.link", + "protonet.io", + "chirurgiens-dentistes-en-france.fr", + "byen.site", + "instantcloud.cn", + "ras.ru", + "qa2.com", + "dev-myqnapcloud.com", + "alpha-myqnapcloud.com", + "myqnapcloud.com", + "*.quipelements.com", + "vapor.cloud", + "vaporcloud.io", + "rackmaze.com", + "rackmaze.net", + "*.on-rancher.cloud", + "*.on-rio.io", + "readthedocs.io", + "rhcloud.com", + "app.render.com", + "onrender.com", + "repl.co", + "repl.run", + "resindevice.io", + "devices.resinstaging.io", + "hzc.io", + "wellbeingzone.eu", + "ptplus.fit", + "wellbeingzone.co.uk", + "git-pages.rit.edu", + "sandcats.io", + "logoip.de", + "logoip.com", + "schokokeks.net", + "scrysec.com", + "firewall-gateway.com", + "firewall-gateway.de", + "my-gateway.de", + "my-router.de", + "spdns.de", + "spdns.eu", + "firewall-gateway.net", + "my-firewall.org", + "myfirewall.org", + "spdns.org", + "*.s5y.io", + "*.sensiosite.cloud", + "biz.ua", + "co.ua", + "pp.ua", + "shiftedit.io", + "myshopblocks.com", + "mo-siemens.io", + "1kapp.com", + "appchizi.com", + "applinzi.com", + "sinaapp.com", + "vipsinaapp.com", + "siteleaf.net", + "bounty-full.com", + "alpha.bounty-full.com", + "beta.bounty-full.com", + "stackhero-network.com", + "static.land", + "dev.static.land", + "sites.static.land", + "apps.lair.io", + "*.stolos.io", + "spacekit.io", + "customer.speedpartner.de", + "api.stdlib.com", + "storj.farm", + "utwente.io", + "soc.srcf.net", + "user.srcf.net", + "temp-dns.com", + "applicationcloud.io", + "scapp.io", + "syncloud.it", + "diskstation.me", + "dscloud.biz", + "dscloud.me", + "dscloud.mobi", + "dsmynas.com", + "dsmynas.net", + "dsmynas.org", + "familyds.com", + "familyds.net", + "familyds.org", + "i234.me", + "myds.me", + "synology.me", + "vpnplus.to", + "taifun-dns.de", + "gda.pl", + "gdansk.pl", + "gdynia.pl", + "med.pl", + "sopot.pl", + "edugit.org", + "telebit.app", + "telebit.io", + "*.telebit.xyz", + "gwiddle.co.uk", + "thingdustdata.com", + "cust.dev.thingdust.io", + "cust.disrec.thingdust.io", + "cust.prod.thingdust.io", + "cust.testing.thingdust.io", + "arvo.network", + "azimuth.network", + "bloxcms.com", + "townnews-staging.com", + "12hp.at", + "2ix.at", + "4lima.at", + "lima-city.at", + "12hp.ch", + "2ix.ch", + "4lima.ch", + "lima-city.ch", + "trafficplex.cloud", + "de.cool", + "12hp.de", + "2ix.de", + "4lima.de", + "lima-city.de", + "1337.pictures", + "clan.rip", + "lima-city.rocks", + "webspace.rocks", + "lima.zone", + "*.transurl.be", + "*.transurl.eu", + "*.transurl.nl", + "tuxfamily.org", + "dd-dns.de", + "diskstation.eu", + "diskstation.org", + "dray-dns.de", + "draydns.de", + "dyn-vpn.de", + "dynvpn.de", + "mein-vigor.de", + "my-vigor.de", + "my-wan.de", + "syno-ds.de", + "synology-diskstation.de", + "synology-ds.de", + "uber.space", + "*.uberspace.de", + "hk.com", + "hk.org", + "ltd.hk", + "inc.hk", + "virtualuser.de", + "virtual-user.de", + "lib.de.us", + "2038.io", + "router.management", + "v-info.info", + "voorloper.cloud", + "wafflecell.com", + "wedeploy.io", + "wedeploy.me", + "wedeploy.sh", + "remotewd.com", + "wmflabs.org", + "half.host", + "xnbay.com", + "u2.xnbay.com", + "u2-local.xnbay.com", + "cistron.nl", + "demon.nl", + "xs4all.space", + "official.academy", + "yolasite.com", + "ybo.faith", + "yombo.me", + "homelink.one", + "ybo.party", + "ybo.review", + "ybo.science", + "ybo.trade", + "nohost.me", + "noho.st", + "za.net", + "za.org", + "now.sh", + "bss.design", + "basicserver.io", + "virtualserver.io", + "site.builder.nu", + "enterprisecloud.nu", + "zone.id", +} + +var nodeLabels = [...]string{ + "aaa", + "aarp", + "abarth", + "abb", + "abbott", + "abbvie", + "abc", + "able", + "abogado", + "abudhabi", + "ac", + "academy", + "accenture", + "accountant", + "accountants", + "aco", + "actor", + "ad", + "adac", + "ads", + "adult", + "ae", + "aeg", + "aero", + "aetna", + "af", + "afamilycompany", + "afl", + "africa", + "ag", + "agakhan", + "agency", + "ai", + "aig", + "aigo", + "airbus", + "airforce", + "airtel", + "akdn", + "al", + "alfaromeo", + "alibaba", + "alipay", + "allfinanz", + "allstate", + "ally", + "alsace", + "alstom", + "am", + "americanexpress", + "americanfamily", + "amex", + "amfam", + "amica", + "amsterdam", + "analytics", + "android", + "anquan", + "anz", + "ao", + "aol", + "apartments", + "app", + "apple", + "aq", + "aquarelle", + "ar", + "arab", + "aramco", + "archi", + "army", + "arpa", + "art", + "arte", + "as", + "asda", + "asia", + "associates", + "at", + "athleta", + "attorney", + "au", + "auction", + "audi", + "audible", + "audio", + "auspost", + "author", + "auto", + "autos", + "avianca", + "aw", + "aws", + "ax", + "axa", + "az", + "azure", + "ba", + "baby", + "baidu", + "banamex", + "bananarepublic", + "band", + "bank", + "bar", + "barcelona", + "barclaycard", + "barclays", + "barefoot", + "bargains", + "baseball", + "basketball", + "bauhaus", + "bayern", + "bb", + "bbc", + "bbt", + "bbva", + "bcg", + "bcn", + "bd", + "be", + "beats", + "beauty", + "beer", + "bentley", + "berlin", + "best", + "bestbuy", + "bet", + "bf", + "bg", + "bh", + "bharti", + "bi", + "bible", + "bid", + "bike", + "bing", + "bingo", + "bio", + "biz", + "bj", + "black", + "blackfriday", + "blockbuster", + "blog", + "bloomberg", + "blue", + "bm", + "bms", + "bmw", + "bn", + "bnl", + "bnpparibas", + "bo", + "boats", + "boehringer", + "bofa", + "bom", + "bond", + "boo", + "book", + "booking", + "bosch", + "bostik", + "boston", + "bot", + "boutique", + "box", + "br", + "bradesco", + "bridgestone", + "broadway", + "broker", + "brother", + "brussels", + "bs", + "bt", + "budapest", + "bugatti", + "build", + "builders", + "business", + "buy", + "buzz", + "bv", + "bw", + "by", + "bz", + "bzh", + "ca", + "cab", + "cafe", + "cal", + "call", + "calvinklein", + "cam", + "camera", + "camp", + "cancerresearch", + "canon", + "capetown", + "capital", + "capitalone", + "car", + "caravan", + "cards", + "care", + "career", + "careers", + "cars", + "cartier", + "casa", + "case", + "caseih", + "cash", + "casino", + "cat", + "catering", + "catholic", + "cba", + "cbn", + "cbre", + "cbs", + "cc", + "cd", + "ceb", + "center", + "ceo", + "cern", + "cf", + "cfa", + "cfd", + "cg", + "ch", + "chanel", + "channel", + "charity", + "chase", + "chat", + "cheap", + "chintai", + "christmas", + "chrome", + "chrysler", + "church", + "ci", + "cipriani", + "circle", + "cisco", + "citadel", + "citi", + "citic", + "city", + "cityeats", + "ck", + "cl", + "claims", + "cleaning", + "click", + "clinic", + "clinique", + "clothing", + "cloud", + "club", + "clubmed", + "cm", + "cn", + "co", + "coach", + "codes", + "coffee", + "college", + "cologne", + "com", + "comcast", + "commbank", + "community", + "company", + "compare", + "computer", + "comsec", + "condos", + "construction", + "consulting", + "contact", + "contractors", + "cooking", + "cookingchannel", + "cool", + "coop", + "corsica", + "country", + "coupon", + "coupons", + "courses", + "cr", + "credit", + "creditcard", + "creditunion", + "cricket", + "crown", + "crs", + "cruise", + "cruises", + "csc", + "cu", + "cuisinella", + "cv", + "cw", + "cx", + "cy", + "cymru", + "cyou", + "cz", + "dabur", + "dad", + "dance", + "data", + "date", + "dating", + "datsun", + "day", + "dclk", + "dds", + "de", + "deal", + "dealer", + "deals", + "degree", + "delivery", + "dell", + "deloitte", + "delta", + "democrat", + "dental", + "dentist", + "desi", + "design", + "dev", + "dhl", + "diamonds", + "diet", + "digital", + "direct", + "directory", + "discount", + "discover", + "dish", + "diy", + "dj", + "dk", + "dm", + "dnp", + "do", + "docs", + "doctor", + "dodge", + "dog", + "domains", + "dot", + "download", + "drive", + "dtv", + "dubai", + "duck", + "dunlop", + "duns", + "dupont", + "durban", + "dvag", + "dvr", + "dz", + "earth", + "eat", + "ec", + "eco", + "edeka", + "edu", + "education", + "ee", + "eg", + "email", + "emerck", + "energy", + "engineer", + "engineering", + "enterprises", + "epson", + "equipment", + "er", + "ericsson", + "erni", + "es", + "esq", + "estate", + "esurance", + "et", + "etisalat", + "eu", + "eurovision", + "eus", + "events", + "everbank", + "exchange", + "expert", + "exposed", + "express", + "extraspace", + "fage", + "fail", + "fairwinds", + "faith", + "family", + "fan", + "fans", + "farm", + "farmers", + "fashion", + "fast", + "fedex", + "feedback", + "ferrari", + "ferrero", + "fi", + "fiat", + "fidelity", + "fido", + "film", + "final", + "finance", + "financial", + "fire", + "firestone", + "firmdale", + "fish", + "fishing", + "fit", + "fitness", + "fj", + "fk", + "flickr", + "flights", + "flir", + "florist", + "flowers", + "fly", + "fm", + "fo", + "foo", + "food", + "foodnetwork", + "football", + "ford", + "forex", + "forsale", + "forum", + "foundation", + "fox", + "fr", + "free", + "fresenius", + "frl", + "frogans", + "frontdoor", + "frontier", + "ftr", + "fujitsu", + "fujixerox", + "fun", + "fund", + "furniture", + "futbol", + "fyi", + "ga", + "gal", + "gallery", + "gallo", + "gallup", + "game", + "games", + "gap", + "garden", + "gb", + "gbiz", + "gd", + "gdn", + "ge", + "gea", + "gent", + "genting", + "george", + "gf", + "gg", + "ggee", + "gh", + "gi", + "gift", + "gifts", + "gives", + "giving", + "gl", + "glade", + "glass", + "gle", + "global", + "globo", + "gm", + "gmail", + "gmbh", + "gmo", + "gmx", + "gn", + "godaddy", + "gold", + "goldpoint", + "golf", + "goo", + "goodyear", + "goog", + "google", + "gop", + "got", + "gov", + "gp", + "gq", + "gr", + "grainger", + "graphics", + "gratis", + "green", + "gripe", + "grocery", + "group", + "gs", + "gt", + "gu", + "guardian", + "gucci", + "guge", + "guide", + "guitars", + "guru", + "gw", + "gy", + "hair", + "hamburg", + "hangout", + "haus", + "hbo", + "hdfc", + "hdfcbank", + "health", + "healthcare", + "help", + "helsinki", + "here", + "hermes", + "hgtv", + "hiphop", + "hisamitsu", + "hitachi", + "hiv", + "hk", + "hkt", + "hm", + "hn", + "hockey", + "holdings", + "holiday", + "homedepot", + "homegoods", + "homes", + "homesense", + "honda", + "honeywell", + "horse", + "hospital", + "host", + "hosting", + "hot", + "hoteles", + "hotels", + "hotmail", + "house", + "how", + "hr", + "hsbc", + "ht", + "hu", + "hughes", + "hyatt", + "hyundai", + "ibm", + "icbc", + "ice", + "icu", + "id", + "ie", + "ieee", + "ifm", + "ikano", + "il", + "im", + "imamat", + "imdb", + "immo", + "immobilien", + "in", + "inc", + "industries", + "infiniti", + "info", + "ing", + "ink", + "institute", + "insurance", + "insure", + "int", + "intel", + "international", + "intuit", + "investments", + "io", + "ipiranga", + "iq", + "ir", + "irish", + "is", + "iselect", + "ismaili", + "ist", + "istanbul", + "it", + "itau", + "itv", + "iveco", + "jaguar", + "java", + "jcb", + "jcp", + "je", + "jeep", + "jetzt", + "jewelry", + "jio", + "jll", + "jm", + "jmp", + "jnj", + "jo", + "jobs", + "joburg", + "jot", + "joy", + "jp", + "jpmorgan", + "jprs", + "juegos", + "juniper", + "kaufen", + "kddi", + "ke", + "kerryhotels", + "kerrylogistics", + "kerryproperties", + "kfh", + "kg", + "kh", + "ki", + "kia", + "kim", + "kinder", + "kindle", + "kitchen", + "kiwi", + "km", + "kn", + "koeln", + "komatsu", + "kosher", + "kp", + "kpmg", + "kpn", + "kr", + "krd", + "kred", + "kuokgroup", + "kw", + "ky", + "kyoto", + "kz", + "la", + "lacaixa", + "ladbrokes", + "lamborghini", + "lamer", + "lancaster", + "lancia", + "lancome", + "land", + "landrover", + "lanxess", + "lasalle", + "lat", + "latino", + "latrobe", + "law", + "lawyer", + "lb", + "lc", + "lds", + "lease", + "leclerc", + "lefrak", + "legal", + "lego", + "lexus", + "lgbt", + "li", + "liaison", + "lidl", + "life", + "lifeinsurance", + "lifestyle", + "lighting", + "like", + "lilly", + "limited", + "limo", + "lincoln", + "linde", + "link", + "lipsy", + "live", + "living", + "lixil", + "lk", + "llc", + "loan", + "loans", + "locker", + "locus", + "loft", + "lol", + "london", + "lotte", + "lotto", + "love", + "lpl", + "lplfinancial", + "lr", + "ls", + "lt", + "ltd", + "ltda", + "lu", + "lundbeck", + "lupin", + "luxe", + "luxury", + "lv", + "ly", + "ma", + "macys", + "madrid", + "maif", + "maison", + "makeup", + "man", + "management", + "mango", + "map", + "market", + "marketing", + "markets", + "marriott", + "marshalls", + "maserati", + "mattel", + "mba", + "mc", + "mckinsey", + "md", + "me", + "med", + "media", + "meet", + "melbourne", + "meme", + "memorial", + "men", + "menu", + "merckmsd", + "metlife", + "mg", + "mh", + "miami", + "microsoft", + "mil", + "mini", + "mint", + "mit", + "mitsubishi", + "mk", + "ml", + "mlb", + "mls", + "mm", + "mma", + "mn", + "mo", + "mobi", + "mobile", + "mobily", + "moda", + "moe", + "moi", + "mom", + "monash", + "money", + "monster", + "mopar", + "mormon", + "mortgage", + "moscow", + "moto", + "motorcycles", + "mov", + "movie", + "movistar", + "mp", + "mq", + "mr", + "ms", + "msd", + "mt", + "mtn", + "mtr", + "mu", + "museum", + "mutual", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nab", + "nadex", + "nagoya", + "name", + "nationwide", + "natura", + "navy", + "nba", + "nc", + "ne", + "nec", + "net", + "netbank", + "netflix", + "network", + "neustar", + "new", + "newholland", + "news", + "next", + "nextdirect", + "nexus", + "nf", + "nfl", + "ng", + "ngo", + "nhk", + "ni", + "nico", + "nike", + "nikon", + "ninja", + "nissan", + "nissay", + "nl", + "no", + "nokia", + "northwesternmutual", + "norton", + "now", + "nowruz", + "nowtv", + "np", + "nr", + "nra", + "nrw", + "ntt", + "nu", + "nyc", + "nz", + "obi", + "observer", + "off", + "office", + "okinawa", + "olayan", + "olayangroup", + "oldnavy", + "ollo", + "om", + "omega", + "one", + "ong", + "onion", + "onl", + "online", + "onyourside", + "ooo", + "open", + "oracle", + "orange", + "org", + "organic", + "origins", + "osaka", + "otsuka", + "ott", + "ovh", + "pa", + "page", + "panasonic", + "paris", + "pars", + "partners", + "parts", + "party", + "passagens", + "pay", + "pccw", + "pe", + "pet", + "pf", + "pfizer", + "pg", + "ph", + "pharmacy", + "phd", + "philips", + "phone", + "photo", + "photography", + "photos", + "physio", + "piaget", + "pics", + "pictet", + "pictures", + "pid", + "pin", + "ping", + "pink", + "pioneer", + "pizza", + "pk", + "pl", + "place", + "play", + "playstation", + "plumbing", + "plus", + "pm", + "pn", + "pnc", + "pohl", + "poker", + "politie", + "porn", + "post", + "pr", + "pramerica", + "praxi", + "press", + "prime", + "pro", + "prod", + "productions", + "prof", + "progressive", + "promo", + "properties", + "property", + "protection", + "pru", + "prudential", + "ps", + "pt", + "pub", + "pw", + "pwc", + "py", + "qa", + "qpon", + "quebec", + "quest", + "qvc", + "racing", + "radio", + "raid", + "re", + "read", + "realestate", + "realtor", + "realty", + "recipes", + "red", + "redstone", + "redumbrella", + "rehab", + "reise", + "reisen", + "reit", + "reliance", + "ren", + "rent", + "rentals", + "repair", + "report", + "republican", + "rest", + "restaurant", + "review", + "reviews", + "rexroth", + "rich", + "richardli", + "ricoh", + "rightathome", + "ril", + "rio", + "rip", + "rmit", + "ro", + "rocher", + "rocks", + "rodeo", + "rogers", + "room", + "rs", + "rsvp", + "ru", + "rugby", + "ruhr", + "run", + "rw", + "rwe", + "ryukyu", + "sa", + "saarland", + "safe", + "safety", + "sakura", + "sale", + "salon", + "samsclub", + "samsung", + "sandvik", + "sandvikcoromant", + "sanofi", + "sap", + "sarl", + "sas", + "save", + "saxo", + "sb", + "sbi", + "sbs", + "sc", + "sca", + "scb", + "schaeffler", + "schmidt", + "scholarships", + "school", + "schule", + "schwarz", + "science", + "scjohnson", + "scor", + "scot", + "sd", + "se", + "search", + "seat", + "secure", + "security", + "seek", + "select", + "sener", + "services", + "ses", + "seven", + "sew", + "sex", + "sexy", + "sfr", + "sg", + "sh", + "shangrila", + "sharp", + "shaw", + "shell", + "shia", + "shiksha", + "shoes", + "shop", + "shopping", + "shouji", + "show", + "showtime", + "shriram", + "si", + "silk", + "sina", + "singles", + "site", + "sj", + "sk", + "ski", + "skin", + "sky", + "skype", + "sl", + "sling", + "sm", + "smart", + "smile", + "sn", + "sncf", + "so", + "soccer", + "social", + "softbank", + "software", + "sohu", + "solar", + "solutions", + "song", + "sony", + "soy", + "space", + "sport", + "spot", + "spreadbetting", + "sr", + "srl", + "srt", + "st", + "stada", + "staples", + "star", + "starhub", + "statebank", + "statefarm", + "stc", + "stcgroup", + "stockholm", + "storage", + "store", + "stream", + "studio", + "study", + "style", + "su", + "sucks", + "supplies", + "supply", + "support", + "surf", + "surgery", + "suzuki", + "sv", + "swatch", + "swiftcover", + "swiss", + "sx", + "sy", + "sydney", + "symantec", + "systems", + "sz", + "tab", + "taipei", + "talk", + "taobao", + "target", + "tatamotors", + "tatar", + "tattoo", + "tax", + "taxi", + "tc", + "tci", + "td", + "tdk", + "team", + "tech", + "technology", + "tel", + "telefonica", + "temasek", + "tennis", + "teva", + "tf", + "tg", + "th", + "thd", + "theater", + "theatre", + "tiaa", + "tickets", + "tienda", + "tiffany", + "tips", + "tires", + "tirol", + "tj", + "tjmaxx", + "tjx", + "tk", + "tkmaxx", + "tl", + "tm", + "tmall", + "tn", + "to", + "today", + "tokyo", + "tools", + "top", + "toray", + "toshiba", + "total", + "tours", + "town", + "toyota", + "toys", + "tr", + "trade", + "trading", + "training", + "travel", + "travelchannel", + "travelers", + "travelersinsurance", + "trust", + "trv", + "tt", + "tube", + "tui", + "tunes", + "tushu", + "tv", + "tvs", + "tw", + "tz", + "ua", + "ubank", + "ubs", + "uconnect", + "ug", + "uk", + "unicom", + "university", + "uno", + "uol", + "ups", + "us", + "uy", + "uz", + "va", + "vacations", + "vana", + "vanguard", + "vc", + "ve", + "vegas", + "ventures", + "verisign", + "versicherung", + "vet", + "vg", + "vi", + "viajes", + "video", + "vig", + "viking", + "villas", + "vin", + "vip", + "virgin", + "visa", + "vision", + "vistaprint", + "viva", + "vivo", + "vlaanderen", + "vn", + "vodka", + "volkswagen", + "volvo", + "vote", + "voting", + "voto", + "voyage", + "vu", + "vuelos", + "wales", + "walmart", + "walter", + "wang", + "wanggou", + "warman", + "watch", + "watches", + "weather", + "weatherchannel", + "webcam", + "weber", + "website", + "wed", + "wedding", + "weibo", + "weir", + "wf", + "whoswho", + "wien", + "wiki", + "williamhill", + "win", + "windows", + "wine", + "winners", + "wme", + "wolterskluwer", + "woodside", + "work", + "works", + "world", + "wow", + "ws", + "wtc", + "wtf", + "xbox", + "xerox", + "xfinity", + "xihuan", + "xin", + "xn--11b4c3d", + "xn--1ck2e1b", + "xn--1qqw23a", + "xn--2scrj9c", + "xn--30rr7y", + "xn--3bst00m", + "xn--3ds443g", + "xn--3e0b707e", + "xn--3hcrj9c", + "xn--3oq18vl8pn36a", + "xn--3pxu8k", + "xn--42c2d9a", + "xn--45br5cyl", + "xn--45brj9c", + "xn--45q11c", + "xn--4gbrim", + "xn--54b7fta0cc", + "xn--55qw42g", + "xn--55qx5d", + "xn--5su34j936bgsg", + "xn--5tzm5g", + "xn--6frz82g", + "xn--6qq986b3xl", + "xn--80adxhks", + "xn--80ao21a", + "xn--80aqecdr1a", + "xn--80asehdb", + "xn--80aswg", + "xn--8y0a063a", + "xn--90a3ac", + "xn--90ae", + "xn--90ais", + "xn--9dbq2a", + "xn--9et52u", + "xn--9krt00a", + "xn--b4w605ferd", + "xn--bck1b9a5dre4c", + "xn--c1avg", + "xn--c2br7g", + "xn--cck2b3b", + "xn--cg4bki", + "xn--clchc0ea0b2g2a9gcd", + "xn--czr694b", + "xn--czrs0t", + "xn--czru2d", + "xn--d1acj3b", + "xn--d1alf", + "xn--e1a4c", + "xn--eckvdtc9d", + "xn--efvy88h", + "xn--estv75g", + "xn--fct429k", + "xn--fhbei", + "xn--fiq228c5hs", + "xn--fiq64b", + "xn--fiqs8s", + "xn--fiqz9s", + "xn--fjq720a", + "xn--flw351e", + "xn--fpcrj9c3d", + "xn--fzc2c9e2c", + "xn--fzys8d69uvgm", + "xn--g2xx48c", + "xn--gckr3f0f", + "xn--gecrj9c", + "xn--gk3at1e", + "xn--h2breg3eve", + "xn--h2brj9c", + "xn--h2brj9c8c", + "xn--hxt814e", + "xn--i1b6b1a6a2e", + "xn--imr513n", + "xn--io0a7i", + "xn--j1aef", + "xn--j1amh", + "xn--j6w193g", + "xn--jlq61u9w7b", + "xn--jvr189m", + "xn--kcrx77d1x4a", + "xn--kprw13d", + "xn--kpry57d", + "xn--kpu716f", + "xn--kput3i", + "xn--l1acc", + "xn--lgbbat1ad8j", + "xn--mgb2ddes", + "xn--mgb9awbf", + "xn--mgba3a3ejt", + "xn--mgba3a4f16a", + "xn--mgba3a4fra", + "xn--mgba7c0bbn0a", + "xn--mgbaakc7dvf", + "xn--mgbaam7a8h", + "xn--mgbab2bd", + "xn--mgbai9a5eva00b", + "xn--mgbai9azgqp6j", + "xn--mgbayh7gpa", + "xn--mgbb9fbpob", + "xn--mgbbh1a", + "xn--mgbbh1a71e", + "xn--mgbc0a9azcg", + "xn--mgbca7dzdo", + "xn--mgberp4a5d4a87g", + "xn--mgberp4a5d4ar", + "xn--mgbgu82a", + "xn--mgbi4ecexp", + "xn--mgbpl2fh", + "xn--mgbqly7c0a67fbc", + "xn--mgbqly7cvafr", + "xn--mgbt3dhd", + "xn--mgbtf8fl", + "xn--mgbtx2b", + "xn--mgbx4cd0ab", + "xn--mix082f", + "xn--mix891f", + "xn--mk1bu44c", + "xn--mxtq1m", + "xn--ngbc5azd", + "xn--ngbe9e0a", + "xn--ngbrx", + "xn--nnx388a", + "xn--node", + "xn--nqv7f", + "xn--nqv7fs00ema", + "xn--nyqy26a", + "xn--o3cw4h", + "xn--ogbpf8fl", + "xn--otu796d", + "xn--p1acf", + "xn--p1ai", + "xn--pbt977c", + "xn--pgbs0dh", + "xn--pssy2u", + "xn--q9jyb4c", + "xn--qcka1pmc", + "xn--qxam", + "xn--rhqv96g", + "xn--rovu88b", + "xn--rvc1e0am3e", + "xn--s9brj9c", + "xn--ses554g", + "xn--t60b56a", + "xn--tckwe", + "xn--tiq49xqyj", + "xn--unup4y", + "xn--vermgensberater-ctb", + "xn--vermgensberatung-pwb", + "xn--vhquv", + "xn--vuq861b", + "xn--w4r85el8fhu5dnra", + "xn--w4rs40l", + "xn--wgbh1c", + "xn--wgbl6a", + "xn--xhq521b", + "xn--xkc2al3hye2a", + "xn--xkc2dl3a5ee0h", + "xn--y9a3aq", + "xn--yfro4i67o", + "xn--ygbi2ammx", + "xn--zfr164b", + "xxx", + "xyz", + "yachts", + "yahoo", + "yamaxun", + "yandex", + "ye", + "yodobashi", + "yoga", + "yokohama", + "you", + "youtube", + "yt", + "yun", + "za", + "zappos", + "zara", + "zero", + "zip", + "zm", + "zone", + "zuerich", + "zw", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "official", + "nom", + "ac", + "blogspot", + "co", + "gov", + "mil", + "net", + "nom", + "org", + "sch", + "accident-investigation", + "accident-prevention", + "aerobatic", + "aeroclub", + "aerodrome", + "agents", + "air-surveillance", + "air-traffic-control", + "aircraft", + "airline", + "airport", + "airtraffic", + "ambulance", + "amusement", + "association", + "author", + "ballooning", + "broker", + "caa", + "cargo", + "catering", + "certification", + "championship", + "charter", + "civilaviation", + "club", + "conference", + "consultant", + "consulting", + "control", + "council", + "crew", + "design", + "dgca", + "educator", + "emergency", + "engine", + "engineer", + "entertainment", + "equipment", + "exchange", + "express", + "federation", + "flight", + "freight", + "fuel", + "gliding", + "government", + "groundhandling", + "group", + "hanggliding", + "homebuilt", + "insurance", + "journal", + "journalist", + "leasing", + "logistics", + "magazine", + "maintenance", + "media", + "microlight", + "modelling", + "navigation", + "parachuting", + "paragliding", + "passenger-association", + "pilot", + "press", + "production", + "recreation", + "repbody", + "res", + "research", + "rotorcraft", + "safety", + "scientist", + "services", + "show", + "skydiving", + "software", + "student", + "trader", + "trading", + "trainer", + "union", + "workinggroup", + "works", + "com", + "edu", + "gov", + "net", + "nom", + "org", + "co", + "com", + "net", + "nom", + "org", + "com", + "net", + "nom", + "off", + "org", + "uwu", + "blogspot", + "com", + "edu", + "gov", + "mil", + "net", + "nom", + "org", + "blogspot", + "co", + "com", + "commune", + "net", + "org", + "co", + "ed", + "gv", + "it", + "og", + "pb", + "hasura", + "loginline", + "run", + "telebit", + "web", + "wnext", + "a", + "com", + "edu", + "gob", + "gov", + "int", + "mil", + "musica", + "net", + "org", + "tur", + "blogspot", + "e164", + "in-addr", + "ip6", + "iris", + "uri", + "urn", + "gov", + "cloudns", + "12hp", + "2ix", + "4lima", + "ac", + "biz", + "co", + "futurecms", + "futurehosting", + "futuremailing", + "gv", + "info", + "lima-city", + "or", + "ortsinfo", + "priv", + "blogspot", + "ex", + "in", + "ex", + "kunden", + "act", + "asn", + "com", + "conf", + "edu", + "gov", + "id", + "info", + "net", + "nsw", + "nt", + "org", + "oz", + "qld", + "sa", + "tas", + "vic", + "wa", + "blogspot", + "act", + "nsw", + "nt", + "qld", + "sa", + "tas", + "vic", + "wa", + "qld", + "sa", + "tas", + "vic", + "wa", + "com", + "biz", + "com", + "edu", + "gov", + "info", + "int", + "mil", + "name", + "net", + "org", + "pp", + "pro", + "blogspot", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "biz", + "co", + "com", + "edu", + "gov", + "info", + "net", + "org", + "store", + "tv", + "ac", + "blogspot", + "transurl", + "webhosting", + "gov", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "a", + "b", + "barsy", + "blogspot", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "com", + "edu", + "gov", + "net", + "org", + "co", + "com", + "edu", + "or", + "org", + "bpl", + "cloudns", + "dscloud", + "dyndns", + "for-better", + "for-more", + "for-some", + "for-the", + "mmafan", + "myftp", + "no-ip", + "orx", + "selfip", + "webhop", + "asso", + "barreau", + "blogspot", + "gouv", + "com", + "edu", + "gov", + "net", + "org", + "co", + "com", + "edu", + "gov", + "net", + "org", + "academia", + "agro", + "arte", + "blog", + "bolivia", + "ciencia", + "com", + "cooperativa", + "democracia", + "deporte", + "ecologia", + "economia", + "edu", + "empresa", + "gob", + "indigena", + "industria", + "info", + "int", + "medicina", + "mil", + "movimiento", + "musica", + "natural", + "net", + "nombre", + "noticias", + "org", + "patria", + "plurinacional", + "politica", + "profesional", + "pueblo", + "revista", + "salud", + "tecnologia", + "tksat", + "transporte", + "tv", + "web", + "wiki", + "9guacu", + "abc", + "adm", + "adv", + "agr", + "aju", + "am", + "anani", + "aparecida", + "arq", + "art", + "ato", + "b", + "barueri", + "belem", + "bhz", + "bio", + "blog", + "bmd", + "boavista", + "bsb", + "campinagrande", + "campinas", + "caxias", + "cim", + "cng", + "cnt", + "com", + "contagem", + "coop", + "cri", + "cuiaba", + "curitiba", + "def", + "ecn", + "eco", + "edu", + "emp", + "eng", + "esp", + "etc", + "eti", + "far", + "feira", + "flog", + "floripa", + "fm", + "fnd", + "fortal", + "fot", + "foz", + "fst", + "g12", + "ggf", + "goiania", + "gov", + "gru", + "imb", + "ind", + "inf", + "jab", + "jampa", + "jdf", + "joinville", + "jor", + "jus", + "leg", + "lel", + "londrina", + "macapa", + "maceio", + "manaus", + "maringa", + "mat", + "med", + "mil", + "morena", + "mp", + "mus", + "natal", + "net", + "niteroi", + "nom", + "not", + "ntr", + "odo", + "ong", + "org", + "osasco", + "palmas", + "poa", + "ppg", + "pro", + "psc", + "psi", + "pvh", + "qsl", + "radio", + "rec", + "recife", + "ribeirao", + "rio", + "riobranco", + "riopreto", + "salvador", + "sampa", + "santamaria", + "santoandre", + "saobernardo", + "saogonca", + "sjc", + "slg", + "slz", + "sorocaba", + "srv", + "taxi", + "tc", + "teo", + "the", + "tmp", + "trd", + "tur", + "tv", + "udi", + "vet", + "vix", + "vlog", + "wiki", + "zlg", + "blogspot", + "ac", + "al", + "am", + "ap", + "ba", + "ce", + "df", + "es", + "go", + "ma", + "mg", + "ms", + "mt", + "pa", + "pb", + "pe", + "pi", + "pr", + "rj", + "rn", + "ro", + "rr", + "rs", + "sc", + "se", + "sp", + "to", + "ac", + "al", + "am", + "ap", + "ba", + "ce", + "df", + "es", + "go", + "ma", + "mg", + "ms", + "mt", + "pa", + "pb", + "pe", + "pi", + "pr", + "rj", + "rn", + "ro", + "rr", + "rs", + "sc", + "se", + "sp", + "to", + "com", + "edu", + "gov", + "net", + "org", + "we", + "com", + "edu", + "gov", + "net", + "org", + "co", + "co", + "org", + "com", + "gov", + "mil", + "nym", + "of", + "blogspot", + "com", + "edu", + "gov", + "net", + "nym", + "org", + "za", + "ab", + "awdev", + "barsy", + "bc", + "blogspot", + "co", + "gc", + "mb", + "nb", + "nf", + "nl", + "no-ip", + "ns", + "nt", + "nu", + "on", + "pe", + "qc", + "sk", + "yk", + "nabu", + "ui", + "cloudns", + "fantasyleague", + "ftpaccess", + "game-server", + "myphotos", + "scrapping", + "twmail", + "gov", + "blogspot", + "12hp", + "2ix", + "4lima", + "blogspot", + "dnsking", + "gotdns", + "lima-city", + "linkyard-cloud", + "square7", + "ac", + "asso", + "co", + "com", + "ed", + "edu", + "fin", + "go", + "gouv", + "int", + "md", + "net", + "or", + "org", + "presse", + "xn--aroport-bya", + "ng", + "www", + "blogspot", + "co", + "gob", + "gov", + "mil", + "nom", + "linkyard", + "magentosite", + "on-rancher", + "sensiosite", + "statics", + "trafficplex", + "vapor", + "voorloper", + "barsy", + "cloudns", + "pony", + "co", + "com", + "gov", + "net", + "ac", + "ah", + "bj", + "com", + "cq", + "edu", + "fj", + "gd", + "gov", + "gs", + "gx", + "gz", + "ha", + "hb", + "he", + "hi", + "hk", + "hl", + "hn", + "instantcloud", + "jl", + "js", + "jx", + "ln", + "mil", + "mo", + "net", + "nm", + "nx", + "org", + "qh", + "sc", + "sd", + "sh", + "sn", + "sx", + "tj", + "tw", + "xj", + "xn--55qx5d", + "xn--io0a7i", + "xn--od0alg", + "xz", + "yn", + "zj", + "amazonaws", + "cn-north-1", + "compute", + "eb", + "elb", + "s3", + "cn-north-1", + "cn-northwest-1", + "arts", + "carrd", + "com", + "crd", + "edu", + "firm", + "go-vip", + "gov", + "info", + "int", + "leadpages", + "lpages", + "mil", + "mypi", + "n4t", + "net", + "nodum", + "nom", + "org", + "otap", + "rec", + "repl", + "web", + "blogspot", + "001www", + "0emm", + "1kapp", + "3utilities", + "4u", + "africa", + "alpha-myqnapcloud", + "amazonaws", + "appchizi", + "applinzi", + "appspot", + "ar", + "balena-devices", + "barsycenter", + "barsyonline", + "betainabox", + "bitballoon", + "blogdns", + "blogspot", + "blogsyte", + "bloxcms", + "bounty-full", + "bplaced", + "br", + "cechire", + "ciscofreak", + "cloudcontrolapp", + "cloudcontrolled", + "cn", + "co", + "codespot", + "damnserver", + "dattolocal", + "dattorelay", + "dattoweb", + "ddnsfree", + "ddnsgeek", + "ddnsking", + "ddnslive", + "de", + "dev-myqnapcloud", + "ditchyourip", + "dnsalias", + "dnsdojo", + "dnsiskinky", + "doesntexist", + "dontexist", + "doomdns", + "drayddns", + "dreamhosters", + "dsmynas", + "dyn-o-saur", + "dynalias", + "dyndns-at-home", + "dyndns-at-work", + "dyndns-blog", + "dyndns-free", + "dyndns-home", + "dyndns-ip", + "dyndns-mail", + "dyndns-office", + "dyndns-pics", + "dyndns-remote", + "dyndns-server", + "dyndns-web", + "dyndns-wiki", + "dyndns-work", + "dynns", + "elasticbeanstalk", + "est-a-la-maison", + "est-a-la-masion", + "est-le-patron", + "est-mon-blogueur", + "eu", + "evennode", + "familyds", + "fastly-terrarium", + "fastvps-server", + "fbsbx", + "firebaseapp", + "firewall-gateway", + "flynnhub", + "freebox-os", + "freeboxos", + "from-ak", + "from-al", + "from-ar", + "from-ca", + "from-ct", + "from-dc", + "from-de", + "from-fl", + "from-ga", + "from-hi", + "from-ia", + "from-id", + "from-il", + "from-in", + "from-ks", + "from-ky", + "from-ma", + "from-md", + "from-mi", + "from-mn", + "from-mo", + "from-ms", + "from-mt", + "from-nc", + "from-nd", + "from-ne", + "from-nh", + "from-nj", + "from-nm", + "from-nv", + "from-oh", + "from-ok", + "from-or", + "from-pa", + "from-pr", + "from-ri", + "from-sc", + "from-sd", + "from-tn", + "from-tx", + "from-ut", + "from-va", + "from-vt", + "from-wa", + "from-wi", + "from-wv", + "from-wy", + "gb", + "geekgalaxy", + "getmyip", + "giize", + "githubusercontent", + "gleeze", + "googleapis", + "googlecode", + "gotdns", + "gotpantheon", + "gr", + "health-carereform", + "herokuapp", + "herokussl", + "hk", + "hobby-site", + "homelinux", + "homesecuritymac", + "homesecuritypc", + "homeunix", + "hu", + "iamallama", + "is-a-anarchist", + "is-a-blogger", + "is-a-bookkeeper", + "is-a-bulls-fan", + "is-a-caterer", + "is-a-chef", + "is-a-conservative", + "is-a-cpa", + "is-a-cubicle-slave", + "is-a-democrat", + "is-a-designer", + "is-a-doctor", + "is-a-financialadvisor", + "is-a-geek", + "is-a-green", + "is-a-guru", + "is-a-hard-worker", + "is-a-hunter", + "is-a-landscaper", + "is-a-lawyer", + "is-a-liberal", + "is-a-libertarian", + "is-a-llama", + "is-a-musician", + "is-a-nascarfan", + "is-a-nurse", + "is-a-painter", + "is-a-personaltrainer", + "is-a-photographer", + "is-a-player", + "is-a-republican", + "is-a-rockstar", + "is-a-socialist", + "is-a-student", + "is-a-teacher", + "is-a-techie", + "is-a-therapist", + "is-an-accountant", + "is-an-actor", + "is-an-actress", + "is-an-anarchist", + "is-an-artist", + "is-an-engineer", + "is-an-entertainer", + "is-certified", + "is-gone", + "is-into-anime", + "is-into-cars", + "is-into-cartoons", + "is-into-games", + "is-leet", + "is-not-certified", + "is-slick", + "is-uberleet", + "is-with-theband", + "isa-geek", + "isa-hockeynut", + "issmarterthanyou", + "jdevcloud", + "joyent", + "jpn", + "kozow", + "kr", + "likes-pie", + "likescandy", + "linode", + "lmpm", + "logoip", + "loseyourip", + "lpusercontent", + "meteorapp", + "mex", + "miniserver", + "myactivedirectory", + "myasustor", + "mydatto", + "mydobiss", + "mydrobo", + "myiphost", + "myqnapcloud", + "myravendb", + "mysecuritycamera", + "myshopblocks", + "mytuleap", + "myvnc", + "neat-url", + "net-freaks", + "netlify", + "nfshost", + "no", + "on-aptible", + "onrender", + "onthewifi", + "ooguy", + "operaunite", + "outsystemscloud", + "ownprovider", + "pagefrontapp", + "pagespeedmobilizer", + "pgfog", + "pixolino", + "point2this", + "prgmr", + "publishproxy", + "qa2", + "qc", + "quicksytes", + "quipelements", + "rackmaze", + "remotewd", + "render", + "rhcloud", + "ru", + "sa", + "saves-the-whales", + "scrysec", + "securitytactics", + "selfip", + "sells-for-less", + "sells-for-u", + "servebbs", + "servebeer", + "servecounterstrike", + "serveexchange", + "serveftp", + "servegame", + "servehalflife", + "servehttp", + "servehumour", + "serveirc", + "servemp3", + "servep2p", + "servepics", + "servequake", + "servesarcasm", + "simple-url", + "sinaapp", + "space-to-rent", + "stackhero-network", + "stdlib", + "stufftoread", + "teaches-yoga", + "temp-dns", + "theworkpc", + "thingdustdata", + "townnews-staging", + "uk", + "unusualperson", + "us", + "uy", + "vipsinaapp", + "wafflecell", + "withgoogle", + "withyoutube", + "workisboring", + "wpcomstaging", + "wpdevcloud", + "writesthisblog", + "xenapponazure", + "xnbay", + "yolasite", + "za", + "ap-northeast-1", + "ap-northeast-2", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "compute", + "compute-1", + "elb", + "eu-central-1", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "s3", + "s3-ap-northeast-1", + "s3-ap-northeast-2", + "s3-ap-south-1", + "s3-ap-southeast-1", + "s3-ap-southeast-2", + "s3-ca-central-1", + "s3-eu-central-1", + "s3-eu-west-1", + "s3-eu-west-2", + "s3-eu-west-3", + "s3-external-1", + "s3-fips-us-gov-west-1", + "s3-sa-east-1", + "s3-us-east-2", + "s3-us-gov-west-1", + "s3-us-west-1", + "s3-us-west-2", + "s3-website-ap-northeast-1", + "s3-website-ap-southeast-1", + "s3-website-ap-southeast-2", + "s3-website-eu-west-1", + "s3-website-sa-east-1", + "s3-website-us-east-1", + "s3-website-us-west-1", + "s3-website-us-west-2", + "sa-east-1", + "us-east-1", + "us-east-2", + "dualstack", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "dualstack", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "dualstack", + "s3", + "dualstack", + "s3", + "dualstack", + "s3", + "s3-website", + "s3", + "alpha", + "beta", + "ap-northeast-1", + "ap-northeast-2", + "ap-northeast-3", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "eu-central-1", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "sa-east-1", + "us-east-1", + "us-east-2", + "us-gov-west-1", + "us-west-1", + "us-west-2", + "eu-1", + "eu-2", + "eu-3", + "eu-4", + "us-1", + "us-2", + "us-3", + "us-4", + "apps", + "cns", + "members", + "nodebalancer", + "app", + "eu", + "xen", + "app", + "api", + "u2", + "u2-local", + "ravendb", + "de", + "ac", + "co", + "ed", + "fi", + "go", + "or", + "sa", + "com", + "edu", + "gov", + "inf", + "net", + "org", + "blogspot", + "com", + "edu", + "net", + "org", + "ath", + "gov", + "info", + "ac", + "biz", + "com", + "ekloges", + "gov", + "ltd", + "name", + "net", + "org", + "parliament", + "press", + "pro", + "tm", + "blogspot", + "blogspot", + "co", + "e4", + "metacentrum", + "muni", + "realm", + "cloud", + "custom", + "cloud", + "flt", + "usr", + "12hp", + "2ix", + "4lima", + "barsy", + "blogspot", + "bplaced", + "com", + "cosidns", + "dd-dns", + "ddnss", + "dnshome", + "dnsupdater", + "dray-dns", + "draydns", + "dyn-berlin", + "dyn-ip24", + "dyn-vpn", + "dynamisches-dns", + "dyndns1", + "dynvpn", + "firewall-gateway", + "fuettertdasnetz", + "git-repos", + "goip", + "home-webserver", + "in-berlin", + "in-brb", + "in-butter", + "in-dsl", + "in-vpn", + "internet-dns", + "isteingeek", + "istmein", + "keymachine", + "l-o-g-i-n", + "lcube-server", + "lebtimnetz", + "leitungsen", + "lima-city", + "logoip", + "mein-iserv", + "mein-vigor", + "my-gateway", + "my-router", + "my-vigor", + "my-wan", + "myhome-server", + "spdns", + "speedpartner", + "square7", + "svn-repos", + "syno-ds", + "synology-diskstation", + "synology-ds", + "taifun-dns", + "test-iserv", + "traeumtgerade", + "uberspace", + "virtual-user", + "virtualuser", + "dyn", + "dyn", + "dyndns", + "dyn", + "customer", + "bss", + "lcl", + "loginline", + "stg", + "workers", + "cloudapps", + "london", + "fastpanel", + "biz", + "blogspot", + "co", + "firm", + "reg", + "store", + "com", + "edu", + "gov", + "net", + "org", + "art", + "com", + "edu", + "gob", + "gov", + "mil", + "net", + "org", + "sld", + "web", + "art", + "asso", + "com", + "edu", + "gov", + "net", + "org", + "pol", + "dapps", + "bzz", + "com", + "edu", + "fin", + "gob", + "gov", + "info", + "k12", + "med", + "mil", + "net", + "org", + "pro", + "rit", + "git-pages", + "co", + "aip", + "com", + "edu", + "fie", + "gov", + "lib", + "med", + "org", + "pri", + "riik", + "blogspot", + "com", + "edu", + "eun", + "gov", + "mil", + "name", + "net", + "org", + "sci", + "blogspot", + "com", + "edu", + "gob", + "nom", + "org", + "blogspot", + "compute", + "biz", + "com", + "edu", + "gov", + "info", + "name", + "net", + "org", + "barsy", + "cloudns", + "diskstation", + "mycd", + "spdns", + "transurl", + "wellbeingzone", + "party", + "user", + "co", + "ybo", + "storj", + "of", + "on", + "aland", + "blogspot", + "dy", + "iki", + "xn--hkkinen-5wa", + "co", + "ptplus", + "of", + "aeroport", + "asso", + "avocat", + "avoues", + "blogspot", + "cci", + "chambagri", + "chirurgiens-dentistes", + "chirurgiens-dentistes-en-france", + "com", + "experts-comptables", + "fbx-os", + "fbxos", + "freebox-os", + "freeboxos", + "geometre-expert", + "gouv", + "greta", + "huissier-justice", + "medecin", + "nom", + "notaires", + "on-web", + "pharmacien", + "port", + "prd", + "tm", + "veterinaire", + "nom", + "cnpy", + "com", + "edu", + "gov", + "mil", + "net", + "nom", + "org", + "pvt", + "co", + "cya", + "kaas", + "net", + "org", + "com", + "edu", + "gov", + "mil", + "org", + "com", + "edu", + "gov", + "ltd", + "mod", + "org", + "biz", + "co", + "com", + "edu", + "net", + "nom", + "org", + "ac", + "com", + "edu", + "gov", + "net", + "org", + "cloud", + "asso", + "com", + "edu", + "mobi", + "net", + "org", + "blogspot", + "com", + "edu", + "gov", + "net", + "nym", + "org", + "discourse", + "com", + "edu", + "gob", + "ind", + "mil", + "net", + "nom", + "org", + "com", + "edu", + "gov", + "guam", + "info", + "net", + "org", + "web", + "co", + "com", + "edu", + "gov", + "net", + "nym", + "org", + "blogspot", + "com", + "edu", + "gov", + "idv", + "inc", + "ltd", + "net", + "org", + "xn--55qx5d", + "xn--ciqpn", + "xn--gmq050i", + "xn--gmqw5a", + "xn--io0a7i", + "xn--lcvr32d", + "xn--mk0axi", + "xn--mxtq1m", + "xn--od0alg", + "xn--od0aq3b", + "xn--tn0ag", + "xn--uc0atv", + "xn--uc0ay4a", + "xn--wcvs22d", + "xn--zf0avx", + "com", + "edu", + "gob", + "mil", + "net", + "nom", + "org", + "cloudaccess", + "freesite", + "half", + "pcloud", + "opencraft", + "blogspot", + "com", + "free", + "from", + "iz", + "name", + "adult", + "art", + "asso", + "com", + "coop", + "edu", + "firm", + "gouv", + "info", + "med", + "net", + "org", + "perso", + "pol", + "pro", + "rel", + "shop", + "2000", + "agrar", + "blogspot", + "bolt", + "casino", + "city", + "co", + "erotica", + "erotika", + "film", + "forum", + "games", + "hotel", + "info", + "ingatlan", + "jogasz", + "konyvelo", + "lakas", + "media", + "news", + "org", + "priv", + "reklam", + "sex", + "shop", + "sport", + "suli", + "szex", + "tm", + "tozsde", + "utazas", + "video", + "ac", + "biz", + "co", + "desa", + "go", + "mil", + "my", + "net", + "or", + "ponpes", + "sch", + "web", + "zone", + "blogspot", + "blogspot", + "gov", + "nym", + "ac", + "co", + "gov", + "idf", + "k12", + "muni", + "net", + "org", + "blogspot", + "ac", + "co", + "com", + "net", + "nom", + "org", + "ro", + "tt", + "tv", + "ltd", + "plc", + "ac", + "barsy", + "blogspot", + "cloudns", + "co", + "edu", + "firm", + "gen", + "gov", + "ind", + "mil", + "net", + "nic", + "org", + "res", + "barrel-of-knowledge", + "barrell-of-knowledge", + "barsy", + "cloudns", + "dvrcam", + "dynamic-dns", + "dyndns", + "for-our", + "forumz", + "groks-the", + "groks-this", + "here-for-more", + "ilovecollege", + "knowsitall", + "mayfirst", + "no-ip", + "nsupdate", + "selfip", + "v-info", + "webhop", + "ng", + "eu", + "2038", + "apigee", + "applicationcloud", + "azurecontainer", + "b-data", + "backplaneapp", + "banzaicloud", + "barsy", + "basicserver", + "bigv", + "boxfuse", + "browsersafetymark", + "cleverapps", + "com", + "dedyn", + "definima", + "drud", + "dyn53", + "enonic", + "github", + "gitlab", + "hasura-app", + "hzc", + "lair", + "loginline", + "mo-siemens", + "moonscale", + "ngrok", + "nid", + "nodeart", + "nodum", + "on-rio", + "pantheonsite", + "protonet", + "readthedocs", + "resindevice", + "resinstaging", + "s5y", + "sandcats", + "scapp", + "shiftedit", + "spacekit", + "stolos", + "telebit", + "thingdust", + "utwente", + "vaporcloud", + "virtualserver", + "wedeploy", + "app", + "uk0", + "customer", + "apps", + "stage", + "devices", + "dev", + "disrec", + "prod", + "testing", + "cust", + "cust", + "cust", + "cust", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "ac", + "co", + "gov", + "id", + "net", + "org", + "sch", + "xn--mgba3a4f16a", + "xn--mgba3a4fra", + "blogspot", + "com", + "cupcake", + "edu", + "gov", + "int", + "net", + "org", + "16-b", + "32-b", + "64-b", + "abr", + "abruzzo", + "ag", + "agrigento", + "al", + "alessandria", + "alto-adige", + "altoadige", + "an", + "ancona", + "andria-barletta-trani", + "andria-trani-barletta", + "andriabarlettatrani", + "andriatranibarletta", + "ao", + "aosta", + "aosta-valley", + "aostavalley", + "aoste", + "ap", + "aq", + "aquila", + "ar", + "arezzo", + "ascoli-piceno", + "ascolipiceno", + "asti", + "at", + "av", + "avellino", + "ba", + "balsan", + "balsan-sudtirol", + "balsan-suedtirol", + "bari", + "barletta-trani-andria", + "barlettatraniandria", + "bas", + "basilicata", + "belluno", + "benevento", + "bergamo", + "bg", + "bi", + "biella", + "bl", + "blogspot", + "bn", + "bo", + "bologna", + "bolzano", + "bolzano-altoadige", + "bozen", + "bozen-sudtirol", + "bozen-suedtirol", + "br", + "brescia", + "brindisi", + "bs", + "bt", + "bulsan", + "bulsan-sudtirol", + "bulsan-suedtirol", + "bz", + "ca", + "cagliari", + "cal", + "calabria", + "caltanissetta", + "cam", + "campania", + "campidano-medio", + "campidanomedio", + "campobasso", + "carbonia-iglesias", + "carboniaiglesias", + "carrara-massa", + "carraramassa", + "caserta", + "catania", + "catanzaro", + "cb", + "ce", + "cesena-forli", + "cesenaforli", + "ch", + "chieti", + "ci", + "cl", + "cn", + "co", + "como", + "cosenza", + "cr", + "cremona", + "crotone", + "cs", + "ct", + "cuneo", + "cz", + "dell-ogliastra", + "dellogliastra", + "edu", + "emilia-romagna", + "emiliaromagna", + "emr", + "en", + "enna", + "fc", + "fe", + "fermo", + "ferrara", + "fg", + "fi", + "firenze", + "florence", + "fm", + "foggia", + "forli-cesena", + "forlicesena", + "fr", + "friuli-v-giulia", + "friuli-ve-giulia", + "friuli-vegiulia", + "friuli-venezia-giulia", + "friuli-veneziagiulia", + "friuli-vgiulia", + "friuliv-giulia", + "friulive-giulia", + "friulivegiulia", + "friulivenezia-giulia", + "friuliveneziagiulia", + "friulivgiulia", + "frosinone", + "fvg", + "ge", + "genoa", + "genova", + "go", + "gorizia", + "gov", + "gr", + "grosseto", + "iglesias-carbonia", + "iglesiascarbonia", + "im", + "imperia", + "is", + "isernia", + "kr", + "la-spezia", + "laquila", + "laspezia", + "latina", + "laz", + "lazio", + "lc", + "le", + "lecce", + "lecco", + "li", + "lig", + "liguria", + "livorno", + "lo", + "lodi", + "lom", + "lombardia", + "lombardy", + "lt", + "lu", + "lucania", + "lucca", + "macerata", + "mantova", + "mar", + "marche", + "massa-carrara", + "massacarrara", + "matera", + "mb", + "mc", + "me", + "medio-campidano", + "mediocampidano", + "messina", + "mi", + "milan", + "milano", + "mn", + "mo", + "modena", + "mol", + "molise", + "monza", + "monza-brianza", + "monza-e-della-brianza", + "monzabrianza", + "monzaebrianza", + "monzaedellabrianza", + "ms", + "mt", + "na", + "naples", + "napoli", + "no", + "novara", + "nu", + "nuoro", + "og", + "ogliastra", + "olbia-tempio", + "olbiatempio", + "or", + "oristano", + "ot", + "pa", + "padova", + "padua", + "palermo", + "parma", + "pavia", + "pc", + "pd", + "pe", + "perugia", + "pesaro-urbino", + "pesarourbino", + "pescara", + "pg", + "pi", + "piacenza", + "piedmont", + "piemonte", + "pisa", + "pistoia", + "pmn", + "pn", + "po", + "pordenone", + "potenza", + "pr", + "prato", + "pt", + "pu", + "pug", + "puglia", + "pv", + "pz", + "ra", + "ragusa", + "ravenna", + "rc", + "re", + "reggio-calabria", + "reggio-emilia", + "reggiocalabria", + "reggioemilia", + "rg", + "ri", + "rieti", + "rimini", + "rm", + "rn", + "ro", + "roma", + "rome", + "rovigo", + "sa", + "salerno", + "sar", + "sardegna", + "sardinia", + "sassari", + "savona", + "si", + "sic", + "sicilia", + "sicily", + "siena", + "siracusa", + "so", + "sondrio", + "sp", + "sr", + "ss", + "suedtirol", + "sv", + "syncloud", + "ta", + "taa", + "taranto", + "te", + "tempio-olbia", + "tempioolbia", + "teramo", + "terni", + "tn", + "to", + "torino", + "tos", + "toscana", + "tp", + "tr", + "trani-andria-barletta", + "trani-barletta-andria", + "traniandriabarletta", + "tranibarlettaandria", + "trapani", + "trentin-sud-tirol", + "trentin-sudtirol", + "trentin-sued-tirol", + "trentin-suedtirol", + "trentino", + "trentino-a-adige", + "trentino-aadige", + "trentino-alto-adige", + "trentino-altoadige", + "trentino-s-tirol", + "trentino-stirol", + "trentino-sud-tirol", + "trentino-sudtirol", + "trentino-sued-tirol", + "trentino-suedtirol", + "trentinoa-adige", + "trentinoaadige", + "trentinoalto-adige", + "trentinoaltoadige", + "trentinos-tirol", + "trentinostirol", + "trentinosud-tirol", + "trentinosudtirol", + "trentinosued-tirol", + "trentinosuedtirol", + "trentinsud-tirol", + "trentinsudtirol", + "trentinsued-tirol", + "trentinsuedtirol", + "trento", + "treviso", + "trieste", + "ts", + "turin", + "tuscany", + "tv", + "ud", + "udine", + "umb", + "umbria", + "urbino-pesaro", + "urbinopesaro", + "va", + "val-d-aosta", + "val-daosta", + "vald-aosta", + "valdaosta", + "valle-aosta", + "valle-d-aosta", + "valle-daosta", + "valleaosta", + "valled-aosta", + "valledaosta", + "vallee-aoste", + "vallee-d-aoste", + "valleeaoste", + "valleedaoste", + "vao", + "varese", + "vb", + "vc", + "vda", + "ve", + "ven", + "veneto", + "venezia", + "venice", + "verbania", + "vercelli", + "verona", + "vi", + "vibo-valentia", + "vibovalentia", + "vicenza", + "viterbo", + "vr", + "vs", + "vt", + "vv", + "xn--balsan-sdtirol-nsb", + "xn--bozen-sdtirol-2ob", + "xn--bulsan-sdtirol-nsb", + "xn--cesena-forl-mcb", + "xn--cesenaforl-i8a", + "xn--forl-cesena-fcb", + "xn--forlcesena-c8a", + "xn--sdtirol-n2a", + "xn--trentin-sd-tirol-rzb", + "xn--trentin-sdtirol-7vb", + "xn--trentino-sd-tirol-c3b", + "xn--trentino-sdtirol-szb", + "xn--trentinosd-tirol-rzb", + "xn--trentinosdtirol-7vb", + "xn--trentinsd-tirol-6vb", + "xn--trentinsdtirol-nsb", + "xn--valle-aoste-ebb", + "xn--valle-d-aoste-ehb", + "xn--valleaoste-e7a", + "xn--valledaoste-ebb", + "co", + "net", + "org", + "com", + "edu", + "gov", + "mil", + "name", + "net", + "org", + "sch", + "ac", + "ad", + "aichi", + "akita", + "aomori", + "blogspot", + "chiba", + "co", + "ed", + "ehime", + "fukui", + "fukuoka", + "fukushima", + "gifu", + "go", + "gr", + "gunma", + "hiroshima", + "hokkaido", + "hyogo", + "ibaraki", + "ishikawa", + "iwate", + "kagawa", + "kagoshima", + "kanagawa", + "kawasaki", + "kitakyushu", + "kobe", + "kochi", + "kumamoto", + "kyoto", + "lg", + "mie", + "miyagi", + "miyazaki", + "nagano", + "nagasaki", + "nagoya", + "nara", + "ne", + "niigata", + "oita", + "okayama", + "okinawa", + "or", + "osaka", + "saga", + "saitama", + "sapporo", + "sendai", + "shiga", + "shimane", + "shizuoka", + "tochigi", + "tokushima", + "tokyo", + "tottori", + "toyama", + "usercontent", + "wakayama", + "xn--0trq7p7nn", + "xn--1ctwo", + "xn--1lqs03n", + "xn--1lqs71d", + "xn--2m4a15e", + "xn--32vp30h", + "xn--4it168d", + "xn--4it797k", + "xn--4pvxs", + "xn--5js045d", + "xn--5rtp49c", + "xn--5rtq34k", + "xn--6btw5a", + "xn--6orx2r", + "xn--7t0a264c", + "xn--8ltr62k", + "xn--8pvr4u", + "xn--c3s14m", + "xn--d5qv7z876c", + "xn--djrs72d6uy", + "xn--djty4k", + "xn--efvn9s", + "xn--ehqz56n", + "xn--elqq16h", + "xn--f6qx53a", + "xn--k7yn95e", + "xn--kbrq7o", + "xn--klt787d", + "xn--kltp7d", + "xn--kltx9a", + "xn--klty5x", + "xn--mkru45i", + "xn--nit225k", + "xn--ntso0iqx3a", + "xn--ntsq17g", + "xn--pssu33l", + "xn--qqqt11m", + "xn--rht27z", + "xn--rht3d", + "xn--rht61e", + "xn--rny31h", + "xn--tor131o", + "xn--uist22h", + "xn--uisz3g", + "xn--uuwu58a", + "xn--vgu402c", + "xn--zbx025d", + "yamagata", + "yamaguchi", + "yamanashi", + "yokohama", + "aisai", + "ama", + "anjo", + "asuke", + "chiryu", + "chita", + "fuso", + "gamagori", + "handa", + "hazu", + "hekinan", + "higashiura", + "ichinomiya", + "inazawa", + "inuyama", + "isshiki", + "iwakura", + "kanie", + "kariya", + "kasugai", + "kira", + "kiyosu", + "komaki", + "konan", + "kota", + "mihama", + "miyoshi", + "nishio", + "nisshin", + "obu", + "oguchi", + "oharu", + "okazaki", + "owariasahi", + "seto", + "shikatsu", + "shinshiro", + "shitara", + "tahara", + "takahama", + "tobishima", + "toei", + "togo", + "tokai", + "tokoname", + "toyoake", + "toyohashi", + "toyokawa", + "toyone", + "toyota", + "tsushima", + "yatomi", + "akita", + "daisen", + "fujisato", + "gojome", + "hachirogata", + "happou", + "higashinaruse", + "honjo", + "honjyo", + "ikawa", + "kamikoani", + "kamioka", + "katagami", + "kazuno", + "kitaakita", + "kosaka", + "kyowa", + "misato", + "mitane", + "moriyoshi", + "nikaho", + "noshiro", + "odate", + "oga", + "ogata", + "semboku", + "yokote", + "yurihonjo", + "aomori", + "gonohe", + "hachinohe", + "hashikami", + "hiranai", + "hirosaki", + "itayanagi", + "kuroishi", + "misawa", + "mutsu", + "nakadomari", + "noheji", + "oirase", + "owani", + "rokunohe", + "sannohe", + "shichinohe", + "shingo", + "takko", + "towada", + "tsugaru", + "tsuruta", + "abiko", + "asahi", + "chonan", + "chosei", + "choshi", + "chuo", + "funabashi", + "futtsu", + "hanamigawa", + "ichihara", + "ichikawa", + "ichinomiya", + "inzai", + "isumi", + "kamagaya", + "kamogawa", + "kashiwa", + "katori", + "katsuura", + "kimitsu", + "kisarazu", + "kozaki", + "kujukuri", + "kyonan", + "matsudo", + "midori", + "mihama", + "minamiboso", + "mobara", + "mutsuzawa", + "nagara", + "nagareyama", + "narashino", + "narita", + "noda", + "oamishirasato", + "omigawa", + "onjuku", + "otaki", + "sakae", + "sakura", + "shimofusa", + "shirako", + "shiroi", + "shisui", + "sodegaura", + "sosa", + "tako", + "tateyama", + "togane", + "tohnosho", + "tomisato", + "urayasu", + "yachimata", + "yachiyo", + "yokaichiba", + "yokoshibahikari", + "yotsukaido", + "ainan", + "honai", + "ikata", + "imabari", + "iyo", + "kamijima", + "kihoku", + "kumakogen", + "masaki", + "matsuno", + "matsuyama", + "namikata", + "niihama", + "ozu", + "saijo", + "seiyo", + "shikokuchuo", + "tobe", + "toon", + "uchiko", + "uwajima", + "yawatahama", + "echizen", + "eiheiji", + "fukui", + "ikeda", + "katsuyama", + "mihama", + "minamiechizen", + "obama", + "ohi", + "ono", + "sabae", + "sakai", + "takahama", + "tsuruga", + "wakasa", + "ashiya", + "buzen", + "chikugo", + "chikuho", + "chikujo", + "chikushino", + "chikuzen", + "chuo", + "dazaifu", + "fukuchi", + "hakata", + "higashi", + "hirokawa", + "hisayama", + "iizuka", + "inatsuki", + "kaho", + "kasuga", + "kasuya", + "kawara", + "keisen", + "koga", + "kurate", + "kurogi", + "kurume", + "minami", + "miyako", + "miyama", + "miyawaka", + "mizumaki", + "munakata", + "nakagawa", + "nakama", + "nishi", + "nogata", + "ogori", + "okagaki", + "okawa", + "oki", + "omuta", + "onga", + "onojo", + "oto", + "saigawa", + "sasaguri", + "shingu", + "shinyoshitomi", + "shonai", + "soeda", + "sue", + "tachiarai", + "tagawa", + "takata", + "toho", + "toyotsu", + "tsuiki", + "ukiha", + "umi", + "usui", + "yamada", + "yame", + "yanagawa", + "yukuhashi", + "aizubange", + "aizumisato", + "aizuwakamatsu", + "asakawa", + "bandai", + "date", + "fukushima", + "furudono", + "futaba", + "hanawa", + "higashi", + "hirata", + "hirono", + "iitate", + "inawashiro", + "ishikawa", + "iwaki", + "izumizaki", + "kagamiishi", + "kaneyama", + "kawamata", + "kitakata", + "kitashiobara", + "koori", + "koriyama", + "kunimi", + "miharu", + "mishima", + "namie", + "nango", + "nishiaizu", + "nishigo", + "okuma", + "omotego", + "ono", + "otama", + "samegawa", + "shimogo", + "shirakawa", + "showa", + "soma", + "sukagawa", + "taishin", + "tamakawa", + "tanagura", + "tenei", + "yabuki", + "yamato", + "yamatsuri", + "yanaizu", + "yugawa", + "anpachi", + "ena", + "gifu", + "ginan", + "godo", + "gujo", + "hashima", + "hichiso", + "hida", + "higashishirakawa", + "ibigawa", + "ikeda", + "kakamigahara", + "kani", + "kasahara", + "kasamatsu", + "kawaue", + "kitagata", + "mino", + "minokamo", + "mitake", + "mizunami", + "motosu", + "nakatsugawa", + "ogaki", + "sakahogi", + "seki", + "sekigahara", + "shirakawa", + "tajimi", + "takayama", + "tarui", + "toki", + "tomika", + "wanouchi", + "yamagata", + "yaotsu", + "yoro", + "annaka", + "chiyoda", + "fujioka", + "higashiagatsuma", + "isesaki", + "itakura", + "kanna", + "kanra", + "katashina", + "kawaba", + "kiryu", + "kusatsu", + "maebashi", + "meiwa", + "midori", + "minakami", + "naganohara", + "nakanojo", + "nanmoku", + "numata", + "oizumi", + "ora", + "ota", + "shibukawa", + "shimonita", + "shinto", + "showa", + "takasaki", + "takayama", + "tamamura", + "tatebayashi", + "tomioka", + "tsukiyono", + "tsumagoi", + "ueno", + "yoshioka", + "asaminami", + "daiwa", + "etajima", + "fuchu", + "fukuyama", + "hatsukaichi", + "higashihiroshima", + "hongo", + "jinsekikogen", + "kaita", + "kui", + "kumano", + "kure", + "mihara", + "miyoshi", + "naka", + "onomichi", + "osakikamijima", + "otake", + "saka", + "sera", + "seranishi", + "shinichi", + "shobara", + "takehara", + "abashiri", + "abira", + "aibetsu", + "akabira", + "akkeshi", + "asahikawa", + "ashibetsu", + "ashoro", + "assabu", + "atsuma", + "bibai", + "biei", + "bifuka", + "bihoro", + "biratori", + "chippubetsu", + "chitose", + "date", + "ebetsu", + "embetsu", + "eniwa", + "erimo", + "esan", + "esashi", + "fukagawa", + "fukushima", + "furano", + "furubira", + "haboro", + "hakodate", + "hamatonbetsu", + "hidaka", + "higashikagura", + "higashikawa", + "hiroo", + "hokuryu", + "hokuto", + "honbetsu", + "horokanai", + "horonobe", + "ikeda", + "imakane", + "ishikari", + "iwamizawa", + "iwanai", + "kamifurano", + "kamikawa", + "kamishihoro", + "kamisunagawa", + "kamoenai", + "kayabe", + "kembuchi", + "kikonai", + "kimobetsu", + "kitahiroshima", + "kitami", + "kiyosato", + "koshimizu", + "kunneppu", + "kuriyama", + "kuromatsunai", + "kushiro", + "kutchan", + "kyowa", + "mashike", + "matsumae", + "mikasa", + "minamifurano", + "mombetsu", + "moseushi", + "mukawa", + "muroran", + "naie", + "nakagawa", + "nakasatsunai", + "nakatombetsu", + "nanae", + "nanporo", + "nayoro", + "nemuro", + "niikappu", + "niki", + "nishiokoppe", + "noboribetsu", + "numata", + "obihiro", + "obira", + "oketo", + "okoppe", + "otaru", + "otobe", + "otofuke", + "otoineppu", + "oumu", + "ozora", + "pippu", + "rankoshi", + "rebun", + "rikubetsu", + "rishiri", + "rishirifuji", + "saroma", + "sarufutsu", + "shakotan", + "shari", + "shibecha", + "shibetsu", + "shikabe", + "shikaoi", + "shimamaki", + "shimizu", + "shimokawa", + "shinshinotsu", + "shintoku", + "shiranuka", + "shiraoi", + "shiriuchi", + "sobetsu", + "sunagawa", + "taiki", + "takasu", + "takikawa", + "takinoue", + "teshikaga", + "tobetsu", + "tohma", + "tomakomai", + "tomari", + "toya", + "toyako", + "toyotomi", + "toyoura", + "tsubetsu", + "tsukigata", + "urakawa", + "urausu", + "uryu", + "utashinai", + "wakkanai", + "wassamu", + "yakumo", + "yoichi", + "aioi", + "akashi", + "ako", + "amagasaki", + "aogaki", + "asago", + "ashiya", + "awaji", + "fukusaki", + "goshiki", + "harima", + "himeji", + "ichikawa", + "inagawa", + "itami", + "kakogawa", + "kamigori", + "kamikawa", + "kasai", + "kasuga", + "kawanishi", + "miki", + "minamiawaji", + "nishinomiya", + "nishiwaki", + "ono", + "sanda", + "sannan", + "sasayama", + "sayo", + "shingu", + "shinonsen", + "shiso", + "sumoto", + "taishi", + "taka", + "takarazuka", + "takasago", + "takino", + "tamba", + "tatsuno", + "toyooka", + "yabu", + "yashiro", + "yoka", + "yokawa", + "ami", + "asahi", + "bando", + "chikusei", + "daigo", + "fujishiro", + "hitachi", + "hitachinaka", + "hitachiomiya", + "hitachiota", + "ibaraki", + "ina", + "inashiki", + "itako", + "iwama", + "joso", + "kamisu", + "kasama", + "kashima", + "kasumigaura", + "koga", + "miho", + "mito", + "moriya", + "naka", + "namegata", + "oarai", + "ogawa", + "omitama", + "ryugasaki", + "sakai", + "sakuragawa", + "shimodate", + "shimotsuma", + "shirosato", + "sowa", + "suifu", + "takahagi", + "tamatsukuri", + "tokai", + "tomobe", + "tone", + "toride", + "tsuchiura", + "tsukuba", + "uchihara", + "ushiku", + "yachiyo", + "yamagata", + "yawara", + "yuki", + "anamizu", + "hakui", + "hakusan", + "kaga", + "kahoku", + "kanazawa", + "kawakita", + "komatsu", + "nakanoto", + "nanao", + "nomi", + "nonoichi", + "noto", + "shika", + "suzu", + "tsubata", + "tsurugi", + "uchinada", + "wajima", + "fudai", + "fujisawa", + "hanamaki", + "hiraizumi", + "hirono", + "ichinohe", + "ichinoseki", + "iwaizumi", + "iwate", + "joboji", + "kamaishi", + "kanegasaki", + "karumai", + "kawai", + "kitakami", + "kuji", + "kunohe", + "kuzumaki", + "miyako", + "mizusawa", + "morioka", + "ninohe", + "noda", + "ofunato", + "oshu", + "otsuchi", + "rikuzentakata", + "shiwa", + "shizukuishi", + "sumita", + "tanohata", + "tono", + "yahaba", + "yamada", + "ayagawa", + "higashikagawa", + "kanonji", + "kotohira", + "manno", + "marugame", + "mitoyo", + "naoshima", + "sanuki", + "tadotsu", + "takamatsu", + "tonosho", + "uchinomi", + "utazu", + "zentsuji", + "akune", + "amami", + "hioki", + "isa", + "isen", + "izumi", + "kagoshima", + "kanoya", + "kawanabe", + "kinko", + "kouyama", + "makurazaki", + "matsumoto", + "minamitane", + "nakatane", + "nishinoomote", + "satsumasendai", + "soo", + "tarumizu", + "yusui", + "aikawa", + "atsugi", + "ayase", + "chigasaki", + "ebina", + "fujisawa", + "hadano", + "hakone", + "hiratsuka", + "isehara", + "kaisei", + "kamakura", + "kiyokawa", + "matsuda", + "minamiashigara", + "miura", + "nakai", + "ninomiya", + "odawara", + "oi", + "oiso", + "sagamihara", + "samukawa", + "tsukui", + "yamakita", + "yamato", + "yokosuka", + "yugawara", + "zama", + "zushi", + "city", + "city", + "city", + "aki", + "geisei", + "hidaka", + "higashitsuno", + "ino", + "kagami", + "kami", + "kitagawa", + "kochi", + "mihara", + "motoyama", + "muroto", + "nahari", + "nakamura", + "nankoku", + "nishitosa", + "niyodogawa", + "ochi", + "okawa", + "otoyo", + "otsuki", + "sakawa", + "sukumo", + "susaki", + "tosa", + "tosashimizu", + "toyo", + "tsuno", + "umaji", + "yasuda", + "yusuhara", + "amakusa", + "arao", + "aso", + "choyo", + "gyokuto", + "kamiamakusa", + "kikuchi", + "kumamoto", + "mashiki", + "mifune", + "minamata", + "minamioguni", + "nagasu", + "nishihara", + "oguni", + "ozu", + "sumoto", + "takamori", + "uki", + "uto", + "yamaga", + "yamato", + "yatsushiro", + "ayabe", + "fukuchiyama", + "higashiyama", + "ide", + "ine", + "joyo", + "kameoka", + "kamo", + "kita", + "kizu", + "kumiyama", + "kyotamba", + "kyotanabe", + "kyotango", + "maizuru", + "minami", + "minamiyamashiro", + "miyazu", + "muko", + "nagaokakyo", + "nakagyo", + "nantan", + "oyamazaki", + "sakyo", + "seika", + "tanabe", + "uji", + "ujitawara", + "wazuka", + "yamashina", + "yawata", + "asahi", + "inabe", + "ise", + "kameyama", + "kawagoe", + "kiho", + "kisosaki", + "kiwa", + "komono", + "kumano", + "kuwana", + "matsusaka", + "meiwa", + "mihama", + "minamiise", + "misugi", + "miyama", + "nabari", + "shima", + "suzuka", + "tado", + "taiki", + "taki", + "tamaki", + "toba", + "tsu", + "udono", + "ureshino", + "watarai", + "yokkaichi", + "furukawa", + "higashimatsushima", + "ishinomaki", + "iwanuma", + "kakuda", + "kami", + "kawasaki", + "marumori", + "matsushima", + "minamisanriku", + "misato", + "murata", + "natori", + "ogawara", + "ohira", + "onagawa", + "osaki", + "rifu", + "semine", + "shibata", + "shichikashuku", + "shikama", + "shiogama", + "shiroishi", + "tagajo", + "taiwa", + "tome", + "tomiya", + "wakuya", + "watari", + "yamamoto", + "zao", + "aya", + "ebino", + "gokase", + "hyuga", + "kadogawa", + "kawaminami", + "kijo", + "kitagawa", + "kitakata", + "kitaura", + "kobayashi", + "kunitomi", + "kushima", + "mimata", + "miyakonojo", + "miyazaki", + "morotsuka", + "nichinan", + "nishimera", + "nobeoka", + "saito", + "shiiba", + "shintomi", + "takaharu", + "takanabe", + "takazaki", + "tsuno", + "achi", + "agematsu", + "anan", + "aoki", + "asahi", + "azumino", + "chikuhoku", + "chikuma", + "chino", + "fujimi", + "hakuba", + "hara", + "hiraya", + "iida", + "iijima", + "iiyama", + "iizuna", + "ikeda", + "ikusaka", + "ina", + "karuizawa", + "kawakami", + "kiso", + "kisofukushima", + "kitaaiki", + "komagane", + "komoro", + "matsukawa", + "matsumoto", + "miasa", + "minamiaiki", + "minamimaki", + "minamiminowa", + "minowa", + "miyada", + "miyota", + "mochizuki", + "nagano", + "nagawa", + "nagiso", + "nakagawa", + "nakano", + "nozawaonsen", + "obuse", + "ogawa", + "okaya", + "omachi", + "omi", + "ookuwa", + "ooshika", + "otaki", + "otari", + "sakae", + "sakaki", + "saku", + "sakuho", + "shimosuwa", + "shinanomachi", + "shiojiri", + "suwa", + "suzaka", + "takagi", + "takamori", + "takayama", + "tateshina", + "tatsuno", + "togakushi", + "togura", + "tomi", + "ueda", + "wada", + "yamagata", + "yamanouchi", + "yasaka", + "yasuoka", + "chijiwa", + "futsu", + "goto", + "hasami", + "hirado", + "iki", + "isahaya", + "kawatana", + "kuchinotsu", + "matsuura", + "nagasaki", + "obama", + "omura", + "oseto", + "saikai", + "sasebo", + "seihi", + "shimabara", + "shinkamigoto", + "togitsu", + "tsushima", + "unzen", + "city", + "ando", + "gose", + "heguri", + "higashiyoshino", + "ikaruga", + "ikoma", + "kamikitayama", + "kanmaki", + "kashiba", + "kashihara", + "katsuragi", + "kawai", + "kawakami", + "kawanishi", + "koryo", + "kurotaki", + "mitsue", + "miyake", + "nara", + "nosegawa", + "oji", + "ouda", + "oyodo", + "sakurai", + "sango", + "shimoichi", + "shimokitayama", + "shinjo", + "soni", + "takatori", + "tawaramoto", + "tenkawa", + "tenri", + "uda", + "yamatokoriyama", + "yamatotakada", + "yamazoe", + "yoshino", + "gehirn", + "aga", + "agano", + "gosen", + "itoigawa", + "izumozaki", + "joetsu", + "kamo", + "kariwa", + "kashiwazaki", + "minamiuonuma", + "mitsuke", + "muika", + "murakami", + "myoko", + "nagaoka", + "niigata", + "ojiya", + "omi", + "sado", + "sanjo", + "seiro", + "seirou", + "sekikawa", + "shibata", + "tagami", + "tainai", + "tochio", + "tokamachi", + "tsubame", + "tsunan", + "uonuma", + "yahiko", + "yoita", + "yuzawa", + "beppu", + "bungoono", + "bungotakada", + "hasama", + "hiji", + "himeshima", + "hita", + "kamitsue", + "kokonoe", + "kuju", + "kunisaki", + "kusu", + "oita", + "saiki", + "taketa", + "tsukumi", + "usa", + "usuki", + "yufu", + "akaiwa", + "asakuchi", + "bizen", + "hayashima", + "ibara", + "kagamino", + "kasaoka", + "kibichuo", + "kumenan", + "kurashiki", + "maniwa", + "misaki", + "nagi", + "niimi", + "nishiawakura", + "okayama", + "satosho", + "setouchi", + "shinjo", + "shoo", + "soja", + "takahashi", + "tamano", + "tsuyama", + "wake", + "yakage", + "aguni", + "ginowan", + "ginoza", + "gushikami", + "haebaru", + "higashi", + "hirara", + "iheya", + "ishigaki", + "ishikawa", + "itoman", + "izena", + "kadena", + "kin", + "kitadaito", + "kitanakagusuku", + "kumejima", + "kunigami", + "minamidaito", + "motobu", + "nago", + "naha", + "nakagusuku", + "nakijin", + "nanjo", + "nishihara", + "ogimi", + "okinawa", + "onna", + "shimoji", + "taketomi", + "tarama", + "tokashiki", + "tomigusuku", + "tonaki", + "urasoe", + "uruma", + "yaese", + "yomitan", + "yonabaru", + "yonaguni", + "zamami", + "abeno", + "chihayaakasaka", + "chuo", + "daito", + "fujiidera", + "habikino", + "hannan", + "higashiosaka", + "higashisumiyoshi", + "higashiyodogawa", + "hirakata", + "ibaraki", + "ikeda", + "izumi", + "izumiotsu", + "izumisano", + "kadoma", + "kaizuka", + "kanan", + "kashiwara", + "katano", + "kawachinagano", + "kishiwada", + "kita", + "kumatori", + "matsubara", + "minato", + "minoh", + "misaki", + "moriguchi", + "neyagawa", + "nishi", + "nose", + "osakasayama", + "sakai", + "sayama", + "sennan", + "settsu", + "shijonawate", + "shimamoto", + "suita", + "tadaoka", + "taishi", + "tajiri", + "takaishi", + "takatsuki", + "tondabayashi", + "toyonaka", + "toyono", + "yao", + "ariake", + "arita", + "fukudomi", + "genkai", + "hamatama", + "hizen", + "imari", + "kamimine", + "kanzaki", + "karatsu", + "kashima", + "kitagata", + "kitahata", + "kiyama", + "kouhoku", + "kyuragi", + "nishiarita", + "ogi", + "omachi", + "ouchi", + "saga", + "shiroishi", + "taku", + "tara", + "tosu", + "yoshinogari", + "arakawa", + "asaka", + "chichibu", + "fujimi", + "fujimino", + "fukaya", + "hanno", + "hanyu", + "hasuda", + "hatogaya", + "hatoyama", + "hidaka", + "higashichichibu", + "higashimatsuyama", + "honjo", + "ina", + "iruma", + "iwatsuki", + "kamiizumi", + "kamikawa", + "kamisato", + "kasukabe", + "kawagoe", + "kawaguchi", + "kawajima", + "kazo", + "kitamoto", + "koshigaya", + "kounosu", + "kuki", + "kumagaya", + "matsubushi", + "minano", + "misato", + "miyashiro", + "miyoshi", + "moroyama", + "nagatoro", + "namegawa", + "niiza", + "ogano", + "ogawa", + "ogose", + "okegawa", + "omiya", + "otaki", + "ranzan", + "ryokami", + "saitama", + "sakado", + "satte", + "sayama", + "shiki", + "shiraoka", + "soka", + "sugito", + "toda", + "tokigawa", + "tokorozawa", + "tsurugashima", + "urawa", + "warabi", + "yashio", + "yokoze", + "yono", + "yorii", + "yoshida", + "yoshikawa", + "yoshimi", + "city", + "city", + "aisho", + "gamo", + "higashiomi", + "hikone", + "koka", + "konan", + "kosei", + "koto", + "kusatsu", + "maibara", + "moriyama", + "nagahama", + "nishiazai", + "notogawa", + "omihachiman", + "otsu", + "ritto", + "ryuoh", + "takashima", + "takatsuki", + "torahime", + "toyosato", + "yasu", + "akagi", + "ama", + "gotsu", + "hamada", + "higashiizumo", + "hikawa", + "hikimi", + "izumo", + "kakinoki", + "masuda", + "matsue", + "misato", + "nishinoshima", + "ohda", + "okinoshima", + "okuizumo", + "shimane", + "tamayu", + "tsuwano", + "unnan", + "yakumo", + "yasugi", + "yatsuka", + "arai", + "atami", + "fuji", + "fujieda", + "fujikawa", + "fujinomiya", + "fukuroi", + "gotemba", + "haibara", + "hamamatsu", + "higashiizu", + "ito", + "iwata", + "izu", + "izunokuni", + "kakegawa", + "kannami", + "kawanehon", + "kawazu", + "kikugawa", + "kosai", + "makinohara", + "matsuzaki", + "minamiizu", + "mishima", + "morimachi", + "nishiizu", + "numazu", + "omaezaki", + "shimada", + "shimizu", + "shimoda", + "shizuoka", + "susono", + "yaizu", + "yoshida", + "ashikaga", + "bato", + "haga", + "ichikai", + "iwafune", + "kaminokawa", + "kanuma", + "karasuyama", + "kuroiso", + "mashiko", + "mibu", + "moka", + "motegi", + "nasu", + "nasushiobara", + "nikko", + "nishikata", + "nogi", + "ohira", + "ohtawara", + "oyama", + "sakura", + "sano", + "shimotsuke", + "shioya", + "takanezawa", + "tochigi", + "tsuga", + "ujiie", + "utsunomiya", + "yaita", + "aizumi", + "anan", + "ichiba", + "itano", + "kainan", + "komatsushima", + "matsushige", + "mima", + "minami", + "miyoshi", + "mugi", + "nakagawa", + "naruto", + "sanagochi", + "shishikui", + "tokushima", + "wajiki", + "adachi", + "akiruno", + "akishima", + "aogashima", + "arakawa", + "bunkyo", + "chiyoda", + "chofu", + "chuo", + "edogawa", + "fuchu", + "fussa", + "hachijo", + "hachioji", + "hamura", + "higashikurume", + "higashimurayama", + "higashiyamato", + "hino", + "hinode", + "hinohara", + "inagi", + "itabashi", + "katsushika", + "kita", + "kiyose", + "kodaira", + "koganei", + "kokubunji", + "komae", + "koto", + "kouzushima", + "kunitachi", + "machida", + "meguro", + "minato", + "mitaka", + "mizuho", + "musashimurayama", + "musashino", + "nakano", + "nerima", + "ogasawara", + "okutama", + "ome", + "oshima", + "ota", + "setagaya", + "shibuya", + "shinagawa", + "shinjuku", + "suginami", + "sumida", + "tachikawa", + "taito", + "tama", + "toshima", + "chizu", + "hino", + "kawahara", + "koge", + "kotoura", + "misasa", + "nanbu", + "nichinan", + "sakaiminato", + "tottori", + "wakasa", + "yazu", + "yonago", + "asahi", + "fuchu", + "fukumitsu", + "funahashi", + "himi", + "imizu", + "inami", + "johana", + "kamiichi", + "kurobe", + "nakaniikawa", + "namerikawa", + "nanto", + "nyuzen", + "oyabe", + "taira", + "takaoka", + "tateyama", + "toga", + "tonami", + "toyama", + "unazuki", + "uozu", + "yamada", + "arida", + "aridagawa", + "gobo", + "hashimoto", + "hidaka", + "hirogawa", + "inami", + "iwade", + "kainan", + "kamitonda", + "katsuragi", + "kimino", + "kinokawa", + "kitayama", + "koya", + "koza", + "kozagawa", + "kudoyama", + "kushimoto", + "mihama", + "misato", + "nachikatsuura", + "shingu", + "shirahama", + "taiji", + "tanabe", + "wakayama", + "yuasa", + "yura", + "asahi", + "funagata", + "higashine", + "iide", + "kahoku", + "kaminoyama", + "kaneyama", + "kawanishi", + "mamurogawa", + "mikawa", + "murayama", + "nagai", + "nakayama", + "nanyo", + "nishikawa", + "obanazawa", + "oe", + "oguni", + "ohkura", + "oishida", + "sagae", + "sakata", + "sakegawa", + "shinjo", + "shirataka", + "shonai", + "takahata", + "tendo", + "tozawa", + "tsuruoka", + "yamagata", + "yamanobe", + "yonezawa", + "yuza", + "abu", + "hagi", + "hikari", + "hofu", + "iwakuni", + "kudamatsu", + "mitou", + "nagato", + "oshima", + "shimonoseki", + "shunan", + "tabuse", + "tokuyama", + "toyota", + "ube", + "yuu", + "chuo", + "doshi", + "fuefuki", + "fujikawa", + "fujikawaguchiko", + "fujiyoshida", + "hayakawa", + "hokuto", + "ichikawamisato", + "kai", + "kofu", + "koshu", + "kosuge", + "minami-alps", + "minobu", + "nakamichi", + "nanbu", + "narusawa", + "nirasaki", + "nishikatsura", + "oshino", + "otsuki", + "showa", + "tabayama", + "tsuru", + "uenohara", + "yamanakako", + "yamanashi", + "city", + "ac", + "co", + "go", + "info", + "me", + "mobi", + "ne", + "nom", + "or", + "sc", + "blogspot", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "biz", + "com", + "edu", + "gov", + "info", + "net", + "org", + "ass", + "asso", + "com", + "coop", + "edu", + "gouv", + "gov", + "medecin", + "mil", + "nom", + "notaires", + "org", + "pharmaciens", + "prd", + "presse", + "tm", + "veterinaire", + "edu", + "gov", + "net", + "org", + "com", + "edu", + "gov", + "org", + "rep", + "tra", + "ac", + "blogspot", + "busan", + "chungbuk", + "chungnam", + "co", + "daegu", + "daejeon", + "es", + "gangwon", + "go", + "gwangju", + "gyeongbuk", + "gyeonggi", + "gyeongnam", + "hs", + "incheon", + "jeju", + "jeonbuk", + "jeonnam", + "kg", + "mil", + "ms", + "ne", + "or", + "pe", + "re", + "sc", + "seoul", + "ulsan", + "co", + "edu", + "com", + "edu", + "emb", + "gov", + "ind", + "net", + "org", + "com", + "edu", + "gov", + "net", + "org", + "com", + "edu", + "gov", + "mil", + "net", + "nym", + "org", + "bnr", + "c", + "com", + "edu", + "gov", + "info", + "int", + "net", + "nym", + "org", + "per", + "static", + "dev", + "sites", + "com", + "edu", + "gov", + "net", + "org", + "co", + "com", + "edu", + "gov", + "net", + "nym", + "org", + "oy", + "blogspot", + "caa", + "nom", + "nym", + "cyon", + "dweb", + "mypep", + "ac", + "assn", + "com", + "edu", + "gov", + "grp", + "hotel", + "int", + "ltd", + "net", + "ngo", + "org", + "sch", + "soc", + "web", + "in", + "of", + "com", + "edu", + "gov", + "net", + "org", + "ac", + "biz", + "co", + "edu", + "gov", + "info", + "net", + "org", + "sc", + "blogspot", + "gov", + "nym", + "blogspot", + "nym", + "asn", + "com", + "conf", + "edu", + "gov", + "id", + "mil", + "net", + "org", + "com", + "edu", + "gov", + "id", + "med", + "net", + "org", + "plc", + "sch", + "ac", + "co", + "gov", + "net", + "org", + "press", + "router", + "asso", + "tm", + "blogspot", + "ac", + "barsy", + "brasilia", + "c66", + "co", + "daplie", + "ddns", + "diskstation", + "dnsfor", + "dscloud", + "edu", + "filegear", + "filegear-au", + "filegear-de", + "filegear-gb", + "filegear-ie", + "filegear-jp", + "filegear-sg", + "glitch", + "gov", + "hopto", + "i234", + "its", + "loginto", + "myds", + "nctu", + "net", + "nohost", + "noip", + "nym", + "org", + "priv", + "ravendb", + "soundcast", + "synology", + "tcp4", + "webhop", + "wedeploy", + "yombo", + "localhost", + "for", + "barsy", + "co", + "com", + "edu", + "gov", + "mil", + "nom", + "org", + "prd", + "tm", + "blogspot", + "com", + "edu", + "gov", + "inf", + "name", + "net", + "nom", + "org", + "com", + "edu", + "gouv", + "gov", + "net", + "org", + "presse", + "edu", + "gov", + "nyc", + "nym", + "org", + "com", + "edu", + "gov", + "net", + "org", + "barsy", + "dscloud", + "and", + "for", + "blogspot", + "gov", + "com", + "edu", + "gov", + "lab", + "net", + "org", + "com", + "edu", + "net", + "org", + "blogspot", + "ac", + "co", + "com", + "gov", + "net", + "or", + "org", + "academy", + "agriculture", + "air", + "airguard", + "alabama", + "alaska", + "amber", + "ambulance", + "american", + "americana", + "americanantiques", + "americanart", + "amsterdam", + "and", + "annefrank", + "anthro", + "anthropology", + "antiques", + "aquarium", + "arboretum", + "archaeological", + "archaeology", + "architecture", + "art", + "artanddesign", + "artcenter", + "artdeco", + "arteducation", + "artgallery", + "arts", + "artsandcrafts", + "asmatart", + "assassination", + "assisi", + "association", + "astronomy", + "atlanta", + "austin", + "australia", + "automotive", + "aviation", + "axis", + "badajoz", + "baghdad", + "bahn", + "bale", + "baltimore", + "barcelona", + "baseball", + "basel", + "baths", + "bauern", + "beauxarts", + "beeldengeluid", + "bellevue", + "bergbau", + "berkeley", + "berlin", + "bern", + "bible", + "bilbao", + "bill", + "birdart", + "birthplace", + "bonn", + "boston", + "botanical", + "botanicalgarden", + "botanicgarden", + "botany", + "brandywinevalley", + "brasil", + "bristol", + "british", + "britishcolumbia", + "broadcast", + "brunel", + "brussel", + "brussels", + "bruxelles", + "building", + "burghof", + "bus", + "bushey", + "cadaques", + "california", + "cambridge", + "can", + "canada", + "capebreton", + "carrier", + "cartoonart", + "casadelamoneda", + "castle", + "castres", + "celtic", + "center", + "chattanooga", + "cheltenham", + "chesapeakebay", + "chicago", + "children", + "childrens", + "childrensgarden", + "chiropractic", + "chocolate", + "christiansburg", + "cincinnati", + "cinema", + "circus", + "civilisation", + "civilization", + "civilwar", + "clinton", + "clock", + "coal", + "coastaldefence", + "cody", + "coldwar", + "collection", + "colonialwilliamsburg", + "coloradoplateau", + "columbia", + "columbus", + "communication", + "communications", + "community", + "computer", + "computerhistory", + "contemporary", + "contemporaryart", + "convent", + "copenhagen", + "corporation", + "corvette", + "costume", + "countryestate", + "county", + "crafts", + "cranbrook", + "creation", + "cultural", + "culturalcenter", + "culture", + "cyber", + "cymru", + "dali", + "dallas", + "database", + "ddr", + "decorativearts", + "delaware", + "delmenhorst", + "denmark", + "depot", + "design", + "detroit", + "dinosaur", + "discovery", + "dolls", + "donostia", + "durham", + "eastafrica", + "eastcoast", + "education", + "educational", + "egyptian", + "eisenbahn", + "elburg", + "elvendrell", + "embroidery", + "encyclopedic", + "england", + "entomology", + "environment", + "environmentalconservation", + "epilepsy", + "essex", + "estate", + "ethnology", + "exeter", + "exhibition", + "family", + "farm", + "farmequipment", + "farmers", + "farmstead", + "field", + "figueres", + "filatelia", + "film", + "fineart", + "finearts", + "finland", + "flanders", + "florida", + "force", + "fortmissoula", + "fortworth", + "foundation", + "francaise", + "frankfurt", + "franziskaner", + "freemasonry", + "freiburg", + "fribourg", + "frog", + "fundacio", + "furniture", + "gallery", + "garden", + "gateway", + "geelvinck", + "gemological", + "geology", + "georgia", + "giessen", + "glas", + "glass", + "gorge", + "grandrapids", + "graz", + "guernsey", + "halloffame", + "hamburg", + "handson", + "harvestcelebration", + "hawaii", + "health", + "heimatunduhren", + "hellas", + "helsinki", + "hembygdsforbund", + "heritage", + "histoire", + "historical", + "historicalsociety", + "historichouses", + "historisch", + "historisches", + "history", + "historyofscience", + "horology", + "house", + "humanities", + "illustration", + "imageandsound", + "indian", + "indiana", + "indianapolis", + "indianmarket", + "intelligence", + "interactive", + "iraq", + "iron", + "isleofman", + "jamison", + "jefferson", + "jerusalem", + "jewelry", + "jewish", + "jewishart", + "jfk", + "journalism", + "judaica", + "judygarland", + "juedisches", + "juif", + "karate", + "karikatur", + "kids", + "koebenhavn", + "koeln", + "kunst", + "kunstsammlung", + "kunstunddesign", + "labor", + "labour", + "lajolla", + "lancashire", + "landes", + "lans", + "larsson", + "lewismiller", + "lincoln", + "linz", + "living", + "livinghistory", + "localhistory", + "london", + "losangeles", + "louvre", + "loyalist", + "lucerne", + "luxembourg", + "luzern", + "mad", + "madrid", + "mallorca", + "manchester", + "mansion", + "mansions", + "manx", + "marburg", + "maritime", + "maritimo", + "maryland", + "marylhurst", + "media", + "medical", + "medizinhistorisches", + "meeres", + "memorial", + "mesaverde", + "michigan", + "midatlantic", + "military", + "mill", + "miners", + "mining", + "minnesota", + "missile", + "missoula", + "modern", + "moma", + "money", + "monmouth", + "monticello", + "montreal", + "moscow", + "motorcycle", + "muenchen", + "muenster", + "mulhouse", + "muncie", + "museet", + "museumcenter", + "museumvereniging", + "music", + "national", + "nationalfirearms", + "nationalheritage", + "nativeamerican", + "naturalhistory", + "naturalhistorymuseum", + "naturalsciences", + "nature", + "naturhistorisches", + "natuurwetenschappen", + "naumburg", + "naval", + "nebraska", + "neues", + "newhampshire", + "newjersey", + "newmexico", + "newport", + "newspaper", + "newyork", + "niepce", + "norfolk", + "north", + "nrw", + "nuernberg", + "nuremberg", + "nyc", + "nyny", + "oceanographic", + "oceanographique", + "omaha", + "online", + "ontario", + "openair", + "oregon", + "oregontrail", + "otago", + "oxford", + "pacific", + "paderborn", + "palace", + "paleo", + "palmsprings", + "panama", + "paris", + "pasadena", + "pharmacy", + "philadelphia", + "philadelphiaarea", + "philately", + "phoenix", + "photography", + "pilots", + "pittsburgh", + "planetarium", + "plantation", + "plants", + "plaza", + "portal", + "portland", + "portlligat", + "posts-and-telecommunications", + "preservation", + "presidio", + "press", + "project", + "public", + "pubol", + "quebec", + "railroad", + "railway", + "research", + "resistance", + "riodejaneiro", + "rochester", + "rockart", + "roma", + "russia", + "saintlouis", + "salem", + "salvadordali", + "salzburg", + "sandiego", + "sanfrancisco", + "santabarbara", + "santacruz", + "santafe", + "saskatchewan", + "satx", + "savannahga", + "schlesisches", + "schoenbrunn", + "schokoladen", + "school", + "schweiz", + "science", + "science-fiction", + "scienceandhistory", + "scienceandindustry", + "sciencecenter", + "sciencecenters", + "sciencehistory", + "sciences", + "sciencesnaturelles", + "scotland", + "seaport", + "settlement", + "settlers", + "shell", + "sherbrooke", + "sibenik", + "silk", + "ski", + "skole", + "society", + "sologne", + "soundandvision", + "southcarolina", + "southwest", + "space", + "spy", + "square", + "stadt", + "stalbans", + "starnberg", + "state", + "stateofdelaware", + "station", + "steam", + "steiermark", + "stjohn", + "stockholm", + "stpetersburg", + "stuttgart", + "suisse", + "surgeonshall", + "surrey", + "svizzera", + "sweden", + "sydney", + "tank", + "tcm", + "technology", + "telekommunikation", + "television", + "texas", + "textile", + "theater", + "time", + "timekeeping", + "topology", + "torino", + "touch", + "town", + "transport", + "tree", + "trolley", + "trust", + "trustee", + "uhren", + "ulm", + "undersea", + "university", + "usa", + "usantiques", + "usarts", + "uscountryestate", + "usculture", + "usdecorativearts", + "usgarden", + "ushistory", + "ushuaia", + "uslivinghistory", + "utah", + "uvic", + "valley", + "vantaa", + "versailles", + "viking", + "village", + "virginia", + "virtual", + "virtuel", + "vlaanderen", + "volkenkunde", + "wales", + "wallonie", + "war", + "washingtondc", + "watch-and-clock", + "watchandclock", + "western", + "westfalen", + "whaling", + "wildlife", + "williamsburg", + "windmill", + "workshop", + "xn--9dbhblg6di", + "xn--comunicaes-v6a2o", + "xn--correios-e-telecomunicaes-ghc29a", + "xn--h1aegh", + "xn--lns-qla", + "york", + "yorkshire", + "yosemite", + "youth", + "zoological", + "zoology", + "aero", + "biz", + "com", + "coop", + "edu", + "gov", + "info", + "int", + "mil", + "museum", + "name", + "net", + "org", + "pro", + "ac", + "biz", + "co", + "com", + "coop", + "edu", + "gov", + "int", + "museum", + "net", + "org", + "blogspot", + "com", + "edu", + "gob", + "net", + "nym", + "org", + "blogspot", + "com", + "edu", + "gov", + "mil", + "name", + "net", + "org", + "ac", + "adv", + "co", + "edu", + "gov", + "mil", + "net", + "org", + "ca", + "cc", + "co", + "com", + "dr", + "in", + "info", + "mobi", + "mx", + "name", + "or", + "org", + "pro", + "school", + "tv", + "us", + "ws", + "her", + "his", + "forgot", + "forgot", + "asso", + "nom", + "alwaysdata", + "at-band-camp", + "azure-mobile", + "azurewebsites", + "barsy", + "blackbaudcdn", + "blogdns", + "boomla", + "bounceme", + "bplaced", + "broke-it", + "buyshouses", + "casacam", + "cdn77", + "cdn77-ssl", + "channelsdvr", + "cloudaccess", + "cloudapp", + "cloudeity", + "cloudfront", + "cloudfunctions", + "cloudycluster", + "cryptonomic", + "dattolocal", + "ddns", + "debian", + "definima", + "dnsalias", + "dnsdojo", + "dnsup", + "does-it", + "dontexist", + "dsmynas", + "dynalias", + "dynathome", + "dynu", + "dynv6", + "eating-organic", + "endofinternet", + "familyds", + "fastly", + "fastlylb", + "feste-ip", + "firewall-gateway", + "flynnhosting", + "from-az", + "from-co", + "from-la", + "from-ny", + "gb", + "gets-it", + "go-vip", + "ham-radio-op", + "hicam", + "homeftp", + "homeip", + "homelinux", + "homeunix", + "hu", + "in", + "in-dsl", + "in-the-band", + "in-vpn", + "iobb", + "ipifony", + "is-a-chef", + "is-a-geek", + "isa-geek", + "jp", + "kicks-ass", + "kinghost", + "knx-server", + "memset", + "moonscale", + "mydatto", + "mydissent", + "myeffect", + "myfritz", + "mymediapc", + "mypsx", + "mysecuritycamera", + "nhlfan", + "no-ip", + "now-dns", + "office-on-the", + "ownip", + "pgafan", + "podzone", + "privatizehealthinsurance", + "rackmaze", + "redirectme", + "ru", + "schokokeks", + "scrapper-site", + "se", + "selfip", + "sells-it", + "servebbs", + "serveblog", + "serveftp", + "serveminecraft", + "siteleaf", + "square7", + "srcf", + "static-access", + "sytes", + "t3l3p0rt", + "thruhere", + "twmail", + "uk", + "uni5", + "vpndns", + "webhop", + "za", + "r", + "freetls", + "map", + "prod", + "ssl", + "a", + "global", + "a", + "b", + "global", + "map", + "soc", + "user", + "alces", + "arvo", + "azimuth", + "co", + "arts", + "com", + "firm", + "info", + "net", + "other", + "per", + "rec", + "store", + "web", + "col", + "com", + "edu", + "gen", + "gov", + "i", + "ltd", + "mil", + "mobi", + "name", + "net", + "org", + "sch", + "blogspot", + "ac", + "biz", + "co", + "com", + "edu", + "gob", + "in", + "info", + "int", + "mil", + "net", + "nom", + "org", + "web", + "blogspot", + "cistron", + "co", + "demon", + "hosting-cluster", + "khplay", + "transurl", + "virtueeldomein", + "aa", + "aarborte", + "aejrie", + "afjord", + "agdenes", + "ah", + "akershus", + "aknoluokta", + "akrehamn", + "al", + "alaheadju", + "alesund", + "algard", + "alstahaug", + "alta", + "alvdal", + "amli", + "amot", + "andasuolo", + "andebu", + "andoy", + "ardal", + "aremark", + "arendal", + "arna", + "aseral", + "asker", + "askim", + "askoy", + "askvoll", + "asnes", + "audnedaln", + "aukra", + "aure", + "aurland", + "aurskog-holand", + "austevoll", + "austrheim", + "averoy", + "badaddja", + "bahcavuotna", + "bahccavuotna", + "baidar", + "bajddar", + "balat", + "balestrand", + "ballangen", + "balsfjord", + "bamble", + "bardu", + "barum", + "batsfjord", + "bearalvahki", + "beardu", + "beiarn", + "berg", + "bergen", + "berlevag", + "bievat", + "bindal", + "birkenes", + "bjarkoy", + "bjerkreim", + "bjugn", + "blogspot", + "bodo", + "bokn", + "bomlo", + "bremanger", + "bronnoy", + "bronnoysund", + "brumunddal", + "bryne", + "bu", + "budejju", + "buskerud", + "bygland", + "bykle", + "cahcesuolo", + "co", + "davvenjarga", + "davvesiida", + "deatnu", + "dep", + "dielddanuorri", + "divtasvuodna", + "divttasvuotna", + "donna", + "dovre", + "drammen", + "drangedal", + "drobak", + "dyroy", + "egersund", + "eid", + "eidfjord", + "eidsberg", + "eidskog", + "eidsvoll", + "eigersund", + "elverum", + "enebakk", + "engerdal", + "etne", + "etnedal", + "evenassi", + "evenes", + "evje-og-hornnes", + "farsund", + "fauske", + "fedje", + "fet", + "fetsund", + "fhs", + "finnoy", + "fitjar", + "fjaler", + "fjell", + "fla", + "flakstad", + "flatanger", + "flekkefjord", + "flesberg", + "flora", + "floro", + "fm", + "folkebibl", + "folldal", + "forde", + "forsand", + "fosnes", + "frana", + "fredrikstad", + "frei", + "frogn", + "froland", + "frosta", + "froya", + "fuoisku", + "fuossko", + "fusa", + "fylkesbibl", + "fyresdal", + "gaivuotna", + "galsa", + "gamvik", + "gangaviika", + "gaular", + "gausdal", + "giehtavuoatna", + "gildeskal", + "giske", + "gjemnes", + "gjerdrum", + "gjerstad", + "gjesdal", + "gjovik", + "gloppen", + "gol", + "gran", + "grane", + "granvin", + "gratangen", + "grimstad", + "grong", + "grue", + "gulen", + "guovdageaidnu", + "ha", + "habmer", + "hadsel", + "hagebostad", + "halden", + "halsa", + "hamar", + "hamaroy", + "hammarfeasta", + "hammerfest", + "hapmir", + "haram", + "hareid", + "harstad", + "hasvik", + "hattfjelldal", + "haugesund", + "hedmark", + "hemne", + "hemnes", + "hemsedal", + "herad", + "hitra", + "hjartdal", + "hjelmeland", + "hl", + "hm", + "hobol", + "hof", + "hokksund", + "hol", + "hole", + "holmestrand", + "holtalen", + "honefoss", + "hordaland", + "hornindal", + "horten", + "hoyanger", + "hoylandet", + "hurdal", + "hurum", + "hvaler", + "hyllestad", + "ibestad", + "idrett", + "inderoy", + "iveland", + "ivgu", + "jan-mayen", + "jessheim", + "jevnaker", + "jolster", + "jondal", + "jorpeland", + "kafjord", + "karasjohka", + "karasjok", + "karlsoy", + "karmoy", + "kautokeino", + "kirkenes", + "klabu", + "klepp", + "kommune", + "kongsberg", + "kongsvinger", + "kopervik", + "kraanghke", + "kragero", + "kristiansand", + "kristiansund", + "krodsherad", + "krokstadelva", + "kvafjord", + "kvalsund", + "kvam", + "kvanangen", + "kvinesdal", + "kvinnherad", + "kviteseid", + "kvitsoy", + "laakesvuemie", + "lahppi", + "langevag", + "lardal", + "larvik", + "lavagis", + "lavangen", + "leangaviika", + "lebesby", + "leikanger", + "leirfjord", + "leirvik", + "leka", + "leksvik", + "lenvik", + "lerdal", + "lesja", + "levanger", + "lier", + "lierne", + "lillehammer", + "lillesand", + "lindas", + "lindesnes", + "loabat", + "lodingen", + "lom", + "loppa", + "lorenskog", + "loten", + "lund", + "lunner", + "luroy", + "luster", + "lyngdal", + "lyngen", + "malatvuopmi", + "malselv", + "malvik", + "mandal", + "marker", + "marnardal", + "masfjorden", + "masoy", + "matta-varjjat", + "meland", + "meldal", + "melhus", + "meloy", + "meraker", + "midsund", + "midtre-gauldal", + "mil", + "mjondalen", + "mo-i-rana", + "moareke", + "modalen", + "modum", + "molde", + "more-og-romsdal", + "mosjoen", + "moskenes", + "moss", + "mosvik", + "mr", + "muosat", + "museum", + "naamesjevuemie", + "namdalseid", + "namsos", + "namsskogan", + "nannestad", + "naroy", + "narviika", + "narvik", + "naustdal", + "navuotna", + "nedre-eiker", + "nesna", + "nesodden", + "nesoddtangen", + "nesseby", + "nesset", + "nissedal", + "nittedal", + "nl", + "nord-aurdal", + "nord-fron", + "nord-odal", + "norddal", + "nordkapp", + "nordland", + "nordre-land", + "nordreisa", + "nore-og-uvdal", + "notodden", + "notteroy", + "nt", + "odda", + "of", + "oksnes", + "ol", + "omasvuotna", + "oppdal", + "oppegard", + "orkanger", + "orkdal", + "orland", + "orskog", + "orsta", + "osen", + "oslo", + "osoyro", + "osteroy", + "ostfold", + "ostre-toten", + "overhalla", + "ovre-eiker", + "oyer", + "oygarden", + "oystre-slidre", + "porsanger", + "porsangu", + "porsgrunn", + "priv", + "rade", + "radoy", + "rahkkeravju", + "raholt", + "raisa", + "rakkestad", + "ralingen", + "rana", + "randaberg", + "rauma", + "rendalen", + "rennebu", + "rennesoy", + "rindal", + "ringebu", + "ringerike", + "ringsaker", + "risor", + "rissa", + "rl", + "roan", + "rodoy", + "rollag", + "romsa", + "romskog", + "roros", + "rost", + "royken", + "royrvik", + "ruovat", + "rygge", + "salangen", + "salat", + "saltdal", + "samnanger", + "sandefjord", + "sandnes", + "sandnessjoen", + "sandoy", + "sarpsborg", + "sauda", + "sauherad", + "sel", + "selbu", + "selje", + "seljord", + "sf", + "siellak", + "sigdal", + "siljan", + "sirdal", + "skanit", + "skanland", + "skaun", + "skedsmo", + "skedsmokorset", + "ski", + "skien", + "skierva", + "skiptvet", + "skjak", + "skjervoy", + "skodje", + "slattum", + "smola", + "snaase", + "snasa", + "snillfjord", + "snoasa", + "sogndal", + "sogne", + "sokndal", + "sola", + "solund", + "somna", + "sondre-land", + "songdalen", + "sor-aurdal", + "sor-fron", + "sor-odal", + "sor-varanger", + "sorfold", + "sorreisa", + "sortland", + "sorum", + "spjelkavik", + "spydeberg", + "st", + "stange", + "stat", + "stathelle", + "stavanger", + "stavern", + "steigen", + "steinkjer", + "stjordal", + "stjordalshalsen", + "stokke", + "stor-elvdal", + "stord", + "stordal", + "storfjord", + "strand", + "stranda", + "stryn", + "sula", + "suldal", + "sund", + "sunndal", + "surnadal", + "svalbard", + "sveio", + "svelvik", + "sykkylven", + "tana", + "tananger", + "telemark", + "time", + "tingvoll", + "tinn", + "tjeldsund", + "tjome", + "tm", + "tokke", + "tolga", + "tonsberg", + "torsken", + "tr", + "trana", + "tranby", + "tranoy", + "troandin", + "trogstad", + "tromsa", + "tromso", + "trondheim", + "trysil", + "tvedestrand", + "tydal", + "tynset", + "tysfjord", + "tysnes", + "tysvar", + "ullensaker", + "ullensvang", + "ulvik", + "unjarga", + "utsira", + "va", + "vaapste", + "vadso", + "vaga", + "vagan", + "vagsoy", + "vaksdal", + "valle", + "vang", + "vanylven", + "vardo", + "varggat", + "varoy", + "vefsn", + "vega", + "vegarshei", + "vennesla", + "verdal", + "verran", + "vestby", + "vestfold", + "vestnes", + "vestre-slidre", + "vestre-toten", + "vestvagoy", + "vevelstad", + "vf", + "vgs", + "vik", + "vikna", + "vindafjord", + "voagat", + "volda", + "voss", + "vossevangen", + "xn--andy-ira", + "xn--asky-ira", + "xn--aurskog-hland-jnb", + "xn--avery-yua", + "xn--bdddj-mrabd", + "xn--bearalvhki-y4a", + "xn--berlevg-jxa", + "xn--bhcavuotna-s4a", + "xn--bhccavuotna-k7a", + "xn--bidr-5nac", + "xn--bievt-0qa", + "xn--bjarky-fya", + "xn--bjddar-pta", + "xn--blt-elab", + "xn--bmlo-gra", + "xn--bod-2na", + "xn--brnny-wuac", + "xn--brnnysund-m8ac", + "xn--brum-voa", + "xn--btsfjord-9za", + "xn--davvenjrga-y4a", + "xn--dnna-gra", + "xn--drbak-wua", + "xn--dyry-ira", + "xn--eveni-0qa01ga", + "xn--finny-yua", + "xn--fjord-lra", + "xn--fl-zia", + "xn--flor-jra", + "xn--frde-gra", + "xn--frna-woa", + "xn--frya-hra", + "xn--ggaviika-8ya47h", + "xn--gildeskl-g0a", + "xn--givuotna-8ya", + "xn--gjvik-wua", + "xn--gls-elac", + "xn--h-2fa", + "xn--hbmer-xqa", + "xn--hcesuolo-7ya35b", + "xn--hgebostad-g3a", + "xn--hmmrfeasta-s4ac", + "xn--hnefoss-q1a", + "xn--hobl-ira", + "xn--holtlen-hxa", + "xn--hpmir-xqa", + "xn--hyanger-q1a", + "xn--hylandet-54a", + "xn--indery-fya", + "xn--jlster-bya", + "xn--jrpeland-54a", + "xn--karmy-yua", + "xn--kfjord-iua", + "xn--klbu-woa", + "xn--koluokta-7ya57h", + "xn--krager-gya", + "xn--kranghke-b0a", + "xn--krdsherad-m8a", + "xn--krehamn-dxa", + "xn--krjohka-hwab49j", + "xn--ksnes-uua", + "xn--kvfjord-nxa", + "xn--kvitsy-fya", + "xn--kvnangen-k0a", + "xn--l-1fa", + "xn--laheadju-7ya", + "xn--langevg-jxa", + "xn--ldingen-q1a", + "xn--leagaviika-52b", + "xn--lesund-hua", + "xn--lgrd-poac", + "xn--lhppi-xqa", + "xn--linds-pra", + "xn--loabt-0qa", + "xn--lrdal-sra", + "xn--lrenskog-54a", + "xn--lt-liac", + "xn--lten-gra", + "xn--lury-ira", + "xn--mely-ira", + "xn--merker-kua", + "xn--mjndalen-64a", + "xn--mlatvuopmi-s4a", + "xn--mli-tla", + "xn--mlselv-iua", + "xn--moreke-jua", + "xn--mosjen-eya", + "xn--mot-tla", + "xn--mre-og-romsdal-qqb", + "xn--msy-ula0h", + "xn--mtta-vrjjat-k7af", + "xn--muost-0qa", + "xn--nmesjevuemie-tcba", + "xn--nry-yla5g", + "xn--nttery-byae", + "xn--nvuotna-hwa", + "xn--oppegrd-ixa", + "xn--ostery-fya", + "xn--osyro-wua", + "xn--porsgu-sta26f", + "xn--rady-ira", + "xn--rdal-poa", + "xn--rde-ula", + "xn--rdy-0nab", + "xn--rennesy-v1a", + "xn--rhkkervju-01af", + "xn--rholt-mra", + "xn--risa-5na", + "xn--risr-ira", + "xn--rland-uua", + "xn--rlingen-mxa", + "xn--rmskog-bya", + "xn--rros-gra", + "xn--rskog-uua", + "xn--rst-0na", + "xn--rsta-fra", + "xn--ryken-vua", + "xn--ryrvik-bya", + "xn--s-1fa", + "xn--sandnessjen-ogb", + "xn--sandy-yua", + "xn--seral-lra", + "xn--sgne-gra", + "xn--skierv-uta", + "xn--skjervy-v1a", + "xn--skjk-soa", + "xn--sknit-yqa", + "xn--sknland-fxa", + "xn--slat-5na", + "xn--slt-elab", + "xn--smla-hra", + "xn--smna-gra", + "xn--snase-nra", + "xn--sndre-land-0cb", + "xn--snes-poa", + "xn--snsa-roa", + "xn--sr-aurdal-l8a", + "xn--sr-fron-q1a", + "xn--sr-odal-q1a", + "xn--sr-varanger-ggb", + "xn--srfold-bya", + "xn--srreisa-q1a", + "xn--srum-gra", + "xn--stfold-9xa", + "xn--stjrdal-s1a", + "xn--stjrdalshalsen-sqb", + "xn--stre-toten-zcb", + "xn--tjme-hra", + "xn--tnsberg-q1a", + "xn--trany-yua", + "xn--trgstad-r1a", + "xn--trna-woa", + "xn--troms-zua", + "xn--tysvr-vra", + "xn--unjrga-rta", + "xn--vads-jra", + "xn--vard-jra", + "xn--vegrshei-c0a", + "xn--vestvgy-ixa6o", + "xn--vg-yiab", + "xn--vgan-qoa", + "xn--vgsy-qoa0j", + "xn--vre-eiker-k8a", + "xn--vrggt-xqad", + "xn--vry-yla5g", + "xn--yer-zna", + "xn--ygarden-p1a", + "xn--ystre-slidre-ujb", + "gs", + "gs", + "nes", + "gs", + "nes", + "gs", + "os", + "valer", + "xn--vler-qoa", + "gs", + "gs", + "os", + "gs", + "heroy", + "sande", + "gs", + "gs", + "bo", + "heroy", + "xn--b-5ga", + "xn--hery-ira", + "gs", + "gs", + "gs", + "gs", + "valer", + "gs", + "gs", + "gs", + "gs", + "bo", + "xn--b-5ga", + "gs", + "gs", + "gs", + "sande", + "gs", + "sande", + "xn--hery-ira", + "xn--vler-qoa", + "biz", + "com", + "edu", + "gov", + "info", + "net", + "org", + "builder", + "enterprisecloud", + "merseine", + "mine", + "nom", + "shacknet", + "site", + "ac", + "co", + "cri", + "geek", + "gen", + "govt", + "health", + "iwi", + "kiwi", + "maori", + "mil", + "net", + "nym", + "org", + "parliament", + "school", + "xn--mori-qsa", + "blogspot", + "co", + "com", + "edu", + "gov", + "med", + "museum", + "net", + "org", + "pro", + "for", + "homelink", + "onred", + "staging", + "barsy", + "accesscam", + "ae", + "amune", + "barsy", + "blogdns", + "blogsite", + "bmoattachments", + "boldlygoingnowhere", + "cable-modem", + "camdvr", + "cdn77", + "cdn77-secure", + "certmgr", + "cloudns", + "collegefan", + "couchpotatofries", + "ddnss", + "diskstation", + "dnsalias", + "dnsdojo", + "doesntexist", + "dontexist", + "doomdns", + "dsmynas", + "duckdns", + "dvrdns", + "dynalias", + "dyndns", + "dynserv", + "edugit", + "endofinternet", + "endoftheinternet", + "eu", + "familyds", + "fedorainfracloud", + "fedorapeople", + "fedoraproject", + "freeddns", + "freedesktop", + "from-me", + "game-host", + "gotdns", + "hepforge", + "hk", + "hobby-site", + "homedns", + "homeftp", + "homelinux", + "homeunix", + "hopto", + "in-dsl", + "in-vpn", + "is-a-bruinsfan", + "is-a-candidate", + "is-a-celticsfan", + "is-a-chef", + "is-a-geek", + "is-a-knight", + "is-a-linux-user", + "is-a-patsfan", + "is-a-soxfan", + "is-found", + "is-lost", + "is-saved", + "is-very-bad", + "is-very-evil", + "is-very-good", + "is-very-nice", + "is-very-sweet", + "isa-geek", + "js", + "kicks-ass", + "mayfirst", + "misconfused", + "mlbfan", + "mozilla-iot", + "my-firewall", + "myfirewall", + "myftp", + "mysecuritycamera", + "mywire", + "nflfan", + "no-ip", + "now-dns", + "pimienta", + "podzone", + "poivron", + "potager", + "read-books", + "readmyblog", + "selfip", + "sellsyourhome", + "servebbs", + "serveftp", + "servegame", + "spdns", + "stuff-4-sale", + "sweetpepper", + "tunk", + "tuxfamily", + "twmail", + "ufcfan", + "uklugs", + "us", + "webhop", + "webredirect", + "wmflabs", + "za", + "zapto", + "tele", + "c", + "rsc", + "origin", + "ssl", + "go", + "home", + "al", + "asso", + "at", + "au", + "be", + "bg", + "ca", + "cd", + "ch", + "cn", + "cy", + "cz", + "de", + "dk", + "edu", + "ee", + "es", + "fi", + "fr", + "gr", + "hr", + "hu", + "ie", + "il", + "in", + "int", + "is", + "it", + "jp", + "kr", + "lt", + "lu", + "lv", + "mc", + "me", + "mk", + "mt", + "my", + "net", + "ng", + "nl", + "no", + "nz", + "paris", + "pl", + "pt", + "q-a", + "ro", + "ru", + "se", + "si", + "sk", + "tr", + "uk", + "us", + "cloud", + "os", + "stg", + "app", + "os", + "app", + "nerdpol", + "abo", + "ac", + "com", + "edu", + "gob", + "ing", + "med", + "net", + "nom", + "org", + "sld", + "prvcy", + "ybo", + "blogspot", + "com", + "edu", + "gob", + "mil", + "net", + "nom", + "nym", + "org", + "com", + "edu", + "org", + "com", + "edu", + "gov", + "i", + "mil", + "net", + "ngo", + "org", + "1337", + "biz", + "com", + "edu", + "fam", + "gob", + "gok", + "gon", + "gop", + "gos", + "gov", + "info", + "net", + "org", + "web", + "agro", + "aid", + "art", + "atm", + "augustow", + "auto", + "babia-gora", + "bedzin", + "beep", + "beskidy", + "bialowieza", + "bialystok", + "bielawa", + "bieszczady", + "biz", + "boleslawiec", + "bydgoszcz", + "bytom", + "cieszyn", + "co", + "com", + "czeladz", + "czest", + "dlugoleka", + "edu", + "elblag", + "elk", + "gda", + "gdansk", + "gdynia", + "gliwice", + "glogow", + "gmina", + "gniezno", + "gorlice", + "gov", + "grajewo", + "gsm", + "ilawa", + "info", + "jaworzno", + "jelenia-gora", + "jgora", + "kalisz", + "karpacz", + "kartuzy", + "kaszuby", + "katowice", + "kazimierz-dolny", + "kepno", + "ketrzyn", + "klodzko", + "kobierzyce", + "kolobrzeg", + "konin", + "konskowola", + "krakow", + "krasnik", + "kutno", + "lapy", + "lebork", + "leczna", + "legnica", + "lezajsk", + "limanowa", + "lomza", + "lowicz", + "lubartow", + "lubin", + "lublin", + "lukow", + "mail", + "malbork", + "malopolska", + "mazowsze", + "mazury", + "med", + "media", + "miasta", + "mielec", + "mielno", + "mil", + "mragowo", + "naklo", + "net", + "nieruchomosci", + "nom", + "nowaruda", + "nysa", + "olawa", + "olecko", + "olkusz", + "olsztyn", + "opoczno", + "opole", + "org", + "ostroda", + "ostroleka", + "ostrowiec", + "ostrowwlkp", + "pc", + "pila", + "pisz", + "podhale", + "podlasie", + "polkowice", + "pomorskie", + "pomorze", + "poniatowa", + "powiat", + "poznan", + "priv", + "prochowice", + "pruszkow", + "przeworsk", + "pulawy", + "radom", + "rawa-maz", + "realestate", + "rel", + "rybnik", + "rzeszow", + "sanok", + "sejny", + "sex", + "shop", + "sklep", + "skoczow", + "slask", + "slupsk", + "sopot", + "sos", + "sosnowiec", + "stalowa-wola", + "starachowice", + "stargard", + "suwalki", + "swidnica", + "swidnik", + "swiebodzin", + "swinoujscie", + "szczecin", + "szczytno", + "szkola", + "targi", + "tarnobrzeg", + "tgory", + "tm", + "tourism", + "travel", + "turek", + "turystyka", + "tychy", + "ustka", + "walbrzych", + "warmia", + "warszawa", + "waw", + "wegrow", + "wielun", + "wlocl", + "wloclawek", + "wodzislaw", + "wolomin", + "wroc", + "wroclaw", + "zachpomor", + "zagan", + "zakopane", + "zarow", + "zgora", + "zgorzelec", + "ap", + "griw", + "ic", + "is", + "kmpsp", + "konsulat", + "kppsp", + "kwp", + "kwpsp", + "mup", + "mw", + "oirm", + "oum", + "pa", + "pinb", + "piw", + "po", + "psp", + "psse", + "pup", + "rzgw", + "sa", + "sdn", + "sko", + "so", + "sr", + "starostwo", + "ug", + "ugim", + "um", + "umig", + "upow", + "uppo", + "us", + "uw", + "uzs", + "wif", + "wiih", + "winb", + "wios", + "witd", + "wiw", + "wsa", + "wskr", + "wuoz", + "wzmiuw", + "zp", + "co", + "own", + "co", + "edu", + "gov", + "net", + "org", + "ac", + "biz", + "com", + "edu", + "est", + "gov", + "info", + "isla", + "name", + "net", + "org", + "pro", + "prof", + "aaa", + "aca", + "acct", + "avocat", + "bar", + "barsy", + "cloudns", + "cpa", + "dnstrace", + "eng", + "jur", + "law", + "med", + "recht", + "bci", + "com", + "edu", + "gov", + "net", + "org", + "plo", + "sec", + "blogspot", + "com", + "edu", + "gov", + "int", + "net", + "nome", + "nym", + "org", + "publ", + "barsy", + "belau", + "cloudns", + "co", + "ed", + "go", + "ne", + "nom", + "or", + "x443", + "com", + "coop", + "edu", + "gov", + "mil", + "net", + "org", + "blogspot", + "com", + "edu", + "gov", + "mil", + "name", + "net", + "nom", + "org", + "sch", + "asso", + "blogspot", + "com", + "nom", + "ybo", + "clan", + "arts", + "blogspot", + "com", + "firm", + "info", + "nom", + "nt", + "nym", + "org", + "rec", + "shop", + "store", + "tm", + "www", + "lima-city", + "myddns", + "webspace", + "ac", + "blogspot", + "co", + "edu", + "gov", + "in", + "nom", + "org", + "ox", + "ua", + "ac", + "adygeya", + "bashkiria", + "bir", + "blogspot", + "cbg", + "cldmail", + "com", + "dagestan", + "edu", + "gov", + "grozny", + "int", + "kalmykia", + "kustanai", + "marine", + "mil", + "mordovia", + "msk", + "myjino", + "mytis", + "nalchik", + "net", + "nov", + "org", + "pp", + "pyatigorsk", + "ras", + "spb", + "test", + "vladikavkaz", + "vladimir", + "hb", + "hosting", + "landing", + "spectrum", + "vps", + "development", + "ravendb", + "repl", + "ac", + "co", + "coop", + "gov", + "mil", + "net", + "org", + "com", + "edu", + "gov", + "med", + "net", + "org", + "pub", + "sch", + "for", + "com", + "edu", + "gov", + "net", + "org", + "com", + "edu", + "gov", + "net", + "org", + "ybo", + "com", + "edu", + "gov", + "info", + "med", + "net", + "org", + "tv", + "a", + "ac", + "b", + "bd", + "blogspot", + "brand", + "c", + "com", + "conf", + "d", + "e", + "f", + "fh", + "fhsk", + "fhv", + "g", + "h", + "i", + "k", + "komforb", + "kommunalforbund", + "komvux", + "l", + "lanbib", + "m", + "n", + "naturbruksgymn", + "o", + "org", + "p", + "parti", + "pp", + "press", + "r", + "s", + "t", + "tm", + "u", + "w", + "x", + "y", + "z", + "loginline", + "blogspot", + "com", + "edu", + "gov", + "net", + "org", + "per", + "com", + "gov", + "hashbang", + "mil", + "net", + "now", + "org", + "platform", + "wedeploy", + "barsy", + "blogspot", + "nom", + "barsy", + "byen", + "cloudera", + "cyon", + "loginline", + "platformsh", + "blogspot", + "nym", + "com", + "edu", + "gov", + "net", + "org", + "art", + "blogspot", + "com", + "edu", + "gouv", + "org", + "perso", + "univ", + "com", + "net", + "org", + "sch", + "linkitools", + "uber", + "xs4all", + "co", + "com", + "consulado", + "edu", + "embaixada", + "gov", + "mil", + "net", + "noho", + "nom", + "org", + "principe", + "saotome", + "store", + "abkhazia", + "adygeya", + "aktyubinsk", + "arkhangelsk", + "armenia", + "ashgabad", + "azerbaijan", + "balashov", + "bashkiria", + "bryansk", + "bukhara", + "chimkent", + "dagestan", + "east-kazakhstan", + "exnet", + "georgia", + "grozny", + "ivanovo", + "jambyl", + "kalmykia", + "kaluga", + "karacol", + "karaganda", + "karelia", + "khakassia", + "krasnodar", + "kurgan", + "kustanai", + "lenug", + "mangyshlak", + "mordovia", + "msk", + "murmansk", + "nalchik", + "navoi", + "north-kazakhstan", + "nov", + "nym", + "obninsk", + "penza", + "pokrovsk", + "sochi", + "spb", + "tashkent", + "termez", + "togliatti", + "troitsk", + "tselinograd", + "tula", + "tuva", + "vladikavkaz", + "vladimir", + "vologda", + "barsy", + "com", + "edu", + "gob", + "org", + "red", + "gov", + "nym", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "knightpoint", + "ac", + "co", + "org", + "blogspot", + "co", + "ac", + "co", + "go", + "in", + "mi", + "net", + "online", + "or", + "shop", + "ac", + "biz", + "co", + "com", + "edu", + "go", + "gov", + "int", + "mil", + "name", + "net", + "nic", + "nom", + "org", + "test", + "web", + "gov", + "co", + "com", + "edu", + "gov", + "mil", + "net", + "nom", + "org", + "agrinet", + "com", + "defense", + "edunet", + "ens", + "fin", + "gov", + "ind", + "info", + "intl", + "mincom", + "nat", + "net", + "org", + "perso", + "rnrt", + "rns", + "rnu", + "tourism", + "turen", + "com", + "edu", + "gov", + "mil", + "net", + "org", + "vpnplus", + "now-dns", + "ntdll", + "av", + "bbs", + "bel", + "biz", + "com", + "dr", + "edu", + "gen", + "gov", + "info", + "k12", + "kep", + "mil", + "name", + "nc", + "net", + "org", + "pol", + "tel", + "tsk", + "tv", + "web", + "blogspot", + "gov", + "ybo", + "aero", + "biz", + "co", + "com", + "coop", + "edu", + "gov", + "info", + "int", + "jobs", + "mobi", + "museum", + "name", + "net", + "org", + "pro", + "travel", + "better-than", + "dyndns", + "on-the-web", + "worse-than", + "blogspot", + "club", + "com", + "ebiz", + "edu", + "game", + "gov", + "idv", + "mil", + "net", + "nym", + "org", + "url", + "xn--czrw28b", + "xn--uc0atv", + "xn--zf0ao64a", + "mymailer", + "ac", + "co", + "go", + "hotel", + "info", + "me", + "mil", + "mobi", + "ne", + "or", + "sc", + "tv", + "biz", + "cc", + "cherkassy", + "cherkasy", + "chernigov", + "chernihiv", + "chernivtsi", + "chernovtsy", + "ck", + "cn", + "co", + "com", + "cr", + "crimea", + "cv", + "dn", + "dnepropetrovsk", + "dnipropetrovsk", + "dominic", + "donetsk", + "dp", + "edu", + "gov", + "if", + "in", + "inf", + "ivano-frankivsk", + "kh", + "kharkiv", + "kharkov", + "kherson", + "khmelnitskiy", + "khmelnytskyi", + "kiev", + "kirovograd", + "km", + "kr", + "krym", + "ks", + "kv", + "kyiv", + "lg", + "lt", + "ltd", + "lugansk", + "lutsk", + "lv", + "lviv", + "mk", + "mykolaiv", + "net", + "nikolaev", + "od", + "odesa", + "odessa", + "org", + "pl", + "poltava", + "pp", + "rivne", + "rovno", + "rv", + "sb", + "sebastopol", + "sevastopol", + "sm", + "sumy", + "te", + "ternopil", + "uz", + "uzhgorod", + "vinnica", + "vinnytsia", + "vn", + "volyn", + "yalta", + "zaporizhzhe", + "zaporizhzhia", + "zhitomir", + "zhytomyr", + "zp", + "zt", + "ac", + "blogspot", + "co", + "com", + "go", + "ne", + "nom", + "or", + "org", + "sc", + "ac", + "barsy", + "co", + "gov", + "ltd", + "me", + "net", + "nhs", + "org", + "plc", + "police", + "sch", + "barsy", + "barsyonline", + "blogspot", + "bytemark", + "gwiddle", + "nh-serv", + "no-ip", + "wellbeingzone", + "dh", + "vm", + "homeoffice", + "service", + "glug", + "lug", + "lugs", + "ak", + "al", + "ar", + "as", + "az", + "ca", + "cloudns", + "co", + "ct", + "dc", + "de", + "dni", + "drud", + "fed", + "fl", + "freeddns", + "ga", + "golffan", + "gu", + "hi", + "ia", + "id", + "il", + "in", + "is-by", + "isa", + "kids", + "ks", + "ky", + "la", + "land-4-sale", + "ma", + "md", + "me", + "mi", + "mn", + "mo", + "ms", + "mt", + "nc", + "nd", + "ne", + "nh", + "nj", + "nm", + "noip", + "nsn", + "nv", + "ny", + "oh", + "ok", + "or", + "pa", + "pointto", + "pr", + "ri", + "sc", + "sd", + "stuff-4-sale", + "tn", + "tx", + "ut", + "va", + "vi", + "vt", + "wa", + "wi", + "wv", + "wy", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "chtr", + "paroch", + "pvt", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "ann-arbor", + "cc", + "cog", + "dst", + "eaton", + "gen", + "k12", + "lib", + "mus", + "tec", + "washtenaw", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "k12", + "lib", + "cc", + "cc", + "k12", + "lib", + "com", + "edu", + "gub", + "mil", + "net", + "nom", + "org", + "blogspot", + "co", + "com", + "net", + "org", + "com", + "edu", + "gov", + "mil", + "net", + "nom", + "org", + "arts", + "co", + "com", + "e12", + "edu", + "firm", + "gob", + "gov", + "info", + "int", + "mil", + "net", + "org", + "rec", + "store", + "tec", + "web", + "nom", + "co", + "com", + "k12", + "net", + "org", + "ac", + "biz", + "blogspot", + "com", + "edu", + "gov", + "health", + "info", + "int", + "name", + "net", + "org", + "pro", + "com", + "edu", + "net", + "org", + "of", + "to", + "advisor", + "cloud66", + "com", + "dyndns", + "edu", + "gov", + "mypets", + "net", + "org", + "xn--80au", + "xn--90azh", + "xn--c1avg", + "xn--d1at", + "xn--o1ac", + "xn--o1ach", + "xn--55qx5d", + "xn--gmqw5a", + "xn--mxtq1m", + "xn--od0alg", + "xn--uc0atv", + "xn--wcvs22d", + "xn--12c1fe0br", + "xn--12cfi8ixb8l", + "xn--12co0c3b4eva", + "xn--h3cuzk1di", + "xn--m3ch0j3a", + "xn--o3cyx2a", + "blogsite", + "crafting", + "fhapp", + "telebit", + "zapto", + "ac", + "agric", + "alt", + "co", + "edu", + "gov", + "grondar", + "law", + "mil", + "net", + "ngo", + "nis", + "nom", + "org", + "school", + "tm", + "web", + "blogspot", + "ac", + "biz", + "co", + "com", + "edu", + "gov", + "info", + "mil", + "net", + "org", + "sch", + "cloud66", + "lima", + "triton", + "ac", + "co", + "gov", + "mil", + "org", +} From 2e5b687a64903458f441d8cb47352ce724ab9c67 Mon Sep 17 00:00:00 2001 From: mortelli Date: Fri, 8 Nov 2019 10:14:12 -0300 Subject: [PATCH 13/49] api: iterate TestRNSResolve function --- api/api_test.go | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index d9f521ee8f..c1ec7c12b0 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -303,38 +303,53 @@ func TestAPIResolve(t *testing.T) { } } -// TestRNSResolve tests resolving content from RNS names +// TestRNSResolve tests resolving content from RNS addresses func TestRNSResolve(t *testing.T) { rnsAddr := "marcelosdomain.rsk" resolvedContent := "88ced8ba8e9396672840b47e332b33d6679d9962d80cf340d3cf615db23d4e07" type test struct { - desc string - ctx context.Context - addr string - content string + desc string + ctx context.Context + addr string + content string + expectedErr error } tests := []*test{ { - desc: "resolve valid RSK domain", - addr: rnsAddr, - content: resolvedContent, - ctx: context.TODO(), + desc: "valid RSK domain", + addr: rnsAddr, + content: resolvedContent, + expectedErr: nil, + }, + { + desc: "invalid RSK domain", + addr: ".rsk", + content: resolvedContent, + expectedErr: nil, }, } for _, x := range tests { t.Run(x.desc, func(t *testing.T) { api := NewAPI(nil, nil, nil, nil, nil) - res, err := api.Resolve(x.ctx, x.addr) - if err != nil { - t.Fatalf(err.Error()) - } - if res.Hex() != x.content { - t.Fatalf("expected result %q, got %q", x.content, res.Hex()) + res, err := api.Resolve(context.TODO(), x.addr) + if err == nil { + if x.expectedErr != nil { + t.Fatalf("expected error %q, got %q", x.expectedErr, res) + } + if x.content != res.Hex() { + t.Fatalf("expected result %q, got %q", x.content, res.Hex()) + } + } else { + if x.expectedErr == nil { + t.Fatalf("expected no error, got %q", err) + } + if x.expectedErr.Error() != err.Error() { + t.Fatalf("expected error %q, got %q", x.expectedErr, err) + } } - }) } } From 6a5b113b039c25bfe2ddcc7e3922b7271274aaa6 Mon Sep 17 00:00:00 2001 From: mortelli Date: Fri, 8 Nov 2019 11:18:24 -0300 Subject: [PATCH 14/49] main: handle rnsAPI flag as single string instead of array --- cmd/swarm/config.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index c7155fd4c5..72e48a53fc 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -248,12 +248,7 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi currentConfig.EnsAPIs = ensAPIs } if ctx.GlobalIsSet(RnsAPIFlag.Name) { - rnsAPI := ctx.GlobalStringSlice(RnsAPIFlag.Name) - // preserve backward compatibility to disable RNS with --rns-api="" - if len(rnsAPI) == 1 && rnsAPI[0] == "" { - rnsAPI = nil - } - currentConfig.RnsAPI = rnsAPI[0] + currentConfig.RnsAPI = ctx.GlobalString(RnsAPIFlag.Name) } if cors := ctx.GlobalString(CorsStringFlag.Name); cors != "" { currentConfig.Cors = cors From 10f63f7c44c910375534b02734ec56b9a37f1590 Mon Sep 17 00:00:00 2001 From: mortelli Date: Fri, 8 Nov 2019 11:18:50 -0300 Subject: [PATCH 15/49] api: add expected error to TestRNSResolve function --- api/api_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api_test.go b/api/api_test.go index c1ec7c12b0..73cc5d64e2 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -327,7 +327,7 @@ func TestRNSResolve(t *testing.T) { desc: "invalid RSK domain", addr: ".rsk", content: resolvedContent, - expectedErr: nil, + expectedErr: errors.New("domain without registered content in RNS Resolvers"), }, } From bcc89005ae37a0c4a2ed0cc8a173dbba8512f310 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Fri, 8 Nov 2019 11:58:40 -0300 Subject: [PATCH 16/49] vendor: re applied --- go.mod | 2 +- go.sum | 6 +- .../btcsuite/btcd/btcec/genprecomps.go | 63 - .../docker/pkg/archive/example_changes.go | 97 - .../crypto/secp256k1/libsecp256k1/.gitignore | 49 - .../crypto/secp256k1/libsecp256k1/.travis.yml | 69 - .../crypto/secp256k1/libsecp256k1/COPYING | 19 - .../crypto/secp256k1/libsecp256k1/Makefile.am | 177 - .../crypto/secp256k1/libsecp256k1/README.md | 61 - .../crypto/secp256k1/libsecp256k1/TODO | 3 - .../crypto/secp256k1/libsecp256k1/autogen.sh | 3 - .../build-aux/m4/ax_jni_include_dir.m4 | 140 - .../build-aux/m4/ax_prog_cc_for_build.m4 | 125 - .../libsecp256k1/build-aux/m4/bitcoin_secp.m4 | 69 - .../secp256k1/libsecp256k1/configure.ac | 493 - .../libsecp256k1/contrib/lax_der_parsing.c | 150 - .../libsecp256k1/contrib/lax_der_parsing.h | 91 - .../contrib/lax_der_privatekey_parsing.c | 113 - .../contrib/lax_der_privatekey_parsing.h | 90 - .../libsecp256k1/include/secp256k1.h | 577 - .../libsecp256k1/include/secp256k1_ecdh.h | 31 - .../libsecp256k1/include/secp256k1_recovery.h | 110 - .../secp256k1/libsecp256k1/libsecp256k1.pc.in | 13 - .../secp256k1/libsecp256k1/obj/.gitignore | 0 .../libsecp256k1/sage/group_prover.sage | 322 - .../libsecp256k1/sage/secp256k1.sage | 306 - .../libsecp256k1/sage/weierstrass_prover.sage | 264 - .../libsecp256k1/src/asm/field_10x26_arm.s | 919 - .../secp256k1/libsecp256k1/src/basic-config.h | 32 - .../crypto/secp256k1/libsecp256k1/src/bench.h | 66 - .../secp256k1/libsecp256k1/src/bench_ecdh.c | 54 - .../libsecp256k1/src/bench_internal.c | 382 - .../libsecp256k1/src/bench_recover.c | 60 - .../libsecp256k1/src/bench_schnorr_verify.c | 73 - .../secp256k1/libsecp256k1/src/bench_sign.c | 56 - .../secp256k1/libsecp256k1/src/bench_verify.c | 112 - .../crypto/secp256k1/libsecp256k1/src/ecdsa.h | 21 - .../secp256k1/libsecp256k1/src/ecdsa_impl.h | 315 - .../crypto/secp256k1/libsecp256k1/src/eckey.h | 25 - .../secp256k1/libsecp256k1/src/eckey_impl.h | 99 - .../secp256k1/libsecp256k1/src/ecmult.h | 31 - .../secp256k1/libsecp256k1/src/ecmult_const.h | 15 - .../libsecp256k1/src/ecmult_const_impl.h | 239 - .../secp256k1/libsecp256k1/src/ecmult_gen.h | 43 - .../libsecp256k1/src/ecmult_gen_impl.h | 210 - .../secp256k1/libsecp256k1/src/ecmult_impl.h | 406 - .../crypto/secp256k1/libsecp256k1/src/field.h | 132 - .../secp256k1/libsecp256k1/src/field_10x26.h | 47 - .../libsecp256k1/src/field_10x26_impl.h | 1140 - .../secp256k1/libsecp256k1/src/field_5x52.h | 47 - .../libsecp256k1/src/field_5x52_asm_impl.h | 502 - .../libsecp256k1/src/field_5x52_impl.h | 451 - .../libsecp256k1/src/field_5x52_int128_impl.h | 277 - .../secp256k1/libsecp256k1/src/field_impl.h | 315 - .../secp256k1/libsecp256k1/src/gen_context.c | 74 - .../crypto/secp256k1/libsecp256k1/src/group.h | 144 - .../secp256k1/libsecp256k1/src/group_impl.h | 700 - .../crypto/secp256k1/libsecp256k1/src/hash.h | 41 - .../secp256k1/libsecp256k1/src/hash_impl.h | 281 - .../src/java/org/bitcoin/NativeSecp256k1.java | 446 - .../java/org/bitcoin/NativeSecp256k1Test.java | 226 - .../java/org/bitcoin/NativeSecp256k1Util.java | 45 - .../java/org/bitcoin/Secp256k1Context.java | 51 - .../src/java/org_bitcoin_NativeSecp256k1.c | 377 - .../src/java/org_bitcoin_NativeSecp256k1.h | 119 - .../src/java/org_bitcoin_Secp256k1Context.c | 15 - .../src/java/org_bitcoin_Secp256k1Context.h | 22 - .../src/modules/ecdh/Makefile.am.include | 8 - .../libsecp256k1/src/modules/ecdh/main_impl.h | 54 - .../src/modules/ecdh/tests_impl.h | 105 - .../src/modules/recovery/Makefile.am.include | 8 - .../src/modules/recovery/main_impl.h | 193 - .../src/modules/recovery/tests_impl.h | 393 - .../crypto/secp256k1/libsecp256k1/src/num.h | 74 - .../secp256k1/libsecp256k1/src/num_gmp.h | 20 - .../secp256k1/libsecp256k1/src/num_gmp_impl.h | 288 - .../secp256k1/libsecp256k1/src/num_impl.h | 24 - .../secp256k1/libsecp256k1/src/scalar.h | 106 - .../secp256k1/libsecp256k1/src/scalar_4x64.h | 19 - .../libsecp256k1/src/scalar_4x64_impl.h | 949 - .../secp256k1/libsecp256k1/src/scalar_8x32.h | 19 - .../libsecp256k1/src/scalar_8x32_impl.h | 721 - .../secp256k1/libsecp256k1/src/scalar_impl.h | 370 - .../secp256k1/libsecp256k1/src/scalar_low.h | 15 - .../libsecp256k1/src/scalar_low_impl.h | 114 - .../secp256k1/libsecp256k1/src/secp256k1.c | 559 - .../secp256k1/libsecp256k1/src/testrand.h | 38 - .../libsecp256k1/src/testrand_impl.h | 110 - .../crypto/secp256k1/libsecp256k1/src/tests.c | 4525 ---- .../libsecp256k1/src/tests_exhaustive.c | 470 - .../crypto/secp256k1/libsecp256k1/src/util.h | 113 - .../karalabe/usb/hidapi/AUTHORS.txt | 16 - .../karalabe/usb/hidapi/LICENSE-bsd.txt | 26 - .../karalabe/usb/hidapi/LICENSE-gpl3.txt | 674 - .../karalabe/usb/hidapi/LICENSE-orig.txt | 9 - .../karalabe/usb/hidapi/LICENSE.txt | 13 - .../github.com/karalabe/usb/hidapi/README.txt | 339 - .../karalabe/usb/hidapi/hidapi/hidapi.h | 390 - .../karalabe/usb/hidapi/libusb/hid.c | 1512 -- .../github.com/karalabe/usb/hidapi/mac/hid.c | 1110 - .../karalabe/usb/hidapi/windows/hid.c | 944 - vendor/github.com/karalabe/usb/libusb/AUTHORS | 119 - vendor/github.com/karalabe/usb/libusb/COPYING | 504 - .../karalabe/usb/libusb/libusb/config.h | 3 - .../karalabe/usb/libusb/libusb/core.c | 2579 --- .../karalabe/usb/libusb/libusb/descriptor.c | 1192 -- .../karalabe/usb/libusb/libusb/hotplug.c | 373 - .../karalabe/usb/libusb/libusb/hotplug.h | 99 - .../karalabe/usb/libusb/libusb/io.c | 2822 --- .../karalabe/usb/libusb/libusb/libusb.h | 2039 -- .../karalabe/usb/libusb/libusb/libusbi.h | 1165 - .../usb/libusb/libusb/os/darwin_usb.c | 2142 -- .../usb/libusb/libusb/os/darwin_usb.h | 199 - .../usb/libusb/libusb/os/haiku_pollfs.cpp | 367 - .../karalabe/usb/libusb/libusb/os/haiku_usb.h | 112 - .../libusb/libusb/os/haiku_usb_backend.cpp | 517 - .../usb/libusb/libusb/os/haiku_usb_raw.cpp | 253 - .../usb/libusb/libusb/os/haiku_usb_raw.h | 180 - .../usb/libusb/libusb/os/linux_netlink.c | 409 - .../usb/libusb/libusb/os/linux_udev.c | 329 - .../usb/libusb/libusb/os/linux_usbfs.c | 2800 --- .../usb/libusb/libusb/os/linux_usbfs.h | 194 - .../usb/libusb/libusb/os/netbsd_usb.c | 677 - .../usb/libusb/libusb/os/openbsd_usb.c | 771 - .../usb/libusb/libusb/os/poll_posix.c | 84 - .../usb/libusb/libusb/os/poll_posix.h | 11 - .../usb/libusb/libusb/os/poll_windows.c | 364 - .../usb/libusb/libusb/os/poll_windows.h | 97 - .../karalabe/usb/libusb/libusb/os/sunos_usb.c | 1675 -- .../karalabe/usb/libusb/libusb/os/sunos_usb.h | 80 - .../usb/libusb/libusb/os/threads_posix.c | 80 - .../usb/libusb/libusb/os/threads_posix.h | 102 - .../usb/libusb/libusb/os/threads_windows.c | 126 - .../usb/libusb/libusb/os/threads_windows.h | 111 - .../karalabe/usb/libusb/libusb/os/wince_usb.c | 888 - .../karalabe/usb/libusb/libusb/os/wince_usb.h | 126 - .../usb/libusb/libusb/os/windows_common.h | 128 - .../usb/libusb/libusb/os/windows_nt_common.c | 1008 - .../usb/libusb/libusb/os/windows_nt_common.h | 110 - .../libusb/os/windows_nt_shared_types.h | 138 - .../usb/libusb/libusb/os/windows_usbdk.c | 830 - .../usb/libusb/libusb/os/windows_usbdk.h | 103 - .../usb/libusb/libusb/os/windows_winusb.c | 3009 --- .../usb/libusb/libusb/os/windows_winusb.h | 680 - .../karalabe/usb/libusb/libusb/strerror.c | 202 - .../karalabe/usb/libusb/libusb/sync.c | 327 - .../karalabe/usb/libusb/libusb/version.h | 18 - .../karalabe/usb/libusb/libusb/version_nano.h | 1 - vendor/golang.org/x/net/html/atom/gen.go | 712 - vendor/golang.org/x/net/html/token.go | 6 + vendor/golang.org/x/net/http2/hpack/encode.go | 2 +- vendor/golang.org/x/net/http2/pipe.go | 7 +- vendor/golang.org/x/net/http2/server.go | 58 +- vendor/golang.org/x/net/http2/transport.go | 52 +- vendor/golang.org/x/net/http2/writesched.go | 8 +- .../x/net/http2/writesched_priority.go | 2 +- .../x/net/http2/writesched_random.go | 9 +- vendor/golang.org/x/net/idna/tables11.0.0.go | 2 +- vendor/golang.org/x/net/idna/tables12.00.go | 4733 +++++ .../golang.org/x/net/internal/socks/socks.go | 2 +- .../x/net/publicsuffix/example_test.go | 93 - vendor/golang.org/x/net/publicsuffix/gen.go | 717 - vendor/golang.org/x/net/publicsuffix/list.go | 0 .../x/net/publicsuffix/list_test.go | 509 - vendor/golang.org/x/net/publicsuffix/table.go | 0 .../x/net/publicsuffix/table_test.go | 17632 ---------------- .../golang.org/x/net/websocket/websocket.go | 6 +- vendor/golang.org/x/sys/unix/mkasm_darwin.go | 61 - vendor/golang.org/x/sys/unix/mkpost.go | 122 - vendor/golang.org/x/sys/unix/mksyscall.go | 407 - .../x/sys/unix/mksyscall_aix_ppc.go | 415 - .../x/sys/unix/mksyscall_aix_ppc64.go | 614 - .../x/sys/unix/mksyscall_solaris.go | 335 - .../golang.org/x/sys/unix/mksysctl_openbsd.go | 355 - vendor/golang.org/x/sys/unix/mksysnum.go | 190 - vendor/golang.org/x/sys/unix/types_aix.go | 237 - vendor/golang.org/x/sys/unix/types_darwin.go | 283 - .../golang.org/x/sys/unix/types_dragonfly.go | 263 - vendor/golang.org/x/sys/unix/types_freebsd.go | 400 - vendor/golang.org/x/sys/unix/types_netbsd.go | 290 - vendor/golang.org/x/sys/unix/types_openbsd.go | 283 - vendor/golang.org/x/sys/unix/types_solaris.go | 266 - .../x/text/encoding/charmap/maketables.go | 556 - .../x/text/encoding/htmlindex/gen.go | 173 - .../text/encoding/internal/identifier/gen.go | 142 - .../x/text/encoding/japanese/maketables.go | 161 - .../x/text/encoding/korean/maketables.go | 143 - .../encoding/simplifiedchinese/maketables.go | 161 - .../encoding/traditionalchinese/maketables.go | 140 - .../x/text/internal/language/compact/gen.go | 64 - .../internal/language/compact/gen_index.go | 113 - .../internal/language/compact/gen_parents.go | 54 - .../x/text/internal/language/gen.go | 1520 -- .../x/text/internal/language/gen_common.go | 20 - vendor/golang.org/x/text/language/gen.go | 305 - vendor/golang.org/x/text/unicode/bidi/gen.go | 133 - .../x/text/unicode/bidi/gen_ranges.go | 57 - .../x/text/unicode/bidi/gen_trieval.go | 64 - .../x/text/unicode/norm/maketables.go | 986 - .../golang.org/x/text/unicode/norm/triegen.go | 117 - vendor/modules.txt | 322 +- 201 files changed, 5029 insertions(+), 85797 deletions(-) delete mode 100644 vendor/github.com/btcsuite/btcd/btcec/genprecomps.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/example_changes.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h delete mode 100644 vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/README.txt delete mode 100644 vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h delete mode 100644 vendor/github.com/karalabe/usb/hidapi/libusb/hid.c delete mode 100644 vendor/github.com/karalabe/usb/hidapi/mac/hid.c delete mode 100644 vendor/github.com/karalabe/usb/hidapi/windows/hid.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/AUTHORS delete mode 100644 vendor/github.com/karalabe/usb/libusb/COPYING delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/config.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/core.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/io.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/libusb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/strerror.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/sync.c delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/version.h delete mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h delete mode 100644 vendor/golang.org/x/net/html/atom/gen.go create mode 100644 vendor/golang.org/x/net/idna/tables12.00.go delete mode 100755 vendor/golang.org/x/net/publicsuffix/example_test.go delete mode 100755 vendor/golang.org/x/net/publicsuffix/gen.go mode change 100755 => 100644 vendor/golang.org/x/net/publicsuffix/list.go delete mode 100755 vendor/golang.org/x/net/publicsuffix/list_test.go mode change 100755 => 100644 vendor/golang.org/x/net/publicsuffix/table.go delete mode 100755 vendor/golang.org/x/net/publicsuffix/table_test.go delete mode 100644 vendor/golang.org/x/sys/unix/mkasm_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/mkpost.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.go delete mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum.go delete mode 100644 vendor/golang.org/x/sys/unix/types_aix.go delete mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go delete mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go delete mode 100644 vendor/golang.org/x/text/encoding/charmap/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/htmlindex/gen.go delete mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/gen.go delete mode 100644 vendor/golang.org/x/text/encoding/japanese/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/korean/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_index.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_parents.go delete mode 100644 vendor/golang.org/x/text/internal/language/gen.go delete mode 100644 vendor/golang.org/x/text/internal/language/gen_common.go delete mode 100644 vendor/golang.org/x/text/language/gen.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go diff --git a/go.mod b/go.mod index 89588a95b3..b60d5f02da 100644 --- a/go.mod +++ b/go.mod @@ -69,7 +69,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a + github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect diff --git a/go.sum b/go.sum index 62f5ec20a3..44e2e59a45 100644 --- a/go.sum +++ b/go.sum @@ -232,10 +232,8 @@ github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwde github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad h1:RPQtR6EeZtD4SGCeJwPde88ZNWa1FCRrkyRvoz05WV8= -github.com/rsksmart/rds-swarm v0.0.0-20191029192525-85b02e96e2ad/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= -github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a h1:wH3H0+fVZPrjTFV1DVypY96/gocO7cXWwRUMQTV6/Y8= -github.com/rsksmart/rds-swarm v0.0.0-20191107190132-24538a14203a/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= +github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 h1:u+awngKkvwHGxPJ4Lk3Yy6A10ThdtyaiQP9OloHK6ao= +github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= diff --git a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go deleted file mode 100644 index d4a9c1b830..0000000000 --- a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -// This file is ignored during the regular build due to the following build tag. -// It is called by go generate and used to automatically generate pre-computed -// tables used to accelerate operations. -// +build ignore - -package main - -import ( - "bytes" - "compress/zlib" - "encoding/base64" - "fmt" - "log" - "os" - - "github.com/btcsuite/btcd/btcec" -) - -func main() { - fi, err := os.Create("secp256k1.go") - if err != nil { - log.Fatal(err) - } - defer fi.Close() - - // Compress the serialized byte points. - serialized := btcec.S256().SerializedBytePoints() - var compressed bytes.Buffer - w := zlib.NewWriter(&compressed) - if _, err := w.Write(serialized); err != nil { - fmt.Println(err) - os.Exit(1) - } - w.Close() - - // Encode the compressed byte points with base64. - encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len())) - base64.StdEncoding.Encode(encoded, compressed.Bytes()) - - fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers") - fmt.Fprintln(fi, "// Use of this source code is governed by an ISC") - fmt.Fprintln(fi, "// license that can be found in the LICENSE file.") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "package btcec") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)") - fmt.Fprintln(fi, "// DO NOT EDIT") - fmt.Fprintln(fi) - fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded)) - - a1, b1, a2, b2 := btcec.S256().EndomorphismVectors() - fmt.Println("The following values are the computed linearly " + - "independent vectors needed to make use of the secp256k1 " + - "endomorphism:") - fmt.Printf("a1: %x\n", a1) - fmt.Printf("b1: %x\n", b1) - fmt.Printf("a2: %x\n", a2) - fmt.Printf("b2: %x\n", b2) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/example_changes.go b/vendor/github.com/docker/docker/pkg/archive/example_changes.go deleted file mode 100644 index 495db809e9..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/example_changes.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build ignore - -// Simple tool to create an archive stream from an old and new directory -// -// By default it will stream the comparison of two temporary directories with junk files -package main - -import ( - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path" - - "github.com/docker/docker/pkg/archive" - "github.com/sirupsen/logrus" -) - -var ( - flDebug = flag.Bool("D", false, "debugging output") - flNewDir = flag.String("newdir", "", "") - flOldDir = flag.String("olddir", "", "") - log = logrus.New() -) - -func main() { - flag.Usage = func() { - fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") - fmt.Printf("%s [OPTIONS]\n", os.Args[0]) - flag.PrintDefaults() - } - flag.Parse() - log.Out = os.Stderr - if (len(os.Getenv("DEBUG")) > 0) || *flDebug { - logrus.SetLevel(logrus.DebugLevel) - } - var newDir, oldDir string - - if len(*flNewDir) == 0 { - var err error - newDir, err = ioutil.TempDir("", "docker-test-newDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(newDir) - if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { - log.Fatal(err) - } - } else { - newDir = *flNewDir - } - - if len(*flOldDir) == 0 { - oldDir, err := ioutil.TempDir("", "docker-test-oldDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(oldDir) - } else { - oldDir = *flOldDir - } - - changes, err := archive.ChangesDirs(newDir, oldDir) - if err != nil { - log.Fatal(err) - } - - a, err := archive.ExportChanges(newDir, changes) - if err != nil { - log.Fatal(err) - } - defer a.Close() - - i, err := io.Copy(os.Stdout, a) - if err != nil && err != io.EOF { - log.Fatal(err) - } - fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) -} - -func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { - fileData := []byte("fooo") - for n := 0; n < numberOfFiles; n++ { - fileName := fmt.Sprintf("file-%d", n) - if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { - return 0, err - } - if makeLinks { - if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { - return 0, err - } - } - } - totalSize := numberOfFiles * len(fileData) - return totalSize, nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore deleted file mode 100644 index 87fea161ba..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -bench_inv -bench_ecdh -bench_sign -bench_verify -bench_schnorr_verify -bench_recover -bench_internal -tests -exhaustive_tests -gen_context -*.exe -*.so -*.a -!.gitignore - -Makefile -configure -.libs/ -Makefile.in -aclocal.m4 -autom4te.cache/ -config.log -config.status -*.tar.gz -*.la -libtool -.deps/ -.dirstamp -*.lo -*.o -*~ -src/libsecp256k1-config.h -src/libsecp256k1-config.h.in -src/ecmult_static_context.h -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/ltmain.sh -build-aux/m4/libtool.m4 -build-aux/m4/lt~obsolete.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/missing -build-aux/compile -build-aux/test-driver -src/stamp-h1 -libsecp256k1.pc diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml deleted file mode 100644 index 2439529242..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml +++ /dev/null @@ -1,69 +0,0 @@ -language: c -sudo: false -addons: - apt: - packages: libgmp-dev -compiler: - - clang - - gcc -cache: - directories: - - src/java/guava/ -env: - global: - - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no - - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar - matrix: - - SCALAR=32bit RECOVERY=yes - - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes - - SCALAR=64bit - - FIELD=64bit RECOVERY=yes - - FIELD=64bit ENDOMORPHISM=yes - - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - - FIELD=64bit ASM=x86_64 - - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - - FIELD=32bit ENDOMORPHISM=yes - - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes - - BIGNUM=no STATICPRECOMPUTATION=no - - BUILD=distcheck - - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - - EXTRAFLAGS=CFLAGS=-O0 - - BUILD=check-java ECDH=yes EXPERIMENTAL=yes -matrix: - fast_finish: true - include: - - compiler: clang - env: HOST=i686-linux-gnu ENDOMORPHISM=yes - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 - - compiler: clang - env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - compiler: gcc - env: HOST=i686-linux-gnu ENDOMORPHISM=yes - addons: - apt: - packages: - - gcc-multilib - - compiler: gcc - env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 -before_install: mkdir -p `dirname $GUAVA_JAR` -install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi -before_script: ./autogen.sh -script: - - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD -os: linux diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING deleted file mode 100644 index 4522a5990e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 Pieter Wuille - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am deleted file mode 100644 index c071fbe275..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am +++ /dev/null @@ -1,177 +0,0 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 - -lib_LTLIBRARIES = libsecp256k1.la -if USE_JNI -JNI_LIB = libsecp256k1_jni.la -noinst_LTLIBRARIES = $(JNI_LIB) -else -JNI_LIB = -endif -include_HEADERS = include/secp256k1.h -noinst_HEADERS = -noinst_HEADERS += src/scalar.h -noinst_HEADERS += src/scalar_4x64.h -noinst_HEADERS += src/scalar_8x32.h -noinst_HEADERS += src/scalar_low.h -noinst_HEADERS += src/scalar_impl.h -noinst_HEADERS += src/scalar_4x64_impl.h -noinst_HEADERS += src/scalar_8x32_impl.h -noinst_HEADERS += src/scalar_low_impl.h -noinst_HEADERS += src/group.h -noinst_HEADERS += src/group_impl.h -noinst_HEADERS += src/num_gmp.h -noinst_HEADERS += src/num_gmp_impl.h -noinst_HEADERS += src/ecdsa.h -noinst_HEADERS += src/ecdsa_impl.h -noinst_HEADERS += src/eckey.h -noinst_HEADERS += src/eckey_impl.h -noinst_HEADERS += src/ecmult.h -noinst_HEADERS += src/ecmult_impl.h -noinst_HEADERS += src/ecmult_const.h -noinst_HEADERS += src/ecmult_const_impl.h -noinst_HEADERS += src/ecmult_gen.h -noinst_HEADERS += src/ecmult_gen_impl.h -noinst_HEADERS += src/num.h -noinst_HEADERS += src/num_impl.h -noinst_HEADERS += src/field_10x26.h -noinst_HEADERS += src/field_10x26_impl.h -noinst_HEADERS += src/field_5x52.h -noinst_HEADERS += src/field_5x52_impl.h -noinst_HEADERS += src/field_5x52_int128_impl.h -noinst_HEADERS += src/field_5x52_asm_impl.h -noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h -noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h -noinst_HEADERS += src/util.h -noinst_HEADERS += src/testrand.h -noinst_HEADERS += src/testrand_impl.h -noinst_HEADERS += src/hash.h -noinst_HEADERS += src/hash_impl.h -noinst_HEADERS += src/field.h -noinst_HEADERS += src/field_impl.h -noinst_HEADERS += src/bench.h -noinst_HEADERS += contrib/lax_der_parsing.h -noinst_HEADERS += contrib/lax_der_parsing.c -noinst_HEADERS += contrib/lax_der_privatekey_parsing.h -noinst_HEADERS += contrib/lax_der_privatekey_parsing.c - -if USE_EXTERNAL_ASM -COMMON_LIB = libsecp256k1_common.la -noinst_LTLIBRARIES = $(COMMON_LIB) -else -COMMON_LIB = -endif - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsecp256k1.pc - -if USE_EXTERNAL_ASM -if USE_ASM_ARM -libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s -endif -endif - -libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) -libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) - -libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c -libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) - -noinst_PROGRAMS = -if USE_BENCHMARK -noinst_PROGRAMS += bench_verify bench_sign bench_internal -bench_verify_SOURCES = src/bench_verify.c -bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -bench_sign_SOURCES = src/bench_sign.c -bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) -bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) -endif - -TESTS = -if USE_TESTS -noinst_PROGRAMS += tests -tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -if !ENABLE_COVERAGE -tests_CPPFLAGS += -DVERIFY -endif -tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -tests_LDFLAGS = -static -TESTS += tests -endif - -if USE_EXHAUSTIVE_TESTS -noinst_PROGRAMS += exhaustive_tests -exhaustive_tests_SOURCES = src/tests_exhaustive.c -exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) -if !ENABLE_COVERAGE -exhaustive_tests_CPPFLAGS += -DVERIFY -endif -exhaustive_tests_LDADD = $(SECP_LIBS) -exhaustive_tests_LDFLAGS = -static -TESTS += exhaustive_tests -endif - -JAVAROOT=src/java -JAVAORG=org/bitcoin -JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar -CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) -JAVA_FILES= \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ - $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java - -if USE_JNI - -$(JAVA_GUAVA): - @echo Guava is missing. Fetch it via: \ - wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) - @false - -.stamp-java: $(JAVA_FILES) - @echo Compiling $^ - $(AM_V_at)$(CLASSPATH_ENV) javac $^ - @touch $@ - -if USE_TESTS - -check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java - $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test - -endif -endif - -if USE_ECMULT_STATIC_PRECOMPUTATION -CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function - -gen_context_OBJECTS = gen_context.o -gen_context_BIN = gen_context$(BUILD_EXEEXT) -gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ - -$(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ - -$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h -$(tests_OBJECTS): src/ecmult_static_context.h -$(bench_internal_OBJECTS): src/ecmult_static_context.h - -src/ecmult_static_context.h: $(gen_context_BIN) - ./$(gen_context_BIN) - -CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java -endif - -EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) - -if ENABLE_MODULE_ECDH -include src/modules/ecdh/Makefile.am.include -endif - -if ENABLE_MODULE_RECOVERY -include src/modules/recovery/Makefile.am.include -endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md deleted file mode 100644 index 8cd344ea81..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md +++ /dev/null @@ -1,61 +0,0 @@ -libsecp256k1 -============ - -[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) - -Optimized C library for EC operations on curve secp256k1. - -This library is a work in progress and is being used to research best practices. Use at your own risk. - -Features: -* secp256k1 ECDSA signing/verification and key generation. -* Adding/multiplying private/public keys. -* Serialization/parsing of private keys, public keys, signatures. -* Constant time, constant memory access signing and pubkey generation. -* Derandomized DSA (via RFC6979 or with a caller provided function.) -* Very efficient implementation. - -Implementation details ----------------------- - -* General - * No runtime heap allocation. - * Extensive testing infrastructure. - * Structured to facilitate review and analysis. - * Intended to be portable to any system with a C89 compiler and uint64_t support. - * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") -* Field operations - * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). - * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). - * Using 10 26-bit limbs. - * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). -* Scalar operations - * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. - * Using 4 64-bit limbs (relying on __int128 support in the compiler). - * Using 8 32-bit limbs. -* Group operations - * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). - * Use addition between points in Jacobian and affine coordinates where possible. - * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. - * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. -* Point multiplication for verification (a*P + b*G). - * Use wNAF notation for point multiplicands. - * Use a much larger window for multiples of G, using precomputed multiples. - * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. - * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. -* Point multiplication for signing - * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. - * Access the table with branch-free conditional moves so memory access is uniform. - * No data-dependent branches - * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. - -Build steps ------------ - -libsecp256k1 is built using autotools: - - $ ./autogen.sh - $ ./configure - $ make - $ ./tests - $ sudo make install # optional diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO deleted file mode 100644 index a300e1c5eb..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* Unit tests for fieldelem/groupelem, including ones intended to - trigger fieldelem's boundary cases. -* Complete constant-time operations for signing/keygen diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh deleted file mode 100644 index 65286b9353..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -set -e -autoreconf -if --warnings=all diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 deleted file mode 100644 index 1fc3627614..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 +++ /dev/null @@ -1,140 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_JNI_INCLUDE_DIR -# -# DESCRIPTION -# -# AX_JNI_INCLUDE_DIR finds include directories needed for compiling -# programs using the JNI interface. -# -# JNI include directories are usually in the Java distribution. This is -# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in -# that order. When this macro completes, a list of directories is left in -# the variable JNI_INCLUDE_DIRS. -# -# Example usage follows: -# -# AX_JNI_INCLUDE_DIR -# -# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS -# do -# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" -# done -# -# If you want to force a specific compiler: -# -# - at the configure.in level, set JAVAC=yourcompiler before calling -# AX_JNI_INCLUDE_DIR -# -# - at the configure level, setenv JAVAC -# -# Note: This macro can work with the autoconf M4 macros for Java programs. -# This particular macro is not part of the original set of macros. -# -# LICENSE -# -# Copyright (c) 2008 Don Anderson -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 10 - -AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) -AC_DEFUN([AX_JNI_INCLUDE_DIR],[ - -JNI_INCLUDE_DIRS="" - -if test "x$JAVA_HOME" != x; then - _JTOPDIR="$JAVA_HOME" -else - if test "x$JAVAC" = x; then - JAVAC=javac - fi - AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) - if test "x$_ACJNI_JAVAC" = xno; then - AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) - fi - _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") - _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` -fi - -case "$host_os" in - darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - _JINC="$_JTOPDIR/Headers";; - *) _JINC="$_JTOPDIR/include";; -esac -_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) -_AS_ECHO_LOG([_JINC=$_JINC]) - -# On Mac OS X 10.6.4, jni.h is a symlink: -# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h -# -> ../../CurrentJDK/Headers/jni.h. - -AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, -[ -if test -f "$_JINC/jni.h"; then - ac_cv_jni_header_path="$_JINC" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" -else - _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - if test -f "$_JTOPDIR/include/jni.h"; then - ac_cv_jni_header_path="$_JTOPDIR/include" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" - else - ac_cv_jni_header_path=none - fi -fi -]) - - - -# get the likely subdirectories for system specific java includes -case "$host_os" in -bsdi*) _JNI_INC_SUBDIRS="bsdos";; -darwin*) _JNI_INC_SUBDIRS="darwin";; -freebsd*) _JNI_INC_SUBDIRS="freebsd";; -linux*) _JNI_INC_SUBDIRS="linux genunix";; -osf*) _JNI_INC_SUBDIRS="alpha";; -solaris*) _JNI_INC_SUBDIRS="solaris";; -mingw*) _JNI_INC_SUBDIRS="win32";; -cygwin*) _JNI_INC_SUBDIRS="win32";; -*) _JNI_INC_SUBDIRS="genunix";; -esac - -if test "x$ac_cv_jni_header_path" != "xnone"; then - # add any subdirectories that are present - for JINCSUBDIR in $_JNI_INC_SUBDIRS - do - if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" - fi - done -fi -]) - -# _ACJNI_FOLLOW_SYMLINKS -# Follows symbolic links on , -# finally setting variable _ACJNI_FOLLOWED -# ---------------------------------------- -AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ -# find the include directory relative to the javac executable -_cur="$1" -while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do - AC_MSG_CHECKING([symlink for $_cur]) - _slink=`ls -ld "$_cur" | sed 's/.* -> //'` - case "$_slink" in - /*) _cur="$_slink";; - # 'X' avoids triggering unwanted echo options. - *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; - esac - AC_MSG_RESULT([$_cur]) -done -_ACJNI_FOLLOWED="$_cur" -])# _ACJNI diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 deleted file mode 100644 index 77fd346a79..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 +++ /dev/null @@ -1,125 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_CC_FOR_BUILD -# -# DESCRIPTION -# -# This macro searches for a C compiler that generates native executables, -# that is a C compiler that surely is not a cross-compiler. This can be -# useful if you have to generate source code at compile-time like for -# example GCC does. -# -# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything -# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). -# The value of these variables can be overridden by the user by specifying -# a compiler with an environment variable (like you do for standard CC). -# -# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object -# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if -# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are -# substituted in the Makefile. -# -# LICENSE -# -# Copyright (c) 2008 Paolo Bonzini -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 8 - -AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) -AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_CPP])dnl -AC_REQUIRE([AC_EXEEXT])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl - -dnl Use the standard macros, but make them use other variable names -dnl -pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl -pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl -pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl -pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl -pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl -pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl -pushdef([ac_cv_objext], ac_cv_build_objext)dnl -pushdef([ac_exeext], ac_build_exeext)dnl -pushdef([ac_objext], ac_build_objext)dnl -pushdef([CC], CC_FOR_BUILD)dnl -pushdef([CPP], CPP_FOR_BUILD)dnl -pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl -pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl -pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl -pushdef([host], build)dnl -pushdef([host_alias], build_alias)dnl -pushdef([host_cpu], build_cpu)dnl -pushdef([host_vendor], build_vendor)dnl -pushdef([host_os], build_os)dnl -pushdef([ac_cv_host], ac_cv_build)dnl -pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl -pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl -pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl -pushdef([ac_cv_host_os], ac_cv_build_os)dnl -pushdef([ac_cpp], ac_build_cpp)dnl -pushdef([ac_compile], ac_build_compile)dnl -pushdef([ac_link], ac_build_link)dnl - -save_cross_compiling=$cross_compiling -save_ac_tool_prefix=$ac_tool_prefix -cross_compiling=no -ac_tool_prefix= - -AC_PROG_CC -AC_PROG_CPP -AC_EXEEXT - -ac_tool_prefix=$save_ac_tool_prefix -cross_compiling=$save_cross_compiling - -dnl Restore the old definitions -dnl -popdef([ac_link])dnl -popdef([ac_compile])dnl -popdef([ac_cpp])dnl -popdef([ac_cv_host_os])dnl -popdef([ac_cv_host_vendor])dnl -popdef([ac_cv_host_cpu])dnl -popdef([ac_cv_host_alias])dnl -popdef([ac_cv_host])dnl -popdef([host_os])dnl -popdef([host_vendor])dnl -popdef([host_cpu])dnl -popdef([host_alias])dnl -popdef([host])dnl -popdef([LDFLAGS])dnl -popdef([CPPFLAGS])dnl -popdef([CFLAGS])dnl -popdef([CPP])dnl -popdef([CC])dnl -popdef([ac_objext])dnl -popdef([ac_exeext])dnl -popdef([ac_cv_objext])dnl -popdef([ac_cv_exeext])dnl -popdef([ac_cv_prog_cc_g])dnl -popdef([ac_cv_prog_cc_cross])dnl -popdef([ac_cv_prog_cc_works])dnl -popdef([ac_cv_prog_gcc])dnl -popdef([ac_cv_prog_CPP])dnl - -dnl Finally, set Makefile variables -dnl -BUILD_EXEEXT=$ac_build_exeext -BUILD_OBJEXT=$ac_build_objext -AC_SUBST(BUILD_EXEEXT)dnl -AC_SUBST(BUILD_OBJEXT)dnl -AC_SUBST([CFLAGS_FOR_BUILD])dnl -AC_SUBST([CPPFLAGS_FOR_BUILD])dnl -AC_SUBST([LDFLAGS_FOR_BUILD])dnl -]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 deleted file mode 100644 index b74acb8c13..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 +++ /dev/null @@ -1,69 +0,0 @@ -dnl libsecp25k1 helper checks -AC_DEFUN([SECP_INT128_CHECK],[ -has_int128=$ac_cv_type___int128 -]) - -dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. -AC_DEFUN([SECP_64BIT_ASM_CHECK],[ -AC_MSG_CHECKING(for x86_64 assembly availability) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include ]],[[ - uint64_t a = 11, tmp; - __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); - ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) -AC_MSG_RESULT([$has_64bit_asm]) -]) - -dnl -AC_DEFUN([SECP_OPENSSL_CHECK],[ - has_libcrypto=no - m4_ifdef([PKG_CHECK_MODULES],[ - PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) - if test x"$has_libcrypto" = x"yes"; then - TEMP_LIBS="$LIBS" - LIBS="$LIBS $CRYPTO_LIBS" - AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) - LIBS="$TEMP_LIBS" - fi - ]) - if test x$has_libcrypto = xno; then - AC_CHECK_HEADER(openssl/crypto.h,[ - AC_CHECK_LIB(crypto, main,[ - has_libcrypto=yes - CRYPTO_LIBS=-lcrypto - AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed]) - ]) - ]) - LIBS= - fi -if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then - AC_MSG_CHECKING(for EC functions in libcrypto) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - #include - #include ]],[[ - EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); - ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); - ECDSA_verify(0, NULL, 0, NULL, 0, eckey); - EC_KEY_free(eckey); - ECDSA_SIG *sig_openssl; - sig_openssl = ECDSA_SIG_new(); - (void)sig_openssl->r; - ECDSA_SIG_free(sig_openssl); - ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) - AC_MSG_RESULT([$has_openssl_ec]) -fi -]) - -dnl -AC_DEFUN([SECP_GMP_CHECK],[ -if test x"$has_gmp" != x"yes"; then - CPPFLAGS_TEMP="$CPPFLAGS" - CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" - LIBS_TEMP="$LIBS" - LIBS="$GMP_LIBS $LIBS" - AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) - CPPFLAGS="$CPPFLAGS_TEMP" - LIBS="$LIBS_TEMP" -fi -]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac deleted file mode 100644 index e5fcbcb4ed..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac +++ /dev/null @@ -1,493 +0,0 @@ -AC_PREREQ([2.60]) -AC_INIT([libsecp256k1],[0.1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) -AC_CANONICAL_HOST -AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) -AH_TOP([#define LIBSECP256K1_CONFIG_H]) -AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) -AM_INIT_AUTOMAKE([foreign subdir-objects]) -LT_INIT - -dnl make the compilation flags quiet unless V=1 is used -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -PKG_PROG_PKG_CONFIG - -AC_PATH_TOOL(AR, ar) -AC_PATH_TOOL(RANLIB, ranlib) -AC_PATH_TOOL(STRIP, strip) -AX_PROG_CC_FOR_BUILD - -if test "x$CFLAGS" = "x"; then - CFLAGS="-g" -fi - -AM_PROG_CC_C_O - -AC_PROG_CC_C89 -if test x"$ac_cv_prog_cc_c89" = x"no"; then - AC_MSG_ERROR([c89 compiler support required]) -fi -AM_PROG_AS - -case $host_os in - *darwin*) - if test x$cross_compiling != xyes; then - AC_PATH_PROG([BREW],brew,) - if test x$BREW != x; then - dnl These Homebrew packages may be keg-only, meaning that they won't be found - dnl in expected paths because they may conflict with system files. Ask - dnl Homebrew where each one is located, then adjust paths accordingly. - - openssl_prefix=`$BREW --prefix openssl 2>/dev/null` - gmp_prefix=`$BREW --prefix gmp 2>/dev/null` - if test x$openssl_prefix != x; then - PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH - fi - if test x$gmp_prefix != x; then - GMP_CPPFLAGS="-I$gmp_prefix/include" - GMP_LIBS="-L$gmp_prefix/lib" - fi - else - AC_PATH_PROG([PORT],port,) - dnl if homebrew isn't installed and macports is, add the macports default paths - dnl as a last resort. - if test x$PORT != x; then - CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" - fi - fi - fi - ;; -esac - -CFLAGS="$CFLAGS -W" - -warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings" -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $warn_CFLAGS" -AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fvisibility=hidden" -AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), - [use_benchmark=$enableval], - [use_benchmark=no]) - -AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), - [enable_coverage=$enableval], - [enable_coverage=no]) - -AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), - [use_tests=$enableval], - [use_tests=yes]) - -AC_ARG_ENABLE(openssl_tests, - AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), - [enable_openssl_tests=$enableval], - [enable_openssl_tests=auto]) - -AC_ARG_ENABLE(experimental, - AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), - [use_experimental=$enableval], - [use_experimental=no]) - -AC_ARG_ENABLE(exhaustive_tests, - AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), - [use_exhaustive_tests=$enableval], - [use_exhaustive_tests=yes]) - -AC_ARG_ENABLE(endomorphism, - AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), - [use_endomorphism=$enableval], - [use_endomorphism=no]) - -AC_ARG_ENABLE(ecmult_static_precomputation, - AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), - [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=auto]) - -AC_ARG_ENABLE(module_ecdh, - AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), - [enable_module_ecdh=$enableval], - [enable_module_ecdh=no]) - -AC_ARG_ENABLE(module_recovery, - AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), - [enable_module_recovery=$enableval], - [enable_module_recovery=no]) - -AC_ARG_ENABLE(jni, - AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), - [use_jni=$enableval], - [use_jni=auto]) - -AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], -[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) - -AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], -[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) - -AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], -[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) - -AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] -[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) - -AC_CHECK_TYPES([__int128]) - -AC_MSG_CHECKING([for __builtin_expect]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], - [ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ], - [ AC_MSG_RESULT([no]) - ]) - -if test x"$enable_coverage" = x"yes"; then - AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) - CFLAGS="$CFLAGS -O0 --coverage" - LDFLAGS="--coverage" -else - CFLAGS="$CFLAGS -O3" -fi - -if test x"$use_ecmult_static_precomputation" != x"no"; then - save_cross_compiling=$cross_compiling - cross_compiling=no - TEMP_CC="$CC" - CC="$CC_FOR_BUILD" - AC_MSG_CHECKING([native compiler: ${CC_FOR_BUILD}]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [return 0])], - [working_native_cc=yes], - [working_native_cc=no],[dnl]) - CC="$TEMP_CC" - cross_compiling=$save_cross_compiling - - if test x"$working_native_cc" = x"no"; then - set_precomp=no - if test x"$use_ecmult_static_precomputation" = x"yes"; then - AC_MSG_ERROR([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) - else - AC_MSG_RESULT([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) - fi - else - AC_MSG_RESULT([ok]) - set_precomp=yes - fi -else - set_precomp=no -fi - -if test x"$req_asm" = x"auto"; then - SECP_64BIT_ASM_CHECK - if test x"$has_64bit_asm" = x"yes"; then - set_asm=x86_64 - fi - if test x"$set_asm" = x; then - set_asm=no - fi -else - set_asm=$req_asm - case $set_asm in - x86_64) - SECP_64BIT_ASM_CHECK - if test x"$has_64bit_asm" != x"yes"; then - AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) - fi - ;; - arm) - ;; - no) - ;; - *) - AC_MSG_ERROR([invalid assembly optimization selection]) - ;; - esac -fi - -if test x"$req_field" = x"auto"; then - if test x"set_asm" = x"x86_64"; then - set_field=64bit - fi - if test x"$set_field" = x; then - SECP_INT128_CHECK - if test x"$has_int128" = x"yes"; then - set_field=64bit - fi - fi - if test x"$set_field" = x; then - set_field=32bit - fi -else - set_field=$req_field - case $set_field in - 64bit) - if test x"$set_asm" != x"x86_64"; then - SECP_INT128_CHECK - if test x"$has_int128" != x"yes"; then - AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available]) - fi - fi - ;; - 32bit) - ;; - *) - AC_MSG_ERROR([invalid field implementation selection]) - ;; - esac -fi - -if test x"$req_scalar" = x"auto"; then - SECP_INT128_CHECK - if test x"$has_int128" = x"yes"; then - set_scalar=64bit - fi - if test x"$set_scalar" = x; then - set_scalar=32bit - fi -else - set_scalar=$req_scalar - case $set_scalar in - 64bit) - SECP_INT128_CHECK - if test x"$has_int128" != x"yes"; then - AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available]) - fi - ;; - 32bit) - ;; - *) - AC_MSG_ERROR([invalid scalar implementation selected]) - ;; - esac -fi - -if test x"$req_bignum" = x"auto"; then - SECP_GMP_CHECK - if test x"$has_gmp" = x"yes"; then - set_bignum=gmp - fi - - if test x"$set_bignum" = x; then - set_bignum=no - fi -else - set_bignum=$req_bignum - case $set_bignum in - gmp) - SECP_GMP_CHECK - if test x"$has_gmp" != x"yes"; then - AC_MSG_ERROR([gmp bignum explicitly requested but libgmp not available]) - fi - ;; - no) - ;; - *) - AC_MSG_ERROR([invalid bignum implementation selection]) - ;; - esac -fi - -# select assembly optimization -use_external_asm=no - -case $set_asm in -x86_64) - AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) - ;; -arm) - use_external_asm=yes - ;; -no) - ;; -*) - AC_MSG_ERROR([invalid assembly optimizations]) - ;; -esac - -# select field implementation -case $set_field in -64bit) - AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) - ;; -32bit) - AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) - ;; -*) - AC_MSG_ERROR([invalid field implementation]) - ;; -esac - -# select bignum implementation -case $set_bignum in -gmp) - AC_DEFINE(HAVE_LIBGMP, 1, [Define this symbol if libgmp is installed]) - AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation for num]) - AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation]) - AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation]) - ;; -no) - AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation]) - AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation]) - AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation]) - ;; -*) - AC_MSG_ERROR([invalid bignum implementation]) - ;; -esac - -#select scalar implementation -case $set_scalar in -64bit) - AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) - ;; -32bit) - AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) - ;; -*) - AC_MSG_ERROR([invalid scalar implementation]) - ;; -esac - -if test x"$use_tests" = x"yes"; then - SECP_OPENSSL_CHECK - if test x"$has_openssl_ec" = x"yes"; then - if test x"$enable_openssl_tests" != x"no"; then - AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) - SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" - SECP_TEST_LIBS="$CRYPTO_LIBS" - - case $host in - *mingw*) - SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" - ;; - esac - fi - else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) - fi - fi -else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) - fi -fi - -if test x"$use_jni" != x"no"; then - AX_JNI_INCLUDE_DIR - have_jni_dependencies=yes - if test x"$enable_module_ecdh" = x"no"; then - have_jni_dependencies=no - fi - if test "x$JNI_INCLUDE_DIRS" = "x"; then - have_jni_dependencies=no - fi - if test "x$have_jni_dependencies" = "xno"; then - if test x"$use_jni" = x"yes"; then - AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) - fi - AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) - use_jni=no - else - use_jni=yes - for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do - JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" - done - fi -fi - -if test x"$set_bignum" = x"gmp"; then - SECP_LIBS="$SECP_LIBS $GMP_LIBS" - SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" -fi - -if test x"$use_endomorphism" = x"yes"; then - AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) -fi - -if test x"$set_precomp" = x"yes"; then - AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) -fi - -if test x"$enable_module_ecdh" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) -fi - -if test x"$enable_module_recovery" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) -fi - -AC_C_BIGENDIAN() - -if test x"$use_external_asm" = x"yes"; then - AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) -fi - -AC_MSG_NOTICE([Using static precomputation: $set_precomp]) -AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) -AC_MSG_NOTICE([Using field implementation: $set_field]) -AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) -AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) -AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) -AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) -AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) -AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) -AC_MSG_NOTICE([Using jni: $use_jni]) - -if test x"$enable_experimental" = x"yes"; then - AC_MSG_NOTICE([******]) - AC_MSG_NOTICE([WARNING: experimental build]) - AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) - AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) - AC_MSG_NOTICE([******]) -else - if test x"$enable_module_ecdh" = x"yes"; then - AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) - fi - if test x"$set_asm" = x"arm"; then - AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) - fi -fi - -AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) -AC_CONFIG_FILES([Makefile libsecp256k1.pc]) -AC_SUBST(JNI_INCLUDES) -AC_SUBST(SECP_INCLUDES) -AC_SUBST(SECP_LIBS) -AC_SUBST(SECP_TEST_LIBS) -AC_SUBST(SECP_TEST_INCLUDES) -AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) -AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) -AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) -AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) -AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) -AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) -AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) -AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) - -dnl make sure nothing new is exported so that we don't break the cache -PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" -unset PKG_CONFIG_PATH -PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" - -AC_OUTPUT diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c deleted file mode 100644 index 5b141a9948..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c +++ /dev/null @@ -1,150 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "lax_der_parsing.h" - -int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - size_t rpos, rlen, spos, slen; - size_t pos = 0; - size_t lenbyte; - unsigned char tmpsig[64] = {0}; - int overflow = 0; - - /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - - /* Sequence tag byte */ - if (pos == inputlen || input[pos] != 0x30) { - return 0; - } - pos++; - - /* Sequence length bytes */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - pos += lenbyte; - } - - /* Integer tag byte for R */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for R */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - rlen = 0; - while (lenbyte > 0) { - rlen = (rlen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - rlen = lenbyte; - } - if (rlen > inputlen - pos) { - return 0; - } - rpos = pos; - pos += rlen; - - /* Integer tag byte for S */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for S */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - slen = 0; - while (lenbyte > 0) { - slen = (slen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - slen = lenbyte; - } - if (slen > inputlen - pos) { - return 0; - } - spos = pos; - pos += slen; - - /* Ignore leading zeroes in R */ - while (rlen > 0 && input[rpos] == 0) { - rlen--; - rpos++; - } - /* Copy R value */ - if (rlen > 32) { - overflow = 1; - } else { - memcpy(tmpsig + 32 - rlen, input + rpos, rlen); - } - - /* Ignore leading zeroes in S */ - while (slen > 0 && input[spos] == 0) { - slen--; - spos++; - } - /* Copy S value */ - if (slen > 32) { - overflow = 1; - } else { - memcpy(tmpsig + 64 - slen, input + spos, slen); - } - - if (!overflow) { - overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - if (overflow) { - memset(tmpsig, 0, 64); - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - return 1; -} - diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h deleted file mode 100644 index 6d27871a7c..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h +++ /dev/null @@ -1,91 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file defines a function that parses DER with various errors and - * violations. This is not a part of the library itself, because the allowed - * violations are chosen arbitrarily and do not follow or establish any - * standard. - * - * In many places it matters that different implementations do not only accept - * the same set of valid signatures, but also reject the same set of signatures. - * The only means to accomplish that is by strictly obeying a standard, and not - * accepting anything else. - * - * Nonetheless, sometimes there is a need for compatibility with systems that - * use signatures which do not strictly obey DER. The snippet below shows how - * certain violations are easily supported. You may need to adapt it. - * - * Do not use this for new systems. Use well-defined DER or compact signatures - * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and - * secp256k1_ecdsa_signature_parse_compact). - * - * The supported violations are: - * - All numbers are parsed as nonnegative integers, even though X.609-0207 - * section 8.3.3 specifies that integers are always encoded as two's - * complement. - * - Integers can have length 0, even though section 8.3.1 says they can't. - * - Integers with overly long padding are accepted, violation section - * 8.3.2. - * - 127-byte long length descriptors are accepted, even though section - * 8.1.3.5.c says that they are not. - * - Trailing garbage data inside or after the signature is ignored. - * - The length descriptor of the sequence is ignored. - * - * Compared to for example OpenSSL, many violations are NOT supported: - * - Using overly long tag descriptors for the sequence or integers inside, - * violating section 8.1.2.2. - * - Encoding primitive integers as constructed values, violating section - * 8.3.1. - */ - -#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ -#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ - -#include - -# ifdef __cplusplus -extern "C" { -# endif - -/** Parse a signature in "lax DER" format - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. In addition, it will accept signatures - * which violate the DER spec in various ways. Its purpose is to allow - * validation of the Bitcoin blockchain, which includes non-DER signatures - * from before the network rules were updated to enforce DER. Note that - * the set of supported violations is a strict subset of what OpenSSL will - * accept. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is - * guaranteed to fail for every message and public key. - */ -int ecdsa_signature_parse_der_lax( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c deleted file mode 100644 index c2e63b4b8d..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c +++ /dev/null @@ -1,113 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "lax_der_privatekey_parsing.h" - -int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { - const unsigned char *end = privkey + privkeylen; - int lenb = 0; - int len = 0; - memset(out32, 0, 32); - /* sequence header */ - if (end < privkey+1 || *privkey != 0x30) { - return 0; - } - privkey++; - /* sequence length constructor */ - if (end < privkey+1 || !(*privkey & 0x80)) { - return 0; - } - lenb = *privkey & ~0x80; privkey++; - if (lenb < 1 || lenb > 2) { - return 0; - } - if (end < privkey+lenb) { - return 0; - } - /* sequence length */ - len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); - privkey += lenb; - if (end < privkey+len) { - return 0; - } - /* sequence element 0: version number (=1) */ - if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { - return 0; - } - privkey += 3; - /* sequence element 1: octet string, up to 32 bytes */ - if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { - return 0; - } - memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); - if (!secp256k1_ec_seckey_verify(ctx, out32)) { - memset(out32, 0, 32); - return 0; - } - return 1; -} - -int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { - secp256k1_pubkey pubkey; - size_t pubkeylen = 0; - if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { - *privkeylen = 0; - return 0; - } - if (compressed) { - static const unsigned char begin[] = { - 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 33; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } else { - static const unsigned char begin[] = { - 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, - 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, - 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 65; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } - return 1; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h deleted file mode 100644 index 2fd088f8ab..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h +++ /dev/null @@ -1,90 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file contains code snippets that parse DER private keys with - * various errors and violations. This is not a part of the library - * itself, because the allowed violations are chosen arbitrarily and - * do not follow or establish any standard. - * - * It also contains code to serialize private keys in a compatible - * manner. - * - * These functions are meant for compatibility with applications - * that require BER encoded keys. When working with secp256k1-specific - * code, the simple 32-byte private keys normally used by the - * library are sufficient. - */ - -#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ -#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ - -#include - -# ifdef __cplusplus -extern "C" { -# endif - -/** Export a private key in DER format. - * - * Returns: 1 if the private key was valid. - * Args: ctx: pointer to a context object, initialized for signing (cannot - * be NULL) - * Out: privkey: pointer to an array for storing the private key in BER. - * Should have space for 279 bytes, and cannot be NULL. - * privkeylen: Pointer to an int where the length of the private key in - * privkey will be stored. - * In: seckey: pointer to a 32-byte secret key to export. - * compressed: 1 if the key should be exported in - * compressed format, 0 otherwise - * - * This function is purely meant for compatibility with applications that - * require BER encoded keys. When working with secp256k1-specific code, the - * simple 32-byte private keys are sufficient. - * - * Note that this function does not guarantee correct DER output. It is - * guaranteed to be parsable by secp256k1_ec_privkey_import_der - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( - const secp256k1_context* ctx, - unsigned char *privkey, - size_t *privkeylen, - const unsigned char *seckey, - int compressed -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Import a private key in DER format. - * Returns: 1 if a private key was extracted. - * Args: ctx: pointer to a context object (cannot be NULL). - * Out: seckey: pointer to a 32-byte array for storing the private key. - * (cannot be NULL). - * In: privkey: pointer to a private key in DER format (cannot be NULL). - * privkeylen: length of the DER private key pointed to be privkey. - * - * This function will accept more than just strict DER, and even allow some BER - * violations. The public key stored inside the DER-encoded private key is not - * verified for correctness, nor are the curve parameters. Use this function - * only if you know in advance it is supposed to contain a secp256k1 private - * key. - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *privkey, - size_t privkeylen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h deleted file mode 100644 index f268e309d0..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h +++ /dev/null @@ -1,577 +0,0 @@ -#ifndef _SECP256K1_ -# define _SECP256K1_ - -# ifdef __cplusplus -extern "C" { -# endif - -#include - -/* These rules specify the order of arguments in API calls: - * - * 1. Context pointers go first, followed by output arguments, combined - * output/input arguments, and finally input-only arguments. - * 2. Array lengths always immediately the follow the argument whose length - * they describe, even if this violates rule 1. - * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated - * later go first. This means: signatures, public nonces, private nonces, - * messages, public keys, secret keys, tweaks. - * 4. Arguments that are not data pointers go last, from more complex to less - * complex: function pointers, algorithm names, messages, void pointers, - * counts, flags, booleans. - * 5. Opaque data pointers follow the function pointer they are to be passed to. - */ - -/** Opaque data structure that holds context information (precomputed tables etc.). - * - * The purpose of context structures is to cache large precomputed data tables - * that are expensive to construct, and also to maintain the randomization data - * for blinding. - * - * Do not create a new context object for each operation, as construction is - * far slower than all other API calls (~100 times slower than an ECDSA - * verification). - * - * A constructed context can safely be used from multiple threads - * simultaneously, but API call that take a non-const pointer to a context - * need exclusive access to it. In particular this is the case for - * secp256k1_context_destroy and secp256k1_context_randomize. - * - * Regarding randomization, either do it once at creation time (in which case - * you do not need any locking for the other calls), or use a read-write lock. - */ -typedef struct secp256k1_context_struct secp256k1_context; - -/** Opaque data structure that holds a parsed and valid public key. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. - */ -typedef struct { - unsigned char data[64]; -} secp256k1_pubkey; - -/** Opaque data structured that holds a parsed ECDSA signature. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_serialize_* functions. - */ -typedef struct { - unsigned char data[64]; -} secp256k1_ecdsa_signature; - -/** A pointer to a function to deterministically generate a nonce. - * - * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. - * Out: nonce32: pointer to a 32-byte array to be filled by the function. - * In: msg32: the 32-byte message hash being verified (will not be NULL) - * key32: pointer to a 32-byte secret key (will not be NULL) - * algo16: pointer to a 16-byte array describing the signature - * algorithm (will be NULL for ECDSA for compatibility). - * data: Arbitrary data pointer that is passed through. - * attempt: how many iterations we have tried to find a nonce. - * This will almost always be 0, but different attempt values - * are required to result in a different nonce. - * - * Except for test cases, this function should compute some cryptographic hash of - * the message, the algorithm, the key and the attempt. - */ -typedef int (*secp256k1_nonce_function)( - unsigned char *nonce32, - const unsigned char *msg32, - const unsigned char *key32, - const unsigned char *algo16, - void *data, - unsigned int attempt -); - -# if !defined(SECP256K1_GNUC_PREREQ) -# if defined(__GNUC__)&&defined(__GNUC_MINOR__) -# define SECP256K1_GNUC_PREREQ(_maj,_min) \ - ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) -# else -# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 -# endif -# endif - -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(2,7) -# define SECP256K1_INLINE __inline__ -# elif (defined(_MSC_VER)) -# define SECP256K1_INLINE __inline -# else -# define SECP256K1_INLINE -# endif -# else -# define SECP256K1_INLINE inline -# endif - -#ifndef SECP256K1_API -# if defined(_WIN32) -# ifdef SECP256K1_BUILD -# define SECP256K1_API __declspec(dllexport) -# else -# define SECP256K1_API -# endif -# elif defined(__GNUC__) && defined(SECP256K1_BUILD) -# define SECP256K1_API __attribute__ ((visibility ("default"))) -# else -# define SECP256K1_API -# endif -#endif - -/**Warning attributes - * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out - * some paranoid null checks. */ -# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) -# else -# define SECP256K1_WARN_UNUSED_RESULT -# endif -# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) -# else -# define SECP256K1_ARG_NONNULL(_x) -# endif - -/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ -#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) -#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) -#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) -/** The higher bits contain the actual data. Do not use directly. */ -#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) -#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) -#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) - -/** Flags to pass to secp256k1_context_create. */ -#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) -#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) -#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) - -/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ -#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) -#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) - -/** Create a secp256k1 context object. - * - * Returns: a newly created context object. - * In: flags: which parts of the context to initialize. - */ -SECP256K1_API secp256k1_context* secp256k1_context_create( - unsigned int flags -) SECP256K1_WARN_UNUSED_RESULT; - -/** Copies a secp256k1 context object. - * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (cannot be NULL) - */ -SECP256K1_API secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; - -/** Destroy a secp256k1 context object. - * - * The context pointer may not be used afterwards. - * Args: ctx: an existing context to destroy (cannot be NULL) - */ -SECP256K1_API void secp256k1_context_destroy( - secp256k1_context* ctx -); - -/** Set a callback function to be called when an illegal argument is passed to - * an API call. It will only trigger for violations that are mentioned - * explicitly in the header. - * - * The philosophy is that these shouldn't be dealt with through a - * specific return value, as calling code should not have branches to deal with - * the case that this code itself is broken. - * - * On the other hand, during debug stage, one would want to be informed about - * such mistakes, and the default (crashing) may be inadvisable. - * When this callback is triggered, the API function called is guaranteed not - * to cause a crash, though its return value and output arguments are - * undefined. - * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an illegal argument is - * passed to the API, taking a message and an opaque pointer - * (NULL restores a default handler that calls abort). - * data: the opaque pointer to pass to fun above. - */ -SECP256K1_API void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -) SECP256K1_ARG_NONNULL(1); - -/** Set a callback function to be called when an internal consistency check - * fails. The default is crashing. - * - * This can only trigger in case of a hardware failure, miscompilation, - * memory corruption, serious bug in the library, or other error would can - * otherwise result in undefined behaviour. It will not trigger due to mere - * incorrect usage of the API (see secp256k1_context_set_illegal_callback - * for that). After this callback returns, anything may happen, including - * crashing. - * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an internal error occurs, - * taking a message and an opaque pointer (NULL restores a default - * handler that calls abort). - * data: the opaque pointer to pass to fun above. - */ -SECP256K1_API void secp256k1_context_set_error_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -) SECP256K1_ARG_NONNULL(1); - -/** Parse a variable-length public key into the pubkey object. - * - * Returns: 1 if the public key was fully valid. - * 0 if the public key could not be parsed or is invalid. - * Args: ctx: a secp256k1 context object. - * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a - * parsed version of input. If not, its value is undefined. - * In: input: pointer to a serialized public key - * inputlen: length of the array pointed to by input - * - * This function supports parsing compressed (33 bytes, header byte 0x02 or - * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header - * byte 0x06 or 0x07) format public keys. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a pubkey object into a serialized byte sequence. - * - * Returns: 1 always. - * Args: ctx: a secp256k1 context object. - * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if - * compressed==1) byte array to place the serialized key - * in. - * In/Out: outputlen: a pointer to an integer which is initially set to the - * size of output, and is overwritten with the written - * size. - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key. - * flags: SECP256K1_EC_COMPRESSED if serialization should be in - * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. - */ -SECP256K1_API int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_pubkey* pubkey, - unsigned int flags -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Parse an ECDSA signature in compact (64 bytes) format. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to the 64-byte array to parse - * - * The signature must consist of a 32-byte big endian R value, followed by a - * 32-byte big endian S value. If R or S fall outside of [0..order-1], the - * encoding is invalid. R and S with value 0 are allowed in the encoding. - * - * After the call, sig will always be initialized. If parsing failed or R or - * S are zero, the resulting sig value is guaranteed to fail validation for any - * message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input64 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse a DER ECDSA signature. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is - * guaranteed to fail for every message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in DER format. - * - * Returns: 1 if enough space was available to serialize, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: output: a pointer to an array to store the DER serialization - * In/Out: outputlen: a pointer to a length integer. Initially, this integer - * should be set to the length of output. After the call - * it will be set to the length of the serialization (even - * if 0 was returned). - * In: sig: a pointer to an initialized signature object - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_ecdsa_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Serialize an ECDSA signature in compact (64 byte) format. - * - * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array to store the compact serialization - * In: sig: a pointer to an initialized signature object - * - * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, - unsigned char *output64, - const secp256k1_ecdsa_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Verify an ECDSA signature. - * - * Returns: 1: correct signature - * 0: incorrect or unparseable signature - * Args: ctx: a secp256k1 context object, initialized for verification. - * In: sig: the signature being verified (cannot be NULL) - * msg32: the 32-byte message hash being verified (cannot be NULL) - * pubkey: pointer to an initialized public key to verify with (cannot be NULL) - * - * To avoid accepting malleable signatures, only ECDSA signatures in lower-S - * form are accepted. - * - * If you need to accept ECDSA signatures from sources that do not obey this - * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to - * validation, but be aware that doing so results in malleable signatures. - * - * For details, see the comments for that function. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, - const secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, - const secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Convert a signature to a normalized lower-S form. - * - * Returns: 1 if sigin was not normalized, 0 if it already was. - * Args: ctx: a secp256k1 context object - * Out: sigout: a pointer to a signature to fill with the normalized form, - * or copy if the input was already normalized. (can be NULL if - * you're only interested in whether the input was already - * normalized). - * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, - * can be identical to sigout) - * - * With ECDSA a third-party can forge a second distinct signature of the same - * message, given a single initial signature, but without knowing the key. This - * is done by negating the S value modulo the order of the curve, 'flipping' - * the sign of the random point R which is not included in the signature. - * - * Forgery of the same message isn't universally problematic, but in systems - * where message malleability or uniqueness of signatures is important this can - * cause issues. This forgery can be blocked by all verifiers forcing signers - * to use a normalized form. - * - * The lower-S form reduces the size of signatures slightly on average when - * variable length encodings (such as DER) are used and is cheap to verify, - * making it a good choice. Security of always using lower-S is assured because - * anyone can trivially modify a signature after the fact to enforce this - * property anyway. - * - * The lower S value is always between 0x1 and - * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, - * inclusive. - * - * No other forms of ECDSA malleability are known and none seem likely, but - * there is no formal proof that ECDSA, even with this additional restriction, - * is free of other malleability. Commonly used serialization schemes will also - * accept various non-unique encodings, so care should be taken when this - * property is required for an application. - * - * The secp256k1_ecdsa_sign function will by default create signatures in the - * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case - * signatures come from a system that cannot enforce this property, - * secp256k1_ecdsa_signature_normalize must be called before verification. - */ -SECP256K1_API int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sigout, - const secp256k1_ecdsa_signature *sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); - -/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. - * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of - * extra entropy. - */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; - -/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; - -/** Create an ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) - * - * The created signature is always in lower-S form. See - * secp256k1_ecdsa_signature_normalize for more details. - */ -SECP256K1_API int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Verify an ECDSA secret key. - * - * Returns: 1: secret key is valid - * 0: secret key is invalid - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seckey: pointer to a 32-byte secret key (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Compute the public key for a secret key. - * - * Returns: 1: secret was valid, public key stores - * 0: secret was invalid, try again - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: pubkey: pointer to the created public key (cannot be NULL) - * In: seckey: pointer to a 32-byte private key (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a private key by adding tweak to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting private key - * would be invalid (only when the tweak is the complement of the - * private key). 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a public key by adding tweak times the generator to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting public key - * would be invalid (only when the tweak is the complement of the - * corresponding private key). 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key object. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a private key by multiplying it by a tweak. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a public key by multiplying it by a tweak value. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key obkect. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Updates the context randomization. - * Returns: 1: randomization successfully updated - * 0: error - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( - secp256k1_context* ctx, - const unsigned char *seed32 -) SECP256K1_ARG_NONNULL(1); - -/** Add a number of public keys together. - * Returns: 1: the sum of the public keys is valid. - * 0: the sum of the public keys is not valid. - * Args: ctx: pointer to a context object - * Out: out: pointer to a public key object for placing the resulting public key - * (cannot be NULL) - * In: ins: pointer to array of pointers to public keys (cannot be NULL) - * n: the number of public keys to add together (must be at least 1) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, - secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, - size_t n -) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h deleted file mode 100644 index 4b84d7a963..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _SECP256K1_ECDH_ -# define _SECP256K1_ECDH_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Compute an EC Diffie-Hellman secret in constant time - * Returns: 1: exponentiation was successful - * 0: scalar was invalid (zero or overflow) - * Args: ctx: pointer to a context object (cannot be NULL) - * Out: result: a 32-byte array which will be populated by an ECDH - * secret computed from the point and scalar - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key - * privkey: a 32-byte scalar with which to multiply the point - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( - const secp256k1_context* ctx, - unsigned char *result, - const secp256k1_pubkey *pubkey, - const unsigned char *privkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h deleted file mode 100644 index 0553797253..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef _SECP256K1_RECOVERY_ -# define _SECP256K1_RECOVERY_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Opaque data structured that holds a parsed ECDSA signature, - * supporting pubkey recovery. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 65 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, use - * the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. - * - * Furthermore, it is guaranteed that identical signatures (including their - * recoverability) will have identical representation, so they can be - * memcmp'ed. - */ -typedef struct { - unsigned char data[65]; -} secp256k1_ecdsa_recoverable_signature; - -/** Parse a compact ECDSA signature (64 bytes + recovery id). - * - * Returns: 1 when the signature could be parsed, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to a 64-byte compact signature - * recid: the recovery id (0, 1, 2 or 3) - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, - const unsigned char *input64, - int recid -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Convert a recoverable signature into a normal signature. - * - * Returns: 1 - * Out: sig: a pointer to a normal signature (cannot be NULL). - * In: sigin: a pointer to a recoverable signature (cannot be NULL). - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). - * - * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) - * recid: a pointer to an integer to hold the recovery id (can be NULL). - * In: sig: a pointer to an initialized signature object (cannot be NULL) - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, - unsigned char *output64, - int *recid, - const secp256k1_ecdsa_recoverable_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Create a recoverable ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) - */ -SECP256K1_API int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Recover an ECDSA public key from a signature. - * - * Returns: 1: public key successfully recovered (which guarantees a correct signature). - * 0: otherwise. - * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) - * Out: pubkey: pointer to the recovered public key (cannot be NULL) - * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) - * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in deleted file mode 100644 index a0d006f113..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libsecp256k1 -Description: Optimized C library for EC operations on curve secp256k1 -URL: https://github.com/bitcoin-core/secp256k1 -Version: @PACKAGE_VERSION@ -Cflags: -I${includedir} -Libs.private: @SECP_LIBS@ -Libs: -L${libdir} -lsecp256k1 - diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage deleted file mode 100644 index ab580c5b23..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage +++ /dev/null @@ -1,322 +0,0 @@ -# This code supports verifying group implementations which have branches -# or conditional statements (like cmovs), by allowing each execution path -# to independently set assumptions on input or intermediary variables. -# -# The general approach is: -# * A constraint is a tuple of two sets of of symbolic expressions: -# the first of which are required to evaluate to zero, the second of which -# are required to evaluate to nonzero. -# - A constraint is said to be conflicting if any of its nonzero expressions -# is in the ideal with basis the zero expressions (in other words: when the -# zero expressions imply that one of the nonzero expressions are zero). -# * There is a list of laws that describe the intended behaviour, including -# laws for addition and doubling. Each law is called with the symbolic point -# coordinates as arguments, and returns: -# - A constraint describing the assumptions under which it is applicable, -# called "assumeLaw" -# - A constraint describing the requirements of the law, called "require" -# * Implementations are transliterated into functions that operate as well on -# algebraic input points, and are called once per combination of branches -# exectured. Each execution returns: -# - A constraint describing the assumptions this implementation requires -# (such as Z1=1), called "assumeFormula" -# - A constraint describing the assumptions this specific branch requires, -# but which is by construction guaranteed to cover the entire space by -# merging the results from all branches, called "assumeBranch" -# - The result of the computation -# * All combinations of laws with implementation branches are tried, and: -# - If the combination of assumeLaw, assumeFormula, and assumeBranch results -# in a conflict, it means this law does not apply to this branch, and it is -# skipped. -# - For others, we try to prove the require constraints hold, assuming the -# information in assumeLaw + assumeFormula + assumeBranch, and if this does -# not succeed, we fail. -# + To prove an expression is zero, we check whether it belongs to the -# ideal with the assumed zero expressions as basis. This test is exact. -# + To prove an expression is nonzero, we check whether each of its -# factors is contained in the set of nonzero assumptions' factors. -# This test is not exact, so various combinations of original and -# reduced expressions' factors are tried. -# - If we succeed, we print out the assumptions from assumeFormula that -# weren't implied by assumeLaw already. Those from assumeBranch are skipped, -# as we assume that all constraints in it are complementary with each other. -# -# Based on the sage verification scripts used in the Explicit-Formulas Database -# by Tanja Lange and others, see http://hyperelliptic.org/EFD - -class fastfrac: - """Fractions over rings.""" - - def __init__(self,R,top,bot=1): - """Construct a fractional, given a ring, a numerator, and denominator.""" - self.R = R - if parent(top) == ZZ or parent(top) == R: - self.top = R(top) - self.bot = R(bot) - elif top.__class__ == fastfrac: - self.top = top.top - self.bot = top.bot * bot - else: - self.top = R(numerator(top)) - self.bot = R(denominator(top)) * bot - - def iszero(self,I): - """Return whether this fraction is zero given an ideal.""" - return self.top in I and self.bot not in I - - def reduce(self,assumeZero): - zero = self.R.ideal(map(numerator, assumeZero)) - return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) - - def __add__(self,other): - """Add two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top + self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __sub__(self,other): - """Subtract two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top - self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __neg__(self): - """Return the negation of a fraction.""" - return fastfrac(self.R,-self.top,self.bot) - - def __mul__(self,other): - """Multiply two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.top,self.bot * other.bot) - return NotImplemented - - def __rmul__(self,other): - """Multiply something else with a fraction.""" - return self.__mul__(other) - - def __div__(self,other): - """Divide two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top,self.bot * other) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot,self.bot * other.top) - return NotImplemented - - def __pow__(self,other): - """Compute a power of a fraction.""" - if parent(other) == ZZ: - if other < 0: - # Negative powers require flipping top and bottom - return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) - else: - return fastfrac(self.R,self.top ^ other,self.bot ^ other) - return NotImplemented - - def __str__(self): - return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" - def __repr__(self): - return "%s" % self - - def numerator(self): - return self.top - -class constraints: - """A set of constraints, consisting of zero and nonzero expressions. - - Constraints can either be used to express knowledge or a requirement. - - Both the fields zero and nonzero are maps from expressions to description - strings. The expressions that are the keys in zero are required to be zero, - and the expressions that are the keys in nonzero are required to be nonzero. - - Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in - nonzero could be multiplied into a single key. This is often much less - efficient to work with though, so we keep them separate inside the - constraints. This allows higher-level code to do fast checks on the individual - nonzero elements, or combine them if needed for stronger checks. - - We can't multiply the different zero elements, as it would suffice for one of - the factors to be zero, instead of all of them. Instead, the zero elements are - typically combined into an ideal first. - """ - - def __init__(self, **kwargs): - if 'zero' in kwargs: - self.zero = dict(kwargs['zero']) - else: - self.zero = dict() - if 'nonzero' in kwargs: - self.nonzero = dict(kwargs['nonzero']) - else: - self.nonzero = dict() - - def negate(self): - return constraints(zero=self.nonzero, nonzero=self.zero) - - def __add__(self, other): - zero = self.zero.copy() - zero.update(other.zero) - nonzero = self.nonzero.copy() - nonzero.update(other.nonzero) - return constraints(zero=zero, nonzero=nonzero) - - def __str__(self): - return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) - - def __repr__(self): - return "%s" % self - - -def conflicts(R, con): - """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" - zero = R.ideal(map(numerator, con.zero)) - if 1 in zero: - return True - # First a cheap check whether any of the individual nonzero terms conflict on - # their own. - for nonzero in con.nonzero: - if nonzero.iszero(zero): - return True - # It can be the case that entries in the nonzero set do not individually - # conflict with the zero set, but their combination does. For example, knowing - # that either x or y is zero is equivalent to having x*y in the zero set. - # Having x or y individually in the nonzero set is not a conflict, but both - # simultaneously is, so that is the right thing to check for. - if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): - return True - return False - - -def get_nonzero_set(R, assume): - """Calculate a simple set of nonzero expressions""" - zero = R.ideal(map(numerator, assume.zero)) - nonzero = set() - for nz in map(numerator, assume.nonzero): - for (f,n) in nz.factor(): - nonzero.add(f) - rnz = zero.reduce(nz) - for (f,n) in rnz.factor(): - nonzero.add(f) - return nonzero - - -def prove_nonzero(R, exprs, assume): - """Check whether an expression is provably nonzero, given assumptions""" - zero = R.ideal(map(numerator, assume.zero)) - nonzero = get_nonzero_set(R, assume) - expl = set() - ok = True - for expr in exprs: - if numerator(expr) in zero: - return (False, [exprs[expr]]) - allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) - for (f, n) in allexprs.factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for (f, n) in zero.reduce(numerator(allexprs)).factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in numerator(expr).factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in zero.reduce(numerator(expr)).factor(): - if f not in nonzero: - expl.add(exprs[expr]) - if expl: - return (False, list(expl)) - else: - return (True, None) - - -def prove_zero(R, exprs, assume): - """Check whether all of the passed expressions are provably zero, given assumptions""" - r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) - if not r: - return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) - zero = R.ideal(map(numerator, assume.zero)) - nonzero = prod(x for x in assume.nonzero) - expl = [] - for expr in exprs: - if not expr.iszero(zero): - expl.append(exprs[expr]) - if not expl: - return (True, None) - return (False, expl) - - -def describe_extra(R, assume, assumeExtra): - """Describe what assumptions are added, given existing assumptions""" - zerox = assume.zero.copy() - zerox.update(assumeExtra.zero) - zero = R.ideal(map(numerator, assume.zero)) - zeroextra = R.ideal(map(numerator, zerox)) - nonzero = get_nonzero_set(R, assume) - ret = set() - # Iterate over the extra zero expressions - for base in assumeExtra.zero: - if base not in zero: - add = [] - for (f, n) in numerator(base).factor(): - if f not in nonzero: - add += ["%s" % f] - if add: - ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) - # Iterate over the extra nonzero expressions - for nz in assumeExtra.nonzero: - nzr = zeroextra.reduce(numerator(nz)) - if nzr not in zeroextra: - for (f,n) in nzr.factor(): - if zeroextra.reduce(f) not in nonzero: - ret.add("%s != 0" % zeroextra.reduce(f)) - return ", ".join(x for x in ret) - - -def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): - """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" - assume = assumeLaw + assumeAssert + assumeBranch - - if conflicts(R, assume): - # This formula does not apply - return None - - describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) - - ok, msg = prove_zero(R, require.zero, assume) - if not ok: - return "FAIL, %s fails (assuming %s)" % (str(msg), describe) - - res, expl = prove_nonzero(R, require.nonzero, assume) - if not res: - return "FAIL, %s fails (assuming %s)" % (str(expl), describe) - - if describe != "": - return "OK (assuming %s)" % describe - else: - return "OK" - - -def concrete_verify(c): - for k in c.zero: - if k != 0: - return (False, c.zero[k]) - for k in c.nonzero: - if k == 0: - return (False, c.nonzero[k]) - return (True, None) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage deleted file mode 100644 index a97e732f7f..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage +++ /dev/null @@ -1,306 +0,0 @@ -# Test libsecp256k1' group operation implementations using prover.sage - -import sys - -load("group_prover.sage") -load("weierstrass_prover.sage") - -def formula_secp256k1_gej_double_var(a): - """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" - rz = a.Z * a.Y - rz = rz * 2 - t1 = a.X^2 - t1 = t1 * 3 - t2 = t1^2 - t3 = a.Y^2 - t3 = t3 * 2 - t4 = t3^2 - t4 = t4 * 2 - t3 = t3 * a.X - rx = t3 - rx = rx * 4 - rx = -rx - rx = rx + t2 - t2 = -t2 - t3 = t3 * 6 - t3 = t3 + t2 - ry = t1 * t3 - t2 = -t4 - ry = ry + t2 - return jacobianpoint(rx, ry, rz) - -def formula_secp256k1_gej_add_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_var""" - if branch == 0: - return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z22 = b.Z^2 - z12 = a.Z^2 - u1 = a.X * z22 - u2 = b.X * z12 - s1 = a.Y * z22 - s1 = s1 * b.Z - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) - if branch == 3: - return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h2 * h - h = h * b.Z - rz = a.Z * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" - if branch == 0: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z12 = a.Z^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if (branch == 2): - r = formula_secp256k1_gej_double_var(a) - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if (branch == 3): - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h * h2 - rz = a.Z * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_zinv_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_zinv_var""" - bzinv = b.Z^(-1) - if branch == 0: - return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) - if branch == 1: - bzinv2 = bzinv^2 - bzinv3 = bzinv2 * bzinv - rx = b.X * bzinv2 - ry = b.Y * bzinv3 - rz = 1 - return (constraints(), constraints(zero={b.Infinity : 'b_finite'}, nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz)) - azz = a.Z * bzinv - z12 = azz^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * azz - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if branch == 3: - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h * h2 - rz = a.Z - rz = rz * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge""" - zeroes = {} - nonzeroes = {} - a_infinity = False - if (branch & 4) != 0: - nonzeroes.update({a.Infinity : 'a_infinite'}) - a_infinity = True - else: - zeroes.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - rr = t^2 - m_alt = -u2 - tt = u1 * m_alt - rr = rr + tt - degenerate = (branch & 3) == 3 - if (branch & 1) != 0: - zeroes.update({m : 'm_zero'}) - else: - nonzeroes.update({m : 'm_nonzero'}) - if (branch & 2) != 0: - zeroes.update({rr : 'rr_zero'}) - else: - nonzeroes.update({rr : 'rr_nonzero'}) - rr_alt = s1 - rr_alt = rr_alt * 2 - m_alt = m_alt + u1 - if not degenerate: - rr_alt = rr - m_alt = m - n = m_alt^2 - q = n * t - n = n^2 - if degenerate: - n = m - t = rr_alt^2 - rz = a.Z * m_alt - infinity = False - if (branch & 8) != 0: - if not a_infinity: - infinity = True - zeroes.update({rz : 'r.z=0'}) - else: - nonzeroes.update({rz : 'r.z!=0'}) - rz = rz * 2 - q = -q - t = t + q - rx = t - t = t * 2 - t = t + q - t = t * rr_alt - t = t + n - ry = -t - rx = rx * 4 - ry = ry * 4 - if a_infinity: - rx = b.X - ry = b.Y - rz = 1 - if infinity: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_old(branch, a, b): - """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" - a_infinity = (branch & 1) != 0 - zero = {} - nonzero = {} - if a_infinity: - nonzero.update({a.Infinity : 'a_infinite'}) - else: - zero.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - z = a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - n = m^2 - q = n * t - n = n^2 - rr = t^2 - t = u1 * u2 - t = -t - rr = rr + t - t = rr^2 - rz = m * z - infinity = False - if (branch & 2) != 0: - if not a_infinity: - infinity = True - else: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) - zero.update({rz : 'r.z=0'}) - else: - nonzero.update({rz : 'r.z!=0'}) - rz = rz * (0 if a_infinity else 2) - rx = t - q = -q - rx = rx + q - q = q * 3 - t = t * 2 - t = t + q - t = t * rr - t = t + n - ry = -t - rx = rx * (0 if a_infinity else 4) - ry = ry * (0 if a_infinity else 4) - t = b.X - t = t * (1 if a_infinity else 0) - rx = rx + t - t = b.Y - t = t * (1 if a_infinity else 0) - ry = ry + t - t = (1 if a_infinity else 0) - rz = rz + t - if infinity: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) - -if __name__ == "__main__": - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) - - if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage deleted file mode 100644 index 03ef2ec901..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage +++ /dev/null @@ -1,264 +0,0 @@ -# Prover implementation for Weierstrass curves of the form -# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws -# operating on affine and Jacobian coordinates, including the point at infinity -# represented by a 4th variable in coordinates. - -load("group_prover.sage") - - -class affinepoint: - def __init__(self, x, y, infinity=0): - self.x = x - self.y = y - self.infinity = infinity - def __str__(self): - return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) - - -class jacobianpoint: - def __init__(self, x, y, z, infinity=0): - self.X = x - self.Y = y - self.Z = z - self.Infinity = infinity - def __str__(self): - return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) - - -def point_at_infinity(): - return jacobianpoint(1, 1, 1, 1) - - -def negate(p): - if p.__class__ == affinepoint: - return affinepoint(p.x, -p.y) - if p.__class__ == jacobianpoint: - return jacobianpoint(p.X, -p.Y, p.Z) - assert(False) - - -def on_weierstrass_curve(A, B, p): - """Return a set of zero-expressions for an affine point to be on the curve""" - return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) - - -def tangential_to_weierstrass_curve(A, B, p12, p3): - """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" - return constraints(zero={ - (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' - }) - - -def colinear(p1, p2, p3): - """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" - return constraints(zero={ - (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', - (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', - (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' - }) - - -def good_affine_point(p): - return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) - - -def good_jacobian_point(p): - return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) - - -def good_point(p): - return constraints(nonzero={p.Z^6 : 'nonzero_X'}) - - -def finite(p, *affine_fns): - con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) - if p.Z != 0: - return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) - else: - return con - -def infinite(p): - return constraints(nonzero={p.Infinity : 'infinite_point'}) - - -def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(nonzero={pa.x - pb.x : 'different_x'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - colinear(pa, pb, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) - require = infinite(pC) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pb) + - infinite(pA) + - finite(pB)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - infinite(pB) + - finite(pA)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - infinite(pA) + - infinite(pB)) - require = infinite(pC) - return (assumeLaw, require) - - -laws_jacobian_weierstrass = { - 'add': law_jacobian_weierstrass_add, - 'double': law_jacobian_weierstrass_double, - 'add_opposite': law_jacobian_weierstrass_add_opposites, - 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, - 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, - 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab -} - - -def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" - F = Integers(p) - print "Formula %s on Z%i:" % (name, p) - points = [] - for x in xrange(0, p): - for y in xrange(0, p): - point = affinepoint(F(x), F(y)) - r, e = concrete_verify(on_weierstrass_curve(A, B, point)) - if r: - points.append(point) - - for za in xrange(1, p): - for zb in xrange(1, p): - for pa in points: - for pb in points: - for ia in xrange(2): - for ib in xrange(2): - pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) - pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) - for branch in xrange(0, branches): - assumeAssert, assumeBranch, pC = formula(branch, pA, pB) - pC.X = F(pC.X) - pC.Y = F(pC.Y) - pC.Z = F(pC.Z) - pC.Infinity = F(pC.Infinity) - r, e = concrete_verify(assumeAssert + assumeBranch) - if r: - match = False - for key in laws_jacobian_weierstrass: - assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) - r, e = concrete_verify(assumeLaw) - if r: - if match: - print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) - else: - match = True - r, e = concrete_verify(require) - if not r: - print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) - print - - -def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): - assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) - return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) - -def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" - R. = PolynomialRing(QQ,8,order='invlex') - lift = lambda x: fastfrac(R,x) - ax = lift(ax) - ay = lift(ay) - Az = lift(Az) - bx = lift(bx) - by = lift(by) - Bz = lift(Bz) - Ai = lift(Ai) - Bi = lift(Bi) - - pa = affinepoint(ax, ay, Ai) - pb = affinepoint(bx, by, Bi) - pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) - pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) - - res = {} - - for key in laws_jacobian_weierstrass: - res[key] = [] - - print ("Formula " + name + ":") - count = 0 - for branch in xrange(branches): - assumeFormula, assumeBranch, pC = formula(branch, pA, pB) - pC.X = lift(pC.X) - pC.Y = lift(pC.Y) - pC.Z = lift(pC.Z) - pC.Infinity = lift(pC.Infinity) - - for key in laws_jacobian_weierstrass: - res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) - - for key in res: - print " %s:" % key - val = res[key] - for x in val: - if x[0] is not None: - print " branch %i: %s" % (x[1], x[0]) - - print diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s deleted file mode 100644 index 1e2d7ff961..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s +++ /dev/null @@ -1,919 +0,0 @@ -@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: -/********************************************************************** - * Copyright (c) 2014 Wladimir J. van der Laan * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ -/* -ARM implementation of field_10x26 inner loops. - -Note: - -- To avoid unnecessary loads and make use of available registers, two - 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the the even passes - -*/ - - .syntax unified - .arch armv7-a - @ eabi attributes - see readelf -A - .eabi_attribute 8, 1 @ Tag_ARM_ISA_use = yes - .eabi_attribute 9, 0 @ Tag_Thumb_ISA_use = no - .eabi_attribute 10, 0 @ Tag_FP_arch = none - .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte - .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP - .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed - .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 - .text - - @ Field constants - .set field_R0, 0x3d10 - .set field_R1, 0x400 - .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff - - .align 2 - .global secp256k1_fe_mul_inner - .type secp256k1_fe_mul_inner, %function - @ Arguments: - @ r0 r Restrict: can overlap with a, not with b - @ r1 a - @ r2 b - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_mul_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r7,r8 scratch - r1 a (pointer) - r2 b (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - - /* A - interleaved with B */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #9*4] @ b[9] - ldr r0, [r1, #1*4] @ a[1] - umull r5, r6, r7, r8 @ d = a[0] * b[9] - ldr r14, [r2, #8*4] @ b[8] - umull r9, r10, r0, r8 @ d' = a[1] * b[9] - ldr r7, [r1, #2*4] @ a[2] - umlal r5, r6, r0, r14 @ d += a[1] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r14 @ d' += a[2] * b[8] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r8 @ d += a[2] * b[7] - ldr r14, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r8 @ d' += a[3] * b[7] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r14 @ d += a[3] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r14 @ d' += a[4] * b[6] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r8 @ d += a[4] * b[5] - ldr r14, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r8 @ d' += a[5] * b[5] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r14 @ d += a[5] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r14 @ d' += a[6] * b[4] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[3] - ldr r14, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r8 @ d' += a[7] * b[3] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[7] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r9, r10, r7, r14 @ d' += a[8] * b[2] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r8 @ d += a[8] * b[1] - ldr r14, [r2, #0*4] @ b[0] - umlal r9, r10, r0, r8 @ d' += a[9] * b[1] - ldr r7, [r1, #0*4] @ a[0] - umlal r5, r6, r0, r14 @ d += a[9] * b[0] - @ r7,r14 used in B - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 4*9] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - umull r3, r4, r7, r14 @ c = a[0] * b[0] - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C - interleaved with D */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #2*4] @ b[2] - ldr r14, [r2, #1*4] @ b[1] - umull r11, r12, r7, r8 @ c' = a[0] * b[2] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[1] * b[1] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[2] * b[0] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r14 @ d += a[2] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[3] * b[9] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r8 @ d += a[3] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[4] * b[8] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r14 @ d += a[4] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[5] * b[7] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r8 @ d += a[5] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r8 @ d' += a[6] * b[6] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r14 @ d' += a[7] * b[5] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r8 @ d' += a[8] * b[4] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r14 @ d' += a[9] * b[3] - umlal r5, r6, r0, r8 @ d += a[9] * b[2] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E - interleaved with F */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #4*4] @ b[4] - umull r11, r12, r7, r8 @ c' = a[0] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r3, r4, r7, r8 @ c += a[0] * b[3] - ldr r7, [r1, #1*4] @ a[1] - umlal r11, r12, r7, r8 @ c' += a[1] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r3, r4, r7, r8 @ c += a[1] * b[2] - ldr r7, [r1, #2*4] @ a[2] - umlal r11, r12, r7, r8 @ c' += a[2] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r3, r4, r7, r8 @ c += a[2] * b[1] - ldr r7, [r1, #3*4] @ a[3] - umlal r11, r12, r7, r8 @ c' += a[3] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r3, r4, r7, r8 @ c += a[3] * b[0] - ldr r7, [r1, #4*4] @ a[4] - umlal r11, r12, r7, r8 @ c' += a[4] * b[0] - ldr r8, [r2, #9*4] @ b[9] - umlal r5, r6, r7, r8 @ d += a[4] * b[9] - ldr r7, [r1, #5*4] @ a[5] - umull r9, r10, r7, r8 @ d' = a[5] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umlal r5, r6, r7, r8 @ d += a[5] * b[8] - ldr r7, [r1, #6*4] @ a[6] - umlal r9, r10, r7, r8 @ d' += a[6] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[7] - ldr r7, [r1, #7*4] @ a[7] - umlal r9, r10, r7, r8 @ d' += a[7] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r5, r6, r7, r8 @ d += a[7] * b[6] - ldr r7, [r1, #8*4] @ a[8] - umlal r9, r10, r7, r8 @ d' += a[8] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r5, r6, r7, r8 @ d += a[8] * b[5] - ldr r7, [r1, #9*4] @ a[9] - umlal r9, r10, r7, r8 @ d' += a[9] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r5, r6, r7, r8 @ d += a[9] * b[4] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G - interleaved with H */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #6*4] @ b[6] - ldr r14, [r2, #5*4] @ b[5] - umull r11, r12, r7, r8 @ c' = a[0] * b[6] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[1] * b[5] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[2] * b[4] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[3] * b[3] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[4] * b[2] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[5] * b[1] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[6] * b[0] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[7] * b[9] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[8] * b[8] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[9] * b[7] - umlal r5, r6, r0, r8 @ d += a[9] * b[6] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I - interleaved with J */ - ldr r8, [r2, #8*4] @ b[8] - ldr r7, [r1, #0*4] @ a[0] - ldr r14, [r2, #7*4] @ b[7] - umull r11, r12, r7, r8 @ c' = a[0] * b[8] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r11, r12, r0, r14 @ c' += a[1] * b[7] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r11, r12, r7, r8 @ c' += a[2] * b[6] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[3] * b[5] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[4] * b[4] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[5] * b[3] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[6] * b[2] - ldr r0, [r1, #7*4] @ a[7] - umlal r3, r4, r7, r14 @ c += a[6] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[7] * b[1] - ldr r7, [r1, #8*4] @ a[8] - umlal r3, r4, r0, r8 @ c += a[7] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[8] * b[0] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[9] * b[9] - umlal r5, r6, r0, r8 @ d += a[9] * b[8] - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner - - .align 2 - .global secp256k1_fe_sqr_inner - .type secp256k1_fe_sqr_inner, %function - @ Arguments: - @ r0 r Can overlap with a - @ r1 a - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_sqr_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r2,r7,r8 scratch - r1 a (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - /* A interleaved with B */ - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r7, [r1, #0*4] @ a[0] - mov r0, r0, asl #1 - ldr r14, [r1, #9*4] @ a[9] - umull r3, r4, r7, r7 @ c = a[0] * a[0] - ldr r8, [r1, #8*4] @ a[8] - mov r7, r7, asl #1 - umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] - ldr r7, [r1, #2*4] @ a[2]*2 - umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #3*4] @ a[3]*2 - umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] - ldr r14, [r1, #5*4] @ a[5] - mov r7, r7, asl #1 - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] - umlal r9, r10, r14, r14 @ d' += a[5] * a[5] - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 9*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C interleaved with D */ - ldr r0, [r1, #0*4] @ a[0]*2 - ldr r14, [r1, #1*4] @ a[1] - mov r0, r0, asl #1 - ldr r8, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] - mov r7, r8, asl #1 @ a[2]*2 - umull r11, r12, r14, r14 @ c' = a[1] * a[1] - ldr r14, [r1, #9*4] @ a[9] - umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] - ldr r0, [r1, #3*4] @ a[3]*2 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] - umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] - umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] - umlal r9, r10, r8, r8 @ d' += a[6] * a[6] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E interleaved with F */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r14, [r1, #2*4] @ a[2] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - ldr r2, [r1, #4*4] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] - mov r2, r2, asl #1 @ a[4]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] - ldr r8, [r1, #9*4] @ a[9] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r11, r12, r14, r14 @ c' += a[2] * a[2] - ldr r14, [r1, #8*4] @ a[8] - mov r0, r0, asl #1 - umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] - ldr r7, [r1, #6*4] @ a[6]*2 - umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] - umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] - umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] - umlal r9, r10, r8, r8 @ d' += a[7] * a[7] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G interleaved with H */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #5*4] @ a[5] - ldr r2, [r1, #6*4] @ a[6] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] - mov r0, r2, asl #1 @ a[6]*2 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] - ldr r14, [r1, #9*4] @ a[9] - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] - ldr r7, [r1, #7*4] @ a[7]*2 - umlal r11, r12, r8, r8 @ c' += a[3] * a[3] - mov r7, r7, asl #1 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] - umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] - umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] - umlal r9, r10, r8, r8 @ d' += a[8] * a[8] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I interleaved with J */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - ldr r2, [r1, #8*4] @ a[8] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] - ldr r14, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] - ldr r8, [r1, #5*4] @ a[5] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] - ldr r0, [r1, #3*4] @ a[3]*2 - mov r7, r7, asl #1 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] - mov r2, r2, asl #1 @ a[8]*2 - umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] - umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] - umlal r11, r12, r14, r14 @ c' += a[4] * a[4] - ldr r8, [r1, #9*4] @ a[9] - umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] - @ r8 will be used in J - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - umlal r5, r6, r8, r8 @ d += a[9] * a[9] - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner - diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h deleted file mode 100644 index c4c16eb7ca..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h +++ /dev/null @@ -1,32 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_BASIC_CONFIG_ -#define _SECP256K1_BASIC_CONFIG_ - -#ifdef USE_BASIC_CONFIG - -#undef USE_ASM_X86_64 -#undef USE_ENDOMORPHISM -#undef USE_FIELD_10X26 -#undef USE_FIELD_5X52 -#undef USE_FIELD_INV_BUILTIN -#undef USE_FIELD_INV_NUM -#undef USE_NUM_GMP -#undef USE_NUM_NONE -#undef USE_SCALAR_4X64 -#undef USE_SCALAR_8X32 -#undef USE_SCALAR_INV_BUILTIN -#undef USE_SCALAR_INV_NUM - -#define USE_NUM_NONE 1 -#define USE_FIELD_INV_BUILTIN 1 -#define USE_SCALAR_INV_BUILTIN 1 -#define USE_FIELD_10X26 1 -#define USE_SCALAR_8X32 1 - -#endif // USE_BASIC_CONFIG -#endif // _SECP256K1_BASIC_CONFIG_ diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h deleted file mode 100644 index 3a71b4aafa..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h +++ /dev/null @@ -1,66 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_BENCH_H_ -#define _SECP256K1_BENCH_H_ - -#include -#include -#include "sys/time.h" - -static double gettimedouble(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_usec * 0.000001 + tv.tv_sec; -} - -void print_number(double x) { - double y = x; - int c = 0; - if (y < 0.0) { - y = -y; - } - while (y < 100.0) { - y *= 10.0; - c++; - } - printf("%.*f", c, x); -} - -void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { - int i; - double min = HUGE_VAL; - double sum = 0.0; - double max = 0.0; - for (i = 0; i < count; i++) { - double begin, total; - if (setup != NULL) { - setup(data); - } - begin = gettimedouble(); - benchmark(data); - total = gettimedouble() - begin; - if (teardown != NULL) { - teardown(data); - } - if (total < min) { - min = total; - } - if (total > max) { - max = total; - } - sum += total; - } - printf("%s: min ", name); - print_number(min * 1000000.0 / iter); - printf("us / avg "); - print_number((sum / count) * 1000000.0 / iter); - printf("us / max "); - print_number(max * 1000000.0 / iter); - printf("us\n"); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c deleted file mode 100644 index cde5e2dbb4..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_ecdh.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context *ctx; - secp256k1_pubkey point; - unsigned char scalar[32]; -} bench_ecdh_t; - -static void bench_ecdh_setup(void* arg) { - int i; - bench_ecdh_t *data = (bench_ecdh_t*)arg; - const unsigned char point[] = { - 0x03, - 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, - 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, - 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, - 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f - }; - - /* create a context with no capabilities */ - data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); - for (i = 0; i < 32; i++) { - data->scalar[i] = i + 1; - } - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); -} - -static void bench_ecdh(void* arg) { - int i; - unsigned char res[32]; - bench_ecdh_t *data = (bench_ecdh_t*)arg; - - for (i = 0; i < 20000; i++) { - CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); - } -} - -int main(void) { - bench_ecdh_t data; - - run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c deleted file mode 100644 index 0809f77bda..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c +++ /dev/null @@ -1,382 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ -#include - -#include "include/secp256k1.h" - -#include "util.h" -#include "hash_impl.h" -#include "num_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_impl.h" -#include "bench.h" -#include "secp256k1.c" - -typedef struct { - secp256k1_scalar scalar_x, scalar_y; - secp256k1_fe fe_x, fe_y; - secp256k1_ge ge_x, ge_y; - secp256k1_gej gej_x, gej_y; - unsigned char data[64]; - int wnaf[256]; -} bench_inv_t; - -void bench_setup(void* arg) { - bench_inv_t *data = (bench_inv_t*)arg; - - static const unsigned char init_x[32] = { - 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, - 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, - 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, - 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 - }; - - static const unsigned char init_y[32] = { - 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, - 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, - 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, - 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 - }; - - secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); - secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); - secp256k1_fe_set_b32(&data->fe_x, init_x); - secp256k1_fe_set_b32(&data->fe_y, init_y); - CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); - CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); - secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); - secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); - memcpy(data->data, init_x, 32); - memcpy(data->data + 32, init_y, 32); -} - -void bench_scalar_add(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_scalar_negate(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); - } -} - -void bench_scalar_sqr(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); - } -} - -void bench_scalar_mul(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -#ifdef USE_ENDOMORPHISM -void bench_scalar_split(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_scalar l, r; - secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} -#endif - -void bench_scalar_inverse(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_scalar_inverse_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_field_normalize(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize(&data->fe_x); - } -} - -void bench_field_normalize_weak(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize_weak(&data->fe_x); - } -} - -void bench_field_mul(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); - } -} - -void bench_field_sqr(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_fe_sqr(&data->fe_x, &data->fe_x); - } -} - -void bench_field_inverse(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_inv(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_field_inverse_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_field_sqrt(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_group_double_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); - } -} - -void bench_group_add_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); - } -} - -void bench_group_add_affine(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); - } -} - -void bench_group_add_affine_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); - } -} - -void bench_group_jacobi_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_gej_has_quad_y_var(&data->gej_x); - } -} - -void bench_ecmult_wnaf(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_wnaf_const(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - - -void bench_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_sha256_t sha; - - for (i = 0; i < 20000; i++) { - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data->data, 32); - secp256k1_sha256_finalize(&sha, data->data); - } -} - -void bench_hmac_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_hmac_sha256_t hmac; - - for (i = 0; i < 20000; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); - secp256k1_hmac_sha256_write(&hmac, data->data, 32); - secp256k1_hmac_sha256_finalize(&hmac, data->data); - } -} - -void bench_rfc6979_hmac_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_rfc6979_hmac_sha256_t rng; - - for (i = 0; i < 20000; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); - } -} - -void bench_context_verify(void* arg) { - int i; - (void)arg; - for (i = 0; i < 20; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); - } -} - -void bench_context_sign(void* arg) { - int i; - (void)arg; - for (i = 0; i < 200; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); - } -} - -#ifndef USE_NUM_NONE -void bench_num_jacobi(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_num nx, norder; - - secp256k1_scalar_get_num(&nx, &data->scalar_x); - secp256k1_scalar_order_get_num(&norder); - secp256k1_scalar_get_num(&norder, &data->scalar_y); - - for (i = 0; i < 200000; i++) { - secp256k1_num_jacobi(&nx, &norder); - } -} -#endif - -int have_flag(int argc, char** argv, char *flag) { - char** argm = argv + argc; - argv++; - if (argv == argm) { - return 1; - } - while (argv != NULL && argv != argm) { - if (strcmp(*argv, flag) == 0) { - return 1; - } - argv++; - } - return 0; -} - -int main(int argc, char **argv) { - bench_inv_t data; - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000); -#ifdef USE_ENDOMORPHISM - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000); -#endif - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); - - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); - if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); - -#ifndef USE_NUM_NONE - if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); -#endif - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c deleted file mode 100644 index 6489378cc6..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" -#include "include/secp256k1_recovery.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char sig[64]; -} bench_recover_t; - -void bench_recover(void* arg) { - int i; - bench_recover_t *data = (bench_recover_t*)arg; - secp256k1_pubkey pubkey; - unsigned char pubkeyc[33]; - - for (i = 0; i < 20000; i++) { - int j; - size_t pubkeylen = 33; - secp256k1_ecdsa_recoverable_signature sig; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); - CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - for (j = 0; j < 32; j++) { - data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ - data->msg[j] = data->sig[j]; /* Move former R to message. */ - data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ - } - } -} - -void bench_recover_setup(void* arg) { - int i; - bench_recover_t *data = (bench_recover_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (i = 0; i < 64; i++) { - data->sig[i] = 65 + i; - } -} - -int main(void) { - bench_recover_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - - run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c deleted file mode 100644 index 5f137dda23..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c +++ /dev/null @@ -1,73 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_schnorr.h" -#include "util.h" -#include "bench.h" - -typedef struct { - unsigned char key[32]; - unsigned char sig[64]; - unsigned char pubkey[33]; - size_t pubkeylen; -} benchmark_schnorr_sig_t; - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - benchmark_schnorr_sig_t sigs[64]; - int numsigs; -} benchmark_schnorr_verify_t; - -static void benchmark_schnorr_init(void* arg) { - int i, k; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (k = 0; k < data->numsigs; k++) { - secp256k1_pubkey pubkey; - for (i = 0; i < 32; i++) { - data->sigs[k].key[i] = 33 + i + k; - } - secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); - data->sigs[k].pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - } -} - -static void benchmark_schnorr_verify(void* arg) { - int i; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 20000 / data->numsigs; i++) { - secp256k1_pubkey pubkey; - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); - CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - } -} - - - -int main(void) { - benchmark_schnorr_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - data.numsigs = 1; - run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c deleted file mode 100644 index ed7224d757..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c +++ /dev/null @@ -1,56 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context* ctx; - unsigned char msg[32]; - unsigned char key[32]; -} bench_sign_t; - -static void bench_sign_setup(void* arg) { - int i; - bench_sign_t *data = (bench_sign_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = i + 1; - } - for (i = 0; i < 32; i++) { - data->key[i] = i + 65; - } -} - -static void bench_sign(void* arg) { - int i; - bench_sign_t *data = (bench_sign_t*)arg; - - unsigned char sig[74]; - for (i = 0; i < 20000; i++) { - size_t siglen = 74; - int j; - secp256k1_ecdsa_signature signature; - CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); - for (j = 0; j < 32; j++) { - data->msg[j] = sig[j]; - data->key[j] = sig[j + 32]; - } - } -} - -int main(void) { - bench_sign_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - - run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c deleted file mode 100644 index 418defa0aa..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c +++ /dev/null @@ -1,112 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "util.h" -#include "bench.h" - -#ifdef ENABLE_OPENSSL_TESTS -#include -#include -#include -#endif - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char key[32]; - unsigned char sig[72]; - size_t siglen; - unsigned char pubkey[33]; - size_t pubkeylen; -#ifdef ENABLE_OPENSSL_TESTS - EC_GROUP* ec_group; -#endif -} benchmark_verify_t; - -static void benchmark_verify(void* arg) { - int i; - benchmark_verify_t* data = (benchmark_verify_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); - CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - } -} - -#ifdef ENABLE_OPENSSL_TESTS -static void benchmark_verify_openssl(void* arg) { - int i; - benchmark_verify_t* data = (benchmark_verify_t*)arg; - - for (i = 0; i < 20000; i++) { - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - { - EC_KEY *pkey = EC_KEY_new(); - const unsigned char *pubkey = &data->pubkey[0]; - int result; - - CHECK(pkey != NULL); - result = EC_KEY_set_group(pkey, data->ec_group); - CHECK(result); - result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; - CHECK(result); - result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); - CHECK(result); - EC_KEY_free(pkey); - } - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - } -} -#endif - -int main(void) { - int i; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - benchmark_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - for (i = 0; i < 32; i++) { - data.msg[i] = 1 + i; - } - for (i = 0; i < 32; i++) { - data.key[i] = 33 + i; - } - data.siglen = 72; - CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); - CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); - data.pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - - run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); -#ifdef ENABLE_OPENSSL_TESTS - data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); - run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); - EC_GROUP_free(data.ec_group); -#endif - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h deleted file mode 100644 index 54ae101b92..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h +++ /dev/null @@ -1,21 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECDSA_ -#define _SECP256K1_ECDSA_ - -#include - -#include "scalar.h" -#include "group.h" -#include "ecmult.h" - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h deleted file mode 100644 index 453bb11880..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h +++ /dev/null @@ -1,315 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - - -#ifndef _SECP256K1_ECDSA_IMPL_H_ -#define _SECP256K1_ECDSA_IMPL_H_ - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult.h" -#include "ecmult_gen.h" -#include "ecdsa.h" - -/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 - * sage: for t in xrange(1023, -1, -1): - * .. p = 2**256 - 2**32 - t - * .. if p.is_prime(): - * .. print '%x'%p - * .. break - * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' - * sage: a = 0 - * sage: b = 7 - * sage: F = FiniteField (p) - * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) - * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' - */ -static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL -); - -/** Difference between field and order, values 'p' and 'n' values defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - * sage: a = 0 - * sage: b = 7 - * sage: F = FiniteField (p) - * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) - * '14551231950b75fc4402da1722fc9baee' - */ -static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( - 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL -); - -static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { - int lenleft, b1; - size_t ret = 0; - if (*sigp >= sigend) { - return -1; - } - b1 = *((*sigp)++); - if (b1 == 0xFF) { - /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ - return -1; - } - if ((b1 & 0x80) == 0) { - /* X.690-0207 8.1.3.4 short form length octets */ - return b1; - } - if (b1 == 0x80) { - /* Indefinite length is not allowed in DER. */ - return -1; - } - /* X.690-207 8.1.3.5 long form length octets */ - lenleft = b1 & 0x7F; - if (lenleft > sigend - *sigp) { - return -1; - } - if (**sigp == 0) { - /* Not the shortest possible length encoding. */ - return -1; - } - if ((size_t)lenleft > sizeof(size_t)) { - /* The resulting length would exceed the range of a size_t, so - * certainly longer than the passed array size. - */ - return -1; - } - while (lenleft > 0) { - if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { - } - ret = (ret << 8) | **sigp; - if (ret + lenleft > (size_t)(sigend - *sigp)) { - /* Result exceeds the length of the passed array. */ - return -1; - } - (*sigp)++; - lenleft--; - } - if (ret < 128) { - /* Not the shortest possible length encoding. */ - return -1; - } - return ret; -} - -static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { - int overflow = 0; - unsigned char ra[32] = {0}; - int rlen; - - if (*sig == sigend || **sig != 0x02) { - /* Not a primitive integer (X.690-0207 8.3.1). */ - return 0; - } - (*sig)++; - rlen = secp256k1_der_read_len(sig, sigend); - if (rlen <= 0 || (*sig) + rlen > sigend) { - /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ - return 0; - } - if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { - /* Excessive 0x00 padding. */ - return 0; - } - if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { - /* Excessive 0xFF padding. */ - return 0; - } - if ((**sig & 0x80) == 0x80) { - /* Negative. */ - overflow = 1; - } - while (rlen > 0 && **sig == 0) { - /* Skip leading zero bytes */ - rlen--; - (*sig)++; - } - if (rlen > 32) { - overflow = 1; - } - if (!overflow) { - memcpy(ra + 32 - rlen, *sig, rlen); - secp256k1_scalar_set_b32(r, ra, &overflow); - } - if (overflow) { - secp256k1_scalar_set_int(r, 0); - } - (*sig) += rlen; - return 1; -} - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { - const unsigned char *sigend = sig + size; - int rlen; - if (sig == sigend || *(sig++) != 0x30) { - /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ - return 0; - } - rlen = secp256k1_der_read_len(&sig, sigend); - if (rlen < 0 || sig + rlen > sigend) { - /* Tuple exceeds bounds */ - return 0; - } - if (sig + rlen != sigend) { - /* Garbage after tuple. */ - return 0; - } - - if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { - return 0; - } - if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { - return 0; - } - - if (sig != sigend) { - /* Trailing garbage inside tuple. */ - return 0; - } - - return 1; -} - -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { - unsigned char r[33] = {0}, s[33] = {0}; - unsigned char *rp = r, *sp = s; - size_t lenR = 33, lenS = 33; - secp256k1_scalar_get_b32(&r[1], ar); - secp256k1_scalar_get_b32(&s[1], as); - while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } - while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } - if (*size < 6+lenS+lenR) { - *size = 6 + lenS + lenR; - return 0; - } - *size = 6 + lenS + lenR; - sig[0] = 0x30; - sig[1] = 4 + lenS + lenR; - sig[2] = 0x02; - sig[3] = lenR; - memcpy(sig+4, rp, lenR); - sig[4+lenR] = 0x02; - sig[5+lenR] = lenS; - memcpy(sig+lenR+6, sp, lenS); - return 1; -} - -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { - unsigned char c[32]; - secp256k1_scalar sn, u1, u2; -#if !defined(EXHAUSTIVE_TEST_ORDER) - secp256k1_fe xr; -#endif - secp256k1_gej pubkeyj; - secp256k1_gej pr; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_inverse_var(&sn, sigs); - secp256k1_scalar_mul(&u1, &sn, message); - secp256k1_scalar_mul(&u2, &sn, sigr); - secp256k1_gej_set_ge(&pubkeyj, pubkey); - secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); - if (secp256k1_gej_is_infinity(&pr)) { - return 0; - } - -#if defined(EXHAUSTIVE_TEST_ORDER) -{ - secp256k1_scalar computed_r; - secp256k1_ge pr_ge; - secp256k1_ge_set_gej(&pr_ge, &pr); - secp256k1_fe_normalize(&pr_ge.x); - - secp256k1_fe_get_b32(c, &pr_ge.x); - secp256k1_scalar_set_b32(&computed_r, c, NULL); - return secp256k1_scalar_eq(sigr, &computed_r); -} -#else - secp256k1_scalar_get_b32(c, sigr); - secp256k1_fe_set_b32(&xr, c); - - /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) - * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), - * compute the remainder modulo n, and compare it to xr. However: - * - * xr == X(pr) mod n - * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) - * [Since 2 * n > p, h can only be 0 or 1] - * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) - * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] - * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) - * [Multiplying both sides of the equations by pr.z^2 mod p] - * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) - * - * Thus, we can avoid the inversion, but we have to check both cases separately. - * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. - */ - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - /* xr + n >= p, so we can skip testing the second case. */ - return 0; - } - secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - return 0; -#endif -} - -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { - unsigned char b[32]; - secp256k1_gej rp; - secp256k1_ge r; - secp256k1_scalar n; - int overflow = 0; - - secp256k1_ecmult_gen(ctx, &rp, nonce); - secp256k1_ge_set_gej(&r, &rp); - secp256k1_fe_normalize(&r.x); - secp256k1_fe_normalize(&r.y); - secp256k1_fe_get_b32(b, &r.x); - secp256k1_scalar_set_b32(sigr, b, &overflow); - /* These two conditions should be checked before calling */ - VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); - VERIFY_CHECK(overflow == 0); - - if (recid) { - /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log - * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. - */ - *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); - } - secp256k1_scalar_mul(&n, sigr, seckey); - secp256k1_scalar_add(&n, &n, message); - secp256k1_scalar_inverse(sigs, nonce); - secp256k1_scalar_mul(sigs, sigs, &n); - secp256k1_scalar_clear(&n); - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - if (secp256k1_scalar_is_zero(sigs)) { - return 0; - } - if (secp256k1_scalar_is_high(sigs)) { - secp256k1_scalar_negate(sigs, sigs); - if (recid) { - *recid ^= 1; - } - } - return 1; -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h deleted file mode 100644 index 42739a3bea..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECKEY_ -#define _SECP256K1_ECKEY_ - -#include - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h deleted file mode 100644 index ce38071ac2..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h +++ /dev/null @@ -1,99 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECKEY_IMPL_H_ -#define _SECP256K1_ECKEY_IMPL_H_ - -#include "eckey.h" - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { - if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { - secp256k1_fe x; - return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); - } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { - secp256k1_fe x, y; - if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { - return 0; - } - secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { - return 0; - } - return secp256k1_ge_is_valid_var(elem); - } else { - return 0; - } -} - -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { - if (secp256k1_ge_is_infinity(elem)) { - return 0; - } - secp256k1_fe_normalize_var(&elem->x); - secp256k1_fe_normalize_var(&elem->y); - secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { - *size = 33; - pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); - } else { - *size = 65; - pub[0] = 0x04; - secp256k1_fe_get_b32(&pub[33], &elem->y); - } - return 1; -} - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - secp256k1_scalar_add(key, key, tweak); - if (secp256k1_scalar_is_zero(key)) { - return 0; - } - return 1; -} - -static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_gej pt; - secp256k1_scalar one; - secp256k1_gej_set_ge(&pt, key); - secp256k1_scalar_set_int(&one, 1); - secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); - - if (secp256k1_gej_is_infinity(&pt)) { - return 0; - } - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_scalar_mul(key, key, tweak); - return 1; -} - -static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_scalar zero; - secp256k1_gej pt; - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_scalar_set_int(&zero, 0); - secp256k1_gej_set_ge(&pt, key); - secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h deleted file mode 100644 index 20484134f5..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_ -#define _SECP256K1_ECMULT_ - -#include "num.h" -#include "group.h" - -typedef struct { - /* For accelerating the computation of a*P + b*G: */ - secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ -#endif -} secp256k1_ecmult_context; - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); - -/** Double multiply: R = na*A + ng*G */ -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h deleted file mode 100644 index 2b0097655c..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_CONST_ -#define _SECP256K1_ECMULT_CONST_ - -#include "scalar.h" -#include "group.h" - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h deleted file mode 100644 index 0db314c48e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h +++ /dev/null @@ -1,239 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_CONST_IMPL_ -#define _SECP256K1_ECMULT_CONST_IMPL_ - -#include "scalar.h" -#include "group.h" -#include "ecmult_const.h" -#include "ecmult_impl.h" - -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) - -/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ -#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ - int m; \ - int abs_n = (n) * (((n) > 0) * 2 - 1); \ - int idx_n = abs_n / 2; \ - secp256k1_fe neg_y; \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ - for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ - /* This loop is used to avoid secret data in array indices. See - * the comment in ecmult_gen_impl.h for rationale. */ \ - secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ - secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ - } \ - (r)->infinity = 0; \ - secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ - secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ -} while(0) - - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) - * with the following guarantees: - * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) - * - each wnaf[i] is nonzero - * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w - * - * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar - * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) - * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 - * - * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 - */ -static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { - int global_sign; - int skew = 0; - int word = 0; - - /* 1 2 3 */ - int u_last; - int u; - - int flip; - int bit; - secp256k1_scalar neg_s; - int not_neg_one; - /* Note that we cannot handle even numbers by negating them to be odd, as is - * done in other implementations, since if our scalars were specified to have - * width < 256 for performance reasons, their negations would have width 256 - * and we'd lose any performance benefit. Instead, we use a technique from - * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) - * or 2 (for odd) to the number we are encoding, returning a skew value indicating - * this, and having the caller compensate after doing the multiplication. */ - - /* Negative numbers will be negated to keep their bit representation below the maximum width */ - flip = secp256k1_scalar_is_high(&s); - /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ !secp256k1_scalar_is_even(&s); - /* We check for negative one, since adding 2 to it will cause an overflow */ - secp256k1_scalar_negate(&neg_s, &s); - not_neg_one = !secp256k1_scalar_is_one(&neg_s); - secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); - /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects - * that we added two to it and flipped it. In fact for -1 these operations are - * identical. We only flipped, but since skewing is required (in the sense that - * the skew must be 1 or 2, never zero) and flipping is not, we need to change - * our flags to claim that we only skewed. */ - global_sign = secp256k1_scalar_cond_negate(&s, flip); - global_sign *= not_neg_one * 2 - 1; - skew = 1 << bit; - - /* 4 */ - u_last = secp256k1_scalar_shr_int(&s, w); - while (word * w < WNAF_BITS) { - int sign; - int even; - - /* 4.1 4.4 */ - u = secp256k1_scalar_shr_int(&s, w); - /* 4.2 */ - even = ((u & 1) == 0); - sign = 2 * (u_last > 0) - 1; - u += sign * even; - u_last -= sign * even * (1 << w); - - /* 4.3, adapted for global sign change */ - wnaf[word++] = u_last * global_sign; - - u_last = u; - } - wnaf[word] = u * global_sign; - - VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); - VERIFY_CHECK(word == WNAF_SIZE(w)); - return skew; -} - - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; - - int skew_1; - int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; - int skew_lam; - secp256k1_scalar q_1, q_lam; -#endif - - int i; - secp256k1_scalar sc = *scalar; - - /* build wnaf representation for q. */ -#ifdef USE_ENDOMORPHISM - /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); - skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); - skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); -#else - skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - */ - secp256k1_gej_set_ge(r, a); - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_normalize_weak(&pre_a[i].y); - } -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } -#endif - - /* first loop iteration (separated out so we can directly set r, rather - * than having it start at infinity, get doubled several times, then have - * its new value added to it) */ - i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); - secp256k1_gej_set_ge(r, &tmpa); -#ifdef USE_ENDOMORPHISM - i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); -#endif - /* remaining loop iterations */ - for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { - int n; - int j; - for (j = 0; j < WINDOW_A - 1; ++j) { - secp256k1_gej_double_nonzero(r, r, NULL); - } - - n = wnaf_1[i]; - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - VERIFY_CHECK(n != 0); - secp256k1_gej_add_ge(r, r, &tmpa); -#ifdef USE_ENDOMORPHISM - n = wnaf_lam[i]; - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - VERIFY_CHECK(n != 0); - secp256k1_gej_add_ge(r, r, &tmpa); -#endif - } - - secp256k1_fe_mul(&r->z, &r->z, &Z); - - { - /* Correct for wNAF skew */ - secp256k1_ge correction = *a; - secp256k1_ge_storage correction_1_stor; -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage correction_lam_stor; -#endif - secp256k1_ge_storage a2_stor; - secp256k1_gej tmpj; - secp256k1_gej_set_ge(&tmpj, &correction); - secp256k1_gej_double_var(&tmpj, &tmpj, NULL); - secp256k1_ge_set_gej(&correction, &tmpj); - secp256k1_ge_to_storage(&correction_1_stor, a); -#ifdef USE_ENDOMORPHISM - secp256k1_ge_to_storage(&correction_lam_stor, a); -#endif - secp256k1_ge_to_storage(&a2_stor, &correction); - - /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ - secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); -#endif - - /* Apply the correction */ - secp256k1_ge_from_storage(&correction, &correction_1_stor); - secp256k1_ge_neg(&correction, &correction); - secp256k1_gej_add_ge(r, r, &correction); - -#ifdef USE_ENDOMORPHISM - secp256k1_ge_from_storage(&correction, &correction_lam_stor); - secp256k1_ge_neg(&correction, &correction); - secp256k1_ge_mul_lambda(&correction, &correction); - secp256k1_gej_add_ge(r, r, &correction); -#endif - } -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h deleted file mode 100644 index eb2cc9ead6..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_ -#define _SECP256K1_ECMULT_GEN_ - -#include "scalar.h" -#include "group.h" - -typedef struct { - /* For accelerating the computation of a*G: - * To harden against timing attacks, use the following mechanism: - * * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. - * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: - * * U_i = U * 2^i (for i=0..62) - * * U_i = U * (1-2^63) (for i=63) - * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. - * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is - * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). - * None of the resulting prec group elements have a known scalar, and neither do any of - * the intermediate sums while computing a*G. - */ - secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ - secp256k1_scalar blind; - secp256k1_gej initial; -} secp256k1_ecmult_gen_context; - -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); -static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); -static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); - -/** Multiply with the generator: R = a*G */ -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); - -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h deleted file mode 100644 index 35f2546077..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h +++ /dev/null @@ -1,210 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ -#define _SECP256K1_ECMULT_GEN_IMPL_H_ - -#include "scalar.h" -#include "group.h" -#include "ecmult_gen.h" -#include "hash_impl.h" -#ifdef USE_ECMULT_STATIC_PRECOMPUTATION -#include "ecmult_static_context.h" -#endif -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { - ctx->prec = NULL; -} - -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - secp256k1_ge prec[1024]; - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; -#endif - - if (ctx->prec != NULL) { - return; - } -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ - { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - secp256k1_fe nums_x; - secp256k1_ge nums_ge; - int r; - r = secp256k1_fe_set_b32(&nums_x, nums_b32); - (void)r; - VERIFY_CHECK(r); - r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); - (void)r; - VERIFY_CHECK(r); - secp256k1_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); - } - - /* compute prec. */ - { - secp256k1_gej precj[1024]; /* Jacobian versions of prec. */ - secp256k1_gej gbase; - secp256k1_gej numsbase; - gbase = gj; /* 16^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < 64; j++) { - /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ - precj[j*16] = numsbase; - for (i = 1; i < 16; i++) { - secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); - } - /* Multiply gbase by 16. */ - for (i = 0; i < 4; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == 62) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); - } - } - secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); - } - for (j = 0; j < 64; j++) { - for (i = 0; i < 16; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); - } - } -#else - (void)cb; - ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context; -#endif - secp256k1_ecmult_gen_blind(ctx, NULL); -} - -static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { - return ctx->prec != NULL; -} - -static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { - if (src->prec == NULL) { - dst->prec = NULL; - } else { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); - memcpy(dst->prec, src->prec, sizeof(*dst->prec)); -#else - (void)cb; - dst->prec = src->prec; -#endif - dst->initial = src->initial; - dst->blind = src->blind; - } -} - -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - free(ctx->prec); -#endif - secp256k1_scalar_clear(&ctx->blind); - secp256k1_gej_clear(&ctx->initial); - ctx->prec = NULL; -} - -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { - secp256k1_ge add; - secp256k1_ge_storage adds; - secp256k1_scalar gnb; - int bits; - int i, j; - memset(&adds, 0, sizeof(adds)); - *r = ctx->initial; - /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ - secp256k1_scalar_add(&gnb, gn, &ctx->blind); - add.infinity = 0; - for (j = 0; j < 64; j++) { - bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); - for (i = 0; i < 16; i++) { - /** This uses a conditional move to avoid any secret data in array indexes. - * _Any_ use of secret indexes has been demonstrated to result in timing - * sidechannels, even when the cache-line access patterns are uniform. - * See also: - * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe - * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and - * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, - * by Dag Arne Osvik, Adi Shamir, and Eran Tromer - * (http://www.tau.ac.il/~tromer/papers/cache.pdf) - */ - secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); - } - secp256k1_ge_from_storage(&add, &adds); - secp256k1_gej_add_ge(r, r, &add); - } - bits = 0; - secp256k1_ge_clear(&add); - secp256k1_scalar_clear(&gnb); -} - -/* Setup blinding values for secp256k1_ecmult_gen. */ -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { - secp256k1_scalar b; - secp256k1_gej gb; - secp256k1_fe s; - unsigned char nonce32[32]; - secp256k1_rfc6979_hmac_sha256_t rng; - int retry; - unsigned char keydata[64] = {0}; - if (seed32 == NULL) { - /* When seed is NULL, reset the initial point and blinding value. */ - secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); - secp256k1_gej_neg(&ctx->initial, &ctx->initial); - secp256k1_scalar_set_int(&ctx->blind, 1); - } - /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ - secp256k1_scalar_get_b32(nonce32, &ctx->blind); - /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, - * and guards against weak or adversarial seeds. This is a simpler and safer interface than - * asking the caller for blinding values directly and expecting them to retry on failure. - */ - memcpy(keydata, nonce32, 32); - if (seed32 != NULL) { - memcpy(keydata + 32, seed32, 32); - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); - memset(keydata, 0, sizeof(keydata)); - /* Retry for out of range results to achieve uniformity. */ - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - retry = !secp256k1_fe_set_b32(&s, nonce32); - retry |= secp256k1_fe_is_zero(&s); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ - /* Randomize the projection to defend against multiplier sidechannels. */ - secp256k1_gej_rescale(&ctx->initial, &s); - secp256k1_fe_clear(&s); - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_scalar_set_b32(&b, nonce32, &retry); - /* A blinding value of 0 works, but would undermine the projection hardening. */ - retry |= secp256k1_scalar_is_zero(&b); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - memset(nonce32, 0, 32); - secp256k1_ecmult_gen(ctx, &gb, &b); - secp256k1_scalar_negate(&b, &b); - ctx->blind = b; - ctx->initial = gb; - secp256k1_scalar_clear(&b); - secp256k1_gej_clear(&gb); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h deleted file mode 100644 index 4e40104ad4..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h +++ /dev/null @@ -1,406 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_IMPL_H_ -#define _SECP256K1_ECMULT_IMPL_H_ - -#include - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need to lower these values for exhaustive tests because - * the tables cannot have infinities in them (this breaks the - * affine-isomorphism stuff which tracks z-ratios) */ -# if EXHAUSTIVE_TEST_ORDER > 128 -# define WINDOW_A 5 -# define WINDOW_G 8 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define WINDOW_A 4 -# define WINDOW_G 4 -# else -# define WINDOW_A 2 -# define WINDOW_G 2 -# endif -#else -/* optimal for 128-bit and 256-bit exponents. */ -#define WINDOW_A 5 -/** larger numbers may result in slightly better performance, at the cost of - exponentially larger precomputed tables. */ -#ifdef USE_ENDOMORPHISM -/** Two tables for window size 15: 1.375 MiB. */ -#define WINDOW_G 15 -#else -/** One table for window size 16: 1.375 MiB. */ -#define WINDOW_G 16 -#endif -#endif - -/** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) - -/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain - * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will - * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. - * Prej's Z values are undefined, except for the last value. - */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { - secp256k1_gej d; - secp256k1_ge a_ge, d_ge; - int i; - - VERIFY_CHECK(!a->infinity); - - secp256k1_gej_double_var(&d, a, NULL); - - /* - * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate - * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. - */ - d_ge.x = d.x; - d_ge.y = d.y; - d_ge.infinity = 0; - - secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); - prej[0].x = a_ge.x; - prej[0].y = a_ge.y; - prej[0].z = a->z; - prej[0].infinity = 0; - - zr[0] = d.z; - for (i = 1; i < n; i++) { - secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); - } - - /* - * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only - * the final point's z coordinate is actually used though, so just update that. - */ - secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); -} - -/** Fill a table 'pre' with precomputed odd multiples of a. - * - * There are two versions of this function: - * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its - * resulting point set to a single constant Z denominator, stores the X and Y - * coordinates as ge_storage points in pre, and stores the global Z in rz. - * It only operates on tables sized for WINDOW_A wnaf multiples. - * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its - * resulting point set to actually affine points, and stores those in pre. - * It operates on tables of any size, but uses heap-allocated temporaries. - * - * To compute a*P + b*G, we compute a table for P using the first function, - * and for G using the second (which requires an inverse, but it only needs to - * happen once). - */ -static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { - secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); - /* Bring them to the same Z denominator. */ - secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); -} - -static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { - secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); - secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); - secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); - int i; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); - /* Convert them in batch to affine coordinates. */ - secp256k1_ge_set_table_gej_var(prea, prej, zr, n); - /* Convert them to compact storage form. */ - for (i = 0; i < n; i++) { - secp256k1_ge_to_storage(&pre[i], &prea[i]); - } - - free(prea); - free(prej); - free(zr); -} - -/** The following two macro retrieves a particular odd multiple from a table - * of precomputed multiples. */ -#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - *(r) = (pre)[((n)-1)/2]; \ - } else { \ - secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ - } \ -} while(0) - -#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ - } else { \ - secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ - secp256k1_ge_neg((r), (r)); \ - } \ -} while(0) - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { - ctx->pre_g = NULL; -#ifdef USE_ENDOMORPHISM - ctx->pre_g_128 = NULL; -#endif -} - -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { - secp256k1_gej gj; - - if (ctx->pre_g != NULL) { - return; - } - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* precompute the tables with odd multiples */ - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); - -#ifdef USE_ENDOMORPHISM - { - secp256k1_gej g_128j; - int i; - - ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* calculate 2^128*generator */ - g_128j = gj; - for (i = 0; i < 128; i++) { - secp256k1_gej_double_var(&g_128j, &g_128j, NULL); - } - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); - } -#endif -} - -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { - if (src->pre_g == NULL) { - dst->pre_g = NULL; - } else { - size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g, src->pre_g, size); - } -#ifdef USE_ENDOMORPHISM - if (src->pre_g_128 == NULL) { - dst->pre_g_128 = NULL; - } else { - size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g_128, src->pre_g_128, size); - } -#endif -} - -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { - return ctx->pre_g != NULL; -} - -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { - free(ctx->pre_g); -#ifdef USE_ENDOMORPHISM - free(ctx->pre_g_128); -#endif - secp256k1_ecmult_context_init(ctx); -} - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), - * with the following guarantees: - * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) - * - two non-zero entries in wnaf are separated by at least w-1 zeroes. - * - the number of set values in wnaf is returned. This number is at most 256, and at most one more - * than the number of bits in the (absolute value) of the input. - */ -static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { - secp256k1_scalar s = *a; - int last_set_bit = -1; - int bit = 0; - int sign = 1; - int carry = 0; - - VERIFY_CHECK(wnaf != NULL); - VERIFY_CHECK(0 <= len && len <= 256); - VERIFY_CHECK(a != NULL); - VERIFY_CHECK(2 <= w && w <= 31); - - memset(wnaf, 0, len * sizeof(wnaf[0])); - - if (secp256k1_scalar_get_bits(&s, 255, 1)) { - secp256k1_scalar_negate(&s, &s); - sign = -1; - } - - while (bit < len) { - int now; - int word; - if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { - bit++; - continue; - } - - now = w; - if (now > len - bit) { - now = len - bit; - } - - word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; - - carry = (word >> (w-1)) & 1; - word -= carry << w; - - wnaf[bit] = sign * word; - last_set_bit = bit; - - bit += now; - } -#ifdef VERIFY - CHECK(carry == 0); - while (bit < 256) { - CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); - } -#endif - return last_set_bit + 1; -} - -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_scalar na_1, na_lam; - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; - int wnaf_na_1[130]; - int wnaf_na_lam[130]; - int bits_na_1; - int bits_na_lam; - int wnaf_ng_1[129]; - int bits_ng_1; - int wnaf_ng_128[129]; - int bits_ng_128; -#else - int wnaf_na[256]; - int bits_na; - int wnaf_ng[256]; - int bits_ng; -#endif - int i; - int bits; - -#ifdef USE_ENDOMORPHISM - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&na_1, &na_lam, na); - - /* build wnaf representation for na_1 and na_lam. */ - bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); - bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); - VERIFY_CHECK(bits_na_1 <= 130); - VERIFY_CHECK(bits_na_lam <= 130); - bits = bits_na_1; - if (bits_na_lam > bits) { - bits = bits_na_lam; - } -#else - /* build wnaf representation for na. */ - bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); - bits = bits_na; -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - * The exception is the precomputed G table points, which are actually - * affine. Compared to the base used for other points, they have a Z ratio - * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same - * isomorphism to efficiently add with a known Z inverse. - */ - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); - -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } - - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; - } -#else - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; - } -#endif - - secp256k1_gej_set_infinity(r); - - for (i = bits - 1; i >= 0; i--) { - int n; - secp256k1_gej_double_var(r, r, NULL); -#ifdef USE_ENDOMORPHISM - if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_na_lam && (n = wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } - if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#else - if (i < bits_na && (n = wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng && (n = wnaf_ng[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#endif - } - - if (!r->infinity) { - secp256k1_fe_mul(&r->z, &r->z, &Z); - } -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h deleted file mode 100644 index bbb1ee866c..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h +++ /dev/null @@ -1,132 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_ -#define _SECP256K1_FIELD_ - -/** Field element module. - * - * Field elements can be represented in several ways, but code accessing - * it (and implementations) need to take certain properties into account: - * - Each field element can be normalized or not. - * - Each field element has a magnitude, which represents how far away - * its representation is away from normalization. Normalized elements - * always have a magnitude of 1, but a magnitude of 1 doesn't imply - * normality. - */ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_FIELD_10X26) -#include "field_10x26.h" -#elif defined(USE_FIELD_5X52) -#include "field_5x52.h" -#else -#error "Please select field implementation" -#endif - -#include "util.h" - -/** Normalize a field element. */ -static void secp256k1_fe_normalize(secp256k1_fe *r); - -/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */ -static void secp256k1_fe_normalize_weak(secp256k1_fe *r); - -/** Normalize a field element, without constant-time guarantee. */ -static void secp256k1_fe_normalize_var(secp256k1_fe *r); - -/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field - * implementation may optionally normalize the input, but this should not be relied upon. */ -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r); - -/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field - * implementation may optionally normalize the input, but this should not be relied upon. */ -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); - -/** Set a field element equal to a small integer. Resulting field element is normalized. */ -static void secp256k1_fe_set_int(secp256k1_fe *r, int a); - -/** Sets a field element equal to zero, initializing all fields. */ -static void secp256k1_fe_clear(secp256k1_fe *a); - -/** Verify whether a field element is zero. Requires the input to be normalized. */ -static int secp256k1_fe_is_zero(const secp256k1_fe *a); - -/** Check the "oddness" of a field element. Requires the input to be normalized. */ -static int secp256k1_fe_is_odd(const secp256k1_fe *a); - -/** Compare two field elements. Requires magnitude-1 inputs. */ -static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Same as secp256k1_fe_equal, but may be variable time. */ -static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Compare two field elements. Requires both inputs to be normalized */ -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */ -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); - -/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input - * as an argument. The magnitude of the output is one higher. */ -static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); - -/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that - * small integer. */ -static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); - -/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ -static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); - -/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. - * The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); - -/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. - * The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); - -/** If a has a square root, it is computed in r and 1 is returned. If a does not - * have a square root, the root of its negation is computed and 0 is returned. - * The input's magnitude can be at most 8. The output magnitude is 1 (but not - * guaranteed to be normalized). The result in r will always be a square - * itself. */ -static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); - -/** Checks whether a field element is a quadratic residue. */ -static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); - -/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be - * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); - -/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ -static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); - -/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be - * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and - * outputs must not overlap in memory. */ -static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len); - -/** Convert a field element to the storage type. */ -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); - -/** Convert a field element back from the storage type. */ -static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h deleted file mode 100644 index 61ee1e0965..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ - -#include - -typedef struct { - /* X = sum(i=0..9, elem[i]*2^26) mod n */ - uint32_t n[10]; -#ifdef VERIFY - int magnitude; - int normalized; -#endif -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) & 0x3FFFFFFUL, \ - (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ - (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ - (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ - (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ - (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ - (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ - (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ - (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ - (((uint32_t)d7) >> 10) \ -} - -#ifdef VERIFY -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} -#else -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} -#endif - -typedef struct { - uint32_t n[8]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} -#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h deleted file mode 100644 index 5fb092f1be..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h +++ /dev/null @@ -1,1140 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ - -#include "util.h" -#include "num.h" -#include "field.h" - -#ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { - const uint32_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; - r &= (d[0] <= 0x3FFFFFFUL * m); - r &= (d[1] <= 0x3FFFFFFUL * m); - r &= (d[2] <= 0x3FFFFFFUL * m); - r &= (d[3] <= 0x3FFFFFFUL * m); - r &= (d[4] <= 0x3FFFFFFUL * m); - r &= (d[5] <= 0x3FFFFFFUL * m); - r &= (d[6] <= 0x3FFFFFFUL * m); - r &= (d[7] <= 0x3FFFFFFUL * m); - r &= (d[8] <= 0x3FFFFFFUL * m); - r &= (d[9] <= 0x03FFFFFUL * m); - r &= (a->magnitude >= 0); - r &= (a->magnitude <= 32); - if (a->normalized) { - r &= (a->magnitude <= 1); - if (r && (d[9] == 0x03FFFFFUL)) { - uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; - if (mid == 0x3FFFFFFUL) { - r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); - } - } - } - VERIFY_CHECK(r == 1); -} -#endif - -static void secp256k1_fe_normalize(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - if (x) { - t0 += 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint32_t z0, z1; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t z0, z1; - uint32_t x; - - t0 = r->n[0]; - t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - x = t9 >> 22; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0x3FFFFFFUL; - z1 = z0 ^ 0x3D0UL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - t4 = r->n[4]; - t5 = r->n[5]; - t6 = r->n[6]; - t7 = r->n[7]; - t8 = r->n[8]; - - t9 &= 0x03FFFFFUL; - t1 += (x << 6); - - t1 += (t0 >> 26); - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { - const uint32_t *t = a->n; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return a->n[0] & 1; -} - -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - int i; -#ifdef VERIFY - a->magnitude = 0; - a->normalized = 1; -#endif - for (i=0; i<10; i++) { - a->n[i] = 0; - } -} - -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); -#endif - for (i = 9; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; - } - } - if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { - return 0; - } -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif - return 1; -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); - } - r[31-i] = c; - } -} - -SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); -#endif - r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; - r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; - r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; - r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; - r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; - r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; -#ifdef VERIFY - r->magnitude = m + 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; - r->n[5] *= a; - r->n[6] *= a; - r->n[7] *= a; - r->n[8] *= a; - r->n[9] *= a; -#ifdef VERIFY - r->magnitude *= a; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - secp256k1_fe_verify(a); -#endif - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; - r->n[5] += a->n[5]; - r->n[6] += a->n[6]; - r->n[7] += a->n[7]; - r->n[8] += a->n[8]; - r->n[9] += a->n[9]; -#ifdef VERIFY - r->magnitude += a->magnitude; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -#if defined(USE_EXTERNAL_ASM) - -/* External assembler implementation */ -void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); -void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); - -#else - -#ifdef VERIFY -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#else -#define VERIFY_BITS(x, n) do { } while(0) -#endif - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - VERIFY_BITS(b[0], 30); - VERIFY_BITS(b[1], 30); - VERIFY_BITS(b[2], 30); - VERIFY_BITS(b[3], 30); - VERIFY_BITS(b[4], 30); - VERIFY_BITS(b[5], 30); - VERIFY_BITS(b[6], 30); - VERIFY_BITS(b[7], 30); - VERIFY_BITS(b[8], 30); - VERIFY_BITS(b[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)a[0] * b[9] - + (uint64_t)a[1] * b[8] - + (uint64_t)a[2] * b[7] - + (uint64_t)a[3] * b[6] - + (uint64_t)a[4] * b[5] - + (uint64_t)a[5] * b[4] - + (uint64_t)a[6] * b[3] - + (uint64_t)a[7] * b[2] - + (uint64_t)a[8] * b[1] - + (uint64_t)a[9] * b[0]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * b[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)a[1] * b[9] - + (uint64_t)a[2] * b[8] - + (uint64_t)a[3] * b[7] - + (uint64_t)a[4] * b[6] - + (uint64_t)a[5] * b[5] - + (uint64_t)a[6] * b[4] - + (uint64_t)a[7] * b[3] - + (uint64_t)a[8] * b[2] - + (uint64_t)a[9] * b[1]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)a[0] * b[1] - + (uint64_t)a[1] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)a[2] * b[9] - + (uint64_t)a[3] * b[8] - + (uint64_t)a[4] * b[7] - + (uint64_t)a[5] * b[6] - + (uint64_t)a[6] * b[5] - + (uint64_t)a[7] * b[4] - + (uint64_t)a[8] * b[3] - + (uint64_t)a[9] * b[2]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)a[0] * b[2] - + (uint64_t)a[1] * b[1] - + (uint64_t)a[2] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)a[3] * b[9] - + (uint64_t)a[4] * b[8] - + (uint64_t)a[5] * b[7] - + (uint64_t)a[6] * b[6] - + (uint64_t)a[7] * b[5] - + (uint64_t)a[8] * b[4] - + (uint64_t)a[9] * b[3]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[3] - + (uint64_t)a[1] * b[2] - + (uint64_t)a[2] * b[1] - + (uint64_t)a[3] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)a[4] * b[9] - + (uint64_t)a[5] * b[8] - + (uint64_t)a[6] * b[7] - + (uint64_t)a[7] * b[6] - + (uint64_t)a[8] * b[5] - + (uint64_t)a[9] * b[4]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[4] - + (uint64_t)a[1] * b[3] - + (uint64_t)a[2] * b[2] - + (uint64_t)a[3] * b[1] - + (uint64_t)a[4] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[5] * b[9] - + (uint64_t)a[6] * b[8] - + (uint64_t)a[7] * b[7] - + (uint64_t)a[8] * b[6] - + (uint64_t)a[9] * b[5]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[5] - + (uint64_t)a[1] * b[4] - + (uint64_t)a[2] * b[3] - + (uint64_t)a[3] * b[2] - + (uint64_t)a[4] * b[1] - + (uint64_t)a[5] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[6] * b[9] - + (uint64_t)a[7] * b[8] - + (uint64_t)a[8] * b[7] - + (uint64_t)a[9] * b[6]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[6] - + (uint64_t)a[1] * b[5] - + (uint64_t)a[2] * b[4] - + (uint64_t)a[3] * b[3] - + (uint64_t)a[4] * b[2] - + (uint64_t)a[5] * b[1] - + (uint64_t)a[6] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[7] * b[9] - + (uint64_t)a[8] * b[8] - + (uint64_t)a[9] * b[7]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[7] - + (uint64_t)a[1] * b[6] - + (uint64_t)a[2] * b[5] - + (uint64_t)a[3] * b[4] - + (uint64_t)a[4] * b[3] - + (uint64_t)a[5] * b[2] - + (uint64_t)a[6] * b[1] - + (uint64_t)a[7] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[8] * b[9] - + (uint64_t)a[9] * b[8]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[8] - + (uint64_t)a[1] * b[7] - + (uint64_t)a[2] * b[6] - + (uint64_t)a[3] * b[5] - + (uint64_t)a[4] * b[4] - + (uint64_t)a[5] * b[3] - + (uint64_t)a[6] * b[2] - + (uint64_t)a[7] * b[1] - + (uint64_t)a[8] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * b[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)(a[0]*2) * a[9] - + (uint64_t)(a[1]*2) * a[8] - + (uint64_t)(a[2]*2) * a[7] - + (uint64_t)(a[3]*2) * a[6] - + (uint64_t)(a[4]*2) * a[5]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * a[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)(a[1]*2) * a[9] - + (uint64_t)(a[2]*2) * a[8] - + (uint64_t)(a[3]*2) * a[7] - + (uint64_t)(a[4]*2) * a[6] - + (uint64_t)a[5] * a[5]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)(a[0]*2) * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)(a[2]*2) * a[9] - + (uint64_t)(a[3]*2) * a[8] - + (uint64_t)(a[4]*2) * a[7] - + (uint64_t)(a[5]*2) * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[2] - + (uint64_t)a[1] * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)(a[3]*2) * a[9] - + (uint64_t)(a[4]*2) * a[8] - + (uint64_t)(a[5]*2) * a[7] - + (uint64_t)a[6] * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[3] - + (uint64_t)(a[1]*2) * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)(a[4]*2) * a[9] - + (uint64_t)(a[5]*2) * a[8] - + (uint64_t)(a[6]*2) * a[7]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[4] - + (uint64_t)(a[1]*2) * a[3] - + (uint64_t)a[2] * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[5]*2) * a[9] - + (uint64_t)(a[6]*2) * a[8] - + (uint64_t)a[7] * a[7]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[5] - + (uint64_t)(a[1]*2) * a[4] - + (uint64_t)(a[2]*2) * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[6]*2) * a[9] - + (uint64_t)(a[7]*2) * a[8]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[6] - + (uint64_t)(a[1]*2) * a[5] - + (uint64_t)(a[2]*2) * a[4] - + (uint64_t)a[3] * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[7]*2) * a[9] - + (uint64_t)a[8] * a[8]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[7] - + (uint64_t)(a[1]*2) * a[6] - + (uint64_t)(a[2]*2) * a[5] - + (uint64_t)(a[3]*2) * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[8]*2) * a[9]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[8] - + (uint64_t)(a[1]*2) * a[7] - + (uint64_t)(a[2]*2) * a[6] - + (uint64_t)(a[3]*2) * a[5] - + (uint64_t)a[4] * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * a[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} -#endif - -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); - VERIFY_CHECK(r != b); -#endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); -#endif - secp256k1_fe_sqr_inner(r->n, a->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint32_t mask0, mask1; - mask0 = flag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); - r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); - r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); -#ifdef VERIFY - if (a->magnitude > r->magnitude) { - r->magnitude = a->magnitude; - } - r->normalized &= a->normalized; -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint32_t mask0, mask1; - mask0 = flag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); -} - -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); -#endif - r->n[0] = a->n[0] | a->n[1] << 26; - r->n[1] = a->n[1] >> 6 | a->n[2] << 20; - r->n[2] = a->n[2] >> 12 | a->n[3] << 14; - r->n[3] = a->n[3] >> 18 | a->n[4] << 8; - r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; - r->n[5] = a->n[6] >> 4 | a->n[7] << 22; - r->n[6] = a->n[7] >> 10 | a->n[8] << 16; - r->n[7] = a->n[8] >> 16 | a->n[9] << 10; -} - -static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0x3FFFFFFUL; - r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); - r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); - r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); - r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); - r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; - r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); - r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); - r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); - r->n[9] = a->n[7] >> 10; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; -#endif -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h deleted file mode 100644 index 8e69a560dc..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ - -#include - -typedef struct { - /* X = sum(i=0..4, elem[i]*2^52) mod n */ - uint64_t n[5]; -#ifdef VERIFY - int magnitude; - int normalized; -#endif -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ - ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ - ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ - ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ - ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ -} - -#ifdef VERIFY -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} -#else -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} -#endif - -typedef struct { - uint64_t n[4]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ - (d0) | (((uint64_t)(d1)) << 32), \ - (d2) | (((uint64_t)(d3)) << 32), \ - (d4) | (((uint64_t)(d5)) << 32), \ - (d6) | (((uint64_t)(d7)) << 32) \ -}} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h deleted file mode 100644 index 98cc004bf0..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h +++ /dev/null @@ -1,502 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/** - * Changelog: - * - March 2013, Diederik Huys: original version - * - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm - * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly - */ - -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { -/** - * Registers: rdx:rax = multiplication accumulator - * r9:r8 = c - * r15:rcx = d - * r10-r14 = a0-a4 - * rbx = b - * rdi = r - * rsi = a / t? - */ - uint64_t tmp1, tmp2, tmp3; -__asm__ __volatile__( - "movq 0(%%rsi),%%r10\n" - "movq 8(%%rsi),%%r11\n" - "movq 16(%%rsi),%%r12\n" - "movq 24(%%rsi),%%r13\n" - "movq 32(%%rsi),%%r14\n" - - /* d += a3 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r13\n" - "movq %%rax,%%rcx\n" - "movq %%rdx,%%r15\n" - /* d += a2 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d = a0 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c = a4 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r14\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += (c & M) * R */ - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* t3 (tmp1) = d & M */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - "movq %%rsi,%q1\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* d += a4 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a0 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += c * R */ - "movq %%r8,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* t4 = d & M (%%rsi) */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* tx = t4 >> 48 (tmp3) */ - "movq %%rsi,%%rax\n" - "shrq $48,%%rax\n" - "movq %%rax,%q3\n" - /* t4 &= (M >> 4) (tmp2) */ - "movq $0xffffffffffff,%%rax\n" - "andq %%rax,%%rsi\n" - "movq %%rsi,%q2\n" - /* c = a0 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r10\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += a4 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* u0 = d & M (%%rsi) */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* u0 = (u0 << 4) | tx (%%rsi) */ - "shlq $4,%%rsi\n" - "movq %q3,%%rax\n" - "orq %%rax,%%rsi\n" - /* c += u0 * (R >> 4) */ - "movq $0x1000003d1,%%rax\n" - "mulq %%rsi\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[0] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,0(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a1 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a0 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a4 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c += (d & M) * R */ - "movq %%rcx,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* r[1] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,8(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a2 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a1 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a0 * b2 (last use of %%r10 = a0) */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */ - "movq %q2,%%rsi\n" - "movq %q1,%%r10\n" - /* d += a4 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c += (d & M) * R */ - "movq %%rcx,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 (%%rcx only) */ - "shrdq $52,%%r15,%%rcx\n" - /* r[2] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,16(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += t3 */ - "addq %%r10,%%r8\n" - /* c += d * R */ - "movq %%rcx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[3] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,24(%%rdi)\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* c += t4 (%%r8 only) */ - "addq %%rsi,%%r8\n" - /* r[4] = c */ - "movq %%r8,32(%%rdi)\n" -: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) -: "b"(b), "D"(r) -: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" -); -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { -/** - * Registers: rdx:rax = multiplication accumulator - * r9:r8 = c - * rcx:rbx = d - * r10-r14 = a0-a4 - * r15 = M (0xfffffffffffff) - * rdi = r - * rsi = a / t? - */ - uint64_t tmp1, tmp2, tmp3; -__asm__ __volatile__( - "movq 0(%%rsi),%%r10\n" - "movq 8(%%rsi),%%r11\n" - "movq 16(%%rsi),%%r12\n" - "movq 24(%%rsi),%%r13\n" - "movq 32(%%rsi),%%r14\n" - "movq $0xfffffffffffff,%%r15\n" - - /* d = (a0*2) * a3 */ - "leaq (%%r10,%%r10,1),%%rax\n" - "mulq %%r13\n" - "movq %%rax,%%rbx\n" - "movq %%rdx,%%rcx\n" - /* d += (a1*2) * a2 */ - "leaq (%%r11,%%r11,1),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c = a4 * a4 */ - "movq %%r14,%%rax\n" - "mulq %%r14\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += (c & M) * R */ - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* t3 (tmp1) = d & M */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - "movq %%rsi,%q1\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* a4 *= 2 */ - "addq %%r14,%%r14\n" - /* d += a0 * a4 */ - "movq %%r10,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d+= (a1*2) * a3 */ - "leaq (%%r11,%%r11,1),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += a2 * a2 */ - "movq %%r12,%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += c * R */ - "movq %%r8,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* t4 = d & M (%%rsi) */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* tx = t4 >> 48 (tmp3) */ - "movq %%rsi,%%rax\n" - "shrq $48,%%rax\n" - "movq %%rax,%q3\n" - /* t4 &= (M >> 4) (tmp2) */ - "movq $0xffffffffffff,%%rax\n" - "andq %%rax,%%rsi\n" - "movq %%rsi,%q2\n" - /* c = a0 * a0 */ - "movq %%r10,%%rax\n" - "mulq %%r10\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += a1 * a4 */ - "movq %%r11,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += (a2*2) * a3 */ - "leaq (%%r12,%%r12,1),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* u0 = d & M (%%rsi) */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* u0 = (u0 << 4) | tx (%%rsi) */ - "shlq $4,%%rsi\n" - "movq %q3,%%rax\n" - "orq %%rax,%%rsi\n" - /* c += u0 * (R >> 4) */ - "movq $0x1000003d1,%%rax\n" - "mulq %%rsi\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[0] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,0(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* a0 *= 2 */ - "addq %%r10,%%r10\n" - /* c += a0 * a1 */ - "movq %%r10,%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a2 * a4 */ - "movq %%r12,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += a3 * a3 */ - "movq %%r13,%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c += (d & M) * R */ - "movq %%rbx,%%rax\n" - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* r[1] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,8(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a0 * a2 (last use of %%r10) */ - "movq %%r10,%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */ - "movq %q2,%%rsi\n" - "movq %q1,%%r10\n" - /* c += a1 * a1 */ - "movq %%r11,%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a3 * a4 */ - "movq %%r13,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c += (d & M) * R */ - "movq %%rbx,%%rax\n" - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 (%%rbx only) */ - "shrdq $52,%%rcx,%%rbx\n" - /* r[2] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,16(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += t3 */ - "addq %%r10,%%r8\n" - /* c += d * R */ - "movq %%rbx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[3] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,24(%%rdi)\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* c += t4 (%%r8 only) */ - "addq %%rsi,%%r8\n" - /* r[4] = c */ - "movq %%r8,32(%%rdi)\n" -: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) -: "D"(r) -: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" -); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h deleted file mode 100644 index dd88f38c77..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h +++ /dev/null @@ -1,451 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "util.h" -#include "num.h" -#include "field.h" - -#if defined(USE_ASM_X86_64) -#include "field_5x52_asm_impl.h" -#else -#include "field_5x52_int128_impl.h" -#endif - -/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, - * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, - * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element - * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations - * accept any input with magnitude at most M, and have different rules for propagating magnitude to their - * output. - */ - -#ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { - const uint64_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; - /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); - r &= (a->magnitude >= 0); - r &= (a->magnitude <= 2048); - if (a->normalized) { - r &= (a->magnitude <= 1); - if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { - r &= (d[0] < 0xFFFFEFFFFFC2FULL); - } - } - VERIFY_CHECK(r == 1); -} -#endif - -static void secp256k1_fe_normalize(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - if (x) { - t0 += 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint64_t z0, z1; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { - uint64_t t0, t1, t2, t3, t4; - uint64_t z0, z1; - uint64_t x; - - t0 = r->n[0]; - t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - x = t4 >> 48; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0xFFFFFFFFFFFFFULL; - z1 = z0 ^ 0x1000003D0ULL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - - t4 &= 0x0FFFFFFFFFFFFULL; - - t1 += (t0 >> 52); - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { - const uint64_t *t = a->n; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return a->n[0] & 1; -} - -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - int i; -#ifdef VERIFY - a->magnitude = 0; - a->normalized = 1; -#endif - for (i=0; i<5; i++) { - a->n[i] = 0; - } -} - -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); -#endif - for (i = 4; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; - } - } - if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { - return 0; - } -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif - return 1; -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); - } - r[31-i] = c; - } -} - -SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); -#endif - r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; -#ifdef VERIFY - r->magnitude = m + 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; -#ifdef VERIFY - r->magnitude *= a; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - secp256k1_fe_verify(a); -#endif - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; -#ifdef VERIFY - r->magnitude += a->magnitude; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); - VERIFY_CHECK(r != b); -#endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); -#endif - secp256k1_fe_sqr_inner(r->n, a->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint64_t mask0, mask1; - mask0 = flag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); -#ifdef VERIFY - if (a->magnitude > r->magnitude) { - r->magnitude = a->magnitude; - } - r->normalized &= a->normalized; -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint64_t mask0, mask1; - mask0 = flag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); -} - -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); -#endif - r->n[0] = a->n[0] | a->n[1] << 52; - r->n[1] = a->n[1] >> 12 | a->n[2] << 40; - r->n[2] = a->n[2] >> 24 | a->n[3] << 28; - r->n[3] = a->n[3] >> 36 | a->n[4] << 16; -} - -static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; - r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); - r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); - r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); - r->n[4] = a->n[3] >> 16; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; -#endif -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h deleted file mode 100644 index 0bf22bdd3e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h +++ /dev/null @@ -1,277 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ - -#include - -#ifdef VERIFY -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#else -#define VERIFY_BITS(x, n) do { } while(0) -#endif - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { - uint128_t c, d; - uint64_t t3, t4, tx, u0; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - VERIFY_BITS(b[0], 56); - VERIFY_BITS(b[1], 56); - VERIFY_BITS(b[2], 56); - VERIFY_BITS(b[3], 56); - VERIFY_BITS(b[4], 52); - VERIFY_CHECK(r != b); - - /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - d = (uint128_t)a0 * b[3] - + (uint128_t)a1 * b[2] - + (uint128_t)a2 * b[1] - + (uint128_t)a3 * b[0]; - VERIFY_BITS(d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - c = (uint128_t)a4 * b[4]; - VERIFY_BITS(c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - d += (c & M) * R; c >>= 52; - VERIFY_BITS(d, 115); - VERIFY_BITS(c, 60); - /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = d & M; d >>= 52; - VERIFY_BITS(t3, 52); - VERIFY_BITS(d, 63); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - d += (uint128_t)a0 * b[4] - + (uint128_t)a1 * b[3] - + (uint128_t)a2 * b[2] - + (uint128_t)a3 * b[1] - + (uint128_t)a4 * b[0]; - VERIFY_BITS(d, 115); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - d += c * R; - VERIFY_BITS(d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = d & M; d >>= 52; - VERIFY_BITS(t4, 52); - VERIFY_BITS(d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - c = (uint128_t)a0 * b[0]; - VERIFY_BITS(c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - d += (uint128_t)a1 * b[4] - + (uint128_t)a2 * b[3] - + (uint128_t)a3 * b[2] - + (uint128_t)a4 * b[1]; - VERIFY_BITS(d, 115); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = d & M; d >>= 52; - VERIFY_BITS(u0, 52); - VERIFY_BITS(d, 63); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - c += (uint128_t)u0 * (R >> 4); - VERIFY_BITS(c, 115); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = c & M; c >>= 52; - VERIFY_BITS(r[0], 52); - VERIFY_BITS(c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - c += (uint128_t)a0 * b[1] - + (uint128_t)a1 * b[0]; - VERIFY_BITS(c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - d += (uint128_t)a2 * b[4] - + (uint128_t)a3 * b[3] - + (uint128_t)a4 * b[2]; - VERIFY_BITS(d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = c & M; c >>= 52; - VERIFY_BITS(r[1], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - c += (uint128_t)a0 * b[2] - + (uint128_t)a1 * b[1] - + (uint128_t)a2 * b[0]; - VERIFY_BITS(c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint128_t)a3 * b[4] - + (uint128_t)a4 * b[3]; - VERIFY_BITS(d, 114); - /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = c & M; c >>= 52; - VERIFY_BITS(r[2], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R + t3; - VERIFY_BITS(c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = c & M; c >>= 52; - VERIFY_BITS(r[3], 52); - VERIFY_BITS(c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += t4; - VERIFY_BITS(c, 49); - /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = c; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { - uint128_t c, d; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - int64_t t3, t4, tx, u0; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - - /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - d = (uint128_t)(a0*2) * a3 - + (uint128_t)(a1*2) * a2; - VERIFY_BITS(d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - c = (uint128_t)a4 * a4; - VERIFY_BITS(c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - d += (c & M) * R; c >>= 52; - VERIFY_BITS(d, 115); - VERIFY_BITS(c, 60); - /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = d & M; d >>= 52; - VERIFY_BITS(t3, 52); - VERIFY_BITS(d, 63); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - a4 *= 2; - d += (uint128_t)a0 * a4 - + (uint128_t)(a1*2) * a3 - + (uint128_t)a2 * a2; - VERIFY_BITS(d, 115); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - d += c * R; - VERIFY_BITS(d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = d & M; d >>= 52; - VERIFY_BITS(t4, 52); - VERIFY_BITS(d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - c = (uint128_t)a0 * a0; - VERIFY_BITS(c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - d += (uint128_t)a1 * a4 - + (uint128_t)(a2*2) * a3; - VERIFY_BITS(d, 114); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = d & M; d >>= 52; - VERIFY_BITS(u0, 52); - VERIFY_BITS(d, 62); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - c += (uint128_t)u0 * (R >> 4); - VERIFY_BITS(c, 113); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = c & M; c >>= 52; - VERIFY_BITS(r[0], 52); - VERIFY_BITS(c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - a0 *= 2; - c += (uint128_t)a0 * a1; - VERIFY_BITS(c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - d += (uint128_t)a2 * a4 - + (uint128_t)a3 * a3; - VERIFY_BITS(d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = c & M; c >>= 52; - VERIFY_BITS(r[1], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - c += (uint128_t)a0 * a2 - + (uint128_t)a1 * a1; - VERIFY_BITS(c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint128_t)a3 * a4; - VERIFY_BITS(d, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = c & M; c >>= 52; - VERIFY_BITS(r[2], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += d * R + t3; - VERIFY_BITS(c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = c & M; c >>= 52; - VERIFY_BITS(r[3], 52); - VERIFY_BITS(c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += t4; - VERIFY_BITS(c, 49); - /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = c; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h deleted file mode 100644 index 5127b279bc..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h +++ /dev/null @@ -1,315 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_IMPL_H_ -#define _SECP256K1_FIELD_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "util.h" - -#if defined(USE_FIELD_10X26) -#include "field_10x26_impl.h" -#elif defined(USE_FIELD_5X52) -#include "field_5x52_impl.h" -#else -#error "Please select field implementation" -#endif - -SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe na; - secp256k1_fe_negate(&na, a, 1); - secp256k1_fe_add(&na, b); - return secp256k1_fe_normalizes_to_zero(&na); -} - -SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe na; - secp256k1_fe_negate(&na, a, 1); - secp256k1_fe_add(&na, b); - return secp256k1_fe_normalizes_to_zero_var(&na); -} - -static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { - /** Given that p is congruent to 3 mod 4, we can compute the square root of - * a mod p as the (p+1)/4'th power of a. - * - * As (p+1)/4 is an even number, it will have the same result for a and for - * (-a). Only one of these two numbers actually has a square root however, - * so we test at the end by squaring and comparing to the input. - * Also because (p+1)/4 is an even number, the computed square root is - * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). - */ - secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; - int j; - - /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in - * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - */ - - secp256k1_fe_sqr(&x2, a); - secp256k1_fe_mul(&x2, &x2, a); - - secp256k1_fe_sqr(&x3, &x2); - secp256k1_fe_mul(&x3, &x3, a); - - x6 = x3; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x6, &x6); - } - secp256k1_fe_mul(&x6, &x6, &x3); - - x9 = x6; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x9, &x9); - } - secp256k1_fe_mul(&x9, &x9, &x3); - - x11 = x9; - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&x11, &x11); - } - secp256k1_fe_mul(&x11, &x11, &x2); - - x22 = x11; - for (j=0; j<11; j++) { - secp256k1_fe_sqr(&x22, &x22); - } - secp256k1_fe_mul(&x22, &x22, &x11); - - x44 = x22; - for (j=0; j<22; j++) { - secp256k1_fe_sqr(&x44, &x44); - } - secp256k1_fe_mul(&x44, &x44, &x22); - - x88 = x44; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x88, &x88); - } - secp256k1_fe_mul(&x88, &x88, &x44); - - x176 = x88; - for (j=0; j<88; j++) { - secp256k1_fe_sqr(&x176, &x176); - } - secp256k1_fe_mul(&x176, &x176, &x88); - - x220 = x176; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x220, &x220); - } - secp256k1_fe_mul(&x220, &x220, &x44); - - x223 = x220; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x223, &x223); - } - secp256k1_fe_mul(&x223, &x223, &x3); - - /* The final result is then assembled using a sliding window over the blocks. */ - - t1 = x223; - for (j=0; j<23; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x22); - for (j=0; j<6; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x2); - secp256k1_fe_sqr(&t1, &t1); - secp256k1_fe_sqr(r, &t1); - - /* Check that a square root was actually calculated */ - - secp256k1_fe_sqr(&t1, r); - return secp256k1_fe_equal(&t1, a); -} - -static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { - secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; - int j; - - /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in - * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - */ - - secp256k1_fe_sqr(&x2, a); - secp256k1_fe_mul(&x2, &x2, a); - - secp256k1_fe_sqr(&x3, &x2); - secp256k1_fe_mul(&x3, &x3, a); - - x6 = x3; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x6, &x6); - } - secp256k1_fe_mul(&x6, &x6, &x3); - - x9 = x6; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x9, &x9); - } - secp256k1_fe_mul(&x9, &x9, &x3); - - x11 = x9; - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&x11, &x11); - } - secp256k1_fe_mul(&x11, &x11, &x2); - - x22 = x11; - for (j=0; j<11; j++) { - secp256k1_fe_sqr(&x22, &x22); - } - secp256k1_fe_mul(&x22, &x22, &x11); - - x44 = x22; - for (j=0; j<22; j++) { - secp256k1_fe_sqr(&x44, &x44); - } - secp256k1_fe_mul(&x44, &x44, &x22); - - x88 = x44; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x88, &x88); - } - secp256k1_fe_mul(&x88, &x88, &x44); - - x176 = x88; - for (j=0; j<88; j++) { - secp256k1_fe_sqr(&x176, &x176); - } - secp256k1_fe_mul(&x176, &x176, &x88); - - x220 = x176; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x220, &x220); - } - secp256k1_fe_mul(&x220, &x220, &x44); - - x223 = x220; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x223, &x223); - } - secp256k1_fe_mul(&x223, &x223, &x3); - - /* The final result is then assembled using a sliding window over the blocks. */ - - t1 = x223; - for (j=0; j<23; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x22); - for (j=0; j<5; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, a); - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x2); - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(r, a, &t1); -} - -static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) { -#if defined(USE_FIELD_INV_BUILTIN) - secp256k1_fe_inv(r, a); -#elif defined(USE_FIELD_INV_NUM) - secp256k1_num n, m; - static const secp256k1_fe negone = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL - ); - /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - static const unsigned char prime[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F - }; - unsigned char b[32]; - int res; - secp256k1_fe c = *a; - secp256k1_fe_normalize_var(&c); - secp256k1_fe_get_b32(b, &c); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_num_set_bin(&m, prime, 32); - secp256k1_num_mod_inverse(&n, &n, &m); - secp256k1_num_get_bin(b, 32, &n); - res = secp256k1_fe_set_b32(r, b); - (void)res; - VERIFY_CHECK(res); - /* Verify the result is the (unique) valid inverse using non-GMP code. */ - secp256k1_fe_mul(&c, &c, r); - secp256k1_fe_add(&c, &negone); - CHECK(secp256k1_fe_normalizes_to_zero_var(&c)); -#else -#error "Please select field inverse implementation" -#endif -} - -static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) { - secp256k1_fe u; - size_t i; - if (len < 1) { - return; - } - - VERIFY_CHECK((r + len <= a) || (a + len <= r)); - - r[0] = a[0]; - - i = 0; - while (++i < len) { - secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); - } - - secp256k1_fe_inv_var(&u, &r[--i]); - - while (i > 0) { - size_t j = i--; - secp256k1_fe_mul(&r[j], &r[i], &u); - secp256k1_fe_mul(&u, &u, &a[j]); - } - - r[0] = u; -} - -static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { -#ifndef USE_NUM_NONE - unsigned char b[32]; - secp256k1_num n; - secp256k1_num m; - /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - static const unsigned char prime[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F - }; - - secp256k1_fe c = *a; - secp256k1_fe_normalize_var(&c); - secp256k1_fe_get_b32(b, &c); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_num_set_bin(&m, prime, 32); - return secp256k1_num_jacobi(&n, &m) >= 0; -#else - secp256k1_fe r; - return secp256k1_fe_sqrt(&r, a); -#endif -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c deleted file mode 100644 index 1835fd491d..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c +++ /dev/null @@ -1,74 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#define USE_BASIC_CONFIG 1 - -#include "basic-config.h" -#include "include/secp256k1.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_gen_impl.h" - -static void default_error_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} - -static const secp256k1_callback default_error_callback = { - default_error_callback_fn, - NULL -}; - -int main(int argc, char **argv) { - secp256k1_ecmult_gen_context ctx; - int inner; - int outer; - FILE* fp; - - (void)argc; - (void)argv; - - fp = fopen("src/ecmult_static_context.h","w"); - if (fp == NULL) { - fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); - return -1; - } - - fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#include \"group.h\"\n"); - fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); - fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); - - secp256k1_ecmult_gen_context_init(&ctx); - secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); - for(outer = 0; outer != 64; outer++) { - fprintf(fp,"{\n"); - for(inner = 0; inner != 16; inner++) { - fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); - if (inner != 15) { - fprintf(fp,",\n"); - } else { - fprintf(fp,"\n"); - } - } - if (outer != 63) { - fprintf(fp,"},\n"); - } else { - fprintf(fp,"}\n"); - } - } - fprintf(fp,"};\n"); - secp256k1_ecmult_gen_context_clear(&ctx); - - fprintf(fp, "#undef SC\n"); - fprintf(fp, "#endif\n"); - fclose(fp); - - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h deleted file mode 100644 index 4957b248fe..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h +++ /dev/null @@ -1,144 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_GROUP_ -#define _SECP256K1_GROUP_ - -#include "num.h" -#include "field.h" - -/** A group element of the secp256k1 curve, in affine coordinates. */ -typedef struct { - secp256k1_fe x; - secp256k1_fe y; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_ge; - -#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} -#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -/** A group element of the secp256k1 curve, in jacobian coordinates. */ -typedef struct { - secp256k1_fe x; /* actual X: x/z^2 */ - secp256k1_fe y; /* actual Y: y/z^3 */ - secp256k1_fe z; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_gej; - -#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} -#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -typedef struct { - secp256k1_fe_storage x; - secp256k1_fe_storage y; -} secp256k1_ge_storage; - -#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} - -#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) - -/** Set a group element equal to the point with given X and Y coordinates */ -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); - -/** Set a group element (affine) equal to the point with the given X coordinate - * and a Y coordinate that is a quadratic residue modulo p. The return value - * is true iff a coordinate with the given X coordinate exists. - */ -static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); - -/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness - * for Y. Return value indicates whether the result is valid. */ -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_ge_is_infinity(const secp256k1_ge *a); - -/** Check whether a group element is valid (i.e., on the curve). */ -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); - -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); - -/** Set a group element equal to another which is given in jacobian coordinates */ -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); - -/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); - -/** Set a batch of group elements equal to the inputs given in jacobian - * coordinates (with known z-ratios). zr must contain the known z-ratios such - * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ -static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len); - -/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to - * the same global z "denominator". zr must contain the known z-ratios such - * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y - * coordinates of the result are stored in r, the common z coordinate is - * stored in globalz. */ -static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); - -/** Set a group element (jacobian) equal to the point at infinity. */ -static void secp256k1_gej_set_infinity(secp256k1_gej *r); - -/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); - -/** Compare the X coordinate of a group element (jacobian). */ -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); - -/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_gej_is_infinity(const secp256k1_gej *a); - -/** Check whether a group element's y coordinate is a quadratic residue. */ -static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); - -/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). - * a may not be zero. Constant time. */ -static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); - -/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); - -/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient - than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time - guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); - -#ifdef USE_ENDOMORPHISM -/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); -#endif - -/** Clear a secp256k1_gej to prevent leaking sensitive information. */ -static void secp256k1_gej_clear(secp256k1_gej *r); - -/** Clear a secp256k1_ge to prevent leaking sensitive information. */ -static void secp256k1_ge_clear(secp256k1_ge *r); - -/** Convert a group element to the storage type. */ -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); - -/** Convert a group element back from the storage type. */ -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); - -/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h deleted file mode 100644 index 7d723532ff..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h +++ /dev/null @@ -1,700 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_GROUP_IMPL_H_ -#define _SECP256K1_GROUP_IMPL_H_ - -#include "num.h" -#include "field.h" -#include "group.h" - -/* These points can be generated in sage as follows: - * - * 0. Setup a worksheet with the following parameters. - * b = 4 # whatever CURVE_B will be set to - * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) - * C = EllipticCurve ([F (0), F (b)]) - * - * 1. Determine all the small orders available to you. (If there are - * no satisfactory ones, go back and change b.) - * print C.order().factor(limit=1000) - * - * 2. Choose an order as one of the prime factors listed in the above step. - * (You can also multiply some to get a composite order, though the - * tests will crash trying to invert scalars during signing.) We take a - * random point and scale it to drop its order to the desired value. - * There is some probability this won't work; just try again. - * order = 199 - * P = C.random_point() - * P = (int(P.order()) / int(order)) * P - * assert(P.order() == order) - * - * 3. Print the values. You'll need to use a vim macro or something to - * split the hex output into 4-byte chunks. - * print "%x %x" % P.xy() - */ -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 199 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, - 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, - 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, - 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED -); - -const int CURVE_B = 4; -# elif EXHAUSTIVE_TEST_ORDER == 13 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, - 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, - 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, - 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac -); -const int CURVE_B = 2; -# else -# error No known generator for the specified exhaustive test group order. -# endif -#else -/** Generator for secp256k1, value 'g' defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - */ -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, - 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, - 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, - 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL -); - -const int CURVE_B = 7; -#endif - -static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { - secp256k1_fe zi2; - secp256k1_fe zi3; - secp256k1_fe_sqr(&zi2, zi); - secp256k1_fe_mul(&zi3, &zi2, zi); - secp256k1_fe_mul(&r->x, &a->x, &zi2); - secp256k1_fe_mul(&r->y, &a->y, &zi3); - r->infinity = a->infinity; -} - -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { - r->infinity = 0; - r->x = *x; - r->y = *y; -} - -static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { - return a->infinity; -} - -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { - *r = *a; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); -} - -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - r->infinity = a->infinity; - secp256k1_fe_inv(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - r->x = a->x; - r->y = a->y; -} - -static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - r->infinity = a->infinity; - if (a->infinity) { - return; - } - secp256k1_fe_inv_var(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - r->x = a->x; - r->y = a->y; -} - -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { - secp256k1_fe *az; - secp256k1_fe *azi; - size_t i; - size_t count = 0; - az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); - for (i = 0; i < len; i++) { - if (!a[i].infinity) { - az[count++] = a[i].z; - } - } - - azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); - secp256k1_fe_inv_all_var(azi, az, count); - free(az); - - count = 0; - for (i = 0; i < len; i++) { - r[i].infinity = a[i].infinity; - if (!a[i].infinity) { - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); - } - } - free(azi); -} - -static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { - size_t i = len - 1; - secp256k1_fe zi; - - if (len > 0) { - /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ - secp256k1_fe_inv(&zi, &a[i].z); - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - - /* Work out way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - secp256k1_fe_mul(&zi, &zi, &zr[i]); - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - } - } -} - -static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { - size_t i = len - 1; - secp256k1_fe zs; - - if (len > 0) { - /* The z of the final point gives us the "global Z" for the table. */ - r[i].x = a[i].x; - r[i].y = a[i].y; - *globalz = a[i].z; - r[i].infinity = 0; - zs = zr[i]; - - /* Work our way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - if (i != len - 1) { - secp256k1_fe_mul(&zs, &zs, &zr[i]); - } - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); - } - } -} - -static void secp256k1_gej_set_infinity(secp256k1_gej *r) { - r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); -} - -static void secp256k1_gej_clear(secp256k1_gej *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); -} - -static void secp256k1_ge_clear(secp256k1_ge *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); -} - -static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { - secp256k1_fe x2, x3, c; - r->x = *x; - secp256k1_fe_sqr(&x2, x); - secp256k1_fe_mul(&x3, x, &x2); - r->infinity = 0; - secp256k1_fe_set_int(&c, CURVE_B); - secp256k1_fe_add(&c, &x3); - return secp256k1_fe_sqrt(&r->y, &c); -} - -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { - if (!secp256k1_ge_set_xquad(r, x)) { - return 0; - } - secp256k1_fe_normalize_var(&r->y); - if (secp256k1_fe_is_odd(&r->y) != odd) { - secp256k1_fe_negate(&r->y, &r->y, 1); - } - return 1; - -} - -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - secp256k1_fe_set_int(&r->z, 1); -} - -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { - secp256k1_fe r, r2; - VERIFY_CHECK(!a->infinity); - secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); - r2 = a->x; secp256k1_fe_normalize_weak(&r2); - return secp256k1_fe_equal_var(&r, &r2); -} - -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - r->z = a->z; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); -} - -static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { - return a->infinity; -} - -static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { - secp256k1_fe y2, x3, z2, z6; - if (a->infinity) { - return 0; - } - /** y^2 = x^3 + 7 - * (Y/Z^3)^2 = (X/Z^2)^3 + 7 - * Y^2 / Z^6 = X^3 / Z^6 + 7 - * Y^2 = X^3 + 7*Z^6 - */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); - secp256k1_fe_mul_int(&z6, CURVE_B); - secp256k1_fe_add(&x3, &z6); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { - secp256k1_fe y2, x3, c; - if (a->infinity) { - return 0; - } - /* y^2 = x^3 + 7 */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_set_int(&c, CURVE_B); - secp256k1_fe_add(&x3, &c); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. - * - * Note that there is an implementation described at - * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - * which trades a multiply for a square, but in practice this is actually slower, - * mainly because it requires more normalizations. - */ - secp256k1_fe t1,t2,t3,t4; - /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, - * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have - * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. - * - * Having said this, if this function receives a point on a sextic twist, e.g. by - * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, - * since -6 does have a cube root mod p. For this point, this function will not set - * the infinity flag even though the point doubles to infinity, and the result - * point will be gibberish (z = 0 but infinity = 0). - */ - r->infinity = a->infinity; - if (r->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - return; - } - - if (rzr != NULL) { - *rzr = a->y; - secp256k1_fe_normalize_weak(rzr); - secp256k1_fe_mul_int(rzr, 2); - } - - secp256k1_fe_mul(&r->z, &a->z, &a->y); - secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ - secp256k1_fe_sqr(&t1, &a->x); - secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ - secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ - secp256k1_fe_sqr(&t3, &a->y); - secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ - secp256k1_fe_sqr(&t4, &t3); - secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ - secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ - r->x = t3; - secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ - secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ - secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ - secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ - secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ - secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ - secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ - secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ - secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ -} - -static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); - secp256k1_gej_double_var(r, a, rzr); -} - -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { - /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ - secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - *r = *b; - return; - } - - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - - r->infinity = 0; - secp256k1_fe_sqr(&z22, &b->z); - secp256k1_fe_sqr(&z12, &a->z); - secp256k1_fe_mul(&u1, &a->x, &z22); - secp256k1_fe_mul(&u2, &b->x, &z12); - secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - secp256k1_fe_mul(&h, &h, &b->z); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { - /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - secp256k1_gej_set_ge(r, b); - return; - } - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - r->infinity = 0; - - secp256k1_fe_sqr(&z12, &a->z); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { - /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (b->infinity) { - *r = *a; - return; - } - if (a->infinity) { - secp256k1_fe bzinv2, bzinv3; - r->infinity = b->infinity; - secp256k1_fe_sqr(&bzinv2, bzinv); - secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); - secp256k1_fe_mul(&r->x, &b->x, &bzinv2); - secp256k1_fe_mul(&r->y, &b->y, &bzinv3); - secp256k1_fe_set_int(&r->z, 1); - return; - } - r->infinity = 0; - - /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to - * secp256k1's isomorphism we can multiply the Z coordinates on both sides - * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). - * This means that (rx,ry,rz) can be calculated as - * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. - * The variable az below holds the modified Z coordinate for a, which is used - * for the computation of rx and ry, but not for rz. - */ - secp256k1_fe_mul(&az, &a->z, bzinv); - - secp256k1_fe_sqr(&z12, &az); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, NULL); - } else { - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - - -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { - /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ - static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; - secp256k1_fe m_alt, rr_alt; - int infinity, degenerate; - VERIFY_CHECK(!b->infinity); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); - - /** In: - * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. - * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. - * we find as solution for a unified addition/doubling formula: - * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. - * x3 = lambda^2 - (x1 + x2) - * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). - * - * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: - * U1 = X1*Z2^2, U2 = X2*Z1^2 - * S1 = Y1*Z2^3, S2 = Y2*Z1^3 - * Z = Z1*Z2 - * T = U1+U2 - * M = S1+S2 - * Q = T*M^2 - * R = T^2-U1*U2 - * X3 = 4*(R^2-Q) - * Y3 = 4*(R*(3*Q-2*R^2)-M^4) - * Z3 = 2*M*Z - * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) - * - * This formula has the benefit of being the same for both addition - * of distinct points and doubling. However, it breaks down in the - * case that either point is infinity, or that y1 = -y2. We handle - * these cases in the following ways: - * - * - If b is infinity we simply bail by means of a VERIFY_CHECK. - * - * - If a is infinity, we detect this, and at the end of the - * computation replace the result (which will be meaningless, - * but we compute to be constant-time) with b.x : b.y : 1. - * - * - If a = -b, we have y1 = -y2, which is a degenerate case. - * But here the answer is infinity, so we simply set the - * infinity flag of the result, overriding the computed values - * without even needing to cmov. - * - * - If y1 = -y2 but x1 != x2, which does occur thanks to certain - * properties of our curve (specifically, 1 has nontrivial cube - * roots in our field, and the curve equation has no x coefficient) - * then the answer is not infinity but also not given by the above - * equation. In this case, we cmov in place an alternate expression - * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these - * expressions for lambda are defined, they are equal, and can be - * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) - * then substitution of x^3 + 7 for y^2 (using the curve equation). - * For all pairs of nonzero points (a, b) at least one is defined, - * so this covers everything. - */ - - secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ - u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ - secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ - s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ - secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ - secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ - m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ - secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ - secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ - secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ - /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" - * case that Z = z1z2 = 0, and this is special-cased later on). */ - degenerate = secp256k1_fe_normalizes_to_zero(&m) & - secp256k1_fe_normalizes_to_zero(&rr); - /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. - * This means either x1 == beta*x2 or beta*x1 == x2, where beta is - * a nontrivial cube root of one. In either case, an alternate - * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), - * so we set R/M equal to this. */ - rr_alt = s1; - secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ - secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ - - secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); - secp256k1_fe_cmov(&m_alt, &m, !degenerate); - /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. - * From here on out Ralt and Malt represent the numerator - * and denominator of lambda; R and M represent the explicit - * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ - secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ - /* These two lines use the observation that either M == Malt or M == 0, - * so M^3 * Malt is either Malt^4 (which is computed by squaring), or - * zero (which is "computed" by cmov). So the cost is one squaring - * versus two multiplications. */ - secp256k1_fe_sqr(&n, &n); - secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ - secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ - secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ - infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); - secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ - secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ - secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ - secp256k1_fe_normalize_weak(&t); - r->x = t; /* r->x = Ralt^2-Q (1) */ - secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ - secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ - secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ - secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ - secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ - secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ - - /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ - secp256k1_fe_cmov(&r->x, &b->x, a->infinity); - secp256k1_fe_cmov(&r->y, &b->y, a->infinity); - secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); - r->infinity = infinity; -} - -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { - /* Operations: 4 mul, 1 sqr */ - secp256k1_fe zz; - VERIFY_CHECK(!secp256k1_fe_is_zero(s)); - secp256k1_fe_sqr(&zz, s); - secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ - secp256k1_fe_mul(&r->y, &r->y, &zz); - secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ - secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ -} - -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { - secp256k1_fe x, y; - VERIFY_CHECK(!a->infinity); - x = a->x; - secp256k1_fe_normalize(&x); - y = a->y; - secp256k1_fe_normalize(&y); - secp256k1_fe_to_storage(&r->x, &x); - secp256k1_fe_to_storage(&r->y, &y); -} - -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { - secp256k1_fe_from_storage(&r->x, &a->x); - secp256k1_fe_from_storage(&r->y, &a->y); - r->infinity = 0; -} - -static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { - secp256k1_fe_storage_cmov(&r->x, &a->x, flag); - secp256k1_fe_storage_cmov(&r->y, &a->y, flag); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { - static const secp256k1_fe beta = SECP256K1_FE_CONST( - 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, - 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul - ); - *r = *a; - secp256k1_fe_mul(&r->x, &r->x, &beta); -} -#endif - -static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { - secp256k1_fe yz; - - if (a->infinity) { - return 0; - } - - /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as - * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z - is */ - secp256k1_fe_mul(&yz, &a->y, &a->z); - return secp256k1_fe_is_quad_var(&yz); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h deleted file mode 100644 index fca98cab9f..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_HASH_ -#define _SECP256K1_HASH_ - -#include -#include - -typedef struct { - uint32_t s[8]; - uint32_t buf[16]; /* In big endian */ - size_t bytes; -} secp256k1_sha256_t; - -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); - -typedef struct { - secp256k1_sha256_t inner, outer; -} secp256k1_hmac_sha256_t; - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); - -typedef struct { - unsigned char v[32]; - unsigned char k[32]; - int retry; -} secp256k1_rfc6979_hmac_sha256_t; - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h deleted file mode 100644 index b47e65f830..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h +++ /dev/null @@ -1,281 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_HASH_IMPL_H_ -#define _SECP256K1_HASH_IMPL_H_ - -#include "hash.h" - -#include -#include -#include - -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) -#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) -#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) -#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) -#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) - -#define Round(a,b,c,d,e,f,g,h,k,w) do { \ - uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ - uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ - (d) += t1; \ - (h) = t1 + t2; \ -} while(0) - -#ifdef WORDS_BIGENDIAN -#define BE32(x) (x) -#else -#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) -#endif - -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { - hash->s[0] = 0x6a09e667ul; - hash->s[1] = 0xbb67ae85ul; - hash->s[2] = 0x3c6ef372ul; - hash->s[3] = 0xa54ff53aul; - hash->s[4] = 0x510e527ful; - hash->s[5] = 0x9b05688cul; - hash->s[6] = 0x1f83d9abul; - hash->s[7] = 0x5be0cd19ul; - hash->bytes = 0; -} - -/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; -} - -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { - size_t bufsize = hash->bytes & 0x3F; - hash->bytes += len; - while (bufsize + len >= 64) { - /* Fill the buffer, and process it. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); - data += 64 - bufsize; - len -= 64 - bufsize; - secp256k1_sha256_transform(hash->s, hash->buf); - bufsize = 0; - } - if (len) { - /* Fill the buffer with what remains. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, len); - } -} - -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { - static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t sizedesc[2]; - uint32_t out[8]; - int i = 0; - sizedesc[0] = BE32(hash->bytes >> 29); - sizedesc[1] = BE32(hash->bytes << 3); - secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); - secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); - for (i = 0; i < 8; i++) { - out[i] = BE32(hash->s[i]); - hash->s[i] = 0; - } - memcpy(out32, (const unsigned char*)out, 32); -} - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { - int n; - unsigned char rkey[64]; - if (keylen <= 64) { - memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, 64 - keylen); - } else { - secp256k1_sha256_t sha256; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, key, keylen); - secp256k1_sha256_finalize(&sha256, rkey); - memset(rkey + 32, 0, 32); - } - - secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < 64; n++) { - rkey[n] ^= 0x5c; - } - secp256k1_sha256_write(&hash->outer, rkey, 64); - - secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < 64; n++) { - rkey[n] ^= 0x5c ^ 0x36; - } - secp256k1_sha256_write(&hash->inner, rkey, 64); - memset(rkey, 0, 64); -} - -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { - secp256k1_sha256_write(&hash->inner, data, size); -} - -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { - unsigned char temp[32]; - secp256k1_sha256_finalize(&hash->inner, temp); - secp256k1_sha256_write(&hash->outer, temp, 32); - memset(temp, 0, 32); - secp256k1_sha256_finalize(&hash->outer, out32); -} - - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256_t hmac; - static const unsigned char zero[1] = {0x00}; - static const unsigned char one[1] = {0x01}; - - memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ - memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ - - /* RFC6979 3.2.d. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - - /* RFC6979 3.2.f. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, one, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - rng->retry = 0; -} - -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { - /* RFC6979 3.2.h. */ - static const unsigned char zero[1] = {0x00}; - if (rng->retry) { - secp256k1_hmac_sha256_t hmac; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - } - - while (outlen > 0) { - secp256k1_hmac_sha256_t hmac; - int now = outlen; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - if (now > 32) { - now = 32; - } - memcpy(out, rng->v, now); - out += now; - outlen -= now; - } - - rng->retry = 1; -} - -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { - memset(rng->k, 0, 32); - memset(rng->v, 0, 32); - rng->retry = 0; -} - -#undef BE32 -#undef Round -#undef sigma1 -#undef sigma0 -#undef Sigma1 -#undef Sigma0 -#undef Maj -#undef Ch - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java deleted file mode 100644 index 1c67802fba..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import java.math.BigInteger; -import com.google.common.base.Preconditions; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import static org.bitcoin.NativeSecp256k1Util.*; - -/** - *

This class holds native methods to handle ECDSA verification.

- * - *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

- * - *

To build secp256k1 for use with bitcoinj, run - * `./configure --enable-jni --enable-experimental --enable-module-ecdh` - * and `make` then copy `.libs/libsecp256k1.so` to your system library path - * or point the JVM to the folder containing it with -Djava.library.path - *

- */ -public class NativeSecp256k1 { - - private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); - private static final Lock r = rwl.readLock(); - private static final Lock w = rwl.writeLock(); - private static ThreadLocal nativeECDSABuffer = new ThreadLocal(); - /** - * Verifies the given secp256k1 signature in native code. - * Calling when enabled == false is undefined (probably library not loaded) - * - * @param data The data which was signed, must be exactly 32 bytes - * @param signature The signature - * @param pub The public key which did the signing - */ - public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ - Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 520) { - byteBuff = ByteBuffer.allocateDirect(520); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.put(signature); - byteBuff.put(pub); - - byte[][] retByteArray; - - r.lock(); - try { - return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; - } finally { - r.unlock(); - } - } - - /** - * libsecp256k1 Create an ECDSA signature. - * - * @param data Message hash, 32 bytes - * @param key Secret key, 32 bytes - * - * Return values - * @param sig byte array of signature - */ - public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ - Preconditions.checkArgument(data.length == 32 && sec.length <= 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 32 + 32) { - byteBuff = ByteBuffer.allocateDirect(32 + 32); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.put(sec); - - byte[][] retByteArray; - - r.lock(); - try { - retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] sigArr = retByteArray[0]; - int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(sigArr.length, sigLen, "Got bad signature length."); - - return retVal == 0 ? new byte[0] : sigArr; - } - - /** - * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid - * - * @param seckey ECDSA Secret key, 32 bytes - */ - public static boolean secKeyVerify(byte[] seckey) { - Preconditions.checkArgument(seckey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seckey.length) { - byteBuff = ByteBuffer.allocateDirect(seckey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - - r.lock(); - try { - return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; - } finally { - r.unlock(); - } - } - - - /** - * libsecp256k1 Compute Pubkey - computes public key from secret key - * - * @param seckey ECDSA Secret key, 32 bytes - * - * Return values - * @param pubkey ECDSA Public key, 33 or 65 bytes - */ - //TODO add a 'compressed' arg - public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ - Preconditions.checkArgument(seckey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seckey.length) { - byteBuff = ByteBuffer.allocateDirect(seckey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - - byte[][] retByteArray; - - r.lock(); - try { - retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - return retVal == 0 ? new byte[0]: pubArr; - } - - /** - * libsecp256k1 Cleanup - This destroys the secp256k1 context object - * This should be called at the end of the program for proper cleanup of the context. - */ - public static synchronized void cleanup() { - w.lock(); - try { - secp256k1_destroy_context(Secp256k1Context.getContext()); - } finally { - w.unlock(); - } - } - - public static long cloneContext() { - r.lock(); - try { - return secp256k1_ctx_clone(Secp256k1Context.getContext()); - } finally { r.unlock(); } - } - - /** - * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it - * - * @param tweak some bytes to tweak with - * @param seckey 32-byte seckey - */ - public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(privkey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(privkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] privArr = retByteArray[0]; - - int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(privArr.length, privLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return privArr; - } - - /** - * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it - * - * @param tweak some bytes to tweak with - * @param seckey 32-byte seckey - */ - public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(privkey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(privkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] privArr = retByteArray[0]; - - int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(privArr.length, privLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return privArr; - } - - /** - * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it - * - * @param tweak some bytes to tweak with - * @param pubkey 32-byte seckey - */ - public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(pubkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - - int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return pubArr; - } - - /** - * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it - * - * @param tweak some bytes to tweak with - * @param pubkey 32-byte seckey - */ - public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(pubkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - - int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return pubArr; - } - - /** - * libsecp256k1 create ECDH secret - constant time ECDH calculation - * - * @param seckey byte array of secret key used in exponentiaion - * @param pubkey byte array of public key used in exponentiaion - */ - public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ - Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { - byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - byteBuff.put(pubkey); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] resArr = retByteArray[0]; - int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - - assertEquals(resArr.length, 32, "Got bad result length."); - assertEquals(retVal, 1, "Failed return value check."); - - return resArr; - } - - /** - * libsecp256k1 randomize - updates the context randomization - * - * @param seed 32-byte random seed - */ - public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ - Preconditions.checkArgument(seed.length == 32 || seed == null); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seed.length) { - byteBuff = ByteBuffer.allocateDirect(seed.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seed); - - w.lock(); - try { - return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; - } finally { - w.unlock(); - } - } - - private static native long secp256k1_ctx_clone(long context); - - private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); - - private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); - - private static native void secp256k1_destroy_context(long context); - - private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); - - private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); - - private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); - - private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); - -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java deleted file mode 100644 index c00d08899b..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.bitcoin; - -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.math.BigInteger; -import javax.xml.bind.DatatypeConverter; -import static org.bitcoin.NativeSecp256k1Util.*; - -/** - * This class holds test cases defined for testing this library. - */ -public class NativeSecp256k1Test { - - //TODO improve comments/add more tests - /** - * This tests verify() for a valid signature - */ - public static void testVerifyPos() throws AssertFailException{ - boolean result = false; - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - result = NativeSecp256k1.verify( data, sig, pub); - assertEquals( result, true , "testVerifyPos"); - } - - /** - * This tests verify() for a non-valid signature - */ - public static void testVerifyNeg() throws AssertFailException{ - boolean result = false; - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" - byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - result = NativeSecp256k1.verify( data, sig, pub); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, false , "testVerifyNeg"); - } - - /** - * This tests secret key verify() for a valid secretkey - */ - public static void testSecKeyVerifyPos() throws AssertFailException{ - boolean result = false; - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - result = NativeSecp256k1.secKeyVerify( sec ); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, true , "testSecKeyVerifyPos"); - } - - /** - * This tests secret key verify() for a invalid secretkey - */ - public static void testSecKeyVerifyNeg() throws AssertFailException{ - boolean result = false; - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - result = NativeSecp256k1.secKeyVerify( sec ); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, false , "testSecKeyVerifyNeg"); - } - - /** - * This tests public key create() for a valid secretkey - */ - public static void testPubKeyCreatePos() throws AssertFailException{ - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); - } - - /** - * This tests public key create() for a invalid secretkey - */ - public static void testPubKeyCreateNeg() throws AssertFailException{ - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); - } - - /** - * This tests sign() for a valid secretkey - */ - public static void testSignPos() throws AssertFailException{ - - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); - } - - /** - * This tests sign() for a invalid secretkey - */ - public static void testSignNeg() throws AssertFailException{ - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString, "" , "testSignNeg"); - } - - /** - * This tests private key tweak-add - */ - public static void testPrivKeyTweakAdd_1() throws AssertFailException { - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); - } - - /** - * This tests private key tweak-mul - */ - public static void testPrivKeyTweakMul_1() throws AssertFailException { - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); - } - - /** - * This tests private key tweak-add uncompressed - */ - public static void testPrivKeyTweakAdd_2() throws AssertFailException { - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); - } - - /** - * This tests private key tweak-mul uncompressed - */ - public static void testPrivKeyTweakMul_2() throws AssertFailException { - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); - } - - /** - * This tests seed randomization - */ - public static void testRandomize() throws AssertFailException { - byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" - boolean result = NativeSecp256k1.randomize(seed); - assertEquals( result, true, "testRandomize"); - } - - public static void testCreateECDHSecret() throws AssertFailException{ - - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); - String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); - } - - public static void main(String[] args) throws AssertFailException{ - - - System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); - - assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); - - //Test verify() success/fail - testVerifyPos(); - testVerifyNeg(); - - //Test secKeyVerify() success/fail - testSecKeyVerifyPos(); - testSecKeyVerifyNeg(); - - //Test computePubkey() success/fail - testPubKeyCreatePos(); - testPubKeyCreateNeg(); - - //Test sign() success/fail - testSignPos(); - testSignNeg(); - - //Test privKeyTweakAdd() 1 - testPrivKeyTweakAdd_1(); - - //Test privKeyTweakMul() 2 - testPrivKeyTweakMul_1(); - - //Test privKeyTweakAdd() 3 - testPrivKeyTweakAdd_2(); - - //Test privKeyTweakMul() 4 - testPrivKeyTweakMul_2(); - - //Test randomize() - testRandomize(); - - //Test ECDH - testCreateECDHSecret(); - - NativeSecp256k1.cleanup(); - - System.out.println(" All tests passed." ); - - } -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java deleted file mode 100644 index 04732ba044..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -public class NativeSecp256k1Util{ - - public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ - if( val != val2 ) - throw new AssertFailException("FAIL: " + message); - } - - public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ - if( val != val2 ) - throw new AssertFailException("FAIL: " + message); - else - System.out.println("PASS: " + message); - } - - public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ - if( !val.equals(val2) ) - throw new AssertFailException("FAIL: " + message); - else - System.out.println("PASS: " + message); - } - - public static class AssertFailException extends Exception { - public AssertFailException(String message) { - super( message ); - } - } -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java deleted file mode 100644 index 216c986a8b..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -/** - * This class holds the context reference used in native methods - * to handle ECDSA operations. - */ -public class Secp256k1Context { - private static final boolean enabled; //true if the library is loaded - private static final long context; //ref to pointer to context obj - - static { //static initializer - boolean isEnabled = true; - long contextRef = -1; - try { - System.loadLibrary("secp256k1"); - contextRef = secp256k1_init_context(); - } catch (UnsatisfiedLinkError e) { - System.out.println("UnsatisfiedLinkError: " + e.toString()); - isEnabled = false; - } - enabled = isEnabled; - context = contextRef; - } - - public static boolean isEnabled() { - return enabled; - } - - public static long getContext() { - if(!enabled) return -1; //sanity check - return context; - } - - private static native long secp256k1_init_context(); -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c deleted file mode 100644 index bcef7b32ce..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ /dev/null @@ -1,377 +0,0 @@ -#include -#include -#include -#include "org_bitcoin_NativeSecp256k1.h" -#include "include/secp256k1.h" -#include "include/secp256k1_ecdh.h" -#include "include/secp256k1_recovery.h" - - -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone - (JNIEnv* env, jclass classObject, jlong ctx_l) -{ - const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx); - - (void)classObject;(void)env; - - return ctx_clone_l; - -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - (void)classObject; - - return secp256k1_context_randomize(ctx, seed); - -} - -SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context - (JNIEnv* env, jclass classObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - secp256k1_context_destroy(ctx); - - (void)classObject;(void)env; -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* sigdata = { (unsigned char*) (data + 32) }; - const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; - - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pubkey; - - int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); - - if( ret ) { - ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); - - if( ret ) { - ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); - } - } - - (void)classObject; - - return ret; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - unsigned char* secKey = (unsigned char*) (data + 32); - - jobjectArray retArray; - jbyteArray sigArray, intsByteArray; - unsigned char intsarray[2]; - - secp256k1_ecdsa_signature sig[72]; - - int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); - - unsigned char outputSer[72]; - size_t outputLen = 72; - - if( ret ) { - int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - sigArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - (void)classObject; - - return secp256k1_ec_seckey_verify(ctx, secKey); -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - secp256k1_pubkey pubkey; - - jobjectArray retArray; - jbyteArray pubkeyArray, intsByteArray; - unsigned char intsarray[2]; - - int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); - - unsigned char outputSer[65]; - size_t outputLen = 65; - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubkeyArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; - -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (privkey + 32); - - jobjectArray retArray; - jbyteArray privArray, intsByteArray; - unsigned char intsarray[2]; - - int privkeylen = 32; - - int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); - - intsarray[0] = privkeylen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - privArray = (*env)->NewByteArray(env, privkeylen); - (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); - (*env)->SetObjectArrayElement(env, retArray, 0, privArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (privkey + 32); - - jobjectArray retArray; - jbyteArray privArray, intsByteArray; - unsigned char intsarray[2]; - - int privkeylen = 32; - - int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); - - intsarray[0] = privkeylen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - privArray = (*env)->NewByteArray(env, privkeylen); - (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); - (*env)->SetObjectArrayElement(env, retArray, 0, privArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; -/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ - unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (pkey + publen); - - jobjectArray retArray; - jbyteArray pubArray, intsByteArray; - unsigned char intsarray[2]; - unsigned char outputSer[65]; - size_t outputLen = 65; - - secp256k1_pubkey pubkey; - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); - - if( ret ) { - ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); - } - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (pkey + publen); - - jobjectArray retArray; - jbyteArray pubArray, intsByteArray; - unsigned char intsarray[2]; - unsigned char outputSer[65]; - size_t outputLen = 65; - - secp256k1_pubkey pubkey; - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); - - if ( ret ) { - ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); - } - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine - (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) -{ - (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; - - return 0; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* pubdata = (const unsigned char*) (secdata + 32); - - jobjectArray retArray; - jbyteArray outArray, intsByteArray; - unsigned char intsarray[1]; - secp256k1_pubkey pubkey; - unsigned char nonce_res[32]; - size_t outputLen = 32; - - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); - - if (ret) { - ret = secp256k1_ecdh( - ctx, - nonce_res, - &pubkey, - secdata - ); - } - - intsarray[0] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - outArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); - (*env)->SetObjectArrayElement(env, retArray, 0, outArray); - - intsByteArray = (*env)->NewByteArray(env, 1); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h deleted file mode 100644 index fe613c9e9e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ /dev/null @@ -1,119 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_NativeSecp256k1 */ - -#ifndef _Included_org_bitcoin_NativeSecp256k1 -#define _Included_org_bitcoin_NativeSecp256k1 -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ctx_clone - * Signature: (J)J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_context_randomize - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_destroy_context - * Signature: (J)V - */ -SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_verify - * Signature: (Ljava/nio/ByteBuffer;JII)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv *, jclass, jobject, jlong, jint, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_sign - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_seckey_verify - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_create - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_parse - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdh - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c deleted file mode 100644 index a52939e7e7..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include "org_bitcoin_Secp256k1Context.h" -#include "include/secp256k1.h" - -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context - (JNIEnv* env, jclass classObject) -{ - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - (void)classObject;(void)env; - - return (uintptr_t)ctx; -} - diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h deleted file mode 100644 index 0d2bc84b7f..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h +++ /dev/null @@ -1,22 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_Secp256k1Context */ - -#ifndef _Included_org_bitcoin_Secp256k1Context -#define _Included_org_bitcoin_Secp256k1Context -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_Secp256k1Context - * Method: secp256k1_init_context - * Signature: ()J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include deleted file mode 100644 index e3088b4697..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_ecdh.h -noinst_HEADERS += src/modules/ecdh/main_impl.h -noinst_HEADERS += src/modules/ecdh/tests_impl.h -if USE_BENCHMARK -noinst_PROGRAMS += bench_ecdh -bench_ecdh_SOURCES = src/bench_ecdh.c -bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) -endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h deleted file mode 100644 index 9e30fb73dd..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_MAIN_ -#define _SECP256K1_MODULE_ECDH_MAIN_ - -#include "include/secp256k1_ecdh.h" -#include "ecmult_const_impl.h" - -int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { - int ret = 0; - int overflow = 0; - secp256k1_gej res; - secp256k1_ge pt; - secp256k1_scalar s; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(result != NULL); - ARG_CHECK(point != NULL); - ARG_CHECK(scalar != NULL); - - secp256k1_pubkey_load(ctx, &pt, point); - secp256k1_scalar_set_b32(&s, scalar, &overflow); - if (overflow || secp256k1_scalar_is_zero(&s)) { - ret = 0; - } else { - unsigned char x[32]; - unsigned char y[1]; - secp256k1_sha256_t sha; - - secp256k1_ecmult_const(&res, &pt, &s); - secp256k1_ge_set_gej(&pt, &res); - /* Compute a hash of the point in compressed form - * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not - * expect its output to be secret and has a timing sidechannel. */ - secp256k1_fe_normalize(&pt.x); - secp256k1_fe_normalize(&pt.y); - secp256k1_fe_get_b32(x, &pt.x); - y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, y, sizeof(y)); - secp256k1_sha256_write(&sha, x, sizeof(x)); - secp256k1_sha256_finalize(&sha, result); - ret = 1; - } - - secp256k1_scalar_clear(&s); - return ret; -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h deleted file mode 100644 index 85a5d0a9a6..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h +++ /dev/null @@ -1,105 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_TESTS_ -#define _SECP256K1_MODULE_ECDH_TESTS_ - -void test_ecdh_api(void) { - /* Setup context that just counts errors */ - secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_pubkey point; - unsigned char res[32]; - unsigned char s_one[32] = { 0 }; - int32_t ecount = 0; - s_one[31] = 1; - - secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); - CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); - - /* Check all NULLs are detected */ - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 3); - - /* Cleanup */ - secp256k1_context_destroy(tctx); -} - -void test_ecdh_generator_basepoint(void) { - unsigned char s_one[32] = { 0 }; - secp256k1_pubkey point[2]; - int i; - - s_one[31] = 1; - /* Check against pubkey creation when the basepoint is the generator */ - for (i = 0; i < 100; ++i) { - secp256k1_sha256_t sha; - unsigned char s_b32[32]; - unsigned char output_ecdh[32]; - unsigned char output_ser[32]; - unsigned char point_ser[33]; - size_t point_ser_len = sizeof(point_ser); - secp256k1_scalar s; - - random_scalar_order(&s); - secp256k1_scalar_get_b32(s_b32, &s); - - /* compute using ECDH function */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); - CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); - /* compute "explicitly" */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - CHECK(point_ser_len == sizeof(point_ser)); - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, point_ser, point_ser_len); - secp256k1_sha256_finalize(&sha, output_ser); - /* compare */ - CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); - } -} - -void test_bad_scalar(void) { - unsigned char s_zero[32] = { 0 }; - unsigned char s_overflow[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - unsigned char s_rand[32] = { 0 }; - unsigned char output[32]; - secp256k1_scalar rand; - secp256k1_pubkey point; - - /* Create random point */ - random_scalar_order(&rand); - secp256k1_scalar_get_b32(s_rand, &rand); - CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); - - /* Try to multiply it by bad values */ - CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); - /* ...and a good one */ - s_overflow[31] -= 1; - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); -} - -void run_ecdh_tests(void) { - test_ecdh_api(); - test_ecdh_generator_basepoint(); - test_bad_scalar(); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include deleted file mode 100644 index bf23c26e71..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_recovery.h -noinst_HEADERS += src/modules/recovery/main_impl.h -noinst_HEADERS += src/modules/recovery/tests_impl.h -if USE_BENCHMARK -noinst_PROGRAMS += bench_recover -bench_recover_SOURCES = src/bench_recover.c -bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) -endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h deleted file mode 100644 index c6fbe23981..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h +++ /dev/null @@ -1,193 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ -#define _SECP256K1_MODULE_RECOVERY_MAIN_ - -#include "include/secp256k1_recovery.h" - -static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } - *recid = sig->data[64]; -} - -static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } - sig->data[64] = recid; -} - -int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - (void)ctx; - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - ARG_CHECK(recid >= 0 && recid <= 3); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { - secp256k1_scalar r, s; - - (void)ctx; - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(recid != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { - secp256k1_scalar r, s; - int recid; - - (void)ctx; - ARG_CHECK(sig != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; -} - -static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { - unsigned char brx[32]; - secp256k1_fe fx; - secp256k1_ge x; - secp256k1_gej xj; - secp256k1_scalar rn, u1, u2; - secp256k1_gej qj; - int r; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_get_b32(brx, sigr); - r = secp256k1_fe_set_b32(&fx, brx); - (void)r; - VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ - if (recid & 2) { - if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - return 0; - } - secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); - } - if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { - return 0; - } - secp256k1_gej_set_ge(&xj, &x); - secp256k1_scalar_inverse_var(&rn, sigr); - secp256k1_scalar_mul(&u1, &rn, message); - secp256k1_scalar_negate(&u1, &u1); - secp256k1_scalar_mul(&u2, &rn, sigs); - secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); - secp256k1_ge_set_gej_var(pubkey, &qj); - return !secp256k1_gej_is_infinity(&qj); -} - -int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int recid; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned char nonce32[32]; - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { - break; - } - } - count++; - } - memset(nonce32, 0, 32); - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - int recid; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ - secp256k1_scalar_set_b32(&m, msg32, NULL); - if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { - secp256k1_pubkey_save(pubkey, &q); - return 1; - } else { - memset(pubkey, 0, sizeof(*pubkey)); - return 0; - } -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h deleted file mode 100644 index 765c7dd81e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h +++ /dev/null @@ -1,393 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ -#define _SECP256K1_MODULE_RECOVERY_TESTS_ - -static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void) msg32; - (void) key32; - (void) algo16; - (void) data; - - /* On the first run, return 0 to force a second run */ - if (counter == 0) { - memset(nonce32, 0, 32); - return 1; - } - /* On the second run, return an overflow to force a third run */ - if (counter == 1) { - memset(nonce32, 0xff, 32); - return 1; - } - /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ - memset(nonce32, 1, 32); - return secp256k1_rand_bits(1); -} - -void test_ecdsa_recovery_api(void) { - /* Setup contexts that just count errors */ - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - secp256k1_ecdsa_signature normal_sig; - secp256k1_ecdsa_recoverable_signature recsig; - unsigned char privkey[32] = { 1 }; - unsigned char message[32] = { 2 }; - int32_t ecount = 0; - int recid = 0; - unsigned char sig[74]; - unsigned char zero_privkey[32] = { 0 }; - unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Check bad contexts and NULLs for signing */ - ecount = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); - CHECK(ecount == 5); - /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ - secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); - CHECK(ecount == 5); - /* These will all fail, but not in ARG_CHECK way */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); - /* This one will succeed. */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 5); - - /* Check signing with a goofy nonce function */ - - /* Check bad contexts and NULLs for recovery */ - ecount = 0; - CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); - CHECK(ecount == 5); - - /* Check NULLs for conversion */ - CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); - - /* Check NULLs for de/serialization */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); - CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); - CHECK(ecount == 7); - /* overflow in signature will fail but not affect ecount */ - memcpy(sig, over_privkey, 32); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); - CHECK(ecount == 7); - - /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); -} - -void test_ecdsa_recovery_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - secp256k1_ecdsa_signature signature[5]; - secp256k1_ecdsa_recoverable_signature rsignature[5]; - unsigned char sig[74]; - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - int recid = 0; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Serialize/parse compact and verify/recover. */ - extra[0] = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(memcmp(&signature[4], &signature[0], 64) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); - memset(&rsignature[4], 0, sizeof(rsignature[4])); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); - /* Parse compact (with recovery id) and recover. */ - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); - CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); - /* Serialize/destroy/parse signature and verify again. */ - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); - sig[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); - /* Recover again */ - CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || - memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); -} - -/* Tests several edge cases. */ -void test_ecdsa_recovery_edge_cases(void) { - const unsigned char msg32[32] = { - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', - 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', - 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', - 's', 's', 'a', 'g', 'e', '.', '.', '.' - }; - const unsigned char sig64[64] = { - /* Generated by signing the above message with nonce 'This is the nonce we will use...' - * and secret key 0 (which is not valid), resulting in recid 0. */ - 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, - 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, - 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, - 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, - 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, - 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, - 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, - 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 - }; - secp256k1_pubkey pubkey; - /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ - const unsigned char sigb64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - secp256k1_pubkey pubkeyb; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - int recid; - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - - for (recid = 0; recid < 4; recid++) { - int i; - int recid2; - /* (4,4) encoded in DER. */ - unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; - unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; - unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; - unsigned char sigbderalt1[39] = { - 0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt2[39] = { - 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - unsigned char sigbderalt3[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt4[40] = { - 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - /* (order + r,4) encoded in DER. */ - unsigned char sigbderlong[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, - 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, - 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 - }; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); - for (recid2 = 0; recid2 < 4; recid2++) { - secp256k1_pubkey pubkey2b; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); - /* Verifying with (order + r,4) should always fail. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - } - /* DER parsing tests. */ - /* Zero length r/s. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); - /* Leading zeros. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); - sigbderalt3[4] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - sigbderalt4[7] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - /* Damage signature. */ - sigbder[7]++; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - sigbder[7]--; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); - for(i = 0; i < 8; i++) { - int c; - unsigned char orig = sigbder[i]; - /*Try every single-byte change.*/ - for (c = 0; c < 256; c++) { - if (c == orig ) { - continue; - } - sigbder[i] = c; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - } - sigbder[i] = orig; - } - } - - /* Test r/s equal to zero */ - { - /* (1,1) encoded in DER. */ - unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; - unsigned char sigc64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - secp256k1_pubkey pubkeyc; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); - sigcder[4] = 0; - sigc64[31] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); - sigcder[4] = 1; - sigcder[7] = 0; - sigc64[31] = 1; - sigc64[63] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); - } -} - -void run_recovery_tests(void) { - int i; - for (i = 0; i < count; i++) { - test_ecdsa_recovery_api(); - } - for (i = 0; i < 64*count; i++) { - test_ecdsa_recovery_end_to_end(); - } - test_ecdsa_recovery_edge_cases(); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h deleted file mode 100644 index eff842200f..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h +++ /dev/null @@ -1,74 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_ -#define _SECP256K1_NUM_ - -#ifndef USE_NUM_NONE - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_NUM_GMP) -#include "num_gmp.h" -#else -#error "Please select num implementation" -#endif - -/** Copy a number. */ -static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a); - -/** Convert a number's absolute value to a binary big-endian string. - * There must be enough place. */ -static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a); - -/** Set a number to the value of a binary big-endian string. */ -static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen); - -/** Compute a modular inverse. The input must be less than the modulus. */ -static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); - -/** Compute the jacobi symbol (a|b). b must be positive and odd. */ -static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); - -/** Compare the absolute value of two numbers. */ -static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); - -/** Test whether two number are equal (including sign). */ -static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b); - -/** Add two (signed) numbers. */ -static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Subtract two (signed) numbers. */ -static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Multiply two (signed) numbers. */ -static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, - even if r was negative. */ -static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m); - -/** Right-shift the passed number by bits. */ -static void secp256k1_num_shift(secp256k1_num *r, int bits); - -/** Check whether a number is zero. */ -static int secp256k1_num_is_zero(const secp256k1_num *a); - -/** Check whether a number is one. */ -static int secp256k1_num_is_one(const secp256k1_num *a); - -/** Check whether a number is strictly negative. */ -static int secp256k1_num_is_neg(const secp256k1_num *a); - -/** Change a number's sign. */ -static void secp256k1_num_negate(secp256k1_num *r); - -#endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h deleted file mode 100644 index 7dd813088a..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h +++ /dev/null @@ -1,20 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_REPR_ -#define _SECP256K1_NUM_REPR_ - -#include - -#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) - -typedef struct { - mp_limb_t data[2*NUM_LIMBS]; - int neg; - int limbs; -} secp256k1_num; - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h deleted file mode 100644 index 3a46495eea..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h +++ /dev/null @@ -1,288 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_REPR_IMPL_H_ -#define _SECP256K1_NUM_REPR_IMPL_H_ - -#include -#include -#include - -#include "util.h" -#include "num.h" - -#ifdef VERIFY -static void secp256k1_num_sanity(const secp256k1_num *a) { - VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); -} -#else -#define secp256k1_num_sanity(a) do { } while(0) -#endif - -static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { - *r = *a; -} - -static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { - unsigned char tmp[65]; - int len = 0; - int shift = 0; - if (a->limbs>1 || a->data[0] != 0) { - len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); - } - while (shift < len && tmp[shift] == 0) shift++; - VERIFY_CHECK(len-shift <= (int)rlen); - memset(r, 0, rlen - len + shift); - if (len > shift) { - memcpy(r + rlen - len + shift, tmp + shift, len - shift); - } - memset(tmp, 0, sizeof(tmp)); -} - -static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { - int len; - VERIFY_CHECK(alen > 0); - VERIFY_CHECK(alen <= 64); - len = mpn_set_str(r->data, a, alen, 256); - if (len == 0) { - r->data[0] = 0; - len = 1; - } - VERIFY_CHECK(len <= NUM_LIMBS*2); - r->limbs = len; - r->neg = 0; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); - r->limbs = a->limbs; - if (c != 0) { - VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); - r->data[r->limbs++] = c; - } -} - -static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); - (void)c; - VERIFY_CHECK(c == 0); - r->limbs = a->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { - secp256k1_num_sanity(r); - secp256k1_num_sanity(m); - - if (r->limbs >= m->limbs) { - mp_limb_t t[2*NUM_LIMBS]; - mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); - memset(t, 0, sizeof(t)); - r->limbs = m->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } - } - - if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { - secp256k1_num_sub_abs(r, m, r); - r->neg = 0; - } -} - -static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) { - int i; - mp_limb_t g[NUM_LIMBS+1]; - mp_limb_t u[NUM_LIMBS+1]; - mp_limb_t v[NUM_LIMBS+1]; - mp_size_t sn; - mp_size_t gn; - secp256k1_num_sanity(a); - secp256k1_num_sanity(m); - - /** mpn_gcdext computes: (G,S) = gcdext(U,V), where - * * G = gcd(U,V) - * * G = U*S + V*T - * * U has equal or more limbs than V, and V has no padding - * If we set U to be (a padded version of) a, and V = m: - * G = a*S + m*T - * G = a*S mod m - * Assuming G=1: - * S = 1/a mod m - */ - VERIFY_CHECK(m->limbs <= NUM_LIMBS); - VERIFY_CHECK(m->data[m->limbs-1] != 0); - for (i = 0; i < m->limbs; i++) { - u[i] = (i < a->limbs) ? a->data[i] : 0; - v[i] = m->data[i]; - } - sn = NUM_LIMBS+1; - gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); - (void)gn; - VERIFY_CHECK(gn == 1); - VERIFY_CHECK(g[0] == 1); - r->neg = a->neg ^ m->neg; - if (sn < 0) { - mpn_sub(r->data, m->data, m->limbs, r->data, -sn); - r->limbs = m->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } - } else { - r->limbs = sn; - } - memset(g, 0, sizeof(g)); - memset(u, 0, sizeof(u)); - memset(v, 0, sizeof(v)); -} - -static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { - int ret; - mpz_t ga, gb; - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); - - mpz_inits(ga, gb, NULL); - - mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); - mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); - if (a->neg) { - mpz_neg(ga, ga); - } - - ret = mpz_jacobi(ga, gb); - - mpz_clears(ga, gb, NULL); - - return ret; -} - -static int secp256k1_num_is_one(const secp256k1_num *a) { - return (a->limbs == 1 && a->data[0] == 1); -} - -static int secp256k1_num_is_zero(const secp256k1_num *a) { - return (a->limbs == 1 && a->data[0] == 0); -} - -static int secp256k1_num_is_neg(const secp256k1_num *a) { - return (a->limbs > 1 || a->data[0] != 0) && a->neg; -} - -static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { - if (a->limbs > b->limbs) { - return 1; - } - if (a->limbs < b->limbs) { - return -1; - } - return mpn_cmp(a->data, b->data, a->limbs); -} - -static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { - if (a->limbs > b->limbs) { - return 0; - } - if (a->limbs < b->limbs) { - return 0; - } - if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) { - return 0; - } - return mpn_cmp(a->data, b->data, a->limbs) == 0; -} - -static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) { - if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ - r->neg = a->neg; - if (a->limbs >= b->limbs) { - secp256k1_num_add_abs(r, a, b); - } else { - secp256k1_num_add_abs(r, b, a); - } - } else { - if (secp256k1_num_cmp(a, b) > 0) { - r->neg = a->neg; - secp256k1_num_sub_abs(r, a, b); - } else { - r->neg = b->neg ^ bneg; - secp256k1_num_sub_abs(r, b, a); - } - } -} - -static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - secp256k1_num_subadd(r, a, b, 0); -} - -static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - secp256k1_num_subadd(r, a, b, 1); -} - -static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t tmp[2*NUM_LIMBS+1]; - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - - VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); - if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { - r->limbs = 1; - r->neg = 0; - r->data[0] = 0; - return; - } - if (a->limbs >= b->limbs) { - mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); - } else { - mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); - } - r->limbs = a->limbs + b->limbs; - if (r->limbs > 1 && tmp[r->limbs - 1]==0) { - r->limbs--; - } - VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); - mpn_copyi(r->data, tmp, r->limbs); - r->neg = a->neg ^ b->neg; - memset(tmp, 0, sizeof(tmp)); -} - -static void secp256k1_num_shift(secp256k1_num *r, int bits) { - if (bits % GMP_NUMB_BITS) { - /* Shift within limbs. */ - mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); - } - if (bits >= GMP_NUMB_BITS) { - int i; - /* Shift full limbs. */ - for (i = 0; i < r->limbs; i++) { - int index = i + (bits / GMP_NUMB_BITS); - if (index < r->limbs && index < 2*NUM_LIMBS) { - r->data[i] = r->data[index]; - } else { - r->data[i] = 0; - } - } - } - while (r->limbs>1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_negate(secp256k1_num *r) { - r->neg ^= 1; -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h deleted file mode 100644 index 0b0e3a072a..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h +++ /dev/null @@ -1,24 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_IMPL_H_ -#define _SECP256K1_NUM_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "num.h" - -#if defined(USE_NUM_GMP) -#include "num_gmp_impl.h" -#elif defined(USE_NUM_NONE) -/* Nothing. */ -#else -#error "Please select num implementation" -#endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h deleted file mode 100644 index 27e9d8375e..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h +++ /dev/null @@ -1,106 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_ -#define _SECP256K1_SCALAR_ - -#include "num.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low.h" -#elif defined(USE_SCALAR_4X64) -#include "scalar_4x64.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32.h" -#else -#error "Please select scalar implementation" -#endif - -/** Clear a scalar to prevent the leak of sensitive data. */ -static void secp256k1_scalar_clear(secp256k1_scalar *r); - -/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ -static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Access bits from a scalar. Not constant time. */ -static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Set a scalar from a big endian byte array. */ -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); - -/** Set a scalar to an unsigned integer. */ -static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); - -/** Convert a scalar to a byte array. */ -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); - -/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); - -/** Multiply two scalars (modulo the group order). */ -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Shift a scalar right by some amount strictly between 0 and 16, returning - * the low bits that were shifted off */ -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); - -/** Compute the square of a scalar (modulo the group order). */ -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the inverse of a scalar (modulo the group order). */ -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the complement of a scalar (modulo the group order). */ -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Check whether a scalar equals zero. */ -static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); - -/** Check whether a scalar equals one. */ -static int secp256k1_scalar_is_one(const secp256k1_scalar *a); - -/** Check whether a scalar, considered as an nonnegative integer, is even. */ -static int secp256k1_scalar_is_even(const secp256k1_scalar *a); - -/** Check whether a scalar is higher than the group order divided by 2. */ -static int secp256k1_scalar_is_high(const secp256k1_scalar *a); - -/** Conditionally negate a number, in constant time. - * Returns -1 if the number was negated, 1 otherwise */ -static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); - -#ifndef USE_NUM_NONE -/** Convert a scalar to a number. */ -static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); - -/** Get the order of the group as a number. */ -static void secp256k1_scalar_order_get_num(secp256k1_num *r); -#endif - -/** Compare two scalars. */ -static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); - -#ifdef USE_ENDOMORPHISM -/** Find r1 and r2 such that r1+r2*2^128 = a. */ -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -#endif - -/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ -static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h deleted file mode 100644 index cff406038f..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h +++ /dev/null @@ -1,19 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint64_t d[4]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h deleted file mode 100644 index 56e7bd82af..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h +++ /dev/null @@ -1,949 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) -#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) -#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) -#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) -#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) -#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) -#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); - return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK(count < 32); - VERIFY_CHECK(offset + count <= 256); - if ((offset + count - 1) >> 6 == offset >> 6) { - return secp256k1_scalar_get_bits(a, offset, count); - } else { - VERIFY_CHECK((offset >> 6) + 1 < 4); - return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ - no |= (a->d[2] < SECP256K1_N_2); - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1); - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { - uint128_t t; - VERIFY_CHECK(overflow <= 1); - t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint64_t)r->d[3]; - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - uint128_t t = (uint128_t)a->d[0] + b->d[0]; - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[1] + b->d[1]; - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[2] + b->d[2]; - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[3] + b->d[3]; - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - overflow = t + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - uint128_t t; - VERIFY_CHECK(bit < 256); - bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ - t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; -#ifdef VERIFY - VERIFY_CHECK((t >> 64) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; - r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; - r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; - r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; - bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; - bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; - bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); - uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; - r->d[0] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; - r->d[1] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; - r->d[2] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; - r->d[3] = t & nonzero; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[3] < SECP256K1_N_H_3); - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - uint64_t mask = !flag - 1; - uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; - uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); - r->d[0] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); - r->d[1] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); - r->d[2] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); - r->d[3] = t & nonzero; - return 2 * (mask == 0) - 1; -} - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint64_t tl, th; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint64_t tl, th; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd2(a,b) { \ - uint64_t tl, th, th2, tl2; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ - c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ - tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ - th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c0 += tl2; /* overflow is handled on the next line */ \ - th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ - c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ - c1 += th2; /* overflow is handled on the next line */ \ - c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)) ? 1 : 0; \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { -#ifdef USE_ASM_X86_64 - /* Reduce 512 bits into 385. */ - uint64_t m0, m1, m2, m3, m4, m5, m6; - uint64_t p0, p1, p2, p3, p4; - uint64_t c; - - __asm__ __volatile__( - /* Preload. */ - "movq 32(%%rsi), %%r11\n" - "movq 40(%%rsi), %%r12\n" - "movq 48(%%rsi), %%r13\n" - "movq 56(%%rsi), %%r14\n" - /* Initialize r8,r9,r10 */ - "movq 0(%%rsi), %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += n0 * c0 */ - "movq %8, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract m0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += l1 */ - "addq 8(%%rsi), %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += n1 * c0 */ - "movq %8, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n0 * c1 */ - "movq %9, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract m1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += l2 */ - "addq 16(%%rsi), %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n2 * c0 */ - "movq %8, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n1 * c1 */ - "movq %9, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n0 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract m2 */ - "movq %%r10, %q2\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += l3 */ - "addq 24(%%rsi), %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n3 * c0 */ - "movq %8, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n2 * c1 */ - "movq %9, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n1 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* extract m3 */ - "movq %%r8, %q3\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += n3 * c1 */ - "movq %9, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n2 */ - "addq %%r13, %%r9\n" - "adcq $0, %%r10\n" - "adcq $0, %%r8\n" - /* extract m4 */ - "movq %%r9, %q4\n" - /* (r10,r8) += n3 */ - "addq %%r14, %%r10\n" - "adcq $0, %%r8\n" - /* extract m5 */ - "movq %%r10, %q5\n" - /* extract m6 */ - "movq %%r8, %q6\n" - : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) - : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); - - /* Reduce 385 bits into 258. */ - __asm__ __volatile__( - /* Preload */ - "movq %q9, %%r11\n" - "movq %q10, %%r12\n" - "movq %q11, %%r13\n" - /* Initialize (r8,r9,r10) */ - "movq %q5, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += m4 * c0 */ - "movq %12, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract p0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += m1 */ - "addq %q6, %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += m5 * c0 */ - "movq %12, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += m4 * c1 */ - "movq %13, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract p1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += m2 */ - "addq %q7, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m6 * c0 */ - "movq %12, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m5 * c1 */ - "movq %13, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m4 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract p2 */ - "movq %%r10, %q2\n" - /* (r8,r9) += m3 */ - "addq %q8, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += m6 * c1 */ - "movq %13, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* (r8,r9) += m5 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - /* extract p3 */ - "movq %%r8, %q3\n" - /* (r9) += m6 */ - "addq %%r13, %%r9\n" - /* extract p4 */ - "movq %%r9, %q4\n" - : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) - : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); - - /* Reduce 258 bits into 256. */ - __asm__ __volatile__( - /* Preload */ - "movq %q5, %%r10\n" - /* (rax,rdx) = p4 * c0 */ - "movq %7, %%rax\n" - "mulq %%r10\n" - /* (rax,rdx) += p0 */ - "addq %q1, %%rax\n" - "adcq $0, %%rdx\n" - /* extract r0 */ - "movq %%rax, 0(%q6)\n" - /* Move to (r8,r9) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p1 */ - "addq %q2, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += p4 * c1 */ - "movq %8, %%rax\n" - "mulq %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* Extract r1 */ - "movq %%r8, 8(%q6)\n" - "xorq %%r8, %%r8\n" - /* (r9,r8) += p4 */ - "addq %%r10, %%r9\n" - "adcq $0, %%r8\n" - /* (r9,r8) += p2 */ - "addq %q3, %%r9\n" - "adcq $0, %%r8\n" - /* Extract r2 */ - "movq %%r9, 16(%q6)\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p3 */ - "addq %q4, %%r8\n" - "adcq $0, %%r9\n" - /* Extract r3 */ - "movq %%r8, 24(%q6)\n" - /* Extract c */ - "movq %%r9, %q0\n" - : "=g"(c) - : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); -#else - uint128_t c; - uint64_t c0, c1, c2; - uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; - uint64_t m0, m1, m2, m3, m4, m5; - uint32_t m6; - uint64_t p0, p1, p2, p3; - uint32_t p4; - - /* Reduce 512 bits into 385. */ - /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - sumadd(n0); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - sumadd(n1); - extract(m3); - muladd(n3, SECP256K1_N_C_1); - sumadd(n2); - extract(m4); - sumadd_fast(n3); - extract_fast(m5); - VERIFY_CHECK(c0 <= 1); - m6 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m4, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m5, SECP256K1_N_C_0); - muladd(m4, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m6, SECP256K1_N_C_0); - muladd(m5, SECP256K1_N_C_1); - sumadd(m4); - extract(p2); - sumadd_fast(m3); - muladd_fast(m6, SECP256K1_N_C_1); - sumadd_fast(m5); - extract_fast(p3); - p4 = c0 + m6; - VERIFY_CHECK(p4 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ - c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; - r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; - r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p2 + (uint128_t)p4; - r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p3; - r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; -#endif - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { -#ifdef USE_ASM_X86_64 - const uint64_t *pb = b->d; - __asm__ __volatile__( - /* Preload */ - "movq 0(%%rdi), %%r15\n" - "movq 8(%%rdi), %%rbx\n" - "movq 16(%%rdi), %%rcx\n" - "movq 0(%%rdx), %%r11\n" - "movq 8(%%rdx), %%r12\n" - "movq 16(%%rdx), %%r13\n" - "movq 24(%%rdx), %%r14\n" - /* (rax,rdx) = a0 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - /* Extract l0 */ - "movq %%rax, 0(%%rsi)\n" - /* (r8,r9,r10) = (rdx) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a0 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a1 * b0 */ - "movq %%rbx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l1 */ - "movq %%r8, 8(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a0 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a1 * b1 */ - "movq %%rbx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a2 * b0 */ - "movq %%rcx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l2 */ - "movq %%r9, 16(%%rsi)\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += a0 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Preload a3 */ - "movq 24(%%rdi), %%r15\n" - /* (r10,r8,r9) += a1 * b2 */ - "movq %%rbx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a2 * b1 */ - "movq %%rcx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a3 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Extract l3 */ - "movq %%r10, 24(%%rsi)\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a1 * b3 */ - "movq %%rbx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a2 * b2 */ - "movq %%rcx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a3 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l4 */ - "movq %%r8, 32(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a2 * b3 */ - "movq %%rcx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a3 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l5 */ - "movq %%r9, 40(%%rsi)\n" - /* (r10,r8) += a3 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - /* Extract l6 */ - "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ - "movq %%r8, 56(%%rsi)\n" - : "+d"(pb) - : "S"(l), "D"(a->d) - : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); -#else - /* 160 bit accumulator. */ - uint64_t c0 = 0, c1 = 0; - uint32_t c2 = 0; - - /* l[0..7] = a[0..3] * b[0..3]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l[3]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - extract(l[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - extract(l[5]); - muladd_fast(a->d[3], b->d[3]); - extract_fast(l[6]); - VERIFY_CHECK(c1 == 0); - l[7] = c0; -#endif -} - -static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { -#ifdef USE_ASM_X86_64 - __asm__ __volatile__( - /* Preload */ - "movq 0(%%rdi), %%r11\n" - "movq 8(%%rdi), %%r12\n" - "movq 16(%%rdi), %%r13\n" - "movq 24(%%rdi), %%r14\n" - /* (rax,rdx) = a0 * a0 */ - "movq %%r11, %%rax\n" - "mulq %%r11\n" - /* Extract l0 */ - "movq %%rax, 0(%%rsi)\n" - /* (r8,r9,r10) = (rdx,0) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += 2 * a0 * a1 */ - "movq %%r11, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l1 */ - "movq %%r8, 8(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += 2 * a0 * a2 */ - "movq %%r11, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a1 * a1 */ - "movq %%r12, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l2 */ - "movq %%r9, 16(%%rsi)\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += 2 * a0 * a3 */ - "movq %%r11, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += 2 * a1 * a2 */ - "movq %%r12, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Extract l3 */ - "movq %%r10, 24(%%rsi)\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += 2 * a1 * a3 */ - "movq %%r12, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a2 * a2 */ - "movq %%r13, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l4 */ - "movq %%r8, 32(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += 2 * a2 * a3 */ - "movq %%r13, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l5 */ - "movq %%r9, 40(%%rsi)\n" - /* (r10,r8) += a3 * a3 */ - "movq %%r14, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - /* Extract l6 */ - "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ - "movq %%r8, 56(%%rsi)\n" - : - : "S"(l), "D"(a->d) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); -#else - /* 160 bit accumulator. */ - uint64_t c0 = 0, c1 = 0; - uint32_t c2 = 0; - - /* l[0..7] = a[0..3] * b[0..3]. */ - muladd_fast(a->d[0], a->d[0]); - extract_fast(l[0]); - muladd2(a->d[0], a->d[1]); - extract(l[1]); - muladd2(a->d[0], a->d[2]); - muladd(a->d[1], a->d[1]); - extract(l[2]); - muladd2(a->d[0], a->d[3]); - muladd2(a->d[1], a->d[2]); - extract(l[3]); - muladd2(a->d[1], a->d[3]); - muladd(a->d[2], a->d[2]); - extract(l[4]); - muladd2(a->d[2], a->d[3]); - extract(l[5]); - muladd_fast(a->d[3], a->d[3]); - extract_fast(l[6]); - VERIFY_CHECK(c1 == 0); - l[7] = c0; -#endif -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef muladd2 -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint64_t l[8]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = r->d[0] & ((1 << n) - 1); - r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); - r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); - r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); - r->d[3] = (r->d[3] >> n); - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint64_t l[8]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - r1->d[0] = a->d[0]; - r1->d[1] = a->d[1]; - r1->d[2] = 0; - r1->d[3] = 0; - r2->d[0] = a->d[2]; - r2->d[1] = a->d[3]; - r2->d[2] = 0; - r2->d[3] = 0; -} -#endif - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint64_t l[8]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - VERIFY_CHECK(shift >= 256); - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 6; - shiftlow = shift & 0x3F; - shifthigh = 64 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h deleted file mode 100644 index 1319664f65..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h +++ /dev/null @@ -1,19 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint32_t d[8]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h deleted file mode 100644 index aae4f35c08..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h +++ /dev/null @@ -1,721 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) -#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) -#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) -#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) -#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) -#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (~SECP256K1_N_2) -#define SECP256K1_N_C_3 (~SECP256K1_N_3) -#define SECP256K1_N_C_4 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) -#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) -#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) -#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) -#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); - return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK(count < 32); - VERIFY_CHECK(offset + count <= 256); - if ((offset + count - 1) >> 5 == offset >> 5) { - return secp256k1_scalar_get_bits(a, offset, count); - } else { - VERIFY_CHECK((offset >> 5) + 1 < 8); - return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ - no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_4); - yes |= (a->d[4] > SECP256K1_N_4) & ~no; - no |= (a->d[3] < SECP256K1_N_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_3) & ~no; - no |= (a->d[2] < SECP256K1_N_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { - uint64_t t; - VERIFY_CHECK(overflow <= 1); - t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; - r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; - r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; - r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; - r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; - r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[5]; - r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[6]; - r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[7]; - r->d[7] = t & 0xFFFFFFFFUL; - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - uint64_t t = (uint64_t)a->d[0] + b->d[0]; - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[1] + b->d[1]; - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[2] + b->d[2]; - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[3] + b->d[3]; - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[4] + b->d[4]; - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[5] + b->d[5]; - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[6] + b->d[6]; - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[7] + b->d[7]; - r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; - overflow = t + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - uint64_t t; - VERIFY_CHECK(bit < 256); - bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ - t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); - r->d[7] = t & 0xFFFFFFFFULL; -#ifdef VERIFY - VERIFY_CHECK((t >> 32) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; - r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; - r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; - r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; - r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; - r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; - r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; - r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; - bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; - bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; - bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; - bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; - bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; - bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; - bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); - uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; - r->d[7] = t & nonzero; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[7] < SECP256K1_N_H_7); - yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; - no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ - no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - uint32_t mask = !flag - 1; - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); - uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); - r->d[7] = t & nonzero; - return 2 * (mask == 0) - 1; -} - - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd2(a,b) { \ - uint32_t tl, th, th2, tl2; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ - c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ - tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ - th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c0 += tl2; /* overflow is handled on the next line */ \ - th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ - c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ - c1 += th2; /* overflow is handled on the next line */ \ - c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)) ? 1 : 0; \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { - uint64_t c; - uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; - uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; - uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; - - /* 96 bit accumulator. */ - uint32_t c0, c1, c2; - - /* Reduce 512 bits into 385. */ - /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - muladd(n0, SECP256K1_N_C_2); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - muladd(n1, SECP256K1_N_C_2); - muladd(n0, SECP256K1_N_C_3); - extract(m3); - sumadd(l[4]); - muladd(n4, SECP256K1_N_C_0); - muladd(n3, SECP256K1_N_C_1); - muladd(n2, SECP256K1_N_C_2); - muladd(n1, SECP256K1_N_C_3); - sumadd(n0); - extract(m4); - sumadd(l[5]); - muladd(n5, SECP256K1_N_C_0); - muladd(n4, SECP256K1_N_C_1); - muladd(n3, SECP256K1_N_C_2); - muladd(n2, SECP256K1_N_C_3); - sumadd(n1); - extract(m5); - sumadd(l[6]); - muladd(n6, SECP256K1_N_C_0); - muladd(n5, SECP256K1_N_C_1); - muladd(n4, SECP256K1_N_C_2); - muladd(n3, SECP256K1_N_C_3); - sumadd(n2); - extract(m6); - sumadd(l[7]); - muladd(n7, SECP256K1_N_C_0); - muladd(n6, SECP256K1_N_C_1); - muladd(n5, SECP256K1_N_C_2); - muladd(n4, SECP256K1_N_C_3); - sumadd(n3); - extract(m7); - muladd(n7, SECP256K1_N_C_1); - muladd(n6, SECP256K1_N_C_2); - muladd(n5, SECP256K1_N_C_3); - sumadd(n4); - extract(m8); - muladd(n7, SECP256K1_N_C_2); - muladd(n6, SECP256K1_N_C_3); - sumadd(n5); - extract(m9); - muladd(n7, SECP256K1_N_C_3); - sumadd(n6); - extract(m10); - sumadd_fast(n7); - extract_fast(m11); - VERIFY_CHECK(c0 <= 1); - m12 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m8, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m9, SECP256K1_N_C_0); - muladd(m8, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m10, SECP256K1_N_C_0); - muladd(m9, SECP256K1_N_C_1); - muladd(m8, SECP256K1_N_C_2); - extract(p2); - sumadd(m3); - muladd(m11, SECP256K1_N_C_0); - muladd(m10, SECP256K1_N_C_1); - muladd(m9, SECP256K1_N_C_2); - muladd(m8, SECP256K1_N_C_3); - extract(p3); - sumadd(m4); - muladd(m12, SECP256K1_N_C_0); - muladd(m11, SECP256K1_N_C_1); - muladd(m10, SECP256K1_N_C_2); - muladd(m9, SECP256K1_N_C_3); - sumadd(m8); - extract(p4); - sumadd(m5); - muladd(m12, SECP256K1_N_C_1); - muladd(m11, SECP256K1_N_C_2); - muladd(m10, SECP256K1_N_C_3); - sumadd(m9); - extract(p5); - sumadd(m6); - muladd(m12, SECP256K1_N_C_2); - muladd(m11, SECP256K1_N_C_3); - sumadd(m10); - extract(p6); - sumadd_fast(m7); - muladd_fast(m12, SECP256K1_N_C_3); - sumadd_fast(m11); - extract_fast(p7); - p8 = c0 + m12; - VERIFY_CHECK(p8 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ - c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; - r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; - c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; - r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; - c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; - r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; - c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; - r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; - c += p4 + (uint64_t)p8; - r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; - c += p5; - r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; - c += p6; - r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; - c += p7; - r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { - /* 96 bit accumulator. */ - uint32_t c0 = 0, c1 = 0, c2 = 0; - - /* l[0..15] = a[0..7] * b[0..7]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l[3]); - muladd(a->d[0], b->d[4]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - muladd(a->d[4], b->d[0]); - extract(l[4]); - muladd(a->d[0], b->d[5]); - muladd(a->d[1], b->d[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - muladd(a->d[4], b->d[1]); - muladd(a->d[5], b->d[0]); - extract(l[5]); - muladd(a->d[0], b->d[6]); - muladd(a->d[1], b->d[5]); - muladd(a->d[2], b->d[4]); - muladd(a->d[3], b->d[3]); - muladd(a->d[4], b->d[2]); - muladd(a->d[5], b->d[1]); - muladd(a->d[6], b->d[0]); - extract(l[6]); - muladd(a->d[0], b->d[7]); - muladd(a->d[1], b->d[6]); - muladd(a->d[2], b->d[5]); - muladd(a->d[3], b->d[4]); - muladd(a->d[4], b->d[3]); - muladd(a->d[5], b->d[2]); - muladd(a->d[6], b->d[1]); - muladd(a->d[7], b->d[0]); - extract(l[7]); - muladd(a->d[1], b->d[7]); - muladd(a->d[2], b->d[6]); - muladd(a->d[3], b->d[5]); - muladd(a->d[4], b->d[4]); - muladd(a->d[5], b->d[3]); - muladd(a->d[6], b->d[2]); - muladd(a->d[7], b->d[1]); - extract(l[8]); - muladd(a->d[2], b->d[7]); - muladd(a->d[3], b->d[6]); - muladd(a->d[4], b->d[5]); - muladd(a->d[5], b->d[4]); - muladd(a->d[6], b->d[3]); - muladd(a->d[7], b->d[2]); - extract(l[9]); - muladd(a->d[3], b->d[7]); - muladd(a->d[4], b->d[6]); - muladd(a->d[5], b->d[5]); - muladd(a->d[6], b->d[4]); - muladd(a->d[7], b->d[3]); - extract(l[10]); - muladd(a->d[4], b->d[7]); - muladd(a->d[5], b->d[6]); - muladd(a->d[6], b->d[5]); - muladd(a->d[7], b->d[4]); - extract(l[11]); - muladd(a->d[5], b->d[7]); - muladd(a->d[6], b->d[6]); - muladd(a->d[7], b->d[5]); - extract(l[12]); - muladd(a->d[6], b->d[7]); - muladd(a->d[7], b->d[6]); - extract(l[13]); - muladd_fast(a->d[7], b->d[7]); - extract_fast(l[14]); - VERIFY_CHECK(c1 == 0); - l[15] = c0; -} - -static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { - /* 96 bit accumulator. */ - uint32_t c0 = 0, c1 = 0, c2 = 0; - - /* l[0..15] = a[0..7]^2. */ - muladd_fast(a->d[0], a->d[0]); - extract_fast(l[0]); - muladd2(a->d[0], a->d[1]); - extract(l[1]); - muladd2(a->d[0], a->d[2]); - muladd(a->d[1], a->d[1]); - extract(l[2]); - muladd2(a->d[0], a->d[3]); - muladd2(a->d[1], a->d[2]); - extract(l[3]); - muladd2(a->d[0], a->d[4]); - muladd2(a->d[1], a->d[3]); - muladd(a->d[2], a->d[2]); - extract(l[4]); - muladd2(a->d[0], a->d[5]); - muladd2(a->d[1], a->d[4]); - muladd2(a->d[2], a->d[3]); - extract(l[5]); - muladd2(a->d[0], a->d[6]); - muladd2(a->d[1], a->d[5]); - muladd2(a->d[2], a->d[4]); - muladd(a->d[3], a->d[3]); - extract(l[6]); - muladd2(a->d[0], a->d[7]); - muladd2(a->d[1], a->d[6]); - muladd2(a->d[2], a->d[5]); - muladd2(a->d[3], a->d[4]); - extract(l[7]); - muladd2(a->d[1], a->d[7]); - muladd2(a->d[2], a->d[6]); - muladd2(a->d[3], a->d[5]); - muladd(a->d[4], a->d[4]); - extract(l[8]); - muladd2(a->d[2], a->d[7]); - muladd2(a->d[3], a->d[6]); - muladd2(a->d[4], a->d[5]); - extract(l[9]); - muladd2(a->d[3], a->d[7]); - muladd2(a->d[4], a->d[6]); - muladd(a->d[5], a->d[5]); - extract(l[10]); - muladd2(a->d[4], a->d[7]); - muladd2(a->d[5], a->d[6]); - extract(l[11]); - muladd2(a->d[5], a->d[7]); - muladd(a->d[6], a->d[6]); - extract(l[12]); - muladd2(a->d[6], a->d[7]); - extract(l[13]); - muladd_fast(a->d[7], a->d[7]); - extract_fast(l[14]); - VERIFY_CHECK(c1 == 0); - l[15] = c0; -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef muladd2 -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint32_t l[16]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = r->d[0] & ((1 << n) - 1); - r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); - r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); - r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n)); - r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n)); - r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n)); - r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); - r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); - r->d[7] = (r->d[7] >> n); - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint32_t l[16]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - r1->d[0] = a->d[0]; - r1->d[1] = a->d[1]; - r1->d[2] = a->d[2]; - r1->d[3] = a->d[3]; - r1->d[4] = 0; - r1->d[5] = 0; - r1->d[6] = 0; - r1->d[7] = 0; - r2->d[0] = a->d[4]; - r2->d[1] = a->d[5]; - r2->d[2] = a->d[6]; - r2->d[3] = a->d[7]; - r2->d[4] = 0; - r2->d[5] = 0; - r2->d[6] = 0; - r2->d[7] = 0; -} -#endif - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint32_t l[16]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - VERIFY_CHECK(shift >= 256); - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 5; - shiftlow = shift & 0x1F; - shifthigh = 32 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h deleted file mode 100644 index f5b2376407..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h +++ /dev/null @@ -1,370 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_IMPL_H_ -#define _SECP256K1_SCALAR_IMPL_H_ - -#include "group.h" -#include "scalar.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low_impl.h" -#elif defined(USE_SCALAR_4X64) -#include "scalar_4x64_impl.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32_impl.h" -#else -#error "Please select scalar implementation" -#endif - -#ifndef USE_NUM_NONE -static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) { - unsigned char c[32]; - secp256k1_scalar_get_b32(c, a); - secp256k1_num_set_bin(r, c, 32); -} - -/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ -static void secp256k1_scalar_order_get_num(secp256k1_num *r) { -#if defined(EXHAUSTIVE_TEST_ORDER) - static const unsigned char order[32] = { - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER - }; -#else - static const unsigned char order[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; -#endif - secp256k1_num_set_bin(r, order, 32); -} -#endif - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { -#if defined(EXHAUSTIVE_TEST_ORDER) - int i; - *r = 0; - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) - if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) - *r = i; - /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus - * have a composite group order; fix it in exhaustive_tests.c). */ - VERIFY_CHECK(*r != 0); -} -#else - secp256k1_scalar *t; - int i; - /* First compute x ^ (2^N - 1) for some values of N. */ - secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; - - secp256k1_scalar_sqr(&x2, x); - secp256k1_scalar_mul(&x2, &x2, x); - - secp256k1_scalar_sqr(&x3, &x2); - secp256k1_scalar_mul(&x3, &x3, x); - - secp256k1_scalar_sqr(&x4, &x3); - secp256k1_scalar_mul(&x4, &x4, x); - - secp256k1_scalar_sqr(&x6, &x4); - secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &x2); - - secp256k1_scalar_sqr(&x7, &x6); - secp256k1_scalar_mul(&x7, &x7, x); - - secp256k1_scalar_sqr(&x8, &x7); - secp256k1_scalar_mul(&x8, &x8, x); - - secp256k1_scalar_sqr(&x15, &x8); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x15, &x15); - } - secp256k1_scalar_mul(&x15, &x15, &x7); - - secp256k1_scalar_sqr(&x30, &x15); - for (i = 0; i < 14; i++) { - secp256k1_scalar_sqr(&x30, &x30); - } - secp256k1_scalar_mul(&x30, &x30, &x15); - - secp256k1_scalar_sqr(&x60, &x30); - for (i = 0; i < 29; i++) { - secp256k1_scalar_sqr(&x60, &x60); - } - secp256k1_scalar_mul(&x60, &x60, &x30); - - secp256k1_scalar_sqr(&x120, &x60); - for (i = 0; i < 59; i++) { - secp256k1_scalar_sqr(&x120, &x120); - } - secp256k1_scalar_mul(&x120, &x120, &x60); - - secp256k1_scalar_sqr(&x127, &x120); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x127, &x127); - } - secp256k1_scalar_mul(&x127, &x127, &x7); - - /* Then accumulate the final result (t starts at x127). */ - t = &x127; - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 5; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 10; i++) { /* 0000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 9; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 6; i++) { /* 00000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(r, t, &x6); /* 111111 */ -} - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - return !(a->d[0] & 1); -} -#endif - -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { -#if defined(USE_SCALAR_INV_BUILTIN) - secp256k1_scalar_inverse(r, x); -#elif defined(USE_SCALAR_INV_NUM) - unsigned char b[32]; - secp256k1_num n, m; - secp256k1_scalar t = *x; - secp256k1_scalar_get_b32(b, &t); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_scalar_order_get_num(&m); - secp256k1_num_mod_inverse(&n, &n, &m); - secp256k1_num_get_bin(b, 32, &n); - secp256k1_scalar_set_b32(r, b, NULL); - /* Verify that the inverse was computed correctly, without GMP code. */ - secp256k1_scalar_mul(&t, &t, r); - CHECK(secp256k1_scalar_is_one(&t)); -#else -#error "Please select scalar inverse implementation" -#endif -} - -#ifdef USE_ENDOMORPHISM -#if defined(EXHAUSTIVE_TEST_ORDER) -/** - * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the - * full case we don't bother making k1 and k2 be small, we just want them to be - * nontrivial to get full test coverage for the exhaustive tests. We therefore - * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. - */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; - *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; -} -#else -/** - * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where - * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, - * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} - * - * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm - * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 - * and k2 have a small size. - * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: - * - * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} - * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} - * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives - * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and - * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2. - * - * g1, g2 are precomputed constants used to replace division with a rounded multiplication - * when decomposing the scalar for an endomorphism-based point multiplication. - * - * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve - * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. - * - * The derivation is described in the paper "Efficient Software Implementation of Public-Key - * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), - * Section 4.3 (here we use a somewhat higher-precision estimate): - * d = a1*b2 - b1*a2 - * g1 = round((2^272)*b2/d) - * g2 = round((2^272)*b1/d) - * - * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found - * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). - * - * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). - */ - -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - secp256k1_scalar c1, c2; - static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST( - 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, - 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL - ); - static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, - 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL - ); - static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL - ); - static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, - 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL - ); - static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, - 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL - ); - VERIFY_CHECK(r1 != a); - VERIFY_CHECK(r2 != a); - /* these _var calls are constant time since the shift amount is constant */ - secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); - secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); - secp256k1_scalar_mul(&c1, &c1, &minus_b1); - secp256k1_scalar_mul(&c2, &c2, &minus_b2); - secp256k1_scalar_add(r2, &c1, &c2); - secp256k1_scalar_mul(r1, r2, &minus_lambda); - secp256k1_scalar_add(r1, r1, a); -} -#endif -#endif - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h deleted file mode 100644 index 5574c44c7a..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef uint32_t secp256k1_scalar; - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h deleted file mode 100644 index 4f94441f49..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h +++ /dev/null @@ -1,114 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -#include "scalar.h" - -#include - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - return !(*a & 1); -} - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - if (offset < 32) - return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); - else - return 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - return secp256k1_scalar_get_bits(a, offset, count); -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; - return *r < *b; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - if (flag && bit < 32) - *r += (1 << bit); -#ifdef VERIFY - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; - int i; - *r = 0; - for (i = 0; i < 32; i++) { - *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; - } - /* just deny overflow, it basically always happens */ - if (overflow) *overflow = 0; -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - memset(bin, 0, 32); - bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return *a == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - if (*a == 0) { - *r = 0; - } else { - *r = EXHAUSTIVE_TEST_ORDER - *a; - } -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return *a == 1; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - return *a > EXHAUSTIVE_TEST_ORDER / 2; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - if (flag) secp256k1_scalar_negate(r, r); - return flag ? -1 : 1; -} - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = *r & ((1 << n) - 1); - *r >>= n; - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r1 = *a; - *r2 = 0; -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return *a == *b; -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c deleted file mode 100644 index 7d637bfad1..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c +++ /dev/null @@ -1,559 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" - -#include "util.h" -#include "num_impl.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_gen_impl.h" -#include "ecdsa_impl.h" -#include "eckey_impl.h" -#include "hash_impl.h" - -#define ARG_CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - secp256k1_callback_call(&ctx->illegal_callback, #cond); \ - return 0; \ - } \ -} while(0) - -static void default_illegal_callback_fn(const char* str, void* data) { - fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); - abort(); -} - -static const secp256k1_callback default_illegal_callback = { - default_illegal_callback_fn, - NULL -}; - -static void default_error_callback_fn(const char* str, void* data) { - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} - -static const secp256k1_callback default_error_callback = { - default_error_callback_fn, - NULL -}; - - -struct secp256k1_context_struct { - secp256k1_ecmult_context ecmult_ctx; - secp256k1_ecmult_gen_context ecmult_gen_ctx; - secp256k1_callback illegal_callback; - secp256k1_callback error_callback; -}; - -secp256k1_context* secp256k1_context_create(unsigned int flags) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = default_illegal_callback; - ret->error_callback = default_error_callback; - - if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { - secp256k1_callback_call(&ret->illegal_callback, - "Invalid flags"); - free(ret); - return NULL; - } - - secp256k1_ecmult_context_init(&ret->ecmult_ctx); - secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); - - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { - secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); - } - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { - secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); - } - - return ret; -} - -secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = ctx->illegal_callback; - ret->error_callback = ctx->error_callback; - secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); - secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); - return ret; -} - -void secp256k1_context_destroy(secp256k1_context* ctx) { - if (ctx != NULL) { - secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); - secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); - - free(ctx); - } -} - -void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_illegal_callback_fn; - } - ctx->illegal_callback.fn = fun; - ctx->illegal_callback.data = data; -} - -void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_error_callback_fn; - } - ctx->error_callback.fn = fun; - ctx->error_callback.data = data; -} - -static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { - if (sizeof(secp256k1_ge_storage) == 64) { - /* When the secp256k1_ge_storage type is exactly 64 byte, use its - * representation inside secp256k1_pubkey, as conversion is very fast. - * Note that secp256k1_pubkey_save must use the same representation. */ - secp256k1_ge_storage s; - memcpy(&s, &pubkey->data[0], 64); - secp256k1_ge_from_storage(ge, &s); - } else { - /* Otherwise, fall back to 32-byte big endian for X and Y. */ - secp256k1_fe x, y; - secp256k1_fe_set_b32(&x, pubkey->data); - secp256k1_fe_set_b32(&y, pubkey->data + 32); - secp256k1_ge_set_xy(ge, &x, &y); - } - ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); - return 1; -} - -static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { - if (sizeof(secp256k1_ge_storage) == 64) { - secp256k1_ge_storage s; - secp256k1_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, 64); - } else { - VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); - secp256k1_fe_normalize_var(&ge->x); - secp256k1_fe_normalize_var(&ge->y); - secp256k1_fe_get_b32(pubkey->data, &ge->x); - secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); - } -} - -int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { - secp256k1_ge Q; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(input != NULL); - if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { - return 0; - } - secp256k1_pubkey_save(pubkey, &Q); - secp256k1_ge_clear(&Q); - return 1; -} - -int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { - secp256k1_ge Q; - size_t len; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); - len = *outputlen; - *outputlen = 0; - ARG_CHECK(output != NULL); - memset(output, 0, len); - ARG_CHECK(pubkey != NULL); - ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); - if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); - if (ret) { - *outputlen = len; - } - } - return ret; -} - -static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } -} - -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } -} - -int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input != NULL); - - if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; - } else { - memset(sig, 0, sizeof(*sig)); - return 0; - } -} - -int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); -} - -int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { - secp256k1_scalar r, s; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); - ret = secp256k1_scalar_is_high(&s); - if (sigout != NULL) { - if (ret) { - secp256k1_scalar_negate(&s, &s); - } - secp256k1_ecdsa_signature_save(sigout, &r, &s); - } - - return ret; -} - -int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_scalar_set_b32(&m, msg32, NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return (!secp256k1_scalar_is_high(&s) && - secp256k1_pubkey_load(ctx, &q, pubkey) && - secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); -} - -static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - unsigned char keydata[112]; - int keylen = 64; - secp256k1_rfc6979_hmac_sha256_t rng; - unsigned int i; - /* We feed a byte array to the PRNG as input, consisting of: - * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. - * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. - * - optionally 16 extra bytes with the algorithm name. - * Because the arguments have distinct fixed lengths it is not possible for - * different argument mixtures to emulate each other and result in the same - * nonces. - */ - memcpy(keydata, key32, 32); - memcpy(keydata + 32, msg32, 32); - if (data != NULL) { - memcpy(keydata + 64, data, 32); - keylen = 96; - } - if (algo16 != NULL) { - memcpy(keydata + keylen, algo16, 16); - keylen += 16; - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); - memset(keydata, 0, sizeof(keydata)); - for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - return 1; -} - -const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; -const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; - -int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned char nonce32[32]; - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - if (!overflow && !secp256k1_scalar_is_zero(&non)) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { - break; - } - } - count++; - } - memset(nonce32, 0, 32); - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_signature_save(signature, &r, &s); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { - secp256k1_scalar sec; - int ret; - int overflow; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = !overflow && !secp256k1_scalar_is_zero(&sec); - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { - secp256k1_gej pj; - secp256k1_ge p; - secp256k1_scalar sec; - int overflow; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); - if (ret) { - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); - secp256k1_ge_set_gej(&p, &pj); - secp256k1_pubkey_save(pubkey, &p); - } - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar term; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - - ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&term); - return ret; -} - -int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar term; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar factor; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&factor); - return ret; -} - -int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar factor; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - return 1; -} - -int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { - size_t i; - secp256k1_gej Qj; - secp256k1_ge Q; - - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(n >= 1); - ARG_CHECK(pubnonces != NULL); - - secp256k1_gej_set_infinity(&Qj); - - for (i = 0; i < n; i++) { - secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); - secp256k1_gej_add_ge(&Qj, &Qj, &Q); - } - if (secp256k1_gej_is_infinity(&Qj)) { - return 0; - } - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(pubnonce, &Q); - return 1; -} - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/main_impl.h" -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h deleted file mode 100644 index f8efa93c7c..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h +++ /dev/null @@ -1,38 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_TESTRAND_H_ -#define _SECP256K1_TESTRAND_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -/* A non-cryptographic RNG used only for test infrastructure. */ - -/** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16); - -/** Generate a pseudorandom number in the range [0..2**32-1]. */ -static uint32_t secp256k1_rand32(void); - -/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or - * more. */ -static uint32_t secp256k1_rand_bits(int bits); - -/** Generate a pseudorandom number in the range [0..range-1]. */ -static uint32_t secp256k1_rand_int(uint32_t range); - -/** Generate a pseudorandom 32-byte array. */ -static void secp256k1_rand256(unsigned char *b32); - -/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ -static void secp256k1_rand256_test(unsigned char *b32); - -/** Generate pseudorandom bytes with long sequences of zero and one bits. */ -static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h deleted file mode 100644 index 15c7b9f12d..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h +++ /dev/null @@ -1,110 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_TESTRAND_IMPL_H_ -#define _SECP256K1_TESTRAND_IMPL_H_ - -#include -#include - -#include "testrand.h" -#include "hash.h" - -static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; -static uint32_t secp256k1_test_rng_precomputed[8]; -static int secp256k1_test_rng_precomputed_used = 8; -static uint64_t secp256k1_test_rng_integer; -static int secp256k1_test_rng_integer_bits_left = 0; - -SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) { - secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); -} - -SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { - if (secp256k1_test_rng_precomputed_used == 8) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); - secp256k1_test_rng_precomputed_used = 0; - } - return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; -} - -static uint32_t secp256k1_rand_bits(int bits) { - uint32_t ret; - if (secp256k1_test_rng_integer_bits_left < bits) { - secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left); - secp256k1_test_rng_integer_bits_left += 32; - } - ret = secp256k1_test_rng_integer; - secp256k1_test_rng_integer >>= bits; - secp256k1_test_rng_integer_bits_left -= bits; - ret &= ((~((uint32_t)0)) >> (32 - bits)); - return ret; -} - -static uint32_t secp256k1_rand_int(uint32_t range) { - /* We want a uniform integer between 0 and range-1, inclusive. - * B is the smallest number such that range <= 2**B. - * two mechanisms implemented here: - * - generate B bits numbers until one below range is found, and return it - * - find the largest multiple M of range that is <= 2**(B+A), generate B+A - * bits numbers until one below M is found, and return it modulo range - * The second mechanism consumes A more bits of entropy in every iteration, - * but may need fewer iterations due to M being closer to 2**(B+A) then - * range is to 2**B. The array below (indexed by B) contains a 0 when the - * first mechanism is to be used, and the number A otherwise. - */ - static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0}; - uint32_t trange, mult; - int bits = 0; - if (range <= 1) { - return 0; - } - trange = range - 1; - while (trange > 0) { - trange >>= 1; - bits++; - } - if (addbits[bits]) { - bits = bits + addbits[bits]; - mult = ((~((uint32_t)0)) >> (32 - bits)) / range; - trange = range * mult; - } else { - trange = range; - mult = 1; - } - while(1) { - uint32_t x = secp256k1_rand_bits(bits); - if (x < trange) { - return (mult == 1) ? x : (x % range); - } - } -} - -static void secp256k1_rand256(unsigned char *b32) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); -} - -static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) { - size_t bits = 0; - memset(bytes, 0, len); - while (bits < len * 8) { - int now; - uint32_t val; - now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31; - val = secp256k1_rand_bits(1); - while (now > 0 && bits < len * 8) { - bytes[bits / 8] |= val << (bits % 8); - now--; - bits++; - } - } -} - -static void secp256k1_rand256_test(unsigned char *b32) { - secp256k1_rand_bytes_test(b32, 32); -} - -#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c deleted file mode 100644 index 9ae7d30281..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c +++ /dev/null @@ -1,4525 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include - -#include - -#include "secp256k1.c" -#include "include/secp256k1.h" -#include "testrand_impl.h" - -#ifdef ENABLE_OPENSSL_TESTS -#include "openssl/bn.h" -#include "openssl/ec.h" -#include "openssl/ecdsa.h" -#include "openssl/obj_mac.h" -#endif - -#include "contrib/lax_der_parsing.c" -#include "contrib/lax_der_privatekey_parsing.c" - -#if !defined(VG_CHECK) -# if defined(VALGRIND) -# include -# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y)) -# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y)) -# else -# define VG_UNDEF(x,y) -# define VG_CHECK(x,y) -# endif -#endif - -static int count = 64; -static secp256k1_context *ctx = NULL; - -static void counting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts. */ - int32_t *p; - (void)str; - p = data; - (*p)++; -} - -static void uncounting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts (backwards). */ - int32_t *p; - (void)str; - p = data; - (*p)--; -} - -void random_field_element_test(secp256k1_fe *fe) { - do { - unsigned char b32[32]; - secp256k1_rand256_test(b32); - if (secp256k1_fe_set_b32(fe, b32)) { - break; - } - } while(1); -} - -void random_field_element_magnitude(secp256k1_fe *fe) { - secp256k1_fe zero; - int n = secp256k1_rand_int(9); - secp256k1_fe_normalize(fe); - if (n == 0) { - return; - } - secp256k1_fe_clear(&zero); - secp256k1_fe_negate(&zero, &zero, 0); - secp256k1_fe_mul_int(&zero, n - 1); - secp256k1_fe_add(fe, &zero); - VERIFY_CHECK(fe->magnitude == n); -} - -void random_group_element_test(secp256k1_ge *ge) { - secp256k1_fe fe; - do { - random_field_element_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { - secp256k1_fe_normalize(&ge->y); - break; - } - } while(1); -} - -void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; - do { - random_field_element_test(&gej->z); - if (!secp256k1_fe_is_zero(&gej->z)) { - break; - } - } while(1); - secp256k1_fe_sqr(&z2, &gej->z); - secp256k1_fe_mul(&z3, &z2, &gej->z); - secp256k1_fe_mul(&gej->x, &ge->x, &z2); - secp256k1_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; -} - -void random_scalar_order_test(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_rand256_test(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -void random_scalar_order(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_rand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -void run_context_tests(void) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - unsigned char ctmp[32]; - int32_t ecount; - int32_t ecount2; - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar msg, key, nonce; - secp256k1_scalar sigr, sigs; - - ecount = 0; - ecount2 = 10; - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); - CHECK(vrfy->error_callback.fn != sign->error_callback.fn); - - /*** clone and destroy all of them to make sure cloning was complete ***/ - { - secp256k1_context *ctx_tmp; - - ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); - } - - /* Verify that the error callback makes it across the clone. */ - CHECK(vrfy->error_callback.fn != sign->error_callback.fn); - /* And that it resets back to default. */ - secp256k1_context_set_error_callback(sign, NULL, NULL); - CHECK(vrfy->error_callback.fn == sign->error_callback.fn); - - /*** attempt to use them ***/ - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - - /* Verify context-type checking illegal-argument errors. */ - memset(ctmp, 1, 32); - CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); - CHECK(ecount == 1); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); - CHECK(ecount == 2); - VG_UNDEF(&sig, sizeof(sig)); - CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); - VG_CHECK(&sig, sizeof(sig)); - CHECK(ecount2 == 10); - CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); - CHECK(ecount2 == 11); - CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); - CHECK(ecount2 == 12); - CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); - CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 13); - secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); - secp256k1_context_set_illegal_callback(sign, NULL, NULL); - - /* This shouldn't leak memory, due to already-set tests. */ - secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); - secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); - - /* obtain a working nonce */ - do { - random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try signing */ - CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try verifying */ - CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - - /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); - /* Defined as no-op. */ - secp256k1_context_destroy(NULL); -} - -/***** HASH TESTS *****/ - -void run_sha256_tests(void) { - static const char *inputs[8] = { - "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "For this sample, this 63-byte string will be used as input data", - "This is exactly 64 bytes long, not counting the terminating byte" - }; - static const unsigned char outputs[8][32] = { - {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, - {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, - {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, - {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, - {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, - {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, - {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, - {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} - }; - int i; - for (i = 0; i < 8; i++) { - unsigned char out[32]; - secp256k1_sha256_t hasher; - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - } - } -} - -void run_hmac_sha256_tests(void) { - static const char *keys[6] = { - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - "\x4a\x65\x66\x65", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - }; - static const char *inputs[6] = { - "\x48\x69\x20\x54\x68\x65\x72\x65", - "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", - "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" - }; - static const unsigned char outputs[6][32] = { - {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, - {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, - {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, - {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, - {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, - {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} - }; - int i; - for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256_t hasher; - unsigned char out[32]; - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - } - } -} - -void run_rfc6979_hmac_sha256_tests(void) { - static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; - static const unsigned char out1[3][32] = { - {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, - {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, - {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} - }; - - static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; - static const unsigned char out2[3][32] = { - {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, - {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, - {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} - }; - - secp256k1_rfc6979_hmac_sha256_t rng; - unsigned char out[32]; - int i; - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out1[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out1[i], 32) != 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out2[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); -} - -/***** RANDOM TESTS *****/ - -void test_rand_bits(int rand32, int bits) { - /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to - * get a false negative chance below once in a billion */ - static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316}; - /* We try multiplying the results with various odd numbers, which shouldn't - * influence the uniform distribution modulo a power of 2. */ - static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011}; - /* We only select up to 6 bits from the output to analyse */ - unsigned int usebits = bits > 6 ? 6 : bits; - unsigned int maxshift = bits - usebits; - /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit - number, track all observed outcomes, one per bit in a uint64_t. */ - uint64_t x[6][27] = {{0}}; - unsigned int i, shift, m; - /* Multiply the output of all rand calls with the odd number m, which - should not change the uniformity of its distribution. */ - for (i = 0; i < rounds[usebits]; i++) { - uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); - CHECK((((uint64_t)r) >> bits) == 0); - for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { - uint32_t rm = r * mults[m]; - for (shift = 0; shift <= maxshift; shift++) { - x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1))); - } - } - } - for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { - for (shift = 0; shift <= maxshift; shift++) { - /* Test that the lower usebits bits of x[shift] are 1 */ - CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0); - } - } -} - -/* Subrange must be a whole divisor of range, and at most 64 */ -void test_rand_int(uint32_t range, uint32_t subrange) { - /* (1-1/subrange)^rounds < 1/10^9 */ - int rounds = (subrange * 2073) / 100; - int i; - uint64_t x = 0; - CHECK((range % subrange) == 0); - for (i = 0; i < rounds; i++) { - uint32_t r = secp256k1_rand_int(range); - CHECK(r < range); - r = r % subrange; - x |= (((uint64_t)1) << r); - } - /* Test that the lower subrange bits of x are 1. */ - CHECK(((~x) << (64 - subrange)) == 0); -} - -void run_rand_bits(void) { - size_t b; - test_rand_bits(1, 32); - for (b = 1; b <= 32; b++) { - test_rand_bits(0, b); - } -} - -void run_rand_int(void) { - static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432}; - static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64}; - unsigned int m, s; - for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) { - for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) { - test_rand_int(ms[m] * ss[s], ss[s]); - } - } -} - -/***** NUM TESTS *****/ - -#ifndef USE_NUM_NONE -void random_num_negate(secp256k1_num *num) { - if (secp256k1_rand_bits(1)) { - secp256k1_num_negate(num); - } -} - -void random_num_order_test(secp256k1_num *num) { - secp256k1_scalar sc; - random_scalar_order_test(&sc); - secp256k1_scalar_get_num(num, &sc); -} - -void random_num_order(secp256k1_num *num) { - secp256k1_scalar sc; - random_scalar_order(&sc); - secp256k1_scalar_get_num(num, &sc); -} - -void test_num_negate(void) { - secp256k1_num n1; - secp256k1_num n2; - random_num_order_test(&n1); /* n1 = R */ - random_num_negate(&n1); - secp256k1_num_copy(&n2, &n1); /* n2 = R */ - secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ - CHECK(secp256k1_num_is_zero(&n1)); - secp256k1_num_copy(&n1, &n2); /* n1 = R */ - secp256k1_num_negate(&n1); /* n1 = -R */ - CHECK(!secp256k1_num_is_zero(&n1)); - secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ - CHECK(secp256k1_num_is_zero(&n1)); - secp256k1_num_copy(&n1, &n2); /* n1 = R */ - secp256k1_num_negate(&n1); /* n1 = -R */ - CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); - secp256k1_num_negate(&n1); /* n1 = R */ - CHECK(secp256k1_num_eq(&n1, &n2)); -} - -void test_num_add_sub(void) { - int i; - secp256k1_scalar s; - secp256k1_num n1; - secp256k1_num n2; - secp256k1_num n1p2, n2p1, n1m2, n2m1; - random_num_order_test(&n1); /* n1 = R1 */ - if (secp256k1_rand_bits(1)) { - random_num_negate(&n1); - } - random_num_order_test(&n2); /* n2 = R2 */ - if (secp256k1_rand_bits(1)) { - random_num_negate(&n2); - } - secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ - secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ - secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ - secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ - CHECK(secp256k1_num_eq(&n1p2, &n2p1)); - CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); - secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1m2)); - CHECK(!secp256k1_num_eq(&n2m1, &n1)); - secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1)); - CHECK(!secp256k1_num_eq(&n2p1, &n1)); - secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ - CHECK(secp256k1_num_eq(&n2p1, &n1)); - - /* check is_one */ - secp256k1_scalar_set_int(&s, 1); - secp256k1_scalar_get_num(&n1, &s); - CHECK(secp256k1_num_is_one(&n1)); - /* check that 2^n + 1 is never 1 */ - secp256k1_scalar_get_num(&n2, &s); - for (i = 0; i < 250; ++i) { - secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ - secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ - CHECK(!secp256k1_num_is_one(&n1p2)); - } -} - -void test_num_mod(void) { - int i; - secp256k1_scalar s; - secp256k1_num order, n; - - /* check that 0 mod anything is 0 */ - random_scalar_order_test(&s); - secp256k1_scalar_get_num(&order, &s); - secp256k1_scalar_set_int(&s, 0); - secp256k1_scalar_get_num(&n, &s); - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); - - /* check that anything mod 1 is 0 */ - secp256k1_scalar_set_int(&s, 1); - secp256k1_scalar_get_num(&order, &s); - secp256k1_scalar_get_num(&n, &s); - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); - - /* check that increasing the number past 2^256 does not break this */ - random_scalar_order_test(&s); - secp256k1_scalar_get_num(&n, &s); - /* multiply by 2^8, which'll test this case with high probability */ - for (i = 0; i < 8; ++i) { - secp256k1_num_add(&n, &n, &n); - } - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); -} - -void test_num_jacobi(void) { - secp256k1_scalar sqr; - secp256k1_scalar small; - secp256k1_scalar five; /* five is not a quadratic residue */ - secp256k1_num order, n; - int i; - /* squares mod 5 are 1, 4 */ - const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; - - /* check some small values with 5 as the order */ - secp256k1_scalar_set_int(&five, 5); - secp256k1_scalar_get_num(&order, &five); - for (i = 0; i < 10; ++i) { - secp256k1_scalar_set_int(&small, i); - secp256k1_scalar_get_num(&n, &small); - CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); - } - - /** test large values with 5 as group order */ - secp256k1_scalar_get_num(&order, &five); - /* we first need a scalar which is not a multiple of 5 */ - do { - secp256k1_num fiven; - random_scalar_order_test(&sqr); - secp256k1_scalar_get_num(&fiven, &five); - secp256k1_scalar_get_num(&n, &sqr); - secp256k1_num_mod(&n, &fiven); - } while (secp256k1_num_is_zero(&n)); - /* next force it to be a residue. 2 is a nonresidue mod 5 so we can - * just multiply by two, i.e. add the number to itself */ - if (secp256k1_num_jacobi(&n, &order) == -1) { - secp256k1_num_add(&n, &n, &n); - } - - /* test residue */ - CHECK(secp256k1_num_jacobi(&n, &order) == 1); - /* test nonresidue */ - secp256k1_num_add(&n, &n, &n); - CHECK(secp256k1_num_jacobi(&n, &order) == -1); - - /** test with secp group order as order */ - secp256k1_scalar_order_get_num(&order); - random_scalar_order_test(&sqr); - secp256k1_scalar_sqr(&sqr, &sqr); - /* test residue */ - secp256k1_scalar_get_num(&n, &sqr); - CHECK(secp256k1_num_jacobi(&n, &order) == 1); - /* test nonresidue */ - secp256k1_scalar_mul(&sqr, &sqr, &five); - secp256k1_scalar_get_num(&n, &sqr); - CHECK(secp256k1_num_jacobi(&n, &order) == -1); - /* test multiple of the order*/ - CHECK(secp256k1_num_jacobi(&order, &order) == 0); - - /* check one less than the order */ - secp256k1_scalar_set_int(&small, 1); - secp256k1_scalar_get_num(&n, &small); - secp256k1_num_sub(&n, &order, &n); - CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ -} - -void run_num_smalltests(void) { - int i; - for (i = 0; i < 100*count; i++) { - test_num_negate(); - test_num_add_sub(); - test_num_mod(); - test_num_jacobi(); - } -} -#endif - -/***** SCALAR TESTS *****/ - -void scalar_test(void) { - secp256k1_scalar s; - secp256k1_scalar s1; - secp256k1_scalar s2; -#ifndef USE_NUM_NONE - secp256k1_num snum, s1num, s2num; - secp256k1_num order, half_order; -#endif - unsigned char c[32]; - - /* Set 's' to a random scalar, with value 'snum'. */ - random_scalar_order_test(&s); - - /* Set 's1' to a random scalar, with value 's1num'. */ - random_scalar_order_test(&s1); - - /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ - random_scalar_order_test(&s2); - secp256k1_scalar_get_b32(c, &s2); - -#ifndef USE_NUM_NONE - secp256k1_scalar_get_num(&snum, &s); - secp256k1_scalar_get_num(&s1num, &s1); - secp256k1_scalar_get_num(&s2num, &s2); - - secp256k1_scalar_order_get_num(&order); - half_order = order; - secp256k1_num_shift(&half_order, 1); -#endif - - { - int i; - /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - secp256k1_scalar_set_int(&n, 0); - for (i = 0; i < 256; i += 4) { - secp256k1_scalar t; - int j; - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); - for (j = 0; j < 4; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - - { - /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - int i = 0; - secp256k1_scalar_set_int(&n, 0); - while (i < 256) { - secp256k1_scalar t; - int j; - int now = secp256k1_rand_int(15) + 1; - if (now + i > 256) { - now = 256 - i; - } - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); - for (j = 0; j < now; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - i += now; - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - -#ifndef USE_NUM_NONE - { - /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ - secp256k1_num rnum; - secp256k1_num r2num; - secp256k1_scalar r; - secp256k1_num_add(&rnum, &snum, &s2num); - secp256k1_num_mod(&rnum, &order); - secp256k1_scalar_add(&r, &s, &s2); - secp256k1_scalar_get_num(&r2num, &r); - CHECK(secp256k1_num_eq(&rnum, &r2num)); - } - - { - /* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */ - secp256k1_scalar r; - secp256k1_num r2num; - secp256k1_num rnum; - secp256k1_num_mul(&rnum, &snum, &s2num); - secp256k1_num_mod(&rnum, &order); - secp256k1_scalar_mul(&r, &s, &s2); - secp256k1_scalar_get_num(&r2num, &r); - CHECK(secp256k1_num_eq(&rnum, &r2num)); - /* The result can only be zero if at least one of the factors was zero. */ - CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); - /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ - CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); - CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); - } - - { - secp256k1_scalar neg; - secp256k1_num negnum; - secp256k1_num negnum2; - /* Check that comparison with zero matches comparison with zero on the number. */ - CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); - /* Check that comparison with the half order is equal to testing for high scalar. */ - CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0)); - secp256k1_scalar_negate(&neg, &s); - secp256k1_num_sub(&negnum, &order, &snum); - secp256k1_num_mod(&negnum, &order); - /* Check that comparison with the half order is equal to testing for high scalar after negation. */ - CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0)); - /* Negating should change the high property, unless the value was already zero. */ - CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); - secp256k1_scalar_get_num(&negnum2, &neg); - /* Negating a scalar should be equal to (order - n) mod order on the number. */ - CHECK(secp256k1_num_eq(&negnum, &negnum2)); - secp256k1_scalar_add(&neg, &neg, &s); - /* Adding a number to its negation should result in zero. */ - CHECK(secp256k1_scalar_is_zero(&neg)); - secp256k1_scalar_negate(&neg, &neg); - /* Negating zero should still result in zero. */ - CHECK(secp256k1_scalar_is_zero(&neg)); - } - - { - /* Test secp256k1_scalar_mul_shift_var. */ - secp256k1_scalar r; - secp256k1_num one; - secp256k1_num rnum; - secp256k1_num rnum2; - unsigned char cone[1] = {0x01}; - unsigned int shift = 256 + secp256k1_rand_int(257); - secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); - secp256k1_num_mul(&rnum, &s1num, &s2num); - secp256k1_num_shift(&rnum, shift - 1); - secp256k1_num_set_bin(&one, cone, 1); - secp256k1_num_add(&rnum, &rnum, &one); - secp256k1_num_shift(&rnum, 1); - secp256k1_scalar_get_num(&rnum2, &r); - CHECK(secp256k1_num_eq(&rnum, &rnum2)); - } - - { - /* test secp256k1_scalar_shr_int */ - secp256k1_scalar r; - int i; - random_scalar_order_test(&r); - for (i = 0; i < 100; ++i) { - int low; - int shift = 1 + secp256k1_rand_int(15); - int expected = r.d[0] % (1 << shift); - low = secp256k1_scalar_shr_int(&r, shift); - CHECK(expected == low); - } - } -#endif - - { - /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ - if (!secp256k1_scalar_is_zero(&s)) { - secp256k1_scalar inv; -#ifndef USE_NUM_NONE - secp256k1_num invnum; - secp256k1_num invnum2; -#endif - secp256k1_scalar_inverse(&inv, &s); -#ifndef USE_NUM_NONE - secp256k1_num_mod_inverse(&invnum, &snum, &order); - secp256k1_scalar_get_num(&invnum2, &inv); - CHECK(secp256k1_num_eq(&invnum, &invnum2)); -#endif - secp256k1_scalar_mul(&inv, &inv, &s); - /* Multiplying a scalar with its inverse must result in one. */ - CHECK(secp256k1_scalar_is_one(&inv)); - secp256k1_scalar_inverse(&inv, &inv); - /* Inverting one must result in one. */ - CHECK(secp256k1_scalar_is_one(&inv)); -#ifndef USE_NUM_NONE - secp256k1_scalar_get_num(&invnum, &inv); - CHECK(secp256k1_num_is_one(&invnum)); -#endif - } - } - - { - /* Test commutativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - secp256k1_scalar r1, r2; - secp256k1_scalar b; - int i; - /* Test add_bit. */ - int bit = secp256k1_rand_bits(8); - secp256k1_scalar_set_int(&b, 1); - CHECK(secp256k1_scalar_is_one(&b)); - for (i = 0; i < bit; i++) { - secp256k1_scalar_add(&b, &b, &b); - } - r1 = s1; - r2 = s1; - if (!secp256k1_scalar_add(&r1, &r1, &b)) { - /* No overflow happened. */ - secp256k1_scalar_cadd_bit(&r2, bit, 1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - /* cadd is a noop when flag is zero */ - secp256k1_scalar_cadd_bit(&r2, bit, 0); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - } - - { - /* Test commutativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r1, &r1, &s); - secp256k1_scalar_add(&r2, &s2, &s); - secp256k1_scalar_add(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s2, &s); - secp256k1_scalar_mul(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test distributitivity of mul over add. */ - secp256k1_scalar r1, r2, t; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s1, &s); - secp256k1_scalar_mul(&t, &s2, &s); - secp256k1_scalar_add(&r2, &r2, &t); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test square. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_sqr(&r1, &s1); - secp256k1_scalar_mul(&r2, &s1, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test multiplicative identity. */ - secp256k1_scalar r1, v1; - secp256k1_scalar_set_int(&v1,1); - secp256k1_scalar_mul(&r1, &s1, &v1); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test additive identity. */ - secp256k1_scalar r1, v0; - secp256k1_scalar_set_int(&v0,0); - secp256k1_scalar_add(&r1, &s1, &v0); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test zero product property. */ - secp256k1_scalar r1, v0; - secp256k1_scalar_set_int(&v0,0); - secp256k1_scalar_mul(&r1, &s1, &v0); - CHECK(secp256k1_scalar_eq(&r1, &v0)); - } - -} - -void run_scalar_tests(void) { - int i; - for (i = 0; i < 128 * count; i++) { - scalar_test(); - } - - { - /* (-1)+1 should be zero. */ - secp256k1_scalar s, o; - secp256k1_scalar_set_int(&s, 1); - CHECK(secp256k1_scalar_is_one(&s)); - secp256k1_scalar_negate(&o, &s); - secp256k1_scalar_add(&o, &o, &s); - CHECK(secp256k1_scalar_is_zero(&o)); - secp256k1_scalar_negate(&o, &o); - CHECK(secp256k1_scalar_is_zero(&o)); - } - -#ifndef USE_NUM_NONE - { - /* A scalar with value of the curve order should be 0. */ - secp256k1_num order; - secp256k1_scalar zero; - unsigned char bin[32]; - int overflow = 0; - secp256k1_scalar_order_get_num(&order); - secp256k1_num_get_bin(bin, 32, &order); - secp256k1_scalar_set_b32(&zero, bin, &overflow); - CHECK(overflow == 1); - CHECK(secp256k1_scalar_is_zero(&zero)); - } -#endif - - { - /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); - } - - { - /* Static test vectors. - * These were reduced from ~10^12 random vectors based on comparison-decision - * and edge-case coverage on 32-bit and 64-bit implementations. - * The responses were generated with Sage 5.9. - */ - secp256k1_scalar x; - secp256k1_scalar y; - secp256k1_scalar z; - secp256k1_scalar zz; - secp256k1_scalar one; - secp256k1_scalar r1; - secp256k1_scalar r2; -#if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar zzv; -#endif - int overflow; - unsigned char chal[33][2][32] = { - {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, - {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, - 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, - {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, - 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, - {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, - 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, - 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, - {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, - {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, - {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, - {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, - {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, - 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, - {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, - 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, - {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, - 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, - 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, - {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, - {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} - }; - unsigned char res[33][2][32] = { - {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, - 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, - 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, - 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, - {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, - 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, - 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, - 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, - {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, - 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, - 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, - 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, - {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, - 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, - 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, - 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, - {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, - 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, - 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, - 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, - {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, - 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, - 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, - 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, - {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, - 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, - 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, - 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, - {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, - 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, - 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, - 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, - {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, - 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, - 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, - 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, - {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, - 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, - 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, - 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, - {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, - 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, - 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, - 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, - {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, - 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, - 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, - 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, - {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, - 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, - 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, - 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, - {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, - 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, - 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, - 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, - {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, - 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, - 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, - 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, - {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, - 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, - 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, - 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, - {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, - 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, - 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, - 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, - {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, - 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, - 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, - 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, - {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, - 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, - 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, - 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, - {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, - 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, - 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, - 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, - {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, - 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, - 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, - 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, - {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, - 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, - 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, - 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, - {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, - 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, - 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, - 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, - {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, - 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, - 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, - 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, - {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, - 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, - 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, - 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, - {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, - 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, - 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, - 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, - {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, - 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, - 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, - 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, - {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, - 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, - 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, - 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, - {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, - 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, - 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, - 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, - {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, - 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, - 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, - 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, - {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, - 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, - 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, - 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, - {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, - 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, - 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, - 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, - {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, - 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, - 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, - 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, - {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, - 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, - 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, - 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, - {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, - 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, - 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, - 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, - {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, - 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, - 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, - 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, - {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, - 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, - 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, - 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, - {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, - 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, - 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, - 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, - {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, - 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, - 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, - 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, - {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, - 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, - 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, - 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, - 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, - 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, - 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, - {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, - 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, - 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, - 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, - 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, - 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, - 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, - {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, - 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, - 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, - 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, - {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, - 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, - 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, - 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, - {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, - 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, - 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, - 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, - {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, - 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, - 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, - 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, - {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, - 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, - 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, - 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, - {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, - 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, - 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, - 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, - {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, - 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, - 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, - 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, - {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, - 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, - 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, - 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, - {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, - 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, - 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, - 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, - {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, - 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, - 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, - 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, - {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, - 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, - 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, - 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, - {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, - {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} - }; - secp256k1_scalar_set_int(&one, 1); - for (i = 0; i < 33; i++) { - secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_mul(&z, &x, &y); - CHECK(!secp256k1_scalar_check_overflow(&z)); - CHECK(secp256k1_scalar_eq(&r1, &z)); - if (!secp256k1_scalar_is_zero(&y)) { - secp256k1_scalar_inverse(&zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); -#if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar_inverse_var(&zzv, &y); - CHECK(secp256k1_scalar_eq(&zzv, &zz)); -#endif - secp256k1_scalar_mul(&z, &z, &zz); - CHECK(!secp256k1_scalar_check_overflow(&z)); - CHECK(secp256k1_scalar_eq(&x, &z)); - secp256k1_scalar_mul(&zz, &zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); - CHECK(secp256k1_scalar_eq(&one, &zz)); - } - secp256k1_scalar_mul(&z, &x, &x); - CHECK(!secp256k1_scalar_check_overflow(&z)); - secp256k1_scalar_sqr(&zz, &x); - CHECK(!secp256k1_scalar_check_overflow(&zz)); - CHECK(secp256k1_scalar_eq(&zz, &z)); - CHECK(secp256k1_scalar_eq(&r2, &zz)); - } - } -} - -/***** FIELD TESTS *****/ - -void random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} - -void random_fe_test(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256_test(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} - -void random_fe_non_zero(secp256k1_fe *nz) { - int tries = 10; - while (--tries >= 0) { - random_fe(nz); - secp256k1_fe_normalize(nz); - if (!secp256k1_fe_is_zero(nz)) { - break; - } - } - /* Infinitesimal probability of spurious failure here */ - CHECK(tries >= 0); -} - -void random_fe_non_square(secp256k1_fe *ns) { - secp256k1_fe r; - random_fe_non_zero(ns); - if (secp256k1_fe_sqrt(&r, ns)) { - secp256k1_fe_negate(ns, ns, 1); - } -} - -int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe an = *a; - secp256k1_fe bn = *b; - secp256k1_fe_normalize_weak(&an); - secp256k1_fe_normalize_var(&bn); - return secp256k1_fe_equal_var(&an, &bn); -} - -int check_fe_inverse(const secp256k1_fe *a, const secp256k1_fe *ai) { - secp256k1_fe x; - secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_fe_mul(&x, a, ai); - return check_fe_equal(&x, &one); -} - -void run_field_convert(void) { - static const unsigned char b32[32] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 - }; - static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - static const secp256k1_fe fe = SECP256K1_FE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - secp256k1_fe fe2; - unsigned char b322[32]; - secp256k1_fe_storage fes2; - /* Check conversions to fe. */ - CHECK(secp256k1_fe_set_b32(&fe2, b32)); - CHECK(secp256k1_fe_equal_var(&fe, &fe2)); - secp256k1_fe_from_storage(&fe2, &fes); - CHECK(secp256k1_fe_equal_var(&fe, &fe2)); - /* Check conversion from fe. */ - secp256k1_fe_get_b32(b322, &fe); - CHECK(memcmp(b322, b32, 32) == 0); - secp256k1_fe_to_storage(&fes2, &fe); - CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); -} - -int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe t = *b; -#ifdef VERIFY - t.magnitude = a->magnitude; - t.normalized = a->normalized; -#endif - return memcmp(a, &t, sizeof(secp256k1_fe)); -} - -void run_field_misc(void) { - secp256k1_fe x; - secp256k1_fe y; - secp256k1_fe z; - secp256k1_fe q; - secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); - int i, j; - for (i = 0; i < 5*count; i++) { - secp256k1_fe_storage xs, ys, zs; - random_fe(&x); - random_fe_non_zero(&y); - /* Test the fe equality and comparison operations. */ - CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); - CHECK(secp256k1_fe_equal_var(&x, &x)); - z = x; - secp256k1_fe_add(&z,&y); - /* Test fe conditional move; z is not normalized here. */ - q = x; - secp256k1_fe_cmov(&x, &z, 0); - VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); - secp256k1_fe_cmov(&x, &x, 1); - CHECK(fe_memcmp(&x, &z) != 0); - CHECK(fe_memcmp(&x, &q) == 0); - secp256k1_fe_cmov(&q, &z, 1); - VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); - CHECK(fe_memcmp(&q, &z) == 0); - secp256k1_fe_normalize_var(&x); - secp256k1_fe_normalize_var(&z); - CHECK(!secp256k1_fe_equal_var(&x, &z)); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (i&1)); - VERIFY_CHECK(q.normalized && q.magnitude == 1); - for (j = 0; j < 6; j++) { - secp256k1_fe_negate(&z, &z, j+1); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (j&1)); - VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); - } - secp256k1_fe_normalize_var(&z); - /* Test storage conversion and conditional moves. */ - secp256k1_fe_to_storage(&xs, &x); - secp256k1_fe_to_storage(&ys, &y); - secp256k1_fe_to_storage(&zs, &z); - secp256k1_fe_storage_cmov(&zs, &xs, 0); - secp256k1_fe_storage_cmov(&zs, &zs, 1); - CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); - secp256k1_fe_storage_cmov(&ys, &xs, 1); - CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); - secp256k1_fe_from_storage(&x, &xs); - secp256k1_fe_from_storage(&y, &ys); - secp256k1_fe_from_storage(&z, &zs); - /* Test that mul_int, mul, and add agree. */ - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&y, &x); - z = x; - secp256k1_fe_mul_int(&z, 3); - CHECK(check_fe_equal(&y, &z)); - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&z, &x); - CHECK(check_fe_equal(&z, &y)); - z = x; - secp256k1_fe_mul_int(&z, 5); - secp256k1_fe_mul(&q, &x, &fe5); - CHECK(check_fe_equal(&z, &q)); - secp256k1_fe_negate(&x, &x, 1); - secp256k1_fe_add(&z, &x); - secp256k1_fe_add(&q, &x); - CHECK(check_fe_equal(&y, &z)); - CHECK(check_fe_equal(&q, &y)); - } -} - -void run_field_inv(void) { - secp256k1_fe x, xi, xii; - int i; - for (i = 0; i < 10*count; i++) { - random_fe_non_zero(&x); - secp256k1_fe_inv(&xi, &x); - CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv(&xii, &xi); - CHECK(check_fe_equal(&x, &xii)); - } -} - -void run_field_inv_var(void) { - secp256k1_fe x, xi, xii; - int i; - for (i = 0; i < 10*count; i++) { - random_fe_non_zero(&x); - secp256k1_fe_inv_var(&xi, &x); - CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv_var(&xii, &xi); - CHECK(check_fe_equal(&x, &xii)); - } -} - -void run_field_inv_all_var(void) { - secp256k1_fe x[16], xi[16], xii[16]; - int i; - /* Check it's safe to call for 0 elements */ - secp256k1_fe_inv_all_var(xi, x, 0); - for (i = 0; i < count; i++) { - size_t j; - size_t len = secp256k1_rand_int(15) + 1; - for (j = 0; j < len; j++) { - random_fe_non_zero(&x[j]); - } - secp256k1_fe_inv_all_var(xi, x, len); - for (j = 0; j < len; j++) { - CHECK(check_fe_inverse(&x[j], &xi[j])); - } - secp256k1_fe_inv_all_var(xii, xi, len); - for (j = 0; j < len; j++) { - CHECK(check_fe_equal(&x[j], &xii[j])); - } - } -} - -void run_sqr(void) { - secp256k1_fe x, s; - - { - int i; - secp256k1_fe_set_int(&x, 1); - secp256k1_fe_negate(&x, &x, 1); - - for (i = 1; i <= 512; ++i) { - secp256k1_fe_mul_int(&x, 2); - secp256k1_fe_normalize(&x); - secp256k1_fe_sqr(&s, &x); - } - } -} - -void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { - secp256k1_fe r1, r2; - int v = secp256k1_fe_sqrt(&r1, a); - CHECK((v == 0) == (k == NULL)); - - if (k != NULL) { - /* Check that the returned root is +/- the given known answer */ - secp256k1_fe_negate(&r2, &r1, 1); - secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); - secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); - CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); - } -} - -void run_sqrt(void) { - secp256k1_fe ns, x, s, t; - int i; - - /* Check sqrt(0) is 0 */ - secp256k1_fe_set_int(&x, 0); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - - /* Check sqrt of small squares (and their negatives) */ - for (i = 1; i <= 100; i++) { - secp256k1_fe_set_int(&x, i); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - test_sqrt(&t, NULL); - } - - /* Consistency checks for large random values */ - for (i = 0; i < 10; i++) { - int j; - random_fe_non_square(&ns); - for (j = 0; j < count; j++) { - random_fe(&x); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - test_sqrt(&t, NULL); - secp256k1_fe_mul(&t, &s, &ns); - test_sqrt(&t, NULL); - } - } -} - -/***** GROUP TESTS *****/ - -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); - CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); -} - -/* This compares jacobian points including their Z, not just their geometric meaning. */ -int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { - secp256k1_gej a2; - secp256k1_gej b2; - int ret = 1; - ret &= a->infinity == b->infinity; - if (ret && !a->infinity) { - a2 = *a; - b2 = *b; - secp256k1_fe_normalize(&a2.x); - secp256k1_fe_normalize(&a2.y); - secp256k1_fe_normalize(&a2.z); - secp256k1_fe_normalize(&b2.x); - secp256k1_fe_normalize(&b2.y); - secp256k1_fe_normalize(&b2.z); - ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; - ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; - ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; - } - return ret; -} - -void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; secp256k1_fe_normalize_weak(&u2); - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; secp256k1_fe_normalize_weak(&s2); - CHECK(secp256k1_fe_equal_var(&u1, &u2)); - CHECK(secp256k1_fe_equal_var(&s1, &s2)); -} - -void test_ge(void) { - int i, i1; -#ifdef USE_ENDOMORPHISM - int runs = 6; -#else - int runs = 4; -#endif - /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). - * The second in each pair of identical points uses a random Z coordinate in the Jacobian form. - * All magnitudes are randomized. - * All 17*17 combinations of points are added to each other, using all applicable methods. - * - * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. - */ - secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); - secp256k1_fe zf; - secp256k1_fe zfi2, zfi3; - - secp256k1_gej_set_infinity(&gej[0]); - secp256k1_ge_clear(&ge[0]); - secp256k1_ge_set_gej_var(&ge[0], &gej[0]); - for (i = 0; i < runs; i++) { - int j; - secp256k1_ge g; - random_group_element_test(&g); -#ifdef USE_ENDOMORPHISM - if (i >= runs - 2) { - secp256k1_ge_mul_lambda(&g, &ge[1]); - } - if (i >= runs - 1) { - secp256k1_ge_mul_lambda(&g, &g); - } -#endif - ge[1 + 4 * i] = g; - ge[2 + 4 * i] = g; - secp256k1_ge_neg(&ge[3 + 4 * i], &g); - secp256k1_ge_neg(&ge[4 + 4 * i], &g); - secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); - secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); - for (j = 0; j < 4; j++) { - random_field_element_magnitude(&ge[1 + j + 4 * i].x); - random_field_element_magnitude(&ge[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].x); - random_field_element_magnitude(&gej[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].z); - } - } - - /* Compute z inverses. */ - { - secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); - for (i = 0; i < 4 * runs + 1; i++) { - if (i == 0) { - /* The point at infinity does not have a meaningful z inverse. Any should do. */ - do { - random_field_element_test(&zs[i]); - } while(secp256k1_fe_is_zero(&zs[i])); - } else { - zs[i] = gej[i].z; - } - } - secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1); - free(zs); - } - - /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - do { - random_field_element_test(&zf); - } while(secp256k1_fe_is_zero(&zf)); - random_field_element_magnitude(&zf); - secp256k1_fe_inv_var(&zfi3, &zf); - secp256k1_fe_sqr(&zfi2, &zfi3); - secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); - - for (i1 = 0; i1 < 1 + 4 * runs; i1++) { - int i2; - for (i2 = 0; i2 < 1 + 4 * runs; i2++) { - /* Compute reference result using gej + gej (var). */ - secp256k1_gej refj, resj; - secp256k1_ge ref; - secp256k1_fe zr; - secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - /* Check Z ratio. */ - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zrz, &refj.z)); - } - secp256k1_ge_set_gej_var(&ref, &refj); - - /* Test gej + ge with Z ratio result (var). */ - secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - ge_equals_gej(&ref, &resj); - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zrz, &resj.z)); - } - - /* Test gej + ge (var, with additional Z factor). */ - { - secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ - secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); - secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - random_field_element_magnitude(&ge2_zfi.x); - random_field_element_magnitude(&ge2_zfi.y); - secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); - ge_equals_gej(&ref, &resj); - } - - /* Test gej + ge (const). */ - if (i2 != 0) { - /* secp256k1_gej_add_ge does not support its second argument being infinity. */ - secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); - ge_equals_gej(&ref, &resj); - } - - /* Test doubling (var). */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { - secp256k1_fe zr2; - /* Normal doubling with Z ratio result. */ - secp256k1_gej_double_var(&resj, &gej[i1], &zr2); - ge_equals_gej(&ref, &resj); - /* Check Z ratio. */ - secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zr2, &resj.z)); - /* Normal doubling. */ - secp256k1_gej_double_var(&resj, &gej[i2], NULL); - ge_equals_gej(&ref, &resj); - } - - /* Test adding opposites. */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { - CHECK(secp256k1_ge_is_infinity(&ref)); - } - - /* Test adding infinity. */ - if (i1 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i1])); - CHECK(secp256k1_gej_is_infinity(&gej[i1])); - ge_equals_gej(&ref, &gej[i2]); - } - if (i2 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i2])); - CHECK(secp256k1_gej_is_infinity(&gej[i2])); - ge_equals_gej(&ref, &gej[i1]); - } - } - } - - /* Test adding all points together in random order equals infinity. */ - { - secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); - for (i = 0; i < 4 * runs + 1; i++) { - gej_shuffled[i] = gej[i]; - } - for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + secp256k1_rand_int(4 * runs + 1 - i); - if (swap != i) { - secp256k1_gej t = gej_shuffled[i]; - gej_shuffled[i] = gej_shuffled[swap]; - gej_shuffled[swap] = t; - } - } - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); - } - CHECK(secp256k1_gej_is_infinity(&sum)); - free(gej_shuffled); - } - - /* Test batch gej -> ge conversion with and without known z ratios. */ - { - secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - for (i = 0; i < 4 * runs + 1; i++) { - /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ - if (i < 4 * runs) { - secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); - } - } - secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_fe s; - random_fe_non_zero(&s); - secp256k1_gej_rescale(&gej[i], &s); - ge_equals_gej(&ge_set_table[i], &gej[i]); - ge_equals_gej(&ge_set_all[i], &gej[i]); - } - free(ge_set_table); - free(ge_set_all); - free(zr); - } - - free(ge); - free(gej); - free(zinv); -} - -void test_add_neg_y_diff_x(void) { - /* The point of this test is to check that we can add two points - * whose y-coordinates are negatives of each other but whose x - * coordinates differ. If the x-coordinates were the same, these - * points would be negatives of each other and their sum is - * infinity. This is cool because it "covers up" any degeneracy - * in the addition algorithm that would cause the xy coordinates - * of the sum to be wrong (since infinity has no xy coordinates). - * HOWEVER, if the x-coordinates are different, infinity is the - * wrong answer, and such degeneracies are exposed. This is the - * root of https://github.com/bitcoin-core/secp256k1/issues/257 - * which this test is a regression test for. - * - * These points were generated in sage as - * # secp256k1 params - * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) - * C = EllipticCurve ([F (0), F (7)]) - * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) - * N = FiniteField(G.order()) - * - * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F) - * x = polygen(N) - * lam = (1 - x^3).roots()[1][0] - * - * # random "bad pair" - * P = C.random_element() - * Q = -int(lam) * P - * print " P: %x %x" % P.xy() - * print " Q: %x %x" % Q.xy() - * print "P + Q: %x %x" % (P + Q).xy() - */ - secp256k1_gej aj = SECP256K1_GEJ_CONST( - 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, - 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, - 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, - 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d - ); - secp256k1_gej bj = SECP256K1_GEJ_CONST( - 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, - 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, - 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, - 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 - ); - secp256k1_gej sumj = SECP256K1_GEJ_CONST( - 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, - 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, - 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, - 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe - ); - secp256k1_ge b; - secp256k1_gej resj; - secp256k1_ge res; - secp256k1_ge_set_gej(&b, &bj); - - secp256k1_gej_add_var(&resj, &aj, &bj, NULL); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); - - secp256k1_gej_add_ge(&resj, &aj, &b); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); - - secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); -} - -void run_ge(void) { - int i; - for (i = 0; i < count * 32; i++) { - test_ge(); - } - test_add_neg_y_diff_x(); -} - -void test_ec_combine(void) { - secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_pubkey data[6]; - const secp256k1_pubkey* d[6]; - secp256k1_pubkey sd; - secp256k1_pubkey sd2; - secp256k1_gej Qj; - secp256k1_ge Q; - int i; - for (i = 1; i <= 6; i++) { - secp256k1_scalar s; - random_scalar_order_test(&s); - secp256k1_scalar_add(&sum, &sum, &s); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&data[i - 1], &Q); - d[i - 1] = &data[i - 1]; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&sd, &Q); - CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); - CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); - } -} - -void run_ec_combine(void) { - int i; - for (i = 0; i < count * 8; i++) { - test_ec_combine(); - } -} - -void test_group_decompress(const secp256k1_fe* x) { - /* The input itself, normalized. */ - secp256k1_fe fex = *x; - secp256k1_fe fez; - /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ - secp256k1_ge ge_quad, ge_even, ge_odd; - secp256k1_gej gej_quad; - /* Return values of the above calls. */ - int res_quad, res_even, res_odd; - - secp256k1_fe_normalize_var(&fex); - - res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); - res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); - res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); - - CHECK(res_quad == res_even); - CHECK(res_quad == res_odd); - - if (res_quad) { - secp256k1_fe_normalize_var(&ge_quad.x); - secp256k1_fe_normalize_var(&ge_odd.x); - secp256k1_fe_normalize_var(&ge_even.x); - secp256k1_fe_normalize_var(&ge_quad.y); - secp256k1_fe_normalize_var(&ge_odd.y); - secp256k1_fe_normalize_var(&ge_even.y); - - /* No infinity allowed. */ - CHECK(!ge_quad.infinity); - CHECK(!ge_even.infinity); - CHECK(!ge_odd.infinity); - - /* Check that the x coordinates check out. */ - CHECK(secp256k1_fe_equal_var(&ge_quad.x, x)); - CHECK(secp256k1_fe_equal_var(&ge_even.x, x)); - CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); - - /* Check that the Y coordinate result in ge_quad is a square. */ - CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); - - /* Check odd/even Y in ge_odd, ge_even. */ - CHECK(secp256k1_fe_is_odd(&ge_odd.y)); - CHECK(!secp256k1_fe_is_odd(&ge_even.y)); - - /* Check secp256k1_gej_has_quad_y_var. */ - secp256k1_gej_set_ge(&gej_quad, &ge_quad); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - do { - random_fe_test(&fez); - } while (secp256k1_fe_is_zero(&fez)); - secp256k1_gej_rescale(&gej_quad, &fez); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - secp256k1_gej_neg(&gej_quad, &gej_quad); - CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); - do { - random_fe_test(&fez); - } while (secp256k1_fe_is_zero(&fez)); - secp256k1_gej_rescale(&gej_quad, &fez); - CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); - secp256k1_gej_neg(&gej_quad, &gej_quad); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - } -} - -void run_group_decompress(void) { - int i; - for (i = 0; i < count * 4; i++) { - secp256k1_fe fe; - random_fe_test(&fe); - test_group_decompress(&fe); - } -} - -/***** ECMULT TESTS *****/ - -void run_ecmult_chain(void) { - /* random starting point A (on the curve) */ - secp256k1_gej a = SECP256K1_GEJ_CONST( - 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, - 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, - 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, - 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f - ); - /* two random initial factors xn and gn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, - 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 - ); - secp256k1_scalar gn = SECP256K1_SCALAR_CONST( - 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, - 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de - ); - /* two small multipliers to be applied to xn and gn in every iteration: */ - static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); - static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); - /* accumulators with the resulting coefficients to A and G */ - secp256k1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - /* actual points */ - secp256k1_gej x; - secp256k1_gej x2; - int i; - - /* the point being computed */ - x = a; - for (i = 0; i < 200*count; i++) { - /* in each iteration, compute X = xn*X + gn*G; */ - secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); - /* also compute ae and ge: the actual accumulated factors for A and G */ - /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ - secp256k1_scalar_mul(&ae, &ae, &xn); - secp256k1_scalar_mul(&ge, &ge, &xn); - secp256k1_scalar_add(&ge, &ge, &gn); - /* modify xn and gn */ - secp256k1_scalar_mul(&xn, &xn, &xf); - secp256k1_scalar_mul(&gn, &gn, &gf); - - /* verify */ - if (i == 19999) { - /* expected result after 19999 iterations */ - secp256k1_gej rp = SECP256K1_GEJ_CONST( - 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, - 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, - 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, - 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 - ); - - secp256k1_gej_neg(&rp, &rp); - secp256k1_gej_add_var(&rp, &rp, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&rp)); - } - } - /* redo the computation, but directly with the resulting ae and ge coefficients: */ - secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); - secp256k1_gej_neg(&x2, &x2); - secp256k1_gej_add_var(&x2, &x2, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&x2)); -} - -void test_point_times_order(const secp256k1_gej *point) { - /* X * (point + G) + (order-X) * (pointer + G) = 0 */ - secp256k1_scalar x; - secp256k1_scalar nx; - secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_gej res1, res2; - secp256k1_ge res3; - unsigned char pub[65]; - size_t psize = 65; - random_scalar_order_test(&x); - secp256k1_scalar_negate(&nx, &x); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ - secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ - secp256k1_gej_add_var(&res1, &res1, &res2, NULL); - CHECK(secp256k1_gej_is_infinity(&res1)); - CHECK(secp256k1_gej_is_valid_var(&res1) == 0); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - CHECK(secp256k1_ge_is_valid_var(&res3) == 0); - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); - psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); - /* check zero/one edge cases */ - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); - secp256k1_ge_set_gej(&res3, &res1); - ge_equals_gej(&res3, point); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); - secp256k1_ge_set_gej(&res3, &res1); - ge_equals_ge(&res3, &secp256k1_ge_const_g); -} - -void run_point_times_order(void) { - int i; - secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); - static const secp256k1_fe xr = SECP256K1_FE_CONST( - 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, - 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 - ); - for (i = 0; i < 500; i++) { - secp256k1_ge p; - if (secp256k1_ge_set_xo_var(&p, &x, 1)) { - secp256k1_gej j; - CHECK(secp256k1_ge_is_valid_var(&p)); - secp256k1_gej_set_ge(&j, &p); - CHECK(secp256k1_gej_is_valid_var(&j)); - test_point_times_order(&j); - } - secp256k1_fe_sqr(&x, &x); - } - secp256k1_fe_normalize_var(&x); - CHECK(secp256k1_fe_equal_var(&x, &xr)); -} - -void ecmult_const_random_mult(void) { - /* random starting point A (on the curve) */ - secp256k1_ge a = SECP256K1_GE_CONST( - 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, - 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, - 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, - 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d - ); - /* random initial factor xn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, - 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b - ); - /* expected xn * A (from sage) */ - secp256k1_ge expected_b = SECP256K1_GE_CONST( - 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, - 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, - 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, - 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 - ); - secp256k1_gej b; - secp256k1_ecmult_const(&b, &a, &xn); - - CHECK(secp256k1_ge_is_valid_var(&a)); - ge_equals_gej(&expected_b, &b); -} - -void ecmult_const_commutativity(void) { - secp256k1_scalar a; - secp256k1_scalar b; - secp256k1_gej res1; - secp256k1_gej res2; - secp256k1_ge mid1; - secp256k1_ge mid2; - random_scalar_order_test(&a); - random_scalar_order_test(&b); - - secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); - secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - secp256k1_ecmult_const(&res1, &mid1, &b); - secp256k1_ecmult_const(&res2, &mid2, &a); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - ge_equals_ge(&mid1, &mid2); -} - -void ecmult_const_mult_zero_one(void) { - secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_scalar negone; - secp256k1_gej res1; - secp256k1_ge res2; - secp256k1_ge point; - secp256k1_scalar_negate(&negone, &one); - - random_group_element_test(&point); - secp256k1_ecmult_const(&res1, &point, &zero); - secp256k1_ge_set_gej(&res2, &res1); - CHECK(secp256k1_ge_is_infinity(&res2)); - secp256k1_ecmult_const(&res1, &point, &one); - secp256k1_ge_set_gej(&res2, &res1); - ge_equals_ge(&res2, &point); - secp256k1_ecmult_const(&res1, &point, &negone); - secp256k1_gej_neg(&res1, &res1); - secp256k1_ge_set_gej(&res2, &res1); - ge_equals_ge(&res2, &point); -} - -void ecmult_const_chain_multiply(void) { - /* Check known result (randomly generated test problem from sage) */ - const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( - 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, - 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b - ); - const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( - 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, - 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, - 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, - 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 - ); - secp256k1_gej point; - secp256k1_ge res; - int i; - - secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); - for (i = 0; i < 100; ++i) { - secp256k1_ge tmp; - secp256k1_ge_set_gej(&tmp, &point); - secp256k1_ecmult_const(&point, &tmp, &scalar); - } - secp256k1_ge_set_gej(&res, &point); - ge_equals_gej(&res, &expected_point); -} - -void run_ecmult_const_tests(void) { - ecmult_const_mult_zero_one(); - ecmult_const_random_mult(); - ecmult_const_commutativity(); - ecmult_const_chain_multiply(); -} - -void test_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, two, t; - int wnaf[256]; - int zeroes = -1; - int i; - int bits; - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&two, 2); - bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); - CHECK(bits <= 256); - for (i = bits-1; i >= 0; i--) { - int v = wnaf[i]; - secp256k1_scalar_mul(&x, &x, &two); - if (v) { - CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ - zeroes=0; - CHECK((v & 1) == 1); /* check non-zero elements are odd */ - CHECK(v <= (1 << (w-1)) - 1); /* check range below */ - CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ - } else { - CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ - zeroes++; - } - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ -} - -void test_constant_wnaf_negate(const secp256k1_scalar *number) { - secp256k1_scalar neg1 = *number; - secp256k1_scalar neg2 = *number; - int sign1 = 1; - int sign2 = 1; - - if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { - secp256k1_scalar_negate(&neg1, &neg1); - sign1 = -1; - } - sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); - CHECK(sign1 == sign2); - CHECK(secp256k1_scalar_eq(&neg1, &neg2)); -} - -void test_constant_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, shift; - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num = *number; - - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&shift, 1 << w); - /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ -#ifdef USE_ENDOMORPHISM - for (i = 0; i < 16; ++i) { - secp256k1_scalar_shr_int(&num, 8); - } -#endif - skew = secp256k1_wnaf_const(wnaf, num, w); - - for (i = WNAF_SIZE(w); i >= 0; --i) { - secp256k1_scalar t; - int v = wnaf[i]; - CHECK(v != 0); /* check nonzero */ - CHECK(v & 1); /* check parity */ - CHECK(v > -(1 << w)); /* check range above */ - CHECK(v < (1 << w)); /* check range below */ - - secp256k1_scalar_mul(&x, &x, &shift); - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - /* Skew num because when encoding numbers as odd we use an offset */ - secp256k1_scalar_cadd_bit(&num, skew == 2, 1); - CHECK(secp256k1_scalar_eq(&x, &num)); -} - -void run_wnaf(void) { - int i; - secp256k1_scalar n = {{0}}; - - /* Sanity check: 1 and 2 are the smallest odd and even numbers and should - * have easier-to-diagnose failure modes */ - n.d[0] = 1; - test_constant_wnaf(&n, 4); - n.d[0] = 2; - test_constant_wnaf(&n, 4); - /* Random tests */ - for (i = 0; i < count; i++) { - random_scalar_order(&n); - test_wnaf(&n, 4+(i%10)); - test_constant_wnaf_negate(&n); - test_constant_wnaf(&n, 4 + (i % 10)); - } - secp256k1_scalar_set_int(&n, 0); - CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); - CHECK(secp256k1_scalar_is_zero(&n)); - CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); - CHECK(secp256k1_scalar_is_zero(&n)); -} - -void test_ecmult_constants(void) { - /* Test ecmult_gen() for [0..36) and [order-36..0). */ - secp256k1_scalar x; - secp256k1_gej r; - secp256k1_ge ng; - int i; - int j; - secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); - for (i = 0; i < 36; i++ ) { - secp256k1_scalar_set_int(&x, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); - for (j = 0; j < i; j++) { - if (j == i - 1) { - ge_equals_gej(&secp256k1_ge_const_g, &r); - } - secp256k1_gej_add_ge(&r, &r, &ng); - } - CHECK(secp256k1_gej_is_infinity(&r)); - } - for (i = 1; i <= 36; i++ ) { - secp256k1_scalar_set_int(&x, i); - secp256k1_scalar_negate(&x, &x); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); - for (j = 0; j < i; j++) { - if (j == i - 1) { - ge_equals_gej(&ng, &r); - } - secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g); - } - CHECK(secp256k1_gej_is_infinity(&r)); - } -} - -void run_ecmult_constants(void) { - test_ecmult_constants(); -} - -void test_ecmult_gen_blind(void) { - /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ - secp256k1_scalar key; - secp256k1_scalar b; - unsigned char seed32[32]; - secp256k1_gej pgej; - secp256k1_gej pgej2; - secp256k1_gej i; - secp256k1_ge pge; - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); - secp256k1_rand256(seed32); - b = ctx->ecmult_gen_ctx.blind; - i = ctx->ecmult_gen_ctx.initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); - CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); - CHECK(!gej_xyz_equals_gej(&i, &ctx->ecmult_gen_ctx.initial)); - secp256k1_ge_set_gej(&pge, &pgej); - ge_equals_gej(&pge, &pgej2); -} - -void test_ecmult_gen_blind_reset(void) { - /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ - secp256k1_scalar b; - secp256k1_gej initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); - b = ctx->ecmult_gen_ctx.blind; - initial = ctx->ecmult_gen_ctx.initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); - CHECK(secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); - CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); -} - -void run_ecmult_gen_blind(void) { - int i; - test_ecmult_gen_blind_reset(); - for (i = 0; i < 10; i++) { - test_ecmult_gen_blind(); - } -} - -#ifdef USE_ENDOMORPHISM -/***** ENDOMORPHISH TESTS *****/ -void test_scalar_split(void) { - secp256k1_scalar full; - secp256k1_scalar s1, slam; - const unsigned char zero[32] = {0}; - unsigned char tmp[32]; - - random_scalar_order_test(&full); - secp256k1_scalar_split_lambda(&s1, &slam, &full); - - /* check that both are <= 128 bits in size */ - if (secp256k1_scalar_is_high(&s1)) { - secp256k1_scalar_negate(&s1, &s1); - } - if (secp256k1_scalar_is_high(&slam)) { - secp256k1_scalar_negate(&slam, &slam); - } - - secp256k1_scalar_get_b32(tmp, &s1); - CHECK(memcmp(zero, tmp, 16) == 0); - secp256k1_scalar_get_b32(tmp, &slam); - CHECK(memcmp(zero, tmp, 16) == 0); -} - -void run_endomorphism_tests(void) { - test_scalar_split(); -} -#endif - -void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { - unsigned char pubkeyc[65]; - secp256k1_pubkey pubkey; - secp256k1_ge ge; - size_t pubkeyclen; - int32_t ecount; - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { - /* Smaller sizes are tested exhaustively elsewhere. */ - int32_t i; - memcpy(&pubkeyc[1], input, 64); - VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen); - for (i = 0; i < 256; i++) { - /* Try all type bytes. */ - int xpass; - int ypass; - int ysign; - pubkeyc[0] = i; - /* What sign does this point have? */ - ysign = (input[63] & 1) + 2; - /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ - xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); - /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ - ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && - ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); - if (xpass || ypass) { - /* These cases must parse. */ - unsigned char pubkeyo[65]; - size_t outl; - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - ecount = 0; - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - VG_UNDEF(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - VG_CHECK(pubkeyo, outl); - CHECK(outl == 33); - CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); - CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); - if (ypass) { - /* This test isn't always done because we decode with alternative signs, so the y won't match. */ - CHECK(pubkeyo[0] == ysign); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - secp256k1_pubkey_save(&pubkey, &ge); - VG_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - VG_UNDEF(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - VG_CHECK(pubkeyo, outl); - CHECK(outl == 65); - CHECK(pubkeyo[0] == 4); - CHECK(memcmp(&pubkeyo[1], input, 64) == 0); - } - CHECK(ecount == 0); - } else { - /* These cases must fail to parse. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - } - } - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); -} - -void run_ec_pubkey_parse_test(void) { -#define SECP256K1_EC_PARSE_TEST_NVALID (12) - const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { - { - /* Point with leading and trailing zeros in x and y serialization. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, - 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 - }, - { - /* Point with x equal to a 3rd root of unity.*/ - 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, - 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with largest x. (1/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, - 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, - }, - { - /* Point with largest x. (2/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, - 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, - }, - { - /* Point with smallest x. (1/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with smallest x. (2/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* Point with largest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with smallest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - } - }; -#define SECP256K1_EC_PARSE_TEST_NXVALID (4) - const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { - { - /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* x on curve, y is from y^2 = x^3 + 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 - } - }; -#define SECP256K1_EC_PARSE_TEST_NINVALID (7) - const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { - { - /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ - 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, - 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, - 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, - 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, - 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, - 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 - } - }; - const unsigned char pubkeyc[66] = { - /* Serialization of G. */ - 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, - 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, - 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, - 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, - 0xB8, 0x00 - }; - unsigned char sout[65]; - unsigned char shortkey[2]; - secp256k1_ge ge; - secp256k1_pubkey pubkey; - size_t len; - int32_t i; - int32_t ecount; - int32_t ecount2; - ecount = 0; - /* Nothing should be reading this far into pubkeyc. */ - VG_UNDEF(&pubkeyc[65], 1); - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - /* Zero length claimed, fail, zeroize, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(shortkey, 2); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 0) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* Length one claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 256 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - shortkey[0] = i; - VG_UNDEF(&shortkey[1], 1); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - /* Length two claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 65536 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - shortkey[0] = i & 255; - shortkey[1] = i >> 8; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 33) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, pubkeyc, 65) == 0); - CHECK(ecount == 2); - /* NULL input string. Illegal arg and zeroize output. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, NULL, 65) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 1); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 2); - /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 64) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 66) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* Valid parse. */ - memset(&pubkey, 0, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - VG_UNDEF(&ge, sizeof(ge)); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); - VG_CHECK(&ge.x, sizeof(ge.x)); - VG_CHECK(&ge.y, sizeof(ge.y)); - VG_CHECK(&ge.infinity, sizeof(ge.infinity)); - ge_equals_ge(&secp256k1_ge_const_g, &ge); - CHECK(ecount == 0); - /* secp256k1_ec_pubkey_serialize illegal args. */ - ecount = 0; - len = 65; - CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); - CHECK(ecount == 1); - CHECK(len == 0); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); - CHECK(ecount == 2); - len = 65; - VG_UNDEF(sout, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0); - VG_CHECK(sout, 65); - CHECK(ecount == 3); - CHECK(len == 0); - len = 65; - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, ~0) == 0); - CHECK(ecount == 4); - CHECK(len == 0); - len = 65; - VG_UNDEF(sout, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - VG_CHECK(sout, 65); - CHECK(ecount == 4); - CHECK(len == 65); - /* Multiple illegal args. Should still set arg error only once. */ - ecount = 0; - ecount2 = 11; - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); - CHECK(ecount == 1); - /* Does the illegal arg callback actually change the behavior? */ - secp256k1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); - CHECK(ecount == 1); - CHECK(ecount2 == 10); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); - /* Try a bunch of prefabbed points with all possible encodings. */ - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { - ec_pubkey_parse_pointtest(valid[i], 1, 1); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { - ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { - ec_pubkey_parse_pointtest(invalid[i], 0, 0); - } -} - -void run_eckey_edge_case_test(void) { - const unsigned char orderc[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; - unsigned char ctmp[33]; - unsigned char ctmp2[33]; - secp256k1_pubkey pubkey; - secp256k1_pubkey pubkey2; - secp256k1_pubkey pubkey_one; - secp256k1_pubkey pubkey_negone; - const secp256k1_pubkey *pubkeys[3]; - size_t len; - int32_t ecount; - /* Group order is too large, reject. */ - CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Maximum value is too large, reject. */ - memset(ctmp, 255, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Zero is too small, reject. */ - memset(ctmp, 0, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* One must be accepted. */ - ctmp[31] = 0x01; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_one = pubkey; - /* Group order + 1 is too large, reject. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x42; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* -1 must be accepted. */ - ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_negone = pubkey; - /* Tweak of zero leaves the value changed. */ - memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); - CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); - memcpy(&pubkey2, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Multiply tweak of zero zeroizes the output. */ - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Overflowing key tweak zeroizes. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Private key tweaks results in a key of zero. */ - ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); - CHECK(memcmp(zeros, ctmp2, 32) == 0); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Tweak computation wraps and results in a key of 1. */ - ctmp2[31] = 2; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); - CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Tweak mul * 2 = 1+1. */ - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Test argument errors. */ - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - CHECK(ecount == 0); - /* Zeroize pubkey on parse error. */ - memset(&pubkey, 0, 32); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - memset(&pubkey2, 0, 32); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); - CHECK(ecount == 2); - CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); - /* Plain argument errors. */ - ecount = 0; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); - CHECK(ecount == 1); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); - CHECK(ecount == 1); - memset(&pubkey, 1, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* secp256k1_ec_pubkey_combine tests. */ - ecount = 0; - pubkeys[0] = &pubkey_one; - VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 2); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 3); - pubkeys[0] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); - CHECK(memcmp(ctmp, ctmp2, 33) == 0); - /* Result is infinity. */ - pubkeys[0] = &pubkey_one; - pubkeys[1] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 3); - /* Passes through infinity but comes out one. */ - pubkeys[2] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); - CHECK(memcmp(ctmp, ctmp2, 33) == 0); - /* Adds to two. */ - pubkeys[1] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); -} - -void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { - secp256k1_scalar nonce; - do { - random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); -} - -void test_ecdsa_sign_verify(void) { - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar one; - secp256k1_scalar msg, key; - secp256k1_scalar sigr, sigs; - int recid; - int getrec; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - getrec = secp256k1_rand_bits(1); - random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); - if (getrec) { - CHECK(recid >= 0 && recid < 4); - } - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); -} - -void run_ecdsa_sign_verify(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_ecdsa_sign_verify(); - } -} - -/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ -static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void)msg32; - (void)key32; - (void)algo16; - memcpy(nonce32, data, 32); - return (counter == 0); -} - -static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that has a fatal error on the first counter value. */ - if (counter == 0) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); -} - -static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ - if (counter < 3) { - memset(nonce32, counter==0 ? 0 : 255, 32); - if (counter == 2) { - nonce32[31]--; - } - return 1; - } - if (counter < 5) { - static const unsigned char order[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; - memcpy(nonce32, order, 32); - if (counter == 4) { - nonce32[31]++; - } - return 1; - } - /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ - /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ - if (counter > 5) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); -} - -int is_empty_signature(const secp256k1_ecdsa_signature *sig) { - static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; - return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; -} - -void test_ecdsa_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - unsigned char privkey2[32]; - secp256k1_ecdsa_signature signature[6]; - secp256k1_scalar r, s; - unsigned char sig[74]; - size_t siglen = 74; - unsigned char pubkeyc[65]; - size_t pubkeyclen = 65; - secp256k1_pubkey pubkey; - unsigned char seckey[300]; - size_t seckeylen = 300; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Verify exporting and importing public key. */ - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); - memset(&pubkey, 0, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); - - /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); - CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); - CHECK(memcmp(privkey, privkey2, 32) == 0); - - /* Optionally tweak the keys using addition. */ - if (secp256k1_rand_int(3) == 0) { - int ret1; - int ret2; - unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); - CHECK(ret1 == ret2); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Optionally tweak the keys using multiplication. */ - if (secp256k1_rand_int(3) == 0) { - int ret1; - int ret2; - unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); - CHECK(ret1 == ret2); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Sign. */ - CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &signature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); - CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); - CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); - /* Verify. */ - CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); - /* Test lower-S form, malleate, verify and fail, test again, malleate again */ - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); - CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); - CHECK(memcmp(&signature[5], &signature[0], 64) == 0); - - /* Serialize/parse DER and verify again */ - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); - memset(&signature[0], 0, sizeof(signature[0])); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); - /* Serialize/destroy/parse DER and verify again. */ - siglen = 74; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); - sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || - secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); -} - -void test_random_pubkeys(void) { - secp256k1_ge elem; - secp256k1_ge elem2; - unsigned char in[65]; - /* Generate some randomly sized pubkeys. */ - size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; - if (secp256k1_rand_bits(2) == 0) { - len = secp256k1_rand_bits(6); - } - if (len == 65) { - in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); - } else { - in[0] = secp256k1_rand_bits(1) ? 2 : 3; - } - if (secp256k1_rand_bits(3) == 0) { - in[0] = secp256k1_rand_bits(8); - } - if (len > 1) { - secp256k1_rand256(&in[1]); - } - if (len > 33) { - secp256k1_rand256(&in[33]); - } - if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { - unsigned char out[65]; - unsigned char firstb; - int res; - size_t size = len; - firstb = in[0]; - /* If the pubkey can be parsed, it should round-trip... */ - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); - CHECK(size == len); - CHECK(memcmp(&in[1], &out[1], len-1) == 0); - /* ... except for the type of hybrid inputs. */ - if ((in[0] != 6) && (in[0] != 7)) { - CHECK(in[0] == out[0]); - } - size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); - CHECK(size == 65); - CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); - ge_equals_ge(&elem,&elem2); - /* Check that the X9.62 hybrid type is checked. */ - in[0] = secp256k1_rand_bits(1) ? 6 : 7; - res = secp256k1_eckey_pubkey_parse(&elem2, in, size); - if (firstb == 2 || firstb == 3) { - if (in[0] == firstb + 4) { - CHECK(res); - } else { - CHECK(!res); - } - } - if (res) { - ge_equals_ge(&elem,&elem2); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); - CHECK(memcmp(&in[1], &out[1], 64) == 0); - } - } -} - -void run_random_pubkeys(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_random_pubkeys(); - } -} - -void run_ecdsa_end_to_end(void) { - int i; - for (i = 0; i < 64*count; i++) { - test_ecdsa_end_to_end(); - } -} - -int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { - static const unsigned char zeroes[32] = {0}; -#ifdef ENABLE_OPENSSL_TESTS - static const unsigned char max_scalar[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 - }; -#endif - - int ret = 0; - - secp256k1_ecdsa_signature sig_der; - unsigned char roundtrip_der[2048]; - unsigned char compact_der[64]; - size_t len_der = 2048; - int parsed_der = 0, valid_der = 0, roundtrips_der = 0; - - secp256k1_ecdsa_signature sig_der_lax; - unsigned char roundtrip_der_lax[2048]; - unsigned char compact_der_lax[64]; - size_t len_der_lax = 2048; - int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; - -#ifdef ENABLE_OPENSSL_TESTS - ECDSA_SIG *sig_openssl; - const unsigned char *sigptr; - unsigned char roundtrip_openssl[2048]; - int len_openssl = 2048; - int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0; -#endif - - parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); - if (parsed_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; - valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); - } - if (valid_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; - roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; - } - - parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); - if (parsed_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; - valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); - } - if (valid_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; - roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; - } - - if (certainly_der) { - ret |= (!parsed_der) << 2; - } - if (certainly_not_der) { - ret |= (parsed_der) << 17; - } - if (valid_der) { - ret |= (!roundtrips_der) << 3; - } - - if (valid_der) { - ret |= (!roundtrips_der_lax) << 12; - ret |= (len_der != len_der_lax) << 13; - ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14; - } - ret |= (roundtrips_der != roundtrips_der_lax) << 15; - if (parsed_der) { - ret |= (!parsed_der_lax) << 16; - } - -#ifdef ENABLE_OPENSSL_TESTS - sig_openssl = ECDSA_SIG_new(); - sigptr = sig; - parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); - if (parsed_openssl) { - valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; - if (valid_openssl) { - unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); - valid_openssl = memcmp(tmp, max_scalar, 32) < 0; - } - if (valid_openssl) { - unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); - valid_openssl = memcmp(tmp, max_scalar, 32) < 0; - } - } - len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); - if (len_openssl <= 2048) { - unsigned char *ptr = roundtrip_openssl; - CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); - roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); - } else { - len_openssl = 0; - } - ECDSA_SIG_free(sig_openssl); - - ret |= (parsed_der && !parsed_openssl) << 4; - ret |= (valid_der && !valid_openssl) << 5; - ret |= (roundtrips_openssl && !parsed_der) << 6; - ret |= (roundtrips_der != roundtrips_openssl) << 7; - if (roundtrips_openssl) { - ret |= (len_der != (size_t)len_openssl) << 8; - ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9; - } -#endif - return ret; -} - -static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { - size_t i; - for (i = 0; i < ptrlen; i++) { - int shift = ptrlen - 1 - i; - if (shift >= 4) { - ptr[i] = 0; - } else { - ptr[i] = (val >> shift) & 0xFF; - } - } -} - -static void damage_array(unsigned char *sig, size_t *len) { - int pos; - int action = secp256k1_rand_bits(3); - if (action < 1 && *len > 3) { - /* Delete a byte. */ - pos = secp256k1_rand_int(*len); - memmove(sig + pos, sig + pos + 1, *len - pos - 1); - (*len)--; - return; - } else if (action < 2 && *len < 2048) { - /* Insert a byte. */ - pos = secp256k1_rand_int(1 + *len); - memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = secp256k1_rand_bits(8); - (*len)++; - return; - } else if (action < 4) { - /* Modify a byte. */ - sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); - return; - } else { /* action < 8 */ - /* Modify a bit. */ - sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); - return; - } -} - -static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { - int der; - int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; - size_t tlen, elen, glen; - int indet; - int n; - - *len = 0; - der = secp256k1_rand_bits(2) == 0; - *certainly_der = der; - *certainly_not_der = 0; - indet = der ? 0 : secp256k1_rand_int(10) == 0; - - for (n = 0; n < 2; n++) { - /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ - nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); - /* The length of the number in bytes (the first byte of which will always be nonzero) */ - nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; - CHECK(nlen[n] <= 232); - /* The top bit of the number. */ - nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); - /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ - nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); - /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ - nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); - if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { - *certainly_not_der = 1; - } - CHECK(nlen[n] + nzlen[n] <= 300); - /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ - nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); - if (!der) { - /* nlenlen[n] max 127 bytes */ - int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; - nlenlen[n] += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); - } - - /* The total length of the data to go, so far */ - tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; - CHECK(tlen <= 856); - - /* The length of the garbage inside the tuple. */ - elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; - if (elen != 0) { - *certainly_not_der = 1; - } - tlen += elen; - CHECK(tlen <= 980); - - /* The length of the garbage after the end of the tuple. */ - glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; - if (glen != 0) { - *certainly_not_der = 1; - } - CHECK(tlen + glen <= 990); - - /* Write the tuple header. */ - sig[(*len)++] = 0x30; - if (indet) { - /* Indeterminate length */ - sig[(*len)++] = 0x80; - *certainly_not_der = 1; - } else { - int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); - if (!der) { - int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; - tlenlen += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - if (tlenlen == 0) { - /* Short length notation */ - sig[(*len)++] = tlen; - } else { - /* Long length notation */ - sig[(*len)++] = 128 + tlenlen; - assign_big_endian(sig + *len, tlenlen, tlen); - *len += tlenlen; - } - tlen += tlenlen; - } - tlen += 2; - CHECK(tlen + glen <= 1119); - - for (n = 0; n < 2; n++) { - /* Write the integer header. */ - sig[(*len)++] = 0x02; - if (nlenlen[n] == 0) { - /* Short length notation */ - sig[(*len)++] = nlen[n] + nzlen[n]; - } else { - /* Long length notation. */ - sig[(*len)++] = 128 + nlenlen[n]; - assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); - *len += nlenlen[n]; - } - /* Write zero padding */ - while (nzlen[n] > 0) { - sig[(*len)++] = 0x00; - nzlen[n]--; - } - if (nlen[n] == 32 && !nlow[n]) { - /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ - int i; - for (i = 0; i < 16; i++) { - sig[(*len)++] = 0xFF; - } - nlen[n] -= 16; - } - /* Write first byte of number */ - if (nlen[n] > 0) { - sig[(*len)++] = nhbyte[n]; - nlen[n]--; - } - /* Generate remaining random bytes of number */ - secp256k1_rand_bytes_test(sig + *len, nlen[n]); - *len += nlen[n]; - nlen[n] = 0; - } - - /* Generate random garbage inside tuple. */ - secp256k1_rand_bytes_test(sig + *len, elen); - *len += elen; - - /* Generate end-of-contents bytes. */ - if (indet) { - sig[(*len)++] = 0; - sig[(*len)++] = 0; - tlen += 2; - } - CHECK(tlen + glen <= 1121); - - /* Generate random garbage outside tuple. */ - secp256k1_rand_bytes_test(sig + *len, glen); - *len += glen; - tlen += glen; - CHECK(tlen <= 1121); - CHECK(tlen == *len); -} - -void run_ecdsa_der_parse(void) { - int i,j; - for (i = 0; i < 200 * count; i++) { - unsigned char buffer[2048]; - size_t buflen = 0; - int certainly_der = 0; - int certainly_not_der = 0; - random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); - CHECK(buflen <= 2048); - for (j = 0; j < 16; j++) { - int ret = 0; - if (j > 0) { - damage_array(buffer, &buflen); - /* We don't know anything anymore about the DERness of the result */ - certainly_der = 0; - certainly_not_der = 0; - } - ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); - if (ret != 0) { - size_t k; - fprintf(stderr, "Failure %x on ", ret); - for (k = 0; k < buflen; k++) { - fprintf(stderr, "%02x ", buffer[k]); - } - fprintf(stderr, "\n"); - } - CHECK(ret == 0); - } - } -} - -/* Tests several edge cases. */ -void test_ecdsa_edge_cases(void) { - int t; - secp256k1_ecdsa_signature sig; - - /* Test the case where ECDSA recomputes a point that is infinity. */ - { - secp256k1_gej keyj; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_negate(&ss, &ss); - secp256k1_scalar_inverse(&ss, &ss); - secp256k1_scalar_set_int(&sr, 1); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); - secp256k1_ge_set_gej(&key, &keyj); - msg = ss; - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with r of zero fails. */ - { - const unsigned char pubkey_mods_zero[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x41 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 0); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with s of zero fails. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 0); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 1); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with message 0 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02 - }; - const unsigned char pubkey2[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x43 - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 2); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message 1 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, - 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, - 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, - 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, - 0x25 - }; - const unsigned char pubkey2[33] = { - 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, - 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, - 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, - 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, - 0x62 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message -1 passes. */ - { - const unsigned char pubkey[33] = { - 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, - 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, - 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, - 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, - 0xf1 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_negate(&msg, &msg); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - secp256k1_scalar_set_int(&ss, 3); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Signature where s would be zero. */ - { - secp256k1_pubkey pubkey; - size_t siglen; - int32_t ecount; - unsigned char signature[72]; - static const unsigned char nonce[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - static const unsigned char nonce2[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 - }; - const unsigned char key[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - unsigned char msg[32] = { - 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, - 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, - 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, - 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, - }; - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); - msg[31] = 0xaa; - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); - CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); - CHECK(ecount == 6); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 7); - /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); - CHECK(ecount == 8); - siglen = 72; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); - CHECK(ecount == 9); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); - CHECK(ecount == 10); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); - CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); - CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); - CHECK(ecount == 12); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); - CHECK(ecount == 13); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); - CHECK(ecount == 13); - siglen = 10; - /* Too little room for a signature does not fail via ARGCHECK. */ - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); - CHECK(ecount == 13); - ecount = 0; - CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); - CHECK(ecount == 5); - memset(signature, 255, 64); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); - CHECK(ecount == 5); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); - } - - /* Nonce function corner cases. */ - for (t = 0; t < 2; t++) { - static const unsigned char zero[32] = {0x00}; - int i; - unsigned char key[32]; - unsigned char msg[32]; - secp256k1_ecdsa_signature sig2; - secp256k1_scalar sr[512], ss; - const unsigned char *extra; - extra = t == 0 ? NULL : zero; - memset(msg, 0, 32); - msg[31] = 1; - /* High key results in signature failure. */ - memset(key, 0xFF, 32); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Zero key results in signature failure. */ - memset(key, 0, 32); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Nonce function failure results in signature failure. */ - key[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_fail, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* The retry loop successfully makes its way to the first good value. */ - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_retry, extra) == 1); - CHECK(!is_empty_signature(&sig)); - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function is deterministic. */ - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function changes output with different messages. */ - for(i = 0; i < 256; i++) { - int j; - msg[0] = i; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - msg[0] = 0; - msg[31] = 2; - /* The default nonce function changes output with different keys. */ - for(i = 256; i < 512; i++) { - int j; - key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - key[0] = 0; - } - - { - /* Check that optional nonce arguments do not have equivalent effect. */ - const unsigned char zeros[32] = {0}; - unsigned char nonce[32]; - unsigned char nonce2[32]; - unsigned char nonce3[32]; - unsigned char nonce4[32]; - VG_UNDEF(nonce,32); - VG_UNDEF(nonce2,32); - VG_UNDEF(nonce3,32); - VG_UNDEF(nonce4,32); - CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); - VG_CHECK(nonce,32); - CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); - VG_CHECK(nonce2,32); - CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); - VG_CHECK(nonce3,32); - CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); - VG_CHECK(nonce4,32); - CHECK(memcmp(nonce, nonce2, 32) != 0); - CHECK(memcmp(nonce, nonce3, 32) != 0); - CHECK(memcmp(nonce, nonce4, 32) != 0); - CHECK(memcmp(nonce2, nonce3, 32) != 0); - CHECK(memcmp(nonce2, nonce4, 32) != 0); - CHECK(memcmp(nonce3, nonce4, 32) != 0); - } - - - /* Privkey export where pubkey is the point at infinity. */ - { - unsigned char privkey[300]; - unsigned char seckey[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, - }; - size_t outlen = 300; - CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); - outlen = 300; - CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); - } -} - -void run_ecdsa_edge_cases(void) { - test_ecdsa_edge_cases(); -} - -#ifdef ENABLE_OPENSSL_TESTS -EC_KEY *get_openssl_key(const unsigned char *key32) { - unsigned char privkey[300]; - size_t privkeylen; - const unsigned char* pbegin = privkey; - int compr = secp256k1_rand_bits(1); - EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); - CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); - CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); - CHECK(EC_KEY_check_key(ec_key)); - return ec_key; -} - -void test_ecdsa_openssl(void) { - secp256k1_gej qj; - secp256k1_ge q; - secp256k1_scalar sigr, sigs; - secp256k1_scalar one; - secp256k1_scalar msg2; - secp256k1_scalar key, msg; - EC_KEY *ec_key; - unsigned int sigsize = 80; - size_t secp_sigsize = 80; - unsigned char message[32]; - unsigned char signature[80]; - unsigned char key32[32]; - secp256k1_rand256_test(message); - secp256k1_scalar_set_b32(&msg, message, NULL); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(key32, &key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); - secp256k1_ge_set_gej(&q, &qj); - ec_key = get_openssl_key(key32); - CHECK(ec_key != NULL); - CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); - CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg2, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); - - random_sign(&sigr, &sigs, &key, &msg, NULL); - CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); - CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); - - EC_KEY_free(ec_key); -} - -void run_ecdsa_openssl(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_ecdsa_openssl(); - } -} -#endif - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/tests_impl.h" -#endif - -int main(int argc, char **argv) { - unsigned char seed16[16] = {0}; - unsigned char run32[32] = {0}; - /* find iteration count */ - if (argc > 1) { - count = strtol(argv[1], NULL, 0); - } - - /* find random seed */ - if (argc > 2) { - int pos = 0; - const char* ch = argv[2]; - while (pos < 16 && ch[0] != 0 && ch[1] != 0) { - unsigned short sh; - if (sscanf(ch, "%2hx", &sh)) { - seed16[pos] = sh; - } else { - break; - } - ch += 2; - pos++; - } - } else { - FILE *frand = fopen("/dev/urandom", "r"); - if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { - uint64_t t = time(NULL) * (uint64_t)1337; - seed16[0] ^= t; - seed16[1] ^= t >> 8; - seed16[2] ^= t >> 16; - seed16[3] ^= t >> 24; - seed16[4] ^= t >> 32; - seed16[5] ^= t >> 40; - seed16[6] ^= t >> 48; - seed16[7] ^= t >> 56; - } - fclose(frand); - } - secp256k1_rand_seed(seed16); - - printf("test count = %i\n", count); - printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); - - /* initialize */ - run_context_tests(); - ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - if (secp256k1_rand_bits(1)) { - secp256k1_rand256(run32); - CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); - } - - run_rand_bits(); - run_rand_int(); - - run_sha256_tests(); - run_hmac_sha256_tests(); - run_rfc6979_hmac_sha256_tests(); - -#ifndef USE_NUM_NONE - /* num tests */ - run_num_smalltests(); -#endif - - /* scalar tests */ - run_scalar_tests(); - - /* field tests */ - run_field_inv(); - run_field_inv_var(); - run_field_inv_all_var(); - run_field_misc(); - run_field_convert(); - run_sqr(); - run_sqrt(); - - /* group tests */ - run_ge(); - run_group_decompress(); - - /* ecmult tests */ - run_wnaf(); - run_point_times_order(); - run_ecmult_chain(); - run_ecmult_constants(); - run_ecmult_gen_blind(); - run_ecmult_const_tests(); - run_ec_combine(); - - /* endomorphism tests */ -#ifdef USE_ENDOMORPHISM - run_endomorphism_tests(); -#endif - - /* EC point parser test */ - run_ec_pubkey_parse_test(); - - /* EC key edge cases */ - run_eckey_edge_case_test(); - -#ifdef ENABLE_MODULE_ECDH - /* ecdh tests */ - run_ecdh_tests(); -#endif - - /* ecdsa tests */ - run_random_pubkeys(); - run_ecdsa_der_parse(); - run_ecdsa_sign_verify(); - run_ecdsa_end_to_end(); - run_ecdsa_edge_cases(); -#ifdef ENABLE_OPENSSL_TESTS - run_ecdsa_openssl(); -#endif - -#ifdef ENABLE_MODULE_SCHNORR - /* Schnorr tests */ - run_schnorr_tests(); -#endif - -#ifdef ENABLE_MODULE_RECOVERY - /* ECDSA pubkey recovery tests */ - run_recovery_tests(); -#endif - - secp256k1_rand256(run32); - printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); - - /* shutdown */ - secp256k1_context_destroy(ctx); - - printf("no problems found\n"); - return 0; -} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c deleted file mode 100644 index b040bb0733..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c +++ /dev/null @@ -1,470 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include - -#include - -#undef USE_ECMULT_STATIC_PRECOMPUTATION - -#ifndef EXHAUSTIVE_TEST_ORDER -/* see group_impl.h for allowable values */ -#define EXHAUSTIVE_TEST_ORDER 13 -#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ -#endif - -#include "include/secp256k1.h" -#include "group.h" -#include "secp256k1.c" -#include "testrand_impl.h" - -#ifdef ENABLE_MODULE_RECOVERY -#include "src/modules/recovery/main_impl.h" -#include "include/secp256k1_recovery.h" -#endif - -/** stolen from tests.c */ -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); - CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); -} - -void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; secp256k1_fe_normalize_weak(&u2); - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; secp256k1_fe_normalize_weak(&s2); - CHECK(secp256k1_fe_equal_var(&u1, &u2)); - CHECK(secp256k1_fe_equal_var(&s1, &s2)); -} - -void random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} -/** END stolen from tests.c */ - -int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, - const unsigned char *key32, const unsigned char *algo16, - void *data, unsigned int attempt) { - secp256k1_scalar s; - int *idata = data; - (void)msg32; - (void)key32; - (void)algo16; - /* Some nonces cannot be used because they'd cause s and/or r to be zero. - * The signing function has retry logic here that just re-calls the nonce - * function with an increased `attempt`. So if attempt > 0 this means we - * need to change the nonce to avoid an infinite loop. */ - if (attempt > 0) { - *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; - } - secp256k1_scalar_set_int(&s, *idata); - secp256k1_scalar_get_b32(nonce32, &s); - return 1; -} - -#ifdef USE_ENDOMORPHISM -void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { - int i; - for (i = 0; i < order; i++) { - secp256k1_ge res; - secp256k1_ge_mul_lambda(&res, &group[i]); - ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); - } -} -#endif - -void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j; - - /* Sanity-check (and check infinity functions) */ - CHECK(secp256k1_ge_is_infinity(&group[0])); - CHECK(secp256k1_gej_is_infinity(&groupj[0])); - for (i = 1; i < order; i++) { - CHECK(!secp256k1_ge_is_infinity(&group[i])); - CHECK(!secp256k1_gej_is_infinity(&groupj[i])); - } - - /* Check all addition formulae */ - for (j = 0; j < order; j++) { - secp256k1_fe fe_inv; - secp256k1_fe_inv(&fe_inv, &groupj[j].z); - for (i = 0; i < order; i++) { - secp256k1_ge zless_gej; - secp256k1_gej tmp; - /* add_var */ - secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_ge */ - if (j > 0) { - secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - /* add_ge_var */ - secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_zinv_var */ - zless_gej.infinity = groupj[j].infinity; - zless_gej.x = groupj[j].x; - zless_gej.y = groupj[j].y; - secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - } - - /* Check doubling */ - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - if (i > 0) { - secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - secp256k1_gej_double_var(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - - /* Check negation */ - for (i = 1; i < order; i++) { - secp256k1_ge tmp; - secp256k1_gej tmpj; - secp256k1_ge_neg(&tmp, &group[i]); - ge_equals_ge(&group[order - i], &tmp); - secp256k1_gej_neg(&tmpj, &groupj[i]); - ge_equals_gej(&group[order - i], &tmpj); - } -} - -void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j, r_log; - for (r_log = 1; r_log < order; r_log++) { - for (j = 0; j < order; j++) { - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - secp256k1_scalar na, ng; - secp256k1_scalar_set_int(&na, i); - secp256k1_scalar_set_int(&ng, j); - - secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); - ge_equals_gej(&group[(i * r_log + j) % order], &tmp); - - if (i > 0) { - secp256k1_ecmult_const(&tmp, &group[i], &ng); - ge_equals_gej(&group[(i * j) % order], &tmp); - } - } - } - } -} - -void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { - secp256k1_fe x; - unsigned char x_bin[32]; - k %= EXHAUSTIVE_TEST_ORDER; - x = group[k].x; - secp256k1_fe_normalize(&x); - secp256k1_fe_get_b32(x_bin, &x); - secp256k1_scalar_set_b32(r, x_bin, NULL); -} - -void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* Verify by calling verify */ - secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - secp256k1_scalar_get_b32(msg32, &msg_s); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} - -void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } - - /* We would like to verify zero-knowledge here by counting how often every - * possible (s, r) tuple appears, but because the group order is larger - * than the field order, when coercing the x-values to scalar values, some - * appear more often than others, so we are actually not zero-knowledge. - * (This effect also appears in the real code, but the difference is on the - * order of 1/2^128th the field order, so the deviation is not useful to a - * computationally bounded attacker.) - */ -} - -#ifdef ENABLE_MODULE_RECOVERY -void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_fe r_dot_y_normalized; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - int expected_recid; - int recid; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - /* Check directly */ - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - /* In computing the recid, there is an overflow condition that is disabled in - * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value - * will exceed the group order, and our signing code always holds out for r - * values that don't overflow, so with a proper overflow check the tests would - * loop indefinitely. */ - r_dot_y_normalized = group[k].y; - secp256k1_fe_normalize(&r_dot_y_normalized); - /* Also the recovery id is flipped depending if we hit the low-s branch */ - if ((k * s) % order == (i + r * j) % order) { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; - } else { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; - } - CHECK(recid == expected_recid); - - /* Convert to a standard sig then check */ - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } -} - -void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - /* This is essentially a copy of test_exhaustive_verify, with recovery added */ - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int recid = 0; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - secp256k1_scalar_get_b32(msg32, &msg_s); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* We would like to try recovering the pubkey and checking that it matches, - * but pubkey recovery is impossible in the exhaustive tests (the reason - * being that there are 12 nonzero r values, 12 nonzero points, and no - * overlap between the sets, so there are no valid signatures). */ - - /* Verify by converting to a standard signature and calling verify */ - secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} -#endif - -int main(void) { - int i; - secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; - secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; - - /* Build context */ - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - /* TODO set z = 1, then do num_tests runs with random z values */ - - /* Generate the entire group */ - secp256k1_gej_set_infinity(&groupj[0]); - secp256k1_ge_set_gej(&group[0], &groupj[0]); - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - /* Set a different random z-value for each Jacobian point */ - secp256k1_fe z; - random_fe(&z); - - secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); - secp256k1_ge_set_gej(&group[i], &groupj[i]); - secp256k1_gej_rescale(&groupj[i], &z); - - /* Verify against ecmult_gen */ - { - secp256k1_scalar scalar_i; - secp256k1_gej generatedj; - secp256k1_ge generated; - - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - secp256k1_ge_set_gej(&generated, &generatedj); - - CHECK(group[i].infinity == 0); - CHECK(generated.infinity == 0); - CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); - CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); - } - } - - /* Run the tests */ -#ifdef USE_ENDOMORPHISM - test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); -#endif - test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); - -#ifdef ENABLE_MODULE_RECOVERY - test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); -#endif - - secp256k1_context_destroy(ctx); - return 0; -} - diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h deleted file mode 100644 index 4092a86c91..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h +++ /dev/null @@ -1,113 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_UTIL_H_ -#define _SECP256K1_UTIL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include -#include - -typedef struct { - void (*fn)(const char *text, void* data); - const void* data; -} secp256k1_callback; - -static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { - cb->fn(text, (void*)cb->data); -} - -#ifdef DETERMINISTIC -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s\n", msg); \ - abort(); \ -} while(0); -#else -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ - abort(); \ -} while(0) -#endif - -#ifdef HAVE_BUILTIN_EXPECT -#define EXPECT(x,c) __builtin_expect((x),(c)) -#else -#define EXPECT(x,c) (x) -#endif - -#ifdef DETERMINISTIC -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed"); \ - } \ -} while(0) -#else -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed: " #cond); \ - } \ -} while(0) -#endif - -/* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#if defined(COVERAGE) -#define VERIFY_CHECK(check) -#define VERIFY_SETUP(stmt) -#elif defined(VERIFY) -#define VERIFY_CHECK CHECK -#define VERIFY_SETUP(stmt) do { stmt; } while(0) -#else -#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) -#define VERIFY_SETUP(stmt) -#endif - -static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { - void *ret = malloc(size); - if (ret == NULL) { - secp256k1_callback_call(cb, "Out of memory"); - } - return ret; -} - -/* Macro for restrict, when available and not in a VERIFY build. */ -#if defined(SECP256K1_BUILD) && defined(VERIFY) -# define SECP256K1_RESTRICT -#else -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(3,0) -# define SECP256K1_RESTRICT __restrict__ -# elif (defined(_MSC_VER) && _MSC_VER >= 1400) -# define SECP256K1_RESTRICT __restrict -# else -# define SECP256K1_RESTRICT -# endif -# else -# define SECP256K1_RESTRICT restrict -# endif -#endif - -#if defined(_WIN32) -# define I64FORMAT "I64d" -# define I64uFORMAT "I64u" -#else -# define I64FORMAT "lld" -# define I64uFORMAT "llu" -#endif - -#if defined(HAVE___INT128) -# if defined(__GNUC__) -# define SECP256K1_GNUC_EXT __extension__ -# else -# define SECP256K1_GNUC_EXT -# endif -SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; -#endif - -#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt b/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt deleted file mode 100644 index 7acafd78c3..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt +++ /dev/null @@ -1,16 +0,0 @@ - -HIDAPI Authors: - -Alan Ott : - Original Author and Maintainer - Linux, Windows, and Mac implementations - -Ludovic Rousseau : - Formatting for Doxygen documentation - Bug fixes - Correctness fixes - - -For a comprehensive list of contributions, see the commit list at github: - http://github.com/signal11/hidapi/commits/master - diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt deleted file mode 100644 index 538cdf95cf..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2010, Alan Ott, Signal 11 Software -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Signal 11 Software nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt deleted file mode 100644 index 94a9ed024d..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt deleted file mode 100644 index e3f3380829..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt +++ /dev/null @@ -1,9 +0,0 @@ - HIDAPI - Multi-Platform library for - communication with HID devices. - - Copyright 2009, Alan Ott, Signal 11 Software. - All Rights Reserved. - - This software may be used by anyone for any reason so - long as the copyright notice in the source files - remains intact. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt deleted file mode 100644 index e1676d4c42..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt +++ /dev/null @@ -1,13 +0,0 @@ -HIDAPI can be used under one of three licenses. - -1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt -2. A BSD-Style License, in LICENSE-bsd.txt. -3. The more liberal original HIDAPI license. LICENSE-orig.txt - -The license chosen is at the discretion of the user of HIDAPI. For example: -1. An author of GPL software would likely use HIDAPI under the terms of the -GPL. - -2. An author of commercial closed-source software would likely use HIDAPI -under the terms of the BSD-style license or the original HIDAPI license. - diff --git a/vendor/github.com/karalabe/usb/hidapi/README.txt b/vendor/github.com/karalabe/usb/hidapi/README.txt deleted file mode 100644 index f19dae4ab7..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/README.txt +++ /dev/null @@ -1,339 +0,0 @@ - HIDAPI library for Windows, Linux, FreeBSD and Mac OS X - ========================================================= - -About -====== - -HIDAPI is a multi-platform library which allows an application to interface -with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac -OS X. HIDAPI can be either built as a shared library (.so or .dll) or -can be embedded directly into a target application by adding a single source -file (per platform) and a single header. - -HIDAPI has four back-ends: - * Windows (using hid.dll) - * Linux/hidraw (using the Kernel's hidraw driver) - * Linux/libusb (using libusb-1.0) - * FreeBSD (using libusb-1.0) - * Mac (using IOHidManager) - -On Linux, either the hidraw or the libusb back-end can be used. There are -tradeoffs, and the functionality supported is slightly different. - -Linux/hidraw (linux/hid.c): -This back-end uses the hidraw interface in the Linux kernel. While this -back-end will support both USB and Bluetooth, it has some limitations on -kernels prior to 2.6.39, including the inability to send or receive feature -reports. In addition, it will only communicate with devices which have -hidraw nodes associated with them. Keyboards, mice, and some other devices -which are blacklisted from having hidraw nodes will not work. Fortunately, -for nearly all the uses of hidraw, this is not a problem. - -Linux/FreeBSD/libusb (libusb/hid.c): -This back-end uses libusb-1.0 to communicate directly to a USB device. This -back-end will of course not work with Bluetooth devices. - -HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses -Fox Toolkit (http://www.fox-toolkit.org). It will build on every platform -which HIDAPI supports. Since it relies on a 3rd party library, building it -is optional but recommended because it is so useful when debugging hardware. - -What Does the API Look Like? -============================= -The API provides the the most commonly used HID functions including sending -and receiving of input, output, and feature reports. The sample program, -which communicates with a heavily hacked up version of the Microchip USB -Generic HID sample looks like this (with error checking removed for -simplicity): - -#ifdef WIN32 -#include -#endif -#include -#include -#include "hidapi.h" - -#define MAX_STR 255 - -int main(int argc, char* argv[]) -{ - int res; - unsigned char buf[65]; - wchar_t wstr[MAX_STR]; - hid_device *handle; - int i; - - // Initialize the hidapi library - res = hid_init(); - - // Open the device using the VID, PID, - // and optionally the Serial number. - handle = hid_open(0x4d8, 0x3f, NULL); - - // Read the Manufacturer String - res = hid_get_manufacturer_string(handle, wstr, MAX_STR); - wprintf(L"Manufacturer String: %s\n", wstr); - - // Read the Product String - res = hid_get_product_string(handle, wstr, MAX_STR); - wprintf(L"Product String: %s\n", wstr); - - // Read the Serial Number String - res = hid_get_serial_number_string(handle, wstr, MAX_STR); - wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr); - - // Read Indexed String 1 - res = hid_get_indexed_string(handle, 1, wstr, MAX_STR); - wprintf(L"Indexed String 1: %s\n", wstr); - - // Toggle LED (cmd 0x80). The first byte is the report number (0x0). - buf[0] = 0x0; - buf[1] = 0x80; - res = hid_write(handle, buf, 65); - - // Request state (cmd 0x81). The first byte is the report number (0x0). - buf[0] = 0x0; - buf[1] = 0x81; - res = hid_write(handle, buf, 65); - - // Read requested state - res = hid_read(handle, buf, 65); - - // Print out the returned buffer. - for (i = 0; i < 4; i++) - printf("buf[%d]: %d\n", i, buf[i]); - - // Finalize the hidapi library - res = hid_exit(); - - return 0; -} - -If you have your own simple test programs which communicate with standard -hardware development boards (such as those from Microchip, TI, Atmel, -FreeScale and others), please consider sending me something like the above -for inclusion into the HIDAPI source. This will help others who have the -same hardware as you do. - -License -======== -HIDAPI may be used by one of three licenses as outlined in LICENSE.txt. - -Download -========= -HIDAPI can be downloaded from github - git clone git://github.com/signal11/hidapi.git - -Build Instructions -=================== - -This section is long. Don't be put off by this. It's not long because it's -complicated to build HIDAPI; it's quite the opposite. This section is long -because of the flexibility of HIDAPI and the large number of ways in which -it can be built and used. You will likely pick a single build method. - -HIDAPI can be built in several different ways. If you elect to build a -shared library, you will need to build it from the HIDAPI source -distribution. If you choose instead to embed HIDAPI directly into your -application, you can skip the building and look at the provided platform -Makefiles for guidance. These platform Makefiles are located in linux/ -libusb/ mac/ and windows/ and are called Makefile-manual. In addition, -Visual Studio projects are provided. Even if you're going to embed HIDAPI -into your project, it is still beneficial to build the example programs. - - -Prerequisites: ---------------- - - Linux: - ------- - On Linux, you will need to install development packages for libudev, - libusb and optionally Fox-toolkit (for the test GUI). On - Debian/Ubuntu systems these can be installed by running: - sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev - - If you downloaded the source directly from the git repository (using - git clone), you'll need Autotools: - sudo apt-get install autotools-dev autoconf automake libtool - - FreeBSD: - --------- - On FreeBSD you will need to install GNU make, libiconv, and - optionally Fox-Toolkit (for the test GUI). This is done by running - the following: - pkg_add -r gmake libiconv fox16 - - If you downloaded the source directly from the git repository (using - git clone), you'll need Autotools: - pkg_add -r autotools - - Mac: - ----- - On Mac, you will need to install Fox-Toolkit if you wish to build - the Test GUI. There are two ways to do this, and each has a slight - complication. Which method you use depends on your use case. - - If you wish to build the Test GUI just for your own testing on your - own computer, then the easiest method is to install Fox-Toolkit - using ports: - sudo port install fox - - If you wish to build the TestGUI app bundle to redistribute to - others, you will need to install Fox-toolkit from source. This is - because the version of fox that gets installed using ports uses the - ports X11 libraries which are not compatible with the Apple X11 - libraries. If you install Fox with ports and then try to distribute - your built app bundle, it will simply fail to run on other systems. - To install Fox-Toolkit manually, download the source package from - http://www.fox-toolkit.org, extract it, and run the following from - within the extracted source: - ./configure && make && make install - - Windows: - --------- - On Windows, if you want to build the test GUI, you will need to get - the hidapi-externals.zip package from the download site. This - contains pre-built binaries for Fox-toolkit. Extract - hidapi-externals.zip just outside of hidapi, so that - hidapi-externals and hidapi are on the same level, as shown: - - Parent_Folder - | - +hidapi - +hidapi-externals - - Again, this step is not required if you do not wish to build the - test GUI. - - -Building HIDAPI into a shared library on Unix Platforms: ---------------------------------------------------------- - -On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using -Mingw or Cygwin, the easiest way to build a standard system-installed shared -library is to use the GNU Autotools build system. If you checked out the -source from the git repository, run the following: - - ./bootstrap - ./configure - make - make install <----- as root, or using sudo - -If you downloaded a source package (ie: if you did not run git clone), you -can skip the ./bootstrap step. - -./configure can take several arguments which control the build. The two most -likely to be used are: - --enable-testgui - Enable build of the Test GUI. This requires Fox toolkit to - be installed. Instructions for installing Fox-Toolkit on - each platform are in the Prerequisites section above. - - --prefix=/usr - Specify where you want the output headers and libraries to - be installed. The example above will put the headers in - /usr/include and the binaries in /usr/lib. The default is to - install into /usr/local which is fine on most systems. - -Building the manual way on Unix platforms: -------------------------------------------- - -Manual Makefiles are provided mostly to give the user and idea what it takes -to build a program which embeds HIDAPI directly inside of it. These should -really be used as examples only. If you want to build a system-wide shared -library, use the Autotools method described above. - - To build HIDAPI using the manual makefiles, change to the directory - of your platform and run make. For example, on Linux run: - cd linux/ - make -f Makefile-manual - - To build the Test GUI using the manual makefiles: - cd testgui/ - make -f Makefile-manual - -Building on Windows: ---------------------- - -To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file -in the windows/ directory. - -To build the Test GUI on windows using Visual Studio, build the .sln file in -the testgui/ directory. - -To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions -in the section titled "Building HIDAPI into a shared library on Unix -Platforms" above. Note that building the Test GUI with MinGW or Cygwin will -require the Windows procedure in the Prerequisites section above (ie: -hidapi-externals.zip). - -To build HIDAPI using MinGW using the Manual Makefiles, see the section -"Building the manual way on Unix platforms" above. - -HIDAPI can also be built using the Windows DDK (now also called the Windows -Driver Kit or WDK). This method was originally required for the HIDAPI build -but not anymore. However, some users still prefer this method. It is not as -well supported anymore but should still work. Patches are welcome if it does -not. To build using the DDK: - - 1. Install the Windows Driver Kit (WDK) from Microsoft. - 2. From the Start menu, in the Windows Driver Kits folder, select Build - Environments, then your operating system, then the x86 Free Build - Environment (or one that is appropriate for your system). - 3. From the console, change directory to the windows/ddk_build/ directory, - which is part of the HIDAPI distribution. - 4. Type build. - 5. You can find the output files (DLL and LIB) in a subdirectory created - by the build system which is appropriate for your environment. On - Windows XP, this directory is objfre_wxp_x86/i386. - -Cross Compiling -================ - -This section talks about cross compiling HIDAPI for Linux using autotools. -This is useful for using HIDAPI on embedded Linux targets. These -instructions assume the most raw kind of embedded Linux build, where all -prerequisites will need to be built first. This process will of course vary -based on your embedded Linux build system if you are using one, such as -OpenEmbedded or Buildroot. - -For the purpose of this section, it will be assumed that the following -environment variables are exported. - - $ export STAGING=$HOME/out - $ export HOST=arm-linux - -STAGING and HOST can be modified to suit your setup. - -Prerequisites --------------- - -Note that the build of libudev is the very basic configuration. - -Build Libusb. From the libusb source directory, run: - ./configure --host=$HOST --prefix=$STAGING - make - make install - -Build libudev. From the libudev source directory, run: - ./configure --disable-gudev --disable-introspection --disable-hwdb \ - --host=$HOST --prefix=$STAGING - make - make install - -Building HIDAPI ----------------- - -Build HIDAPI: - - PKG_CONFIG_DIR= \ - PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \ - PKG_CONFIG_SYSROOT_DIR=$STAGING \ - ./configure --host=$HOST --prefix=$STAGING - - -Signal 11 Software - 2010-04-11 - 2010-07-28 - 2011-09-10 - 2012-05-01 - 2012-07-03 diff --git a/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h b/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h deleted file mode 100644 index 166f3509ab..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h +++ /dev/null @@ -1,390 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/** @file - * @defgroup API hidapi API - */ - -#ifndef HIDAPI_H__ -#define HIDAPI_H__ - -#include - -#ifdef _WIN32 - #define HID_API_EXPORT __declspec(dllexport) - #define HID_API_CALL -#else - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ -#endif - -#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ - -#ifdef __cplusplus -extern "C" { -#endif - struct hid_device_; - typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ - - /** hidapi info structure */ - struct hid_device_info { - /** Platform-specific device path */ - char *path; - /** Device Vendor ID */ - unsigned short vendor_id; - /** Device Product ID */ - unsigned short product_id; - /** Serial Number */ - wchar_t *serial_number; - /** Device Release Number in binary-coded decimal, - also known as Device Version Number */ - unsigned short release_number; - /** Manufacturer String */ - wchar_t *manufacturer_string; - /** Product string */ - wchar_t *product_string; - /** Usage Page for this Device/Interface - (Windows/Mac only). */ - unsigned short usage_page; - /** Usage for this Device/Interface - (Windows/Mac only).*/ - unsigned short usage; - /** The USB interface which this logical device - represents. Valid on both Linux implementations - in all cases, and valid on the Windows implementation - only if the device contains more than one interface. */ - int interface_number; - - /** Pointer to the next device */ - struct hid_device_info *next; - }; - - - /** @brief Initialize the HIDAPI library. - - This function initializes the HIDAPI library. Calling it is not - strictly necessary, as it will be called automatically by - hid_enumerate() and any of the hid_open_*() functions if it is - needed. This function should be called at the beginning of - execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_init(void); - - /** @brief Finalize the HIDAPI library. - - This function frees all of the static data associated with - HIDAPI. It should be called at the end of execution to avoid - memory leaks. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_exit(void); - - /** @brief Enumerate the HID Devices. - - This function returns a linked list of all the HID devices - attached to the system which match vendor_id and product_id. - If @p vendor_id is set to 0 then any vendor matches. - If @p product_id is set to 0 then any product matches. - If @p vendor_id and @p product_id are both set to 0, then - all HID devices will be returned. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the types of device - to open. - @param product_id The Product ID (PID) of the types of - device to open. - - @returns - This function returns a pointer to a linked list of type - struct #hid_device, containing information about the HID devices - attached to the system, or NULL in the case of failure. Free - this linked list by calling hid_free_enumeration(). - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); - - /** @brief Free an enumeration Linked List - - This function frees a linked list created by hid_enumerate(). - - @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). - */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); - - /** @brief Open a HID device using a Vendor ID (VID), Product ID - (PID) and optionally a serial number. - - If @p serial_number is NULL, the first device with the - specified VID and PID is opened. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the device to open. - @param product_id The Product ID (PID) of the device to open. - @param serial_number The Serial Number of the device to open - (Optionally NULL). - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); - - /** @brief Open a HID device by its path name. - - The path name be determined by calling hid_enumerate(), or a - platform-specific path name can be used (eg: /dev/hidraw0 on - Linux). - - @ingroup API - @param path The path name of the device to open - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); - - /** @brief Write an Output report to a HID device. - - The first byte of @p data[] must contain the Report ID. For - devices which only support a single report, this must be set - to 0x0. The remaining bytes contain the report data. Since - the Report ID is mandatory, calls to hid_write() will always - contain one more byte than the report contains. For example, - if a hid report is 16 bytes long, 17 bytes must be passed to - hid_write(), the Report ID (or 0x0, for devices with a - single report), followed by the report data (16 bytes). In - this example, the length passed in would be 17. - - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Read an Input report from a HID device with timeout. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - @param milliseconds timeout in milliseconds or -1 for blocking wait. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read within - the timeout period, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); - - /** @brief Read an Input report from a HID device. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read and - the handle is in non-blocking mode, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); - - /** @brief Set the device handle to be non-blocking. - - In non-blocking mode calls to hid_read() will return - immediately with a value of 0 if there is no data to be - read. In blocking mode, hid_read() will wait (block) until - there is data to read before returning. - - Nonblocking can be turned on and off at any time. - - @ingroup API - @param device A device handle returned from hid_open(). - @param nonblock enable or not the nonblocking reads - - 1 to enable nonblocking - - 0 to disable nonblocking. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); - - /** @brief Send a Feature report to the device. - - Feature reports are sent over the Control endpoint as a - Set_Report transfer. The first byte of @p data[] must - contain the Report ID. For devices which only support a - single report, this must be set to 0x0. The remaining bytes - contain the report data. Since the Report ID is mandatory, - calls to hid_send_feature_report() will always contain one - more byte than the report contains. For example, if a hid - report is 16 bytes long, 17 bytes must be passed to - hid_send_feature_report(): the Report ID (or 0x0, for - devices which do not use numbered reports), followed by the - report data (16 bytes). In this example, the length passed - in would be 17. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send, including - the report number. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Get a feature report from a HID device. - - Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this - extra byte in @p data[]. Upon return, the first byte will - still contain the Report ID, and the report data will - start in data[1]. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read, or set it to zero - if your device does not use numbered reports. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read plus - one for the report ID (which is still in the first - byte), or -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); - - /** @brief Close a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); - - /** @brief Get The Manufacturer String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Product String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Serial Number String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get a string from a HID device, based on its string index. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string_index The index of the string to get. - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); - - /** @brief Get a string describing the last error which occurred. - - @ingroup API - @param device A device handle returned from hid_open(). - - @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. - */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c b/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c deleted file mode 100644 index 474dff41c1..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c +++ /dev/null @@ -1,1512 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - Linux Version - 6/2/2010 - Libusb Version - 8/13/2010 - FreeBSD Version - 11/1/2011 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/* C */ -#include -#include -#include -#include -#include -#include - -/* Unix */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* GNU / LibUSB */ -#include -#ifndef __ANDROID__ -#include -#endif - -#include "hidapi.h" - -#ifdef __ANDROID__ - -/* Barrier implementation because Android/Bionic don't have pthread_barrier. - This implementation came from Brent Priddy and was posted on - StackOverflow. It is used with his permission. */ -typedef int pthread_barrierattr_t; -typedef struct pthread_barrier { - pthread_mutex_t mutex; - pthread_cond_t cond; - int count; - int trip_count; -} pthread_barrier_t; - -static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) -{ - if(count == 0) { - errno = EINVAL; - return -1; - } - - if(pthread_mutex_init(&barrier->mutex, 0) < 0) { - return -1; - } - if(pthread_cond_init(&barrier->cond, 0) < 0) { - pthread_mutex_destroy(&barrier->mutex); - return -1; - } - barrier->trip_count = count; - barrier->count = 0; - - return 0; -} - -static int pthread_barrier_destroy(pthread_barrier_t *barrier) -{ - pthread_cond_destroy(&barrier->cond); - pthread_mutex_destroy(&barrier->mutex); - return 0; -} - -static int pthread_barrier_wait(pthread_barrier_t *barrier) -{ - pthread_mutex_lock(&barrier->mutex); - ++(barrier->count); - if(barrier->count >= barrier->trip_count) - { - barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return 1; - } - else - { - pthread_cond_wait(&barrier->cond, &(barrier->mutex)); - pthread_mutex_unlock(&barrier->mutex); - return 0; - } -} - -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DEBUG_PRINTF -#define LOG(...) fprintf(stderr, __VA_ARGS__) -#else -#define LOG(...) do {} while (0) -#endif - -#ifndef __FreeBSD__ -#define DETACH_KERNEL_DRIVER -#endif - -/* Uncomment to enable the retrieval of Usage and Usage Page in -hid_enumerate(). Warning, on platforms different from FreeBSD -this is very invasive as it requires the detach -and re-attach of the kernel driver. See comments inside hid_enumerate(). -libusb HIDAPI programs are encouraged to use the interface number -instead to differentiate between interfaces on a composite HID device. */ -/*#define INVASIVE_GET_USAGE*/ - -/* Linked List of input reports received from the device. */ -struct input_report { - uint8_t *data; - size_t len; - struct input_report *next; -}; - - -struct hid_device_ { - /* Handle to the actual device. */ - libusb_device_handle *device_handle; - - /* Endpoint information */ - int input_endpoint; - int output_endpoint; - int input_ep_max_packet_size; - - /* The interface number of the HID */ - int interface; - - /* Indexes of Strings */ - int manufacturer_index; - int product_index; - int serial_index; - - /* Whether blocking reads are used */ - int blocking; /* boolean */ - - /* Read thread objects */ - pthread_t thread; - pthread_mutex_t mutex; /* Protects input_reports */ - pthread_cond_t condition; - pthread_barrier_t barrier; /* Ensures correct startup sequence */ - int shutdown_thread; - int cancelled; - struct libusb_transfer *transfer; - - /* List of received input reports. */ - struct input_report *input_reports; -}; - -static libusb_context *usb_context = NULL; - -uint16_t get_usb_code_for_current_locale(void); -static int return_data(hid_device *dev, unsigned char *data, size_t length); - -static hid_device *new_hid_device(void) -{ - hid_device *dev = calloc(1, sizeof(hid_device)); - dev->blocking = 1; - - pthread_mutex_init(&dev->mutex, NULL); - pthread_cond_init(&dev->condition, NULL); - pthread_barrier_init(&dev->barrier, NULL, 2); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - /* Clean up the thread objects */ - pthread_barrier_destroy(&dev->barrier); - pthread_cond_destroy(&dev->condition); - pthread_mutex_destroy(&dev->mutex); - - /* Free the device itself */ - free(dev); -} - -#if 0 -/*TODO: Implement this funciton on hidapi/libusb.. */ -static void register_error(hid_device *device, const char *op) -{ - -} -#endif - -#ifdef INVASIVE_GET_USAGE -/* Get bytes from a HID Report Descriptor. - Only call with a num_bytes of 0, 1, 2, or 4. */ -static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) -{ - /* Return if there aren't enough bytes. */ - if (cur + num_bytes >= len) - return 0; - - if (num_bytes == 0) - return 0; - else if (num_bytes == 1) { - return rpt[cur+1]; - } - else if (num_bytes == 2) { - return (rpt[cur+2] * 256 + rpt[cur+1]); - } - else if (num_bytes == 4) { - return (rpt[cur+4] * 0x01000000 + - rpt[cur+3] * 0x00010000 + - rpt[cur+2] * 0x00000100 + - rpt[cur+1] * 0x00000001); - } - else - return 0; -} - -/* Retrieves the device's Usage Page and Usage from the report - descriptor. The algorithm is simple, as it just returns the first - Usage and Usage Page that it finds in the descriptor. - The return value is 0 on success and -1 on failure. */ -static int get_usage(uint8_t *report_descriptor, size_t size, - unsigned short *usage_page, unsigned short *usage) -{ - unsigned int i = 0; - int size_code; - int data_len, key_size; - int usage_found = 0, usage_page_found = 0; - - while (i < size) { - int key = report_descriptor[i]; - int key_cmd = key & 0xfc; - - //printf("key: %02hhx\n", key); - - if ((key & 0xf0) == 0xf0) { - /* This is a Long Item. The next byte contains the - length of the data section (value) for this key. - See the HID specification, version 1.11, section - 6.2.2.3, titled "Long Items." */ - if (i+1 < size) - data_len = report_descriptor[i+1]; - else - data_len = 0; /* malformed report */ - key_size = 3; - } - else { - /* This is a Short Item. The bottom two bits of the - key contain the size code for the data section - (value) for this key. Refer to the HID - specification, version 1.11, section 6.2.2.2, - titled "Short Items." */ - size_code = key & 0x3; - switch (size_code) { - case 0: - case 1: - case 2: - data_len = size_code; - break; - case 3: - data_len = 4; - break; - default: - /* Can't ever happen since size_code is & 0x3 */ - data_len = 0; - break; - }; - key_size = 1; - } - - if (key_cmd == 0x4) { - *usage_page = get_bytes(report_descriptor, size, data_len, i); - usage_page_found = 1; - //printf("Usage Page: %x\n", (uint32_t)*usage_page); - } - if (key_cmd == 0x8) { - *usage = get_bytes(report_descriptor, size, data_len, i); - usage_found = 1; - //printf("Usage: %x\n", (uint32_t)*usage); - } - - if (usage_page_found && usage_found) - return 0; /* success */ - - /* Skip over this key and it's associated data */ - i += data_len + key_size; - } - - return -1; /* failure */ -} -#endif /* INVASIVE_GET_USAGE */ - -#if defined(__FreeBSD__) && __FreeBSD__ < 10 -/* The libusb version included in FreeBSD < 10 doesn't have this function. In - mainline libusb, it's inlined in libusb.h. This function will bear a striking - resemblance to that one, because there's about one way to code it. - - Note that the data parameter is Unicode in UTF-16LE encoding. - Return value is the number of bytes in data, or LIBUSB_ERROR_*. - */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev, - uint8_t descriptor_index, uint16_t lang_id, - unsigned char *data, int length) -{ - return libusb_control_transfer(dev, - LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ - LIBUSB_REQUEST_GET_DESCRIPTOR, - (LIBUSB_DT_STRING << 8) | descriptor_index, - lang_id, data, (uint16_t) length, 1000); -} - -#endif - - -/* Get the first language the device says it reports. This comes from - USB string #0. */ -static uint16_t get_first_language(libusb_device_handle *dev) -{ - uint16_t buf[32]; - int len; - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - 0x0, /* String ID */ - 0x0, /* Language */ - (unsigned char*)buf, - sizeof(buf)); - if (len < 4) - return 0x0; - - return buf[1]; /* First two bytes are len and descriptor type. */ -} - -static int is_language_supported(libusb_device_handle *dev, uint16_t lang) -{ - uint16_t buf[32]; - int len; - int i; - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - 0x0, /* String ID */ - 0x0, /* Language */ - (unsigned char*)buf, - sizeof(buf)); - if (len < 4) - return 0x0; - - - len /= 2; /* language IDs are two-bytes each. */ - /* Start at index 1 because there are two bytes of protocol data. */ - for (i = 1; i < len; i++) { - if (buf[i] == lang) - return 1; - } - - return 0; -} - - -/* This function returns a newly allocated wide string containing the USB - device string numbered by the index. The returned string must be freed - by using free(). */ -static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) -{ - char buf[512]; - int len; - wchar_t *str = NULL; - -#ifndef __ANDROID__ /* we don't use iconv on Android */ - wchar_t wbuf[256]; - /* iconv variables */ - iconv_t ic; - size_t inbytes; - size_t outbytes; - size_t res; -#ifdef __FreeBSD__ - const char *inptr; -#else - char *inptr; -#endif - char *outptr; -#endif - - /* Determine which language to use. */ - uint16_t lang; - lang = get_usb_code_for_current_locale(); - if (!is_language_supported(dev, lang)) - lang = get_first_language(dev); - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - idx, - lang, - (unsigned char*)buf, - sizeof(buf)); - if (len < 0) - return NULL; - -#ifdef __ANDROID__ - - /* Bionic does not have iconv support nor wcsdup() function, so it - has to be done manually. The following code will only work for - code points that can be represented as a single UTF-16 character, - and will incorrectly convert any code points which require more - than one UTF-16 character. - - Skip over the first character (2-bytes). */ - len -= 2; - str = malloc((len / 2 + 1) * sizeof(wchar_t)); - int i; - for (i = 0; i < len / 2; i++) { - str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8); - } - str[len / 2] = 0x00000000; - -#else - - /* buf does not need to be explicitly NULL-terminated because - it is only passed into iconv() which does not need it. */ - - /* Initialize iconv. */ - ic = iconv_open("WCHAR_T", "UTF-16LE"); - if (ic == (iconv_t)-1) { - LOG("iconv_open() failed\n"); - return NULL; - } - - /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). - Skip the first character (2-bytes). */ - inptr = buf+2; - inbytes = len-2; - outptr = (char*) wbuf; - outbytes = sizeof(wbuf); - res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); - if (res == (size_t)-1) { - LOG("iconv() failed\n"); - goto err; - } - - /* Write the terminating NULL. */ - wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; - if (outbytes >= sizeof(wbuf[0])) - *((wchar_t*)outptr) = 0x00000000; - - /* Allocate and copy the string. */ - str = wcsdup(wbuf); - -err: - iconv_close(ic); - -#endif - - return str; -} - -static char *make_path(libusb_device *dev, int interface_number) -{ - char str[64]; - snprintf(str, sizeof(str), "%04x:%04x:%02x", - libusb_get_bus_number(dev), - libusb_get_device_address(dev), - interface_number); - str[sizeof(str)-1] = '\0'; - - return strdup(str); -} - - -int HID_API_EXPORT hid_init(void) -{ - if (!usb_context) { - const char *locale; - - /* Init Libusb */ - if (libusb_init(&usb_context)) - return -1; - - /* Set the locale if it's not set. */ - locale = setlocale(LC_CTYPE, NULL); - if (!locale) - setlocale(LC_CTYPE, ""); - } - - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ - if (usb_context) { - libusb_exit(usb_context); - usb_context = NULL; - } - - return 0; -} - -struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - libusb_device **devs; - libusb_device *dev; - libusb_device_handle *handle; - ssize_t num_devs; - int i = 0; - - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - - if(hid_init() < 0) - return NULL; - - num_devs = libusb_get_device_list(usb_context, &devs); - if (num_devs < 0) - return NULL; - while ((dev = devs[i++]) != NULL) { - struct libusb_device_descriptor desc; - struct libusb_config_descriptor *conf_desc = NULL; - int j, k; - int interface_num = 0; - - int res = libusb_get_device_descriptor(dev, &desc); - unsigned short dev_vid = desc.idVendor; - unsigned short dev_pid = desc.idProduct; - - res = libusb_get_active_config_descriptor(dev, &conf_desc); - if (res < 0) - libusb_get_config_descriptor(dev, 0, &conf_desc); - if (conf_desc) { - for (j = 0; j < conf_desc->bNumInterfaces; j++) { - const struct libusb_interface *intf = &conf_desc->interface[j]; - for (k = 0; k < intf->num_altsetting; k++) { - const struct libusb_interface_descriptor *intf_desc; - intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - interface_num = intf_desc->bInterfaceNumber; - - /* Check the VID/PID against the arguments */ - if ((vendor_id == 0x0 || vendor_id == dev_vid) && - (product_id == 0x0 || product_id == dev_pid)) { - struct hid_device_info *tmp; - - /* VID/PID match. Create the record. */ - tmp = calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Fill out the record */ - cur_dev->next = NULL; - cur_dev->path = make_path(dev, interface_num); - - res = libusb_open(dev, &handle); - - if (res >= 0) { - /* Serial Number */ - if (desc.iSerialNumber > 0) - cur_dev->serial_number = - get_usb_string(handle, desc.iSerialNumber); - - /* Manufacturer and Product strings */ - if (desc.iManufacturer > 0) - cur_dev->manufacturer_string = - get_usb_string(handle, desc.iManufacturer); - if (desc.iProduct > 0) - cur_dev->product_string = - get_usb_string(handle, desc.iProduct); - -#ifdef INVASIVE_GET_USAGE -{ - /* - This section is removed because it is too - invasive on the system. Getting a Usage Page - and Usage requires parsing the HID Report - descriptor. Getting a HID Report descriptor - involves claiming the interface. Claiming the - interface involves detaching the kernel driver. - Detaching the kernel driver is hard on the system - because it will unclaim interfaces (if another - app has them claimed) and the re-attachment of - the driver will sometimes change /dev entry names. - It is for these reasons that this section is - #if 0. For composite devices, use the interface - field in the hid_device_info struct to distinguish - between interfaces. */ - unsigned char data[256]; -#ifdef DETACH_KERNEL_DRIVER - int detached = 0; - /* Usage Page and Usage */ - res = libusb_kernel_driver_active(handle, interface_num); - if (res == 1) { - res = libusb_detach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); - else - detached = 1; - } -#endif - res = libusb_claim_interface(handle, interface_num); - if (res >= 0) { - /* Get the HID Report Descriptor. */ - res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); - if (res >= 0) { - unsigned short page=0, usage=0; - /* Parse the usage and usage page - out of the report descriptor. */ - get_usage(data, res, &page, &usage); - cur_dev->usage_page = page; - cur_dev->usage = usage; - } - else - LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); - - /* Release the interface */ - res = libusb_release_interface(handle, interface_num); - if (res < 0) - LOG("Can't release the interface.\n"); - } - else - LOG("Can't claim interface %d\n", res); -#ifdef DETACH_KERNEL_DRIVER - /* Re-attach kernel driver if necessary. */ - if (detached) { - res = libusb_attach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't re-attach kernel driver.\n"); - } -#endif -} -#endif /* INVASIVE_GET_USAGE */ - - libusb_close(handle); - } - /* VID/PID */ - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - - /* Release Number */ - cur_dev->release_number = desc.bcdDevice; - - /* Interface Number */ - cur_dev->interface_number = interface_num; - } - } - } /* altsettings */ - } /* interfaces */ - libusb_free_config_descriptor(conf_desc); - } - } - - libusb_free_device_list(devs, 1); - - return root; -} - -void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) -{ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - -hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (cur_dev->serial_number && - wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -static void read_callback(struct libusb_transfer *transfer) -{ - hid_device *dev = transfer->user_data; - int res; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - - struct input_report *rpt = malloc(sizeof(*rpt)); - rpt->data = malloc(transfer->actual_length); - memcpy(rpt->data, transfer->buffer, transfer->actual_length); - rpt->len = transfer->actual_length; - rpt->next = NULL; - - pthread_mutex_lock(&dev->mutex); - - /* Attach the new report object to the end of the list. */ - if (dev->input_reports == NULL) { - /* The list is empty. Put it at the root. */ - dev->input_reports = rpt; - pthread_cond_signal(&dev->condition); - } - else { - /* Find the end of the list and attach. */ - struct input_report *cur = dev->input_reports; - int num_queued = 0; - while (cur->next != NULL) { - cur = cur->next; - num_queued++; - } - cur->next = rpt; - - /* Pop one off if we've reached 30 in the queue. This - way we don't grow forever if the user never reads - anything from the device. */ - if (num_queued > 30) { - return_data(dev, NULL, 0); - } - } - pthread_mutex_unlock(&dev->mutex); - } - else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - dev->shutdown_thread = 1; - dev->cancelled = 1; - return; - } - else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { - dev->shutdown_thread = 1; - dev->cancelled = 1; - return; - } - else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { - //LOG("Timeout (normal)\n"); - } - else { - LOG("Unknown transfer code: %d\n", transfer->status); - } - - /* Re-submit the transfer object. */ - res = libusb_submit_transfer(transfer); - if (res != 0) { - LOG("Unable to submit URB. libusb error code: %d\n", res); - dev->shutdown_thread = 1; - dev->cancelled = 1; - } -} - - -static void *read_thread(void *param) -{ - hid_device *dev = param; - unsigned char *buf; - const size_t length = dev->input_ep_max_packet_size; - - /* Set up the transfer object. */ - buf = malloc(length); - dev->transfer = libusb_alloc_transfer(0); - libusb_fill_interrupt_transfer(dev->transfer, - dev->device_handle, - dev->input_endpoint, - buf, - length, - read_callback, - dev, - 5000/*timeout*/); - - /* Make the first submission. Further submissions are made - from inside read_callback() */ - libusb_submit_transfer(dev->transfer); - - /* Notify the main thread that the read thread is up and running. */ - pthread_barrier_wait(&dev->barrier); - - /* Handle all the events. */ - while (!dev->shutdown_thread) { - int res; - res = libusb_handle_events(usb_context); - if (res < 0) { - /* There was an error. */ - LOG("read_thread(): libusb reports error # %d\n", res); - - /* Break out of this loop only on fatal error.*/ - if (res != LIBUSB_ERROR_BUSY && - res != LIBUSB_ERROR_TIMEOUT && - res != LIBUSB_ERROR_OVERFLOW && - res != LIBUSB_ERROR_INTERRUPTED) { - break; - } - } - } - - /* Cancel any transfer that may be pending. This call will fail - if no transfers are pending, but that's OK. */ - libusb_cancel_transfer(dev->transfer); - - while (!dev->cancelled) - libusb_handle_events_completed(usb_context, &dev->cancelled); - - /* Now that the read thread is stopping, Wake any threads which are - waiting on data (in hid_read_timeout()). Do this under a mutex to - make sure that a thread which is about to go to sleep waiting on - the condition actually will go to sleep before the condition is - signaled. */ - pthread_mutex_lock(&dev->mutex); - pthread_cond_broadcast(&dev->condition); - pthread_mutex_unlock(&dev->mutex); - - /* The dev->transfer->buffer and dev->transfer objects are cleaned up - in hid_close(). They are not cleaned up here because this thread - could end either due to a disconnect or due to a user - call to hid_close(). In both cases the objects can be safely - cleaned up after the call to pthread_join() (in hid_close()), but - since hid_close() calls libusb_cancel_transfer(), on these objects, - they can not be cleaned up here. */ - - return NULL; -} - - -hid_device * HID_API_EXPORT hid_open_path(const char *path) -{ - hid_device *dev = NULL; - - libusb_device **devs; - libusb_device *usb_dev; - int res; - int d = 0; - int good_open = 0; - - if(hid_init() < 0) - return NULL; - - dev = new_hid_device(); - - libusb_get_device_list(usb_context, &devs); - while ((usb_dev = devs[d++]) != NULL) { - struct libusb_device_descriptor desc; - struct libusb_config_descriptor *conf_desc = NULL; - int i,j,k; - libusb_get_device_descriptor(usb_dev, &desc); - - if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) - continue; - for (j = 0; j < conf_desc->bNumInterfaces; j++) { - const struct libusb_interface *intf = &conf_desc->interface[j]; - for (k = 0; k < intf->num_altsetting; k++) { - const struct libusb_interface_descriptor *intf_desc; - intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); - if (!strcmp(dev_path, path)) { - /* Matched Paths. Open this device */ - - /* OPEN HERE */ - res = libusb_open(usb_dev, &dev->device_handle); - if (res < 0) { - LOG("can't open device\n"); - free(dev_path); - break; - } - good_open = 1; -#ifdef DETACH_KERNEL_DRIVER - /* Detach the kernel driver, but only if the - device is managed by the kernel */ - if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { - res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); - if (res < 0) { - libusb_close(dev->device_handle); - LOG("Unable to detach Kernel Driver\n"); - free(dev_path); - good_open = 0; - break; - } - } -#endif - res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); - if (res < 0) { - LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); - free(dev_path); - libusb_close(dev->device_handle); - good_open = 0; - break; - } - - /* Store off the string descriptor indexes */ - dev->manufacturer_index = desc.iManufacturer; - dev->product_index = desc.iProduct; - dev->serial_index = desc.iSerialNumber; - - /* Store off the interface number */ - dev->interface = intf_desc->bInterfaceNumber; - - /* Find the INPUT and OUTPUT endpoints. An - OUTPUT endpoint is not required. */ - for (i = 0; i < intf_desc->bNumEndpoints; i++) { - const struct libusb_endpoint_descriptor *ep - = &intf_desc->endpoint[i]; - - /* Determine the type and direction of this - endpoint. */ - int is_interrupt = - (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) - == LIBUSB_TRANSFER_TYPE_INTERRUPT; - int is_output = - (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_OUT; - int is_input = - (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_IN; - - /* Decide whether to use it for input or output. */ - if (dev->input_endpoint == 0 && - is_interrupt && is_input) { - /* Use this endpoint for INPUT */ - dev->input_endpoint = ep->bEndpointAddress; - dev->input_ep_max_packet_size = ep->wMaxPacketSize; - } - if (dev->output_endpoint == 0 && - is_interrupt && is_output) { - /* Use this endpoint for OUTPUT */ - dev->output_endpoint = ep->bEndpointAddress; - } - } - - pthread_create(&dev->thread, NULL, read_thread, dev); - - /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); - - } - free(dev_path); - } - } - } - libusb_free_config_descriptor(conf_desc); - - } - - libusb_free_device_list(devs, 1); - - /* If we have a good handle, return it. */ - if (good_open) { - return dev; - } - else { - /* Unable to open any devices. */ - free_hid_device(dev); - return NULL; - } -} - - -int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - int res; - int report_number = data[0]; - int skipped_report_id = 0; - - if (report_number == 0x0) { - data++; - length--; - skipped_report_id = 1; - } - - - if (dev->output_endpoint <= 0) { - /* No interrupt out endpoint. Use the Control Endpoint */ - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, - 0x09/*HID Set_Report*/, - (2/*HID output*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - if (skipped_report_id) - length++; - - return length; - } - else { - /* Use the interrupt out endpoint */ - int actual_length; - res = libusb_interrupt_transfer(dev->device_handle, - dev->output_endpoint, - (unsigned char*)data, - length, - &actual_length, 1000); - - if (res < 0) - return -1; - - if (skipped_report_id) - actual_length++; - - return actual_length; - } -} - -/* Helper function, to simplify hid_read(). - This should be called with dev->mutex locked. */ -static int return_data(hid_device *dev, unsigned char *data, size_t length) -{ - /* Copy the data out of the linked list item (rpt) into the - return buffer (data), and delete the liked list item. */ - struct input_report *rpt = dev->input_reports; - size_t len = (length < rpt->len)? length: rpt->len; - if (len > 0) - memcpy(data, rpt->data, len); - dev->input_reports = rpt->next; - free(rpt->data); - free(rpt); - return len; -} - -static void cleanup_mutex(void *param) -{ - hid_device *dev = param; - pthread_mutex_unlock(&dev->mutex); -} - - -int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - int bytes_read = -1; - -#if 0 - int transferred; - int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); - LOG("transferred: %d\n", transferred); - return transferred; -#endif - - pthread_mutex_lock(&dev->mutex); - pthread_cleanup_push(&cleanup_mutex, dev); - - /* There's an input report queued up. Return it. */ - if (dev->input_reports) { - /* Return the first one */ - bytes_read = return_data(dev, data, length); - goto ret; - } - - if (dev->shutdown_thread) { - /* This means the device has been disconnected. - An error code of -1 should be returned. */ - bytes_read = -1; - goto ret; - } - - if (milliseconds == -1) { - /* Blocking */ - while (!dev->input_reports && !dev->shutdown_thread) { - pthread_cond_wait(&dev->condition, &dev->mutex); - } - if (dev->input_reports) { - bytes_read = return_data(dev, data, length); - } - } - else if (milliseconds > 0) { - /* Non-blocking, but called with timeout. */ - int res; - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += milliseconds / 1000; - ts.tv_nsec += (milliseconds % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000L) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000L; - } - - while (!dev->input_reports && !dev->shutdown_thread) { - res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); - if (res == 0) { - if (dev->input_reports) { - bytes_read = return_data(dev, data, length); - break; - } - - /* If we're here, there was a spurious wake up - or the read thread was shutdown. Run the - loop again (ie: don't break). */ - } - else if (res == ETIMEDOUT) { - /* Timed out. */ - bytes_read = 0; - break; - } - else { - /* Error. */ - bytes_read = -1; - break; - } - } - } - else { - /* Purely non-blocking */ - bytes_read = 0; - } - -ret: - pthread_mutex_unlock(&dev->mutex); - pthread_cleanup_pop(0); - - return bytes_read; -} - -int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); -} - -int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) -{ - dev->blocking = !nonblock; - - return 0; -} - - -int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - int res = -1; - int skipped_report_id = 0; - int report_number = data[0]; - - if (report_number == 0x0) { - data++; - length--; - skipped_report_id = 1; - } - - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, - 0x09/*HID set_report*/, - (3/*HID feature*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - /* Account for the report ID */ - if (skipped_report_id) - length++; - - return length; -} - -int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - int res = -1; - int skipped_report_id = 0; - int report_number = data[0]; - - if (report_number == 0x0) { - /* Offset the return buffer by 1, so that the report ID - will remain in byte 0. */ - data++; - length--; - skipped_report_id = 1; - } - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, - 0x01/*HID get_report*/, - (3/*HID feature*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - if (skipped_report_id) - res++; - - return res; -} - - -void HID_API_EXPORT hid_close(hid_device *dev) -{ - if (!dev) - return; - - /* Cause read_thread() to stop. */ - dev->shutdown_thread = 1; - libusb_cancel_transfer(dev->transfer); - - /* Wait for read_thread() to end. */ - pthread_join(dev->thread, NULL); - - /* Clean up the Transfer objects allocated in read_thread(). */ - free(dev->transfer->buffer); - libusb_free_transfer(dev->transfer); - - /* release the interface */ - libusb_release_interface(dev->device_handle, dev->interface); - - /* Close the handle */ - libusb_close(dev->device_handle); - - /* Clear out the queue of received reports. */ - pthread_mutex_lock(&dev->mutex); - while (dev->input_reports) { - return_data(dev, NULL, 0); - } - pthread_mutex_unlock(&dev->mutex); - - free_hid_device(dev); -} - - -int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->product_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - wchar_t *str; - - str = get_usb_string(dev->device_handle, string_index); - if (str) { - wcsncpy(string, str, maxlen); - string[maxlen-1] = L'\0'; - free(str); - return 0; - } - else - return -1; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - return NULL; -} - - -struct lang_map_entry { - const char *name; - const char *string_code; - uint16_t usb_code; -}; - -#define LANG(name,code,usb_code) { name, code, usb_code } -static struct lang_map_entry lang_map[] = { - LANG("Afrikaans", "af", 0x0436), - LANG("Albanian", "sq", 0x041C), - LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), - LANG("Arabic - Bahrain", "ar_bh", 0x3C01), - LANG("Arabic - Algeria", "ar_dz", 0x1401), - LANG("Arabic - Egypt", "ar_eg", 0x0C01), - LANG("Arabic - Iraq", "ar_iq", 0x0801), - LANG("Arabic - Jordan", "ar_jo", 0x2C01), - LANG("Arabic - Kuwait", "ar_kw", 0x3401), - LANG("Arabic - Lebanon", "ar_lb", 0x3001), - LANG("Arabic - Libya", "ar_ly", 0x1001), - LANG("Arabic - Morocco", "ar_ma", 0x1801), - LANG("Arabic - Oman", "ar_om", 0x2001), - LANG("Arabic - Qatar", "ar_qa", 0x4001), - LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), - LANG("Arabic - Syria", "ar_sy", 0x2801), - LANG("Arabic - Tunisia", "ar_tn", 0x1C01), - LANG("Arabic - Yemen", "ar_ye", 0x2401), - LANG("Armenian", "hy", 0x042B), - LANG("Azeri - Latin", "az_az", 0x042C), - LANG("Azeri - Cyrillic", "az_az", 0x082C), - LANG("Basque", "eu", 0x042D), - LANG("Belarusian", "be", 0x0423), - LANG("Bulgarian", "bg", 0x0402), - LANG("Catalan", "ca", 0x0403), - LANG("Chinese - China", "zh_cn", 0x0804), - LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), - LANG("Chinese - Macau SAR", "zh_mo", 0x1404), - LANG("Chinese - Singapore", "zh_sg", 0x1004), - LANG("Chinese - Taiwan", "zh_tw", 0x0404), - LANG("Croatian", "hr", 0x041A), - LANG("Czech", "cs", 0x0405), - LANG("Danish", "da", 0x0406), - LANG("Dutch - Netherlands", "nl_nl", 0x0413), - LANG("Dutch - Belgium", "nl_be", 0x0813), - LANG("English - Australia", "en_au", 0x0C09), - LANG("English - Belize", "en_bz", 0x2809), - LANG("English - Canada", "en_ca", 0x1009), - LANG("English - Caribbean", "en_cb", 0x2409), - LANG("English - Ireland", "en_ie", 0x1809), - LANG("English - Jamaica", "en_jm", 0x2009), - LANG("English - New Zealand", "en_nz", 0x1409), - LANG("English - Phillippines", "en_ph", 0x3409), - LANG("English - Southern Africa", "en_za", 0x1C09), - LANG("English - Trinidad", "en_tt", 0x2C09), - LANG("English - Great Britain", "en_gb", 0x0809), - LANG("English - United States", "en_us", 0x0409), - LANG("Estonian", "et", 0x0425), - LANG("Farsi", "fa", 0x0429), - LANG("Finnish", "fi", 0x040B), - LANG("Faroese", "fo", 0x0438), - LANG("French - France", "fr_fr", 0x040C), - LANG("French - Belgium", "fr_be", 0x080C), - LANG("French - Canada", "fr_ca", 0x0C0C), - LANG("French - Luxembourg", "fr_lu", 0x140C), - LANG("French - Switzerland", "fr_ch", 0x100C), - LANG("Gaelic - Ireland", "gd_ie", 0x083C), - LANG("Gaelic - Scotland", "gd", 0x043C), - LANG("German - Germany", "de_de", 0x0407), - LANG("German - Austria", "de_at", 0x0C07), - LANG("German - Liechtenstein", "de_li", 0x1407), - LANG("German - Luxembourg", "de_lu", 0x1007), - LANG("German - Switzerland", "de_ch", 0x0807), - LANG("Greek", "el", 0x0408), - LANG("Hebrew", "he", 0x040D), - LANG("Hindi", "hi", 0x0439), - LANG("Hungarian", "hu", 0x040E), - LANG("Icelandic", "is", 0x040F), - LANG("Indonesian", "id", 0x0421), - LANG("Italian - Italy", "it_it", 0x0410), - LANG("Italian - Switzerland", "it_ch", 0x0810), - LANG("Japanese", "ja", 0x0411), - LANG("Korean", "ko", 0x0412), - LANG("Latvian", "lv", 0x0426), - LANG("Lithuanian", "lt", 0x0427), - LANG("F.Y.R.O. Macedonia", "mk", 0x042F), - LANG("Malay - Malaysia", "ms_my", 0x043E), - LANG("Malay – Brunei", "ms_bn", 0x083E), - LANG("Maltese", "mt", 0x043A), - LANG("Marathi", "mr", 0x044E), - LANG("Norwegian - Bokml", "no_no", 0x0414), - LANG("Norwegian - Nynorsk", "no_no", 0x0814), - LANG("Polish", "pl", 0x0415), - LANG("Portuguese - Portugal", "pt_pt", 0x0816), - LANG("Portuguese - Brazil", "pt_br", 0x0416), - LANG("Raeto-Romance", "rm", 0x0417), - LANG("Romanian - Romania", "ro", 0x0418), - LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), - LANG("Russian", "ru", 0x0419), - LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), - LANG("Sanskrit", "sa", 0x044F), - LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), - LANG("Serbian - Latin", "sr_sp", 0x081A), - LANG("Setsuana", "tn", 0x0432), - LANG("Slovenian", "sl", 0x0424), - LANG("Slovak", "sk", 0x041B), - LANG("Sorbian", "sb", 0x042E), - LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), - LANG("Spanish - Argentina", "es_ar", 0x2C0A), - LANG("Spanish - Bolivia", "es_bo", 0x400A), - LANG("Spanish - Chile", "es_cl", 0x340A), - LANG("Spanish - Colombia", "es_co", 0x240A), - LANG("Spanish - Costa Rica", "es_cr", 0x140A), - LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), - LANG("Spanish - Ecuador", "es_ec", 0x300A), - LANG("Spanish - Guatemala", "es_gt", 0x100A), - LANG("Spanish - Honduras", "es_hn", 0x480A), - LANG("Spanish - Mexico", "es_mx", 0x080A), - LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), - LANG("Spanish - Panama", "es_pa", 0x180A), - LANG("Spanish - Peru", "es_pe", 0x280A), - LANG("Spanish - Puerto Rico", "es_pr", 0x500A), - LANG("Spanish - Paraguay", "es_py", 0x3C0A), - LANG("Spanish - El Salvador", "es_sv", 0x440A), - LANG("Spanish - Uruguay", "es_uy", 0x380A), - LANG("Spanish - Venezuela", "es_ve", 0x200A), - LANG("Southern Sotho", "st", 0x0430), - LANG("Swahili", "sw", 0x0441), - LANG("Swedish - Sweden", "sv_se", 0x041D), - LANG("Swedish - Finland", "sv_fi", 0x081D), - LANG("Tamil", "ta", 0x0449), - LANG("Tatar", "tt", 0X0444), - LANG("Thai", "th", 0x041E), - LANG("Turkish", "tr", 0x041F), - LANG("Tsonga", "ts", 0x0431), - LANG("Ukrainian", "uk", 0x0422), - LANG("Urdu", "ur", 0x0420), - LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), - LANG("Uzbek – Latin", "uz_uz", 0x0443), - LANG("Vietnamese", "vi", 0x042A), - LANG("Xhosa", "xh", 0x0434), - LANG("Yiddish", "yi", 0x043D), - LANG("Zulu", "zu", 0x0435), - LANG(NULL, NULL, 0x0), -}; - -uint16_t get_usb_code_for_current_locale(void) -{ - char *locale; - char search_string[64]; - char *ptr; - struct lang_map_entry *lang; - - /* Get the current locale. */ - locale = setlocale(0, NULL); - if (!locale) - return 0x0; - - /* Make a copy of the current locale string. */ - strncpy(search_string, locale, sizeof(search_string)); - search_string[sizeof(search_string)-1] = '\0'; - - /* Chop off the encoding part, and make it lower case. */ - ptr = search_string; - while (*ptr) { - *ptr = tolower(*ptr); - if (*ptr == '.') { - *ptr = '\0'; - break; - } - ptr++; - } - - /* Find the entry which matches the string code of our locale. */ - lang = lang_map; - while (lang->string_code) { - if (!strcmp(lang->string_code, search_string)) { - return lang->usb_code; - } - lang++; - } - - /* There was no match. Find with just the language only. */ - /* Chop off the variant. Chop it off at the '_'. */ - ptr = search_string; - while (*ptr) { - *ptr = tolower(*ptr); - if (*ptr == '_') { - *ptr = '\0'; - break; - } - ptr++; - } - -#if 0 /* TODO: Do we need this? */ - /* Find the entry which matches the string code of our language. */ - lang = lang_map; - while (lang->string_code) { - if (!strcmp(lang->string_code, search_string)) { - return lang->usb_code; - } - lang++; - } -#endif - - /* Found nothing. */ - return 0x0; -} - -#ifdef __cplusplus -} -#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/mac/hid.c b/vendor/github.com/karalabe/usb/hidapi/mac/hid.c deleted file mode 100644 index e0756a1588..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/mac/hid.c +++ /dev/null @@ -1,1110 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 2010-07-03 - - Copyright 2010, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/* See Apple Technical Note TN2187 for details on IOHidManager. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hidapi.h" - -/* Barrier implementation because Mac OSX doesn't have pthread_barrier. - It also doesn't have clock_gettime(). So much for POSIX and SUSv2. - This implementation came from Brent Priddy and was posted on - StackOverflow. It is used with his permission. */ -typedef int pthread_barrierattr_t; -typedef struct pthread_barrier { - pthread_mutex_t mutex; - pthread_cond_t cond; - int count; - int trip_count; -} pthread_barrier_t; - -static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) -{ - if(count == 0) { - errno = EINVAL; - return -1; - } - - if(pthread_mutex_init(&barrier->mutex, 0) < 0) { - return -1; - } - if(pthread_cond_init(&barrier->cond, 0) < 0) { - pthread_mutex_destroy(&barrier->mutex); - return -1; - } - barrier->trip_count = count; - barrier->count = 0; - - return 0; -} - -static int pthread_barrier_destroy(pthread_barrier_t *barrier) -{ - pthread_cond_destroy(&barrier->cond); - pthread_mutex_destroy(&barrier->mutex); - return 0; -} - -static int pthread_barrier_wait(pthread_barrier_t *barrier) -{ - pthread_mutex_lock(&barrier->mutex); - ++(barrier->count); - if(barrier->count >= barrier->trip_count) - { - barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return 1; - } - else - { - pthread_cond_wait(&barrier->cond, &(barrier->mutex)); - pthread_mutex_unlock(&barrier->mutex); - return 0; - } -} - -static int return_data(hid_device *dev, unsigned char *data, size_t length); - -/* Linked List of input reports received from the device. */ -struct input_report { - uint8_t *data; - size_t len; - struct input_report *next; -}; - -struct hid_device_ { - IOHIDDeviceRef device_handle; - int blocking; - int uses_numbered_reports; - int disconnected; - CFStringRef run_loop_mode; - CFRunLoopRef run_loop; - CFRunLoopSourceRef source; - uint8_t *input_report_buf; - CFIndex max_input_report_len; - struct input_report *input_reports; - - pthread_t thread; - pthread_mutex_t mutex; /* Protects input_reports */ - pthread_cond_t condition; - pthread_barrier_t barrier; /* Ensures correct startup sequence */ - pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ - int shutdown_thread; -}; - -static hid_device *new_hid_device(void) -{ - hid_device *dev = calloc(1, sizeof(hid_device)); - dev->device_handle = NULL; - dev->blocking = 1; - dev->uses_numbered_reports = 0; - dev->disconnected = 0; - dev->run_loop_mode = NULL; - dev->run_loop = NULL; - dev->source = NULL; - dev->input_report_buf = NULL; - dev->input_reports = NULL; - dev->shutdown_thread = 0; - - /* Thread objects */ - pthread_mutex_init(&dev->mutex, NULL); - pthread_cond_init(&dev->condition, NULL); - pthread_barrier_init(&dev->barrier, NULL, 2); - pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - if (!dev) - return; - - /* Delete any input reports still left over. */ - struct input_report *rpt = dev->input_reports; - while (rpt) { - struct input_report *next = rpt->next; - free(rpt->data); - free(rpt); - rpt = next; - } - - /* Free the string and the report buffer. The check for NULL - is necessary here as CFRelease() doesn't handle NULL like - free() and others do. */ - if (dev->run_loop_mode) - CFRelease(dev->run_loop_mode); - if (dev->source) - CFRelease(dev->source); - free(dev->input_report_buf); - - /* Clean up the thread objects */ - pthread_barrier_destroy(&dev->shutdown_barrier); - pthread_barrier_destroy(&dev->barrier); - pthread_cond_destroy(&dev->condition); - pthread_mutex_destroy(&dev->mutex); - - /* Free the structure itself. */ - free(dev); -} - -static IOHIDManagerRef hid_mgr = 0x0; - - -#if 0 -static void register_error(hid_device *device, const char *op) -{ - -} -#endif - - -static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) -{ - CFTypeRef ref; - int32_t value; - - ref = IOHIDDeviceGetProperty(device, key); - if (ref) { - if (CFGetTypeID(ref) == CFNumberGetTypeID()) { - CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); - return value; - } - } - return 0; -} - -static unsigned short get_vendor_id(IOHIDDeviceRef device) -{ - return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); -} - -static unsigned short get_product_id(IOHIDDeviceRef device) -{ - return get_int_property(device, CFSTR(kIOHIDProductIDKey)); -} - -static int32_t get_max_report_length(IOHIDDeviceRef device) -{ - return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); -} - -static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) -{ - CFStringRef str; - - if (!len) - return 0; - - str = IOHIDDeviceGetProperty(device, prop); - - buf[0] = 0; - - if (str) { - CFIndex str_len = CFStringGetLength(str); - CFRange range; - CFIndex used_buf_len; - CFIndex chars_copied; - - len --; - - range.location = 0; - range.length = ((size_t)str_len > len)? len: (size_t)str_len; - chars_copied = CFStringGetBytes(str, - range, - kCFStringEncodingUTF32LE, - (char)'?', - FALSE, - (UInt8*)buf, - len * sizeof(wchar_t), - &used_buf_len); - - if (chars_copied == len) - buf[len] = 0; /* len is decremented above */ - else - buf[chars_copied] = 0; - - return 0; - } - else - return -1; - -} - -static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) -{ - return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); -} - -static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) -{ - return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); -} - -static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) -{ - return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); -} - - -/* Implementation of wcsdup() for Mac. */ -static wchar_t *dup_wcs(const wchar_t *s) -{ - size_t len = wcslen(s); - wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); - wcscpy(ret, s); - - return ret; -} - -/* hidapi_IOHIDDeviceGetService() - * - * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by: - * - on OS X 10.6 and above, calling IOHIDDeviceGetService() - * - on OS X 10.5, extract it from the IOHIDDevice struct - */ -static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device) -{ - static void *iokit_framework = NULL; - static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL; - - /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists. - * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL - * and the fallback method will be used. - */ - if (iokit_framework == NULL) { - iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY); - - if (iokit_framework != NULL) - dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService"); - } - - if (dynamic_IOHIDDeviceGetService != NULL) { - /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */ - return dynamic_IOHIDDeviceGetService(device); - } - else - { - /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist. - * - * Be naughty and pull the service out of the IOHIDDevice. - * IOHIDDevice is an opaque struct not exposed to applications, but its - * layout is stable through all available versions of OS X. - * Tested and working on OS X 10.5.8 i386, x86_64, and ppc. - */ - struct IOHIDDevice_internal { - /* The first field of the IOHIDDevice struct is a - * CFRuntimeBase (which is a private CF struct). - * - * a, b, and c are the 3 fields that make up a CFRuntimeBase. - * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h - * - * The second field of the IOHIDDevice is the io_service_t we're looking for. - */ - uintptr_t a; - uint8_t b[4]; -#if __LP64__ - uint32_t c; -#endif - io_service_t service; - }; - struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device; - - return tmp->service; - } -} - -/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ -static int init_hid_manager(void) -{ - /* Initialize all the HID Manager Objects */ - hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_mgr) { - IOHIDManagerSetDeviceMatching(hid_mgr, NULL); - IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - return 0; - } - - return -1; -} - -/* Initialize the IOHIDManager if necessary. This is the public function, and - it is safe to call this function repeatedly. Return 0 for success and -1 - for failure. */ -int HID_API_EXPORT hid_init(void) -{ - if (!hid_mgr) { - return init_hid_manager(); - } - - /* Already initialized. */ - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ - if (hid_mgr) { - /* Close the HID manager. */ - IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); - CFRelease(hid_mgr); - hid_mgr = NULL; - } - - return 0; -} - -static void process_pending_events(void) { - SInt32 res; - do { - res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); - } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); -} - -struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - CFIndex num_devices; - int i; - - /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) - return NULL; - - /* give the IOHIDManager a chance to update itself */ - process_pending_events(); - - /* Get a list of the Devices */ - IOHIDManagerSetDeviceMatching(hid_mgr, NULL); - CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); - - /* Convert the list into a C array so we can iterate easily. */ - num_devices = CFSetGetCount(device_set); - IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(device_set, (const void **) device_array); - - /* Iterate over each device, making an entry for it. */ - for (i = 0; i < num_devices; i++) { - unsigned short dev_vid; - unsigned short dev_pid; - #define BUF_LEN 256 - wchar_t buf[BUF_LEN]; - - IOHIDDeviceRef dev = device_array[i]; - - if (!dev) { - continue; - } - dev_vid = get_vendor_id(dev); - dev_pid = get_product_id(dev); - - /* Check the VID/PID against the arguments */ - if ((vendor_id == 0x0 || vendor_id == dev_vid) && - (product_id == 0x0 || product_id == dev_pid)) { - struct hid_device_info *tmp; - io_object_t iokit_dev; - kern_return_t res; - io_string_t path; - - /* VID/PID match. Create the record. */ - tmp = malloc(sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Get the Usage Page and Usage for this device. */ - cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); - cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); - - /* Fill out the record */ - cur_dev->next = NULL; - - /* Fill in the path (IOService plane) */ - iokit_dev = hidapi_IOHIDDeviceGetService(dev); - res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); - if (res == KERN_SUCCESS) - cur_dev->path = strdup(path); - else - cur_dev->path = strdup(""); - - /* Serial Number */ - get_serial_number(dev, buf, BUF_LEN); - cur_dev->serial_number = dup_wcs(buf); - - /* Manufacturer and Product strings */ - get_manufacturer_string(dev, buf, BUF_LEN); - cur_dev->manufacturer_string = dup_wcs(buf); - get_product_string(dev, buf, BUF_LEN); - cur_dev->product_string = dup_wcs(buf); - - /* VID/PID */ - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - - /* Release Number */ - cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); - - /* Interface Number (Unsupported on Mac)*/ - cur_dev->interface_number = -1; - } - } - - free(device_array); - CFRelease(device_set); - - return root; -} - -void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) -{ - /* This function is identical to the Linux version. Platform independent. */ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - -hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - /* This function is identical to the Linux version. Platform independent. */ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device * handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -static void hid_device_removal_callback(void *context, IOReturn result, - void *sender) -{ - /* Stop the Run Loop for this device. */ - hid_device *d = context; - - d->disconnected = 1; - CFRunLoopStop(d->run_loop); -} - -/* The Run Loop calls this function for each input report received. - This function puts the data into a linked list to be picked up by - hid_read(). */ -static void hid_report_callback(void *context, IOReturn result, void *sender, - IOHIDReportType report_type, uint32_t report_id, - uint8_t *report, CFIndex report_length) -{ - struct input_report *rpt; - hid_device *dev = context; - - /* Make a new Input Report object */ - rpt = calloc(1, sizeof(struct input_report)); - rpt->data = calloc(1, report_length); - memcpy(rpt->data, report, report_length); - rpt->len = report_length; - rpt->next = NULL; - - /* Lock this section */ - pthread_mutex_lock(&dev->mutex); - - /* Attach the new report object to the end of the list. */ - if (dev->input_reports == NULL) { - /* The list is empty. Put it at the root. */ - dev->input_reports = rpt; - } - else { - /* Find the end of the list and attach. */ - struct input_report *cur = dev->input_reports; - int num_queued = 0; - while (cur->next != NULL) { - cur = cur->next; - num_queued++; - } - cur->next = rpt; - - /* Pop one off if we've reached 30 in the queue. This - way we don't grow forever if the user never reads - anything from the device. */ - if (num_queued > 30) { - return_data(dev, NULL, 0); - } - } - - /* Signal a waiting thread that there is data. */ - pthread_cond_signal(&dev->condition); - - /* Unlock */ - pthread_mutex_unlock(&dev->mutex); - -} - -/* This gets called when the read_thread's run loop gets signaled by - hid_close(), and serves to stop the read_thread's run loop. */ -static void perform_signal_callback(void *context) -{ - hid_device *dev = context; - CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ -} - -static void *read_thread(void *param) -{ - hid_device *dev = param; - SInt32 code; - - /* Move the device's run loop to this thread. */ - IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); - - /* Create the RunLoopSource which is used to signal the - event loop to stop when hid_close() is called. */ - CFRunLoopSourceContext ctx; - memset(&ctx, 0, sizeof(ctx)); - ctx.version = 0; - ctx.info = dev; - ctx.perform = &perform_signal_callback; - dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); - CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); - - /* Store off the Run Loop so it can be stopped from hid_close() - and on device disconnection. */ - dev->run_loop = CFRunLoopGetCurrent(); - - /* Notify the main thread that the read thread is up and running. */ - pthread_barrier_wait(&dev->barrier); - - /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input - reports into the hid_report_callback(). */ - while (!dev->shutdown_thread && !dev->disconnected) { - code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); - /* Return if the device has been disconnected */ - if (code == kCFRunLoopRunFinished) { - dev->disconnected = 1; - break; - } - - - /* Break if The Run Loop returns Finished or Stopped. */ - if (code != kCFRunLoopRunTimedOut && - code != kCFRunLoopRunHandledSource) { - /* There was some kind of error. Setting - shutdown seems to make sense, but - there may be something else more appropriate */ - dev->shutdown_thread = 1; - break; - } - } - - /* Now that the read thread is stopping, Wake any threads which are - waiting on data (in hid_read_timeout()). Do this under a mutex to - make sure that a thread which is about to go to sleep waiting on - the condition actually will go to sleep before the condition is - signaled. */ - pthread_mutex_lock(&dev->mutex); - pthread_cond_broadcast(&dev->condition); - pthread_mutex_unlock(&dev->mutex); - - /* Wait here until hid_close() is called and makes it past - the call to CFRunLoopWakeUp(). This thread still needs to - be valid when that function is called on the other thread. */ - pthread_barrier_wait(&dev->shutdown_barrier); - - return NULL; -} - -/* hid_open_path() - * - * path must be a valid path to an IOHIDDevice in the IOService plane - * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver" - */ -hid_device * HID_API_EXPORT hid_open_path(const char *path) -{ - hid_device *dev = NULL; - io_registry_entry_t entry = MACH_PORT_NULL; - - dev = new_hid_device(); - - /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) - return NULL; - - /* Get the IORegistry entry for the given path */ - entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); - if (entry == MACH_PORT_NULL) { - /* Path wasn't valid (maybe device was removed?) */ - goto return_error; - } - - /* Create an IOHIDDevice for the entry */ - dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); - if (dev->device_handle == NULL) { - /* Error creating the HID device */ - goto return_error; - } - - /* Open the IOHIDDevice */ - IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); - if (ret == kIOReturnSuccess) { - char str[32]; - - /* Create the buffers for receiving data */ - dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); - dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); - - /* Create the Run Loop Mode for this device. - printing the reference seems to work. */ - sprintf(str, "HIDAPI_%p", dev->device_handle); - dev->run_loop_mode = - CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); - - /* Attach the device to a Run Loop */ - IOHIDDeviceRegisterInputReportCallback( - dev->device_handle, dev->input_report_buf, dev->max_input_report_len, - &hid_report_callback, dev); - IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); - - /* Start the read thread */ - pthread_create(&dev->thread, NULL, read_thread, dev); - - /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); - - IOObjectRelease(entry); - return dev; - } - else { - goto return_error; - } - -return_error: - if (dev->device_handle != NULL) - CFRelease(dev->device_handle); - - if (entry != MACH_PORT_NULL) - IOObjectRelease(entry); - - free_hid_device(dev); - return NULL; -} - -static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) -{ - const unsigned char *data_to_send; - size_t length_to_send; - IOReturn res; - - /* Return if the device has been disconnected. */ - if (dev->disconnected) - return -1; - - if (data[0] == 0x0) { - /* Not using numbered Reports. - Don't send the report number. */ - data_to_send = data+1; - length_to_send = length-1; - } - else { - /* Using numbered Reports. - Send the Report Number */ - data_to_send = data; - length_to_send = length; - } - - if (!dev->disconnected) { - res = IOHIDDeviceSetReport(dev->device_handle, - type, - data[0], /* Report ID*/ - data_to_send, length_to_send); - - if (res == kIOReturnSuccess) { - return length; - } - else - return -1; - } - - return -1; -} - -int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - return set_report(dev, kIOHIDReportTypeOutput, data, length); -} - -/* Helper function, so that this isn't duplicated in hid_read(). */ -static int return_data(hid_device *dev, unsigned char *data, size_t length) -{ - /* Copy the data out of the linked list item (rpt) into the - return buffer (data), and delete the liked list item. */ - struct input_report *rpt = dev->input_reports; - size_t len = (length < rpt->len)? length: rpt->len; - memcpy(data, rpt->data, len); - dev->input_reports = rpt->next; - free(rpt->data); - free(rpt); - return len; -} - -static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - while (!dev->input_reports) { - int res = pthread_cond_wait(cond, mutex); - if (res != 0) - return res; - - /* A res of 0 means we may have been signaled or it may - be a spurious wakeup. Check to see that there's acutally - data in the queue before returning, and if not, go back - to sleep. See the pthread_cond_timedwait() man page for - details. */ - - if (dev->shutdown_thread || dev->disconnected) - return -1; - } - - return 0; -} - -static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) -{ - while (!dev->input_reports) { - int res = pthread_cond_timedwait(cond, mutex, abstime); - if (res != 0) - return res; - - /* A res of 0 means we may have been signaled or it may - be a spurious wakeup. Check to see that there's acutally - data in the queue before returning, and if not, go back - to sleep. See the pthread_cond_timedwait() man page for - details. */ - - if (dev->shutdown_thread || dev->disconnected) - return -1; - } - - return 0; - -} - -int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - int bytes_read = -1; - - /* Lock the access to the report list. */ - pthread_mutex_lock(&dev->mutex); - - /* There's an input report queued up. Return it. */ - if (dev->input_reports) { - /* Return the first one */ - bytes_read = return_data(dev, data, length); - goto ret; - } - - /* Return if the device has been disconnected. */ - if (dev->disconnected) { - bytes_read = -1; - goto ret; - } - - if (dev->shutdown_thread) { - /* This means the device has been closed (or there - has been an error. An error code of -1 should - be returned. */ - bytes_read = -1; - goto ret; - } - - /* There is no data. Go to sleep and wait for data. */ - - if (milliseconds == -1) { - /* Blocking */ - int res; - res = cond_wait(dev, &dev->condition, &dev->mutex); - if (res == 0) - bytes_read = return_data(dev, data, length); - else { - /* There was an error, or a device disconnection. */ - bytes_read = -1; - } - } - else if (milliseconds > 0) { - /* Non-blocking, but called with timeout. */ - int res; - struct timespec ts; - struct timeval tv; - gettimeofday(&tv, NULL); - TIMEVAL_TO_TIMESPEC(&tv, &ts); - ts.tv_sec += milliseconds / 1000; - ts.tv_nsec += (milliseconds % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000L) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000L; - } - - res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); - if (res == 0) - bytes_read = return_data(dev, data, length); - else if (res == ETIMEDOUT) - bytes_read = 0; - else - bytes_read = -1; - } - else { - /* Purely non-blocking */ - bytes_read = 0; - } - -ret: - /* Unlock */ - pthread_mutex_unlock(&dev->mutex); - return bytes_read; -} - -int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); -} - -int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) -{ - /* All Nonblocking operation is handled by the library. */ - dev->blocking = !nonblock; - - return 0; -} - -int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - return set_report(dev, kIOHIDReportTypeFeature, data, length); -} - -int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - CFIndex len = length; - IOReturn res; - - /* Return if the device has been unplugged. */ - if (dev->disconnected) - return -1; - - res = IOHIDDeviceGetReport(dev->device_handle, - kIOHIDReportTypeFeature, - data[0], /* Report ID */ - data, &len); - if (res == kIOReturnSuccess) - return len; - else - return -1; -} - - -void HID_API_EXPORT hid_close(hid_device *dev) -{ - if (!dev) - return; - - /* Disconnect the report callback before close. */ - if (!dev->disconnected) { - IOHIDDeviceRegisterInputReportCallback( - dev->device_handle, dev->input_report_buf, dev->max_input_report_len, - NULL, dev); - IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); - IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); - IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); - } - - /* Cause read_thread() to stop. */ - dev->shutdown_thread = 1; - - /* Wake up the run thread's event loop so that the thread can exit. */ - CFRunLoopSourceSignal(dev->source); - CFRunLoopWakeUp(dev->run_loop); - - /* Notify the read thread that it can shut down now. */ - pthread_barrier_wait(&dev->shutdown_barrier); - - /* Wait for read_thread() to end. */ - pthread_join(dev->thread, NULL); - - /* Close the OS handle to the device, but only if it's not - been unplugged. If it's been unplugged, then calling - IOHIDDeviceClose() will crash. */ - if (!dev->disconnected) { - IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); - } - - /* Clear out the queue of received reports. */ - pthread_mutex_lock(&dev->mutex); - while (dev->input_reports) { - return_data(dev, NULL, 0); - } - pthread_mutex_unlock(&dev->mutex); - CFRelease(dev->device_handle); - - free_hid_device(dev); -} - -int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return get_manufacturer_string(dev->device_handle, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return get_product_string(dev->device_handle, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return get_serial_number(dev->device_handle, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - /* TODO: */ - - return 0; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - /* TODO: */ - - return NULL; -} - - - - - - - -#if 0 -static int32_t get_location_id(IOHIDDeviceRef device) -{ - return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); -} - -static int32_t get_usage(IOHIDDeviceRef device) -{ - int32_t res; - res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); - if (!res) - res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); - return res; -} - -static int32_t get_usage_page(IOHIDDeviceRef device) -{ - int32_t res; - res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); - if (!res) - res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); - return res; -} - -static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) -{ - return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); -} - - -int main(void) -{ - IOHIDManagerRef mgr; - int i; - - mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - IOHIDManagerSetDeviceMatching(mgr, NULL); - IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); - - CFSetRef device_set = IOHIDManagerCopyDevices(mgr); - - CFIndex num_devices = CFSetGetCount(device_set); - IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(device_set, (const void **) device_array); - - for (i = 0; i < num_devices; i++) { - IOHIDDeviceRef dev = device_array[i]; - printf("Device: %p\n", dev); - printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); - - wchar_t serial[256], buf[256]; - char cbuf[256]; - get_serial_number(dev, serial, 256); - - - printf(" Serial: %ls\n", serial); - printf(" Loc: %ld\n", get_location_id(dev)); - get_transport(dev, buf, 256); - printf(" Trans: %ls\n", buf); - make_path(dev, cbuf, 256); - printf(" Path: %s\n", cbuf); - - } - - return 0; -} -#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/windows/hid.c b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c deleted file mode 100644 index 4e92cc8bc9..0000000000 --- a/vendor/github.com/karalabe/usb/hidapi/windows/hid.c +++ /dev/null @@ -1,944 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -#include - -#ifndef _NTDEF_ -typedef LONG NTSTATUS; -#endif - -#ifdef __MINGW32__ -#include -#include -#endif - -#ifdef __CYGWIN__ -#include -#define _wcsdup wcsdup -#endif - -/* The maximum number of characters that can be passed into the - HidD_Get*String() functions without it failing.*/ -#define MAX_STRING_WCHARS 0xFFF - -/*#define HIDAPI_USE_DDK*/ - -#ifdef __cplusplus -extern "C" { -#endif - #include - #include - #ifdef HIDAPI_USE_DDK - #include - #endif - - /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ - #define HID_OUT_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#include -#include - - -#include "hidapi.h" - -#undef MIN -#define MIN(x,y) ((x) < (y)? (x): (y)) - -#ifdef _MSC_VER - /* Thanks Microsoft, but I know how to use strncpy(). */ - #pragma warning(disable:4996) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef HIDAPI_USE_DDK - /* Since we're not building with the DDK, and the HID header - files aren't part of the SDK, we have to define all this - stuff here. In lookup_functions(), the function pointers - defined below are set. */ - typedef struct _HIDD_ATTRIBUTES{ - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; - } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - typedef USHORT USAGE; - typedef struct _HIDP_CAPS { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT fields_not_used_by_hidapi[10]; - } HIDP_CAPS, *PHIDP_CAPS; - typedef void* PHIDP_PREPARSED_DATA; - #define HIDP_STATUS_SUCCESS 0x110000 - - typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); - typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); - typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); - typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); - typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); - - static HidD_GetAttributes_ HidD_GetAttributes; - static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; - static HidD_GetManufacturerString_ HidD_GetManufacturerString; - static HidD_GetProductString_ HidD_GetProductString; - static HidD_SetFeature_ HidD_SetFeature; - static HidD_GetFeature_ HidD_GetFeature; - static HidD_GetIndexedString_ HidD_GetIndexedString; - static HidD_GetPreparsedData_ HidD_GetPreparsedData; - static HidD_FreePreparsedData_ HidD_FreePreparsedData; - static HidP_GetCaps_ HidP_GetCaps; - static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; - - static HMODULE lib_handle = NULL; - static BOOLEAN initialized = FALSE; -#endif /* HIDAPI_USE_DDK */ - -struct hid_device_ { - HANDLE device_handle; - BOOL blocking; - USHORT output_report_length; - size_t input_report_length; - void *last_error_str; - DWORD last_error_num; - BOOL read_pending; - char *read_buf; - OVERLAPPED ol; -}; - -static hid_device *new_hid_device() -{ - hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); - dev->device_handle = INVALID_HANDLE_VALUE; - dev->blocking = TRUE; - dev->output_report_length = 0; - dev->input_report_length = 0; - dev->last_error_str = NULL; - dev->last_error_num = 0; - dev->read_pending = FALSE; - dev->read_buf = NULL; - memset(&dev->ol, 0, sizeof(dev->ol)); - dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - CloseHandle(dev->ol.hEvent); - CloseHandle(dev->device_handle); - LocalFree(dev->last_error_str); - free(dev->read_buf); - free(dev); -} - -static void register_error(hid_device *device, const char *op) -{ - WCHAR *ptr, *msg; - - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPVOID)&msg, 0/*sz*/, - NULL); - - /* Get rid of the CR and LF that FormatMessage() sticks at the - end of the message. Thanks Microsoft! */ - ptr = msg; - while (*ptr) { - if (*ptr == '\r') { - *ptr = 0x0000; - break; - } - ptr++; - } - - /* Store the message off in the Device entry so that - the hid_error() function can pick it up. */ - LocalFree(device->last_error_str); - device->last_error_str = msg; -} - -#ifndef HIDAPI_USE_DDK -static int lookup_functions() -{ - lib_handle = LoadLibraryA("hid.dll"); - if (lib_handle) { -#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; - RESOLVE(HidD_GetAttributes); - RESOLVE(HidD_GetSerialNumberString); - RESOLVE(HidD_GetManufacturerString); - RESOLVE(HidD_GetProductString); - RESOLVE(HidD_SetFeature); - RESOLVE(HidD_GetFeature); - RESOLVE(HidD_GetIndexedString); - RESOLVE(HidD_GetPreparsedData); - RESOLVE(HidD_FreePreparsedData); - RESOLVE(HidP_GetCaps); - RESOLVE(HidD_SetNumInputBuffers); -#undef RESOLVE - } - else - return -1; - - return 0; -} -#endif - -static HANDLE open_device(const char *path, BOOL enumerate) -{ - HANDLE handle; - DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); - DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; - - handle = CreateFileA(path, - desired_access, - share_mode, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ - 0); - - return handle; -} - -int HID_API_EXPORT hid_init(void) -{ -#ifndef HIDAPI_USE_DDK - if (!initialized) { - if (lookup_functions() < 0) { - hid_exit(); - return -1; - } - initialized = TRUE; - } -#endif - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ -#ifndef HIDAPI_USE_DDK - if (lib_handle) - FreeLibrary(lib_handle); - lib_handle = NULL; - initialized = FALSE; -#endif - return 0; -} - -struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - BOOL res; - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - - /* Windows objects for interacting with the driver. */ - GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; - SP_DEVINFO_DATA devinfo_data; - SP_DEVICE_INTERFACE_DATA device_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; - HDEVINFO device_info_set = INVALID_HANDLE_VALUE; - int device_index = 0; - int i; - - if (hid_init() < 0) - return NULL; - - /* Initialize the Windows objects. */ - memset(&devinfo_data, 0x0, sizeof(devinfo_data)); - devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); - device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - /* Get information for all the devices belonging to the HID class. */ - device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - - /* Iterate over each device in the HID class, looking for the right one. */ - - for (;;) { - HANDLE write_handle = INVALID_HANDLE_VALUE; - DWORD required_size = 0; - HIDD_ATTRIBUTES attrib; - - res = SetupDiEnumDeviceInterfaces(device_info_set, - NULL, - &InterfaceClassGuid, - device_index, - &device_interface_data); - - if (!res) { - /* A return of FALSE from this function means that - there are no more devices. */ - break; - } - - /* Call with 0-sized detail size, and let the function - tell us how long the detail struct needs to be. The - size is put in &required_size. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - NULL, - 0, - &required_size, - NULL); - - /* Allocate a long enough structure for device_interface_detail_data. */ - device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); - device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - - /* Get the detailed data for this device. The detail data gives us - the device path for this device, which is then passed into - CreateFile() to get a handle to the device. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - device_interface_detail_data, - required_size, - NULL, - NULL); - - if (!res) { - /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); - Continue to the next device. */ - goto cont; - } - - /* Make sure this device is of Setup Class "HIDClass" and has a - driver bound to it. */ - for (i = 0; ; i++) { - char driver_name[256]; - - /* Populate devinfo_data. This function will return failure - when there are no more interfaces left. */ - res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); - if (!res) - goto cont; - - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (!res) - goto cont; - - if (strcmp(driver_name, "HIDClass") == 0) { - /* See if there's a driver bound. */ - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (res) - break; - } - } - - //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); - - /* Open a handle to the device */ - write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); - - /* Check validity of write_handle. */ - if (write_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - //register_error(dev, "CreateFile"); - goto cont_close; - } - - - /* Get the Vendor ID and Product ID for this device. */ - attrib.Size = sizeof(HIDD_ATTRIBUTES); - HidD_GetAttributes(write_handle, &attrib); - //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); - - /* Check the VID/PID to see if we should add this - device to the enumeration list. */ - if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && - (product_id == 0x0 || attrib.ProductID == product_id)) { - - #define WSTR_LEN 512 - const char *str; - struct hid_device_info *tmp; - PHIDP_PREPARSED_DATA pp_data = NULL; - HIDP_CAPS caps; - BOOLEAN res; - NTSTATUS nt_res; - wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ - size_t len; - - /* VID/PID match. Create the record. */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Get the Usage Page and Usage for this device. */ - res = HidD_GetPreparsedData(write_handle, &pp_data); - if (res) { - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res == HIDP_STATUS_SUCCESS) { - cur_dev->usage_page = caps.UsagePage; - cur_dev->usage = caps.Usage; - } - - HidD_FreePreparsedData(pp_data); - } - - /* Fill out the record */ - cur_dev->next = NULL; - str = device_interface_detail_data->DevicePath; - if (str) { - len = strlen(str); - cur_dev->path = (char*) calloc(len+1, sizeof(char)); - strncpy(cur_dev->path, str, sizeof(cur_dev->path)); - cur_dev->path[len] = '\0'; - } - else - cur_dev->path = NULL; - - /* Serial Number */ - res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->serial_number = _wcsdup(wstr); - } - - /* Manufacturer String */ - res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->manufacturer_string = _wcsdup(wstr); - } - - /* Product String */ - res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->product_string = _wcsdup(wstr); - } - - /* VID/PID */ - cur_dev->vendor_id = attrib.VendorID; - cur_dev->product_id = attrib.ProductID; - - /* Release Number */ - cur_dev->release_number = attrib.VersionNumber; - - /* Interface Number. It can sometimes be parsed out of the path - on Windows if a device has multiple interfaces. See - http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or - search for "Hardware IDs for HID Devices" at MSDN. If it's not - in the path, it's set to -1. */ - cur_dev->interface_number = -1; - if (cur_dev->path) { - char *interface_component = strstr(cur_dev->path, "&mi_"); - if (interface_component) { - char *hex_str = interface_component + 4; - char *endptr = NULL; - cur_dev->interface_number = strtol(hex_str, &endptr, 16); - if (endptr == hex_str) { - /* The parsing failed. Set interface_number to -1. */ - cur_dev->interface_number = -1; - } - } - } - } - -cont_close: - CloseHandle(write_handle); -cont: - /* We no longer need the detail data. It can be freed */ - free(device_interface_detail_data); - - device_index++; - - } - - /* Close the device information handle. */ - SetupDiDestroyDeviceInfoList(device_info_set); - - return root; - -} - -void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) -{ - /* TODO: Merge this with the Linux version. This function is platform-independent. */ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - - -HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) -{ - hid_device *dev; - HIDP_CAPS caps; - PHIDP_PREPARSED_DATA pp_data = NULL; - BOOLEAN res; - NTSTATUS nt_res; - - if (hid_init() < 0) { - return NULL; - } - - dev = new_hid_device(); - - /* Open a handle to the device */ - dev->device_handle = open_device(path, FALSE); - - /* Check validity of write_handle. */ - if (dev->device_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - register_error(dev, "CreateFile"); - goto err; - } - - /* Set the Input Report buffer size to 64 reports. */ - res = HidD_SetNumInputBuffers(dev->device_handle, 64); - if (!res) { - register_error(dev, "HidD_SetNumInputBuffers"); - goto err; - } - - /* Get the Input Report length for the device. */ - res = HidD_GetPreparsedData(dev->device_handle, &pp_data); - if (!res) { - register_error(dev, "HidD_GetPreparsedData"); - goto err; - } - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); - goto err_pp_data; - } - dev->output_report_length = caps.OutputReportByteLength; - dev->input_report_length = caps.InputReportByteLength; - HidD_FreePreparsedData(pp_data); - - dev->read_buf = (char*) malloc(dev->input_report_length); - - return dev; - -err_pp_data: - HidD_FreePreparsedData(pp_data); -err: - free_hid_device(dev); - return NULL; -} - -int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - DWORD bytes_written; - BOOL res; - - OVERLAPPED ol; - unsigned char *buf; - memset(&ol, 0, sizeof(ol)); - - /* Make sure the right number of bytes are passed to WriteFile. Windows - expects the number of bytes which are in the _longest_ report (plus - one for the report number) bytes even if the data is a report - which is shorter than that. Windows gives us this value in - caps.OutputReportByteLength. If a user passes in fewer bytes than this, - create a temporary buffer which is the proper size. */ - if (length >= dev->output_report_length) { - /* The user passed the right number of bytes. Use the buffer as-is. */ - buf = (unsigned char *) data; - } else { - /* Create a temporary buffer and copy the user's data - into it, padding the rest with zeros. */ - buf = (unsigned char *) malloc(dev->output_report_length); - memcpy(buf, data, length); - memset(buf + length, 0, dev->output_report_length - length); - length = dev->output_report_length; - } - - res = WriteFile(dev->device_handle, buf, length, NULL, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* WriteFile() failed. Return error. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - } - - /* Wait here until the write is done. This makes - hid_write() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); - if (!res) { - /* The Write operation failed. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - -end_of_function: - if (buf != data) - free(buf); - - return bytes_written; -} - - -int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - DWORD bytes_read = 0; - size_t copy_len = 0; - BOOL res; - - /* Copy the handle for convenience. */ - HANDLE ev = dev->ol.hEvent; - - if (!dev->read_pending) { - /* Start an Overlapped I/O read. */ - dev->read_pending = TRUE; - memset(dev->read_buf, 0, dev->input_report_length); - ResetEvent(ev); - res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* ReadFile() has failed. - Clean up and return error. */ - CancelIo(dev->device_handle); - dev->read_pending = FALSE; - goto end_of_function; - } - } - } - - if (milliseconds >= 0) { - /* See if there is any data yet. */ - res = WaitForSingleObject(ev, milliseconds); - if (res != WAIT_OBJECT_0) { - /* There was no data this time. Return zero bytes available, - but leave the Overlapped I/O running. */ - return 0; - } - } - - /* Either WaitForSingleObject() told us that ReadFile has completed, or - we are in non-blocking mode. Get the number of bytes read. The actual - data has been copied to the data[] array which was passed to ReadFile(). */ - res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - - /* Set pending back to false, even if GetOverlappedResult() returned error. */ - dev->read_pending = FALSE; - - if (res && bytes_read > 0) { - if (dev->read_buf[0] == 0x0) { - /* If report numbers aren't being used, but Windows sticks a report - number (0x0) on the beginning of the report anyway. To make this - work like the other platforms, and to make it work more like the - HID spec, we'll skip over this byte. */ - bytes_read--; - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf+1, copy_len); - } - else { - /* Copy the whole buffer, report number and all. */ - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf, copy_len); - } - } - -end_of_function: - if (!res) { - register_error(dev, "GetOverlappedResult"); - return -1; - } - - return copy_len; -} - -int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); -} - -int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) -{ - dev->blocking = !nonblock; - return 0; /* Success */ -} - -int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length); - if (!res) { - register_error(dev, "HidD_SetFeature"); - return -1; - } - - return length; -} - - -int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - BOOL res; -#if 0 - res = HidD_GetFeature(dev->device_handle, data, length); - if (!res) { - register_error(dev, "HidD_GetFeature"); - return -1; - } - return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ -#else - DWORD bytes_returned; - - OVERLAPPED ol; - memset(&ol, 0, sizeof(ol)); - - res = DeviceIoControl(dev->device_handle, - IOCTL_HID_GET_FEATURE, - data, length, - data, length, - &bytes_returned, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* DeviceIoControl() failed. Return error. */ - register_error(dev, "Send Feature Report DeviceIoControl"); - return -1; - } - } - - /* Wait here until the write is done. This makes - hid_get_feature_report() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); - if (!res) { - /* The operation failed. */ - register_error(dev, "Send Feature Report GetOverLappedResult"); - return -1; - } - - /* bytes_returned does not include the first byte which contains the - report ID. The data buffer actually contains one more byte than - bytes_returned. */ - bytes_returned++; - - return bytes_returned; -#endif -} - -void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) -{ - if (!dev) - return; - CancelIo(dev->device_handle); - free_hid_device(dev); -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); - if (!res) { - register_error(dev, "HidD_GetManufacturerString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); - if (!res) { - register_error(dev, "HidD_GetProductString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); - if (!res) { - register_error(dev, "HidD_GetSerialNumberString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); - if (!res) { - register_error(dev, "HidD_GetIndexedString"); - return -1; - } - - return 0; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - return (wchar_t*)dev->last_error_str; -} - - -/*#define PICPGM*/ -/*#define S11*/ -#define P32 -#ifdef S11 - unsigned short VendorID = 0xa0a0; - unsigned short ProductID = 0x0001; -#endif - -#ifdef P32 - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x3f; -#endif - - -#ifdef PICPGM - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x0033; -#endif - - -#if 0 -int __cdecl main(int argc, char* argv[]) -{ - int res; - unsigned char buf[65]; - - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - /* Set up the command buffer. */ - memset(buf,0x00,sizeof(buf)); - buf[0] = 0; - buf[1] = 0x81; - - - /* Open the device. */ - int handle = open(VendorID, ProductID, L"12345"); - if (handle < 0) - printf("unable to open device\n"); - - - /* Toggle LED (cmd 0x80) */ - buf[1] = 0x80; - res = write(handle, buf, 65); - if (res < 0) - printf("Unable to write()\n"); - - /* Request state (cmd 0x81) */ - buf[1] = 0x81; - write(handle, buf, 65); - if (res < 0) - printf("Unable to write() (2)\n"); - - /* Read requested state */ - read(handle, buf, 65); - if (res < 0) - printf("Unable to read()\n"); - - /* Print out the returned buffer. */ - for (int i = 0; i < 4; i++) - printf("buf[%d]: %d\n", i, buf[i]); - - return 0; -} -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/AUTHORS b/vendor/github.com/karalabe/usb/libusb/AUTHORS deleted file mode 100644 index e90ad9bb2a..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/AUTHORS +++ /dev/null @@ -1,119 +0,0 @@ -Copyright © 2001 Johannes Erdfelt -Copyright © 2007-2009 Daniel Drake -Copyright © 2010-2012 Peter Stuge -Copyright © 2008-2016 Nathan Hjelm -Copyright © 2009-2013 Pete Batard -Copyright © 2009-2013 Ludovic Rousseau -Copyright © 2010-2012 Michael Plante -Copyright © 2011-2013 Hans de Goede -Copyright © 2012-2013 Martin Pieuchot -Copyright © 2012-2013 Toby Gray -Copyright © 2013-2018 Chris Dickens - -Other contributors: -Adrian Bunk -Akshay Jaggi -Alan Ott -Alan Stern -Alex Vatchenko -Andrew Fernandes -Andy Chunyu -Andy McFadden -Angus Gratton -Anil Nair -Anthony Clay -Antonio Ospite -Artem Egorkine -Aurelien Jarno -Bastien Nocera -Bei Zhang -Benjamin Dobell -Brent Rector -Carl Karsten -Christophe Zeitouny -Colin Walters -Dave Camarillo -David Engraf -David Moore -Davidlohr Bueso -Dmitry Fleytman -Doug Johnston -Evan Hunter -Federico Manzan -Felipe Balbi -Florian Albrechtskirchinger -Francesco Montorsi -Francisco Facioni -Gaurav Gupta -Graeme Gill -Gustavo Zacarias -Hans Ulrich Niedermann -Hector Martin -Hoi-Ho Chan -Ilya Konstantinov -Jakub Klama -James Hanko -Jeffrey Nichols -Johann Richard -John Sheu -Jonathon Jongsma -Joost Muller -Josh Gao -Joshua Blake -Justin Bischoff -KIMURA Masaru -Karsten Koenig -Konrad Rzepecki -Kuangye Guo -Lars Kanis -Lars Wirzenius -Lei Chen -Luca Longinotti -Marcus Meissner -Markus Heidelberg -Martin Ettl -Martin Koegler -Matthew Stapleton -Matthias Bolte -Michel Zou -Mike Frysinger -Mikhail Gusarov -Morgan Leborgne -Moritz Fischer -Ларионов Даниил -Nicholas Corgan -Omri Iluz -Orin Eman -Paul Fertser -Pekka Nikander -Rob Walker -Romain Vimont -Roman Kalashnikov -Sameeh Jubran -Sean McBride -Sebastian Pipping -Sergey Serb -Simon Haggett -Simon Newton -Stefan Agner -Stefan Tauner -Steinar H. Gunderson -Thomas Röfer -Tim Hutt -Tim Roberts -Tobias Klauser -Toby Peterson -Tormod Volden -Trygve Laugstøl -Uri Lublin -Vasily Khoruzhick -Vegard Storheil Eriksen -Venkatesh Shukla -Vianney le Clément de Saint-Marcq -Victor Toso -Vitali Lovich -William Skellenger -Xiaofan Chen -Zoltán Kovács -Роман Донченко -parafin diff --git a/vendor/github.com/karalabe/usb/libusb/COPYING b/vendor/github.com/karalabe/usb/libusb/COPYING deleted file mode 100644 index 5ab7695ab8..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/config.h b/vendor/github.com/karalabe/usb/libusb/libusb/config.h deleted file mode 100644 index e004f03cd4..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/config.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/core.c b/vendor/github.com/karalabe/usb/libusb/libusb/core.c deleted file mode 100644 index 50f92f6b1b..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/core.c +++ /dev/null @@ -1,2579 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Core functions for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2007-2008 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYSLOG_H -#include -#endif - -#ifdef __ANDROID__ -#include -#endif - -#include "libusbi.h" -#include "hotplug.h" - -struct libusb_context *usbi_default_context = NULL; -static const struct libusb_version libusb_version_internal = - { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, - LIBUSB_RC, "http://libusb.info" }; -static int default_context_refcnt = 0; -static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; -static struct timespec timestamp_origin = { 0, 0 }; - -usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER; -struct list_head active_contexts_list; - -/** - * \mainpage libusb-1.0 API Reference - * - * \section intro Introduction - * - * libusb is an open source library that allows you to communicate with USB - * devices from userspace. For more info, see the - * libusb homepage. - * - * This documentation is aimed at application developers wishing to - * communicate with USB peripherals from their own software. After reviewing - * this documentation, feedback and questions can be sent to the - * libusb-devel mailing list. - * - * This documentation assumes knowledge of how to operate USB devices from - * a software standpoint (descriptors, configurations, interfaces, endpoints, - * control/bulk/interrupt/isochronous transfers, etc). Full information - * can be found in the USB 3.0 - * Specification which is available for free download. You can probably - * find less verbose introductions by searching the web. - * - * \section API Application Programming Interface (API) - * - * See the \ref libusb_api page for a complete list of the libusb functions. - * - * \section features Library features - * - * - All transfer types supported (control/bulk/interrupt/isochronous) - * - 2 transfer interfaces: - * -# Synchronous (simple) - * -# Asynchronous (more complicated, but more powerful) - * - Thread safe (although the asynchronous interface means that you - * usually won't need to thread) - * - Lightweight with lean API - * - Compatible with libusb-0.1 through the libusb-compat-0.1 translation layer - * - Hotplug support (on some platforms). See \ref libusb_hotplug. - * - * \section gettingstarted Getting Started - * - * To begin reading the API documentation, start with the Modules page which - * links to the different categories of libusb's functionality. - * - * One decision you will have to make is whether to use the synchronous - * or the asynchronous data transfer interface. The \ref libusb_io documentation - * provides some insight into this topic. - * - * Some example programs can be found in the libusb source distribution under - * the "examples" subdirectory. The libusb homepage includes a list of - * real-life project examples which use libusb. - * - * \section errorhandling Error handling - * - * libusb functions typically return 0 on success or a negative error code - * on failure. These negative error codes relate to LIBUSB_ERROR constants - * which are listed on the \ref libusb_misc "miscellaneous" documentation page. - * - * \section msglog Debug message logging - * - * libusb uses stderr for all logging. By default, logging is set to NONE, - * which means that no output will be produced. However, unless the library - * has been compiled with logging disabled, then any application calls to - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the - * environmental variable LIBUSB_DEBUG outside of the application, can result - * in logging being produced. Your application should therefore not close - * stderr, but instead direct it to the null device if its output is - * undesirable. - * - * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be - * used to enable logging of certain messages. Under standard configuration, - * libusb doesn't really log much so you are advised to use this function - * to enable all error/warning/ informational messages. It will help debug - * problems with your software. - * - * The logged messages are unstructured. There is no one-to-one correspondence - * between messages being logged and success or failure return codes from - * libusb functions. There is no format to the messages, so you should not - * try to capture or parse them. They are not and will not be localized. - * These messages are not intended to being passed to your application user; - * instead, you should interpret the error codes returned from libusb functions - * and provide appropriate notification to the user. The messages are simply - * there to aid you as a programmer, and if you're confused because you're - * getting a strange error code from a libusb function, enabling message - * logging may give you a suitable explanation. - * - * The LIBUSB_DEBUG environment variable can be used to enable message logging - * at run-time. This environment variable should be set to a log level number, - * which is interpreted the same as the - * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this - * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does - * nothing. - * - * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) - * and the LIBUSB_DEBUG environment variable have no effects. - * - * libusb can also be compiled with verbose debugging messages always. When - * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and - * the LIBUSB_DEBUG environment variable have no effects. - * - * \section remarks Other remarks - * - * libusb does have imperfections. The \ref libusb_caveats "caveats" page attempts - * to document these. - */ - -/** - * \page libusb_caveats Caveats - * - * \section fork Fork considerations - * - * libusb is not designed to work across fork() calls. Depending on - * the platform, there may be resources in the parent process that are not - * available to the child (e.g. the hotplug monitor thread on Linux). In - * addition, since the parent and child will share libusb's internal file - * descriptors, using libusb in any way from the child could cause the parent - * process's \ref libusb_context to get into an inconsistent state. - * - * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means - * that it is safe to fork() and exec() without worrying about the child - * process needing to clean up state or having access to these file descriptors. - * Other platforms may not be so forgiving, so consider yourself warned! - * - * \section devresets Device resets - * - * The libusb_reset_device() function allows you to reset a device. If your - * program has to call such a function, it should obviously be aware that - * the reset will cause device state to change (e.g. register values may be - * reset). - * - * The problem is that any other program could reset the device your program - * is working with, at any time. libusb does not offer a mechanism to inform - * you when this has happened, so if someone else resets your device it will - * not be clear to your own program why the device state has changed. - * - * Ultimately, this is a limitation of writing drivers in userspace. - * Separation from the USB stack in the underlying kernel makes it difficult - * for the operating system to deliver such notifications to your program. - * The Linux kernel USB stack allows such reset notifications to be delivered - * to in-kernel USB drivers, but it is not clear how such notifications could - * be delivered to second-class drivers that live in userspace. - * - * \section blockonly Blocking-only functionality - * - * The functionality listed below is only available through synchronous, - * blocking functions. There are no asynchronous/non-blocking alternatives, - * and no clear ways of implementing these. - * - * - Configuration activation (libusb_set_configuration()) - * - Interface/alternate setting activation (libusb_set_interface_alt_setting()) - * - Releasing of interfaces (libusb_release_interface()) - * - Clearing of halt/stall condition (libusb_clear_halt()) - * - Device resets (libusb_reset_device()) - * - * \section configsel Configuration selection and handling - * - * When libusb presents a device handle to an application, there is a chance - * that the corresponding device may be in unconfigured state. For devices - * with multiple configurations, there is also a chance that the configuration - * currently selected is not the one that the application wants to use. - * - * The obvious solution is to add a call to libusb_set_configuration() early - * on during your device initialization routines, but there are caveats to - * be aware of: - * -# If the device is already in the desired configuration, calling - * libusb_set_configuration() using the same configuration value will cause - * a lightweight device reset. This may not be desirable behaviour. - * -# In the case where the desired configuration is already active, libusb - * may not even be able to perform a lightweight device reset. For example, - * take my USB keyboard with fingerprint reader: I'm interested in driving - * the fingerprint reader interface through libusb, but the kernel's - * USB-HID driver will almost always have claimed the keyboard interface. - * Because the kernel has claimed an interface, it is not even possible to - * perform the lightweight device reset, so libusb_set_configuration() will - * fail. (Luckily the device in question only has a single configuration.) - * -# libusb will be unable to set a configuration if other programs or - * drivers have claimed interfaces. In particular, this means that kernel - * drivers must be detached from all the interfaces before - * libusb_set_configuration() may succeed. - * - * One solution to some of the above problems is to consider the currently - * active configuration. If the configuration we want is already active, then - * we don't have to select any configuration: -\code -cfg = -1; -libusb_get_configuration(dev, &cfg); -if (cfg != desired) - libusb_set_configuration(dev, desired); -\endcode - * - * This is probably suitable for most scenarios, but is inherently racy: - * another application or driver may change the selected configuration - * after the libusb_get_configuration() call. - * - * Even in cases where libusb_set_configuration() succeeds, consider that other - * applications or drivers may change configuration after your application - * calls libusb_set_configuration(). - * - * One possible way to lock your device into a specific configuration is as - * follows: - * -# Set the desired configuration (or use the logic above to realise that - * it is already in the desired configuration) - * -# Claim the interface that you wish to use - * -# Check that the currently active configuration is the one that you want - * to use. - * - * The above method works because once an interface is claimed, no application - * or driver is able to select another configuration. - * - * \section earlycomp Early transfer completion - * - * NOTE: This section is currently Linux-centric. I am not sure if any of these - * considerations apply to Darwin or other platforms. - * - * When a transfer completes early (i.e. when less data is received/sent in - * any one packet than the transfer buffer allows for) then libusb is designed - * to terminate the transfer immediately, not transferring or receiving any - * more data unless other transfers have been queued by the user. - * - * On legacy platforms, libusb is unable to do this in all situations. After - * the incomplete packet occurs, "surplus" data may be transferred. For recent - * versions of libusb, this information is kept (the data length of the - * transfer is updated) and, for device-to-host transfers, any surplus data was - * added to the buffer. Still, this is not a nice solution because it loses the - * information about the end of the short packet, and the user probably wanted - * that surplus data to arrive in the next logical transfer. - * - * \section zlp Zero length packets - * - * - libusb is able to send a packet of zero length to an endpoint simply by - * submitting a transfer of zero length. - * - The \ref libusb_transfer_flags::LIBUSB_TRANSFER_ADD_ZERO_PACKET - * "LIBUSB_TRANSFER_ADD_ZERO_PACKET" flag is currently only supported on Linux. - */ - -/** - * \page libusb_contexts Contexts - * - * It is possible that libusb may be used simultaneously from two independent - * libraries linked into the same executable. For example, if your application - * has a plugin-like system which allows the user to dynamically load a range - * of modules into your program, it is feasible that two independently - * developed modules may both use libusb. - * - * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_option() calls - * from one user will not affect the same settings for other users, other - * users can continue using libusb after one of them calls libusb_exit(), etc. - * - * This is made possible through libusb's context concept. When you - * call libusb_init(), you are (optionally) given a context. You can then pass - * this context pointer back into future libusb functions. - * - * In order to keep things simple for more simplistic applications, it is - * legal to pass NULL to all functions requiring a context pointer (as long as - * you're sure no other code will attempt to use libusb from the same process). - * When you pass NULL, the default context will be used. The default context - * is created the first time a process calls libusb_init() when no other - * context is alive. Contexts are destroyed during libusb_exit(). - * - * The default context is reference-counted and can be shared. That means that - * if libusb_init(NULL) is called twice within the same process, the two - * users end up sharing the same context. The deinitialization and freeing of - * the default context will only happen when the last user calls libusb_exit(). - * In other words, the default context is created and initialized when its - * reference count goes from 0 to 1, and is deinitialized and destroyed when - * its reference count goes from 1 to 0. - * - * You may be wondering why only a subset of libusb functions require a - * context pointer in their function definition. Internally, libusb stores - * context pointers in other objects (e.g. libusb_device instances) and hence - * can infer the context from those objects. - */ - - /** - * \page libusb_api Application Programming Interface - * - * This is the complete list of libusb functions, structures and - * enumerations in alphabetical order. - * - * \section Functions - * - libusb_alloc_streams() - * - libusb_alloc_transfer() - * - libusb_attach_kernel_driver() - * - libusb_bulk_transfer() - * - libusb_cancel_transfer() - * - libusb_claim_interface() - * - libusb_clear_halt() - * - libusb_close() - * - libusb_control_transfer() - * - libusb_control_transfer_get_data() - * - libusb_control_transfer_get_setup() - * - libusb_cpu_to_le16() - * - libusb_detach_kernel_driver() - * - libusb_dev_mem_alloc() - * - libusb_dev_mem_free() - * - libusb_error_name() - * - libusb_event_handler_active() - * - libusb_event_handling_ok() - * - libusb_exit() - * - libusb_fill_bulk_stream_transfer() - * - libusb_fill_bulk_transfer() - * - libusb_fill_control_setup() - * - libusb_fill_control_transfer() - * - libusb_fill_interrupt_transfer() - * - libusb_fill_iso_transfer() - * - libusb_free_bos_descriptor() - * - libusb_free_config_descriptor() - * - libusb_free_container_id_descriptor() - * - libusb_free_device_list() - * - libusb_free_pollfds() - * - libusb_free_ss_endpoint_companion_descriptor() - * - libusb_free_ss_usb_device_capability_descriptor() - * - libusb_free_streams() - * - libusb_free_transfer() - * - libusb_free_usb_2_0_extension_descriptor() - * - libusb_get_active_config_descriptor() - * - libusb_get_bos_descriptor() - * - libusb_get_bus_number() - * - libusb_get_config_descriptor() - * - libusb_get_config_descriptor_by_value() - * - libusb_get_configuration() - * - libusb_get_container_id_descriptor() - * - libusb_get_descriptor() - * - libusb_get_device() - * - libusb_get_device_address() - * - libusb_get_device_descriptor() - * - libusb_get_device_list() - * - libusb_get_device_speed() - * - libusb_get_iso_packet_buffer() - * - libusb_get_iso_packet_buffer_simple() - * - libusb_get_max_iso_packet_size() - * - libusb_get_max_packet_size() - * - libusb_get_next_timeout() - * - libusb_get_parent() - * - libusb_get_pollfds() - * - libusb_get_port_number() - * - libusb_get_port_numbers() - * - libusb_get_port_path() - * - libusb_get_ss_endpoint_companion_descriptor() - * - libusb_get_ss_usb_device_capability_descriptor() - * - libusb_get_string_descriptor() - * - libusb_get_string_descriptor_ascii() - * - libusb_get_usb_2_0_extension_descriptor() - * - libusb_get_version() - * - libusb_handle_events() - * - libusb_handle_events_completed() - * - libusb_handle_events_locked() - * - libusb_handle_events_timeout() - * - libusb_handle_events_timeout_completed() - * - libusb_has_capability() - * - libusb_hotplug_deregister_callback() - * - libusb_hotplug_register_callback() - * - libusb_init() - * - libusb_interrupt_event_handler() - * - libusb_interrupt_transfer() - * - libusb_kernel_driver_active() - * - libusb_lock_events() - * - libusb_lock_event_waiters() - * - libusb_open() - * - libusb_open_device_with_vid_pid() - * - libusb_pollfds_handle_timeouts() - * - libusb_ref_device() - * - libusb_release_interface() - * - libusb_reset_device() - * - libusb_set_auto_detach_kernel_driver() - * - libusb_set_configuration() - * - libusb_set_debug() - * - libusb_set_interface_alt_setting() - * - libusb_set_iso_packet_lengths() - * - libusb_set_option() - * - libusb_setlocale() - * - libusb_set_pollfd_notifiers() - * - libusb_strerror() - * - libusb_submit_transfer() - * - libusb_transfer_get_stream_id() - * - libusb_transfer_set_stream_id() - * - libusb_try_lock_events() - * - libusb_unlock_events() - * - libusb_unlock_event_waiters() - * - libusb_unref_device() - * - libusb_wait_for_event() - * - * \section Structures - * - libusb_bos_descriptor - * - libusb_bos_dev_capability_descriptor - * - libusb_config_descriptor - * - libusb_container_id_descriptor - * - \ref libusb_context - * - libusb_control_setup - * - \ref libusb_device - * - libusb_device_descriptor - * - \ref libusb_device_handle - * - libusb_endpoint_descriptor - * - libusb_interface - * - libusb_interface_descriptor - * - libusb_iso_packet_descriptor - * - libusb_pollfd - * - libusb_ss_endpoint_companion_descriptor - * - libusb_ss_usb_device_capability_descriptor - * - libusb_transfer - * - libusb_usb_2_0_extension_descriptor - * - libusb_version - * - * \section Enums - * - \ref libusb_bos_type - * - \ref libusb_capability - * - \ref libusb_class_code - * - \ref libusb_descriptor_type - * - \ref libusb_endpoint_direction - * - \ref libusb_error - * - \ref libusb_iso_sync_type - * - \ref libusb_iso_usage_type - * - \ref libusb_log_level - * - \ref libusb_option - * - \ref libusb_request_recipient - * - \ref libusb_request_type - * - \ref libusb_speed - * - \ref libusb_ss_usb_device_capability_attributes - * - \ref libusb_standard_request - * - \ref libusb_supported_speed - * - \ref libusb_transfer_flags - * - \ref libusb_transfer_status - * - \ref libusb_transfer_type - * - \ref libusb_usb_2_0_extension_attributes - */ - -/** - * @defgroup libusb_lib Library initialization/deinitialization - * This page details how to initialize and deinitialize libusb. Initialization - * must be performed before using any libusb functionality, and similarly you - * must not call any libusb functions after deinitialization. - */ - -/** - * @defgroup libusb_dev Device handling and enumeration - * The functionality documented below is designed to help with the following - * operations: - * - Enumerating the USB devices currently attached to the system - * - Choosing a device to operate from your software - * - Opening and closing the chosen device - * - * \section nutshell In a nutshell... - * - * The description below really makes things sound more complicated than they - * actually are. The following sequence of function calls will be suitable - * for almost all scenarios and does not require you to have such a deep - * understanding of the resource management issues: - * \code -// discover devices -libusb_device **list; -libusb_device *found = NULL; -ssize_t cnt = libusb_get_device_list(NULL, &list); -ssize_t i = 0; -int err = 0; -if (cnt < 0) - error(); - -for (i = 0; i < cnt; i++) { - libusb_device *device = list[i]; - if (is_interesting(device)) { - found = device; - break; - } -} - -if (found) { - libusb_device_handle *handle; - - err = libusb_open(found, &handle); - if (err) - error(); - // etc -} - -libusb_free_device_list(list, 1); -\endcode - * - * The two important points: - * - You asked libusb_free_device_list() to unreference the devices (2nd - * parameter) - * - You opened the device before freeing the list and unreferencing the - * devices - * - * If you ended up with a handle, you can now proceed to perform I/O on the - * device. - * - * \section devshandles Devices and device handles - * libusb has a concept of a USB device, represented by the - * \ref libusb_device opaque type. A device represents a USB device that - * is currently or was previously connected to the system. Using a reference - * to a device, you can determine certain information about the device (e.g. - * you can read the descriptor data). - * - * The libusb_get_device_list() function can be used to obtain a list of - * devices currently connected to the system. This is known as device - * discovery. - * - * Just because you have a reference to a device does not mean it is - * necessarily usable. The device may have been unplugged, you may not have - * permission to operate such device, or another program or driver may be - * using the device. - * - * When you've found a device that you'd like to operate, you must ask - * libusb to open the device using the libusb_open() function. Assuming - * success, libusb then returns you a device handle - * (a \ref libusb_device_handle pointer). All "real" I/O operations then - * operate on the handle rather than the original device pointer. - * - * \section devref Device discovery and reference counting - * - * Device discovery (i.e. calling libusb_get_device_list()) returns a - * freshly-allocated list of devices. The list itself must be freed when - * you are done with it. libusb also needs to know when it is OK to free - * the contents of the list - the devices themselves. - * - * To handle these issues, libusb provides you with two separate items: - * - A function to free the list itself - * - A reference counting system for the devices inside - * - * New devices presented by the libusb_get_device_list() function all have a - * reference count of 1. You can increase and decrease reference count using - * libusb_ref_device() and libusb_unref_device(). A device is destroyed when - * its reference count reaches 0. - * - * With the above information in mind, the process of opening a device can - * be viewed as follows: - * -# Discover devices using libusb_get_device_list(). - * -# Choose the device that you want to operate, and call libusb_open(). - * -# Unref all devices in the discovered device list. - * -# Free the discovered device list. - * - * The order is important - you must not unreference the device before - * attempting to open it, because unreferencing it may destroy the device. - * - * For convenience, the libusb_free_device_list() function includes a - * parameter to optionally unreference all the devices in the list before - * freeing the list itself. This combines steps 3 and 4 above. - * - * As an implementation detail, libusb_open() actually adds a reference to - * the device in question. This is because the device remains available - * through the handle via libusb_get_device(). The reference is deleted during - * libusb_close(). - */ - -/** @defgroup libusb_misc Miscellaneous */ - -/* we traverse usbfs without knowing how many devices we are going to find. - * so we create this discovered_devs model which is similar to a linked-list - * which grows when required. it can be freed once discovery has completed, - * eliminating the need for a list node in the libusb_device structure - * itself. */ -#define DISCOVERED_DEVICES_SIZE_STEP 8 - -static struct discovered_devs *discovered_devs_alloc(void) -{ - struct discovered_devs *ret = - malloc(sizeof(*ret) + (sizeof(void *) * DISCOVERED_DEVICES_SIZE_STEP)); - - if (ret) { - ret->len = 0; - ret->capacity = DISCOVERED_DEVICES_SIZE_STEP; - } - return ret; -} - -static void discovered_devs_free(struct discovered_devs *discdevs) -{ - size_t i; - - for (i = 0; i < discdevs->len; i++) - libusb_unref_device(discdevs->devices[i]); - - free(discdevs); -} - -/* append a device to the discovered devices collection. may realloc itself, - * returning new discdevs. returns NULL on realloc failure. */ -struct discovered_devs *discovered_devs_append( - struct discovered_devs *discdevs, struct libusb_device *dev) -{ - size_t len = discdevs->len; - size_t capacity; - struct discovered_devs *new_discdevs; - - /* if there is space, just append the device */ - if (len < discdevs->capacity) { - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; - return discdevs; - } - - /* exceeded capacity, need to grow */ - usbi_dbg("need to increase capacity"); - capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP; - /* can't use usbi_reallocf here because in failure cases it would - * free the existing discdevs without unreferencing its devices. */ - new_discdevs = realloc(discdevs, - sizeof(*discdevs) + (sizeof(void *) * capacity)); - if (!new_discdevs) { - discovered_devs_free(discdevs); - return NULL; - } - - discdevs = new_discdevs; - discdevs->capacity = capacity; - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; - - return discdevs; -} - -/* Allocate a new device with a specific session ID. The returned device has - * a reference count of 1. */ -struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, - unsigned long session_id) -{ - size_t priv_size = usbi_backend.device_priv_size; - struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size); - int r; - - if (!dev) - return NULL; - - r = usbi_mutex_init(&dev->lock); - if (r) { - free(dev); - return NULL; - } - - dev->ctx = ctx; - dev->refcnt = 1; - dev->session_data = session_id; - dev->speed = LIBUSB_SPEED_UNKNOWN; - - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_connect_device (dev); - } - - return dev; -} - -void usbi_connect_device(struct libusb_device *dev) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - - dev->attached = 1; - - usbi_mutex_lock(&dev->ctx->usb_devs_lock); - list_add(&dev->list, &dev->ctx->usb_devs); - usbi_mutex_unlock(&dev->ctx->usb_devs_lock); - - /* Signal that an event has occurred for this device if we support hotplug AND - * the hotplug message list is ready. This prevents an event from getting raised - * during initial enumeration. */ - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { - usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED); - } -} - -void usbi_disconnect_device(struct libusb_device *dev) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - - usbi_mutex_lock(&dev->lock); - dev->attached = 0; - usbi_mutex_unlock(&dev->lock); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_del(&dev->list); - usbi_mutex_unlock(&ctx->usb_devs_lock); - - /* Signal that an event has occurred for this device if we support hotplug AND - * the hotplug message list is ready. This prevents an event from getting raised - * during initial enumeration. libusb_handle_events will take care of dereferencing - * the device. */ - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { - usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT); - } -} - -/* Perform some final sanity checks on a newly discovered device. If this - * function fails (negative return code), the device should not be added - * to the discovered device list. */ -int usbi_sanitize_device(struct libusb_device *dev) -{ - int r; - uint8_t num_configurations; - - r = usbi_device_cache_descriptor(dev); - if (r < 0) - return r; - - num_configurations = dev->device_descriptor.bNumConfigurations; - if (num_configurations > USB_MAXCONFIG) { - usbi_err(DEVICE_CTX(dev), "too many configurations"); - return LIBUSB_ERROR_IO; - } else if (0 == num_configurations) - usbi_dbg("zero configurations, maybe an unauthorized device"); - - dev->num_configurations = num_configurations; - return 0; -} - -/* Examine libusb's internal list of known devices, looking for one with - * a specific session ID. Returns the matching device if it was found, and - * NULL otherwise. */ -struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, - unsigned long session_id) -{ - struct libusb_device *dev; - struct libusb_device *ret = NULL; - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) - if (dev->session_data == session_id) { - ret = libusb_ref_device(dev); - break; - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - return ret; -} - -/** @ingroup libusb_dev - * Returns a list of USB devices currently attached to the system. This is - * your entry point into finding a USB device to operate. - * - * You are expected to unreference all the devices when you are done with - * them, and then free the list with libusb_free_device_list(). Note that - * libusb_free_device_list() can unref all the devices for you. Be careful - * not to unreference a device you are about to open until after you have - * opened it. - * - * This return value of this function indicates the number of devices in - * the resultant list. The list is actually one element larger, as it is - * NULL-terminated. - * - * \param ctx the context to operate on, or NULL for the default context - * \param list output location for a list of devices. Must be later freed with - * libusb_free_device_list(). - * \returns the number of devices in the outputted list, or any - * \ref libusb_error according to errors encountered by the backend. - */ -ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, - libusb_device ***list) -{ - struct discovered_devs *discdevs = discovered_devs_alloc(); - struct libusb_device **ret; - int r = 0; - ssize_t i, len; - USBI_GET_CONTEXT(ctx); - usbi_dbg(""); - - if (!discdevs) - return LIBUSB_ERROR_NO_MEM; - - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - /* backend provides hotplug support */ - struct libusb_device *dev; - - if (usbi_backend.hotplug_poll) - usbi_backend.hotplug_poll(); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { - discdevs = discovered_devs_append(discdevs, dev); - - if (!discdevs) { - r = LIBUSB_ERROR_NO_MEM; - break; - } - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - } else { - /* backend does not provide hotplug support */ - r = usbi_backend.get_device_list(ctx, &discdevs); - } - - if (r < 0) { - len = r; - goto out; - } - - /* convert discovered_devs into a list */ - len = discdevs->len; - ret = calloc(len + 1, sizeof(struct libusb_device *)); - if (!ret) { - len = LIBUSB_ERROR_NO_MEM; - goto out; - } - - ret[len] = NULL; - for (i = 0; i < len; i++) { - struct libusb_device *dev = discdevs->devices[i]; - ret[i] = libusb_ref_device(dev); - } - *list = ret; - -out: - if (discdevs) - discovered_devs_free(discdevs); - return len; -} - -/** \ingroup libusb_dev - * Frees a list of devices previously discovered using - * libusb_get_device_list(). If the unref_devices parameter is set, the - * reference count of each device in the list is decremented by 1. - * \param list the list to free - * \param unref_devices whether to unref the devices in the list - */ -void API_EXPORTED libusb_free_device_list(libusb_device **list, - int unref_devices) -{ - if (!list) - return; - - if (unref_devices) { - int i = 0; - struct libusb_device *dev; - - while ((dev = list[i++]) != NULL) - libusb_unref_device(dev); - } - free(list); -} - -/** \ingroup libusb_dev - * Get the number of the bus that a device is connected to. - * \param dev a device - * \returns the bus number - */ -uint8_t API_EXPORTED libusb_get_bus_number(libusb_device *dev) -{ - return dev->bus_number; -} - -/** \ingroup libusb_dev - * Get the number of the port that a device is connected to. - * Unless the OS does something funky, or you are hot-plugging USB extension cards, - * the port number returned by this call is usually guaranteed to be uniquely tied - * to a physical port, meaning that different devices plugged on the same physical - * port should return the same port number. - * - * But outside of this, there is no guarantee that the port number returned by this - * call will remain the same, or even match the order in which ports have been - * numbered by the HUB/HCD manufacturer. - * - * \param dev a device - * \returns the port number (0 if not available) - */ -uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) -{ - return dev->port_number; -} - -/** \ingroup libusb_dev - * Get the list of all port numbers from root for the specified device - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * \param dev a device - * \param port_numbers the array that should contain the port numbers - * \param port_numbers_len the maximum length of the array. As per the USB 3.0 - * specs, the current maximum limit for the depth is 7. - * \returns the number of elements filled - * \returns LIBUSB_ERROR_OVERFLOW if the array is too small - */ -int API_EXPORTED libusb_get_port_numbers(libusb_device *dev, - uint8_t* port_numbers, int port_numbers_len) -{ - int i = port_numbers_len; - struct libusb_context *ctx = DEVICE_CTX(dev); - - if (port_numbers_len <= 0) - return LIBUSB_ERROR_INVALID_PARAM; - - // HCDs can be listed as devices with port #0 - while((dev) && (dev->port_number != 0)) { - if (--i < 0) { - usbi_warn(ctx, "port numbers array is too small"); - return LIBUSB_ERROR_OVERFLOW; - } - port_numbers[i] = dev->port_number; - dev = dev->parent_dev; - } - if (i < port_numbers_len) - memmove(port_numbers, &port_numbers[i], port_numbers_len - i); - return port_numbers_len - i; -} - -/** \ingroup libusb_dev - * Deprecated please use libusb_get_port_numbers instead. - */ -int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, - uint8_t* port_numbers, uint8_t port_numbers_len) -{ - UNUSED(ctx); - - return libusb_get_port_numbers(dev, port_numbers, port_numbers_len); -} - -/** \ingroup libusb_dev - * Get the the parent from the specified device. - * \param dev a device - * \returns the device parent or NULL if not available - * You should issue a \ref libusb_get_device_list() before calling this - * function and make sure that you only access the parent before issuing - * \ref libusb_free_device_list(). The reason is that libusb currently does - * not maintain a permanent list of device instances, and therefore can - * only guarantee that parents are fully instantiated within a - * libusb_get_device_list() - libusb_free_device_list() block. - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev) -{ - return dev->parent_dev; -} - -/** \ingroup libusb_dev - * Get the address of the device on the bus it is connected to. - * \param dev a device - * \returns the device address - */ -uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev) -{ - return dev->device_address; -} - -/** \ingroup libusb_dev - * Get the negotiated connection speed for a device. - * \param dev a device - * \returns a \ref libusb_speed code, where LIBUSB_SPEED_UNKNOWN means that - * the OS doesn't know or doesn't support returning the negotiated speed. - */ -int API_EXPORTED libusb_get_device_speed(libusb_device *dev) -{ - return dev->speed; -} - -static const struct libusb_endpoint_descriptor *find_endpoint( - struct libusb_config_descriptor *config, unsigned char endpoint) -{ - int iface_idx; - for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { - const struct libusb_interface *iface = &config->interface[iface_idx]; - int altsetting_idx; - - for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; - altsetting_idx++) { - const struct libusb_interface_descriptor *altsetting - = &iface->altsetting[altsetting_idx]; - int ep_idx; - - for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) { - const struct libusb_endpoint_descriptor *ep = - &altsetting->endpoint[ep_idx]; - if (ep->bEndpointAddress == endpoint) - return ep; - } - } - } - return NULL; -} - -/** \ingroup libusb_dev - * Convenience function to retrieve the wMaxPacketSize value for a particular - * endpoint in the active device configuration. - * - * This function was originally intended to be of assistance when setting up - * isochronous transfers, but a design mistake resulted in this function - * instead. It simply returns the wMaxPacketSize value without considering - * its contents. If you're dealing with isochronous transfers, you probably - * want libusb_get_max_iso_packet_size() instead. - * - * \param dev a device - * \param endpoint address of the endpoint in question - * \returns the wMaxPacketSize value - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure - */ -int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, - unsigned char endpoint) -{ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *ep; - int r; - - r = libusb_get_active_config_descriptor(dev, &config); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "could not retrieve active config descriptor"); - return LIBUSB_ERROR_OTHER; - } - - ep = find_endpoint(config, endpoint); - if (!ep) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - r = ep->wMaxPacketSize; - -out: - libusb_free_config_descriptor(config); - return r; -} - -/** \ingroup libusb_dev - * Calculate the maximum packet size which a specific endpoint is capable is - * sending or receiving in the duration of 1 microframe - * - * Only the active configuration is examined. The calculation is based on the - * wMaxPacketSize field in the endpoint descriptor as described in section - * 9.6.6 in the USB 2.0 specifications. - * - * If acting on an isochronous or interrupt endpoint, this function will - * multiply the value found in bits 0:10 by the number of transactions per - * microframe (determined by bits 11:12). Otherwise, this function just - * returns the numeric value found in bits 0:10. - * - * This function is useful for setting up isochronous transfers, for example - * you might pass the return value from this function to - * libusb_set_iso_packet_lengths() in order to set the length field of every - * isochronous packet in a transfer. - * - * Since v1.0.3. - * - * \param dev a device - * \param endpoint address of the endpoint in question - * \returns the maximum packet size which can be sent/received on this endpoint - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure - */ -int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, - unsigned char endpoint) -{ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *ep; - enum libusb_transfer_type ep_type; - uint16_t val; - int r; - - r = libusb_get_active_config_descriptor(dev, &config); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "could not retrieve active config descriptor"); - return LIBUSB_ERROR_OTHER; - } - - ep = find_endpoint(config, endpoint); - if (!ep) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - val = ep->wMaxPacketSize; - ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3); - - r = val & 0x07ff; - if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - || ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) - r *= (1 + ((val >> 11) & 3)); - -out: - libusb_free_config_descriptor(config); - return r; -} - -/** \ingroup libusb_dev - * Increment the reference count of a device. - * \param dev the device to reference - * \returns the same device - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev) -{ - usbi_mutex_lock(&dev->lock); - dev->refcnt++; - usbi_mutex_unlock(&dev->lock); - return dev; -} - -/** \ingroup libusb_dev - * Decrement the reference count of a device. If the decrement operation - * causes the reference count to reach zero, the device shall be destroyed. - * \param dev the device to unreference - */ -void API_EXPORTED libusb_unref_device(libusb_device *dev) -{ - int refcnt; - - if (!dev) - return; - - usbi_mutex_lock(&dev->lock); - refcnt = --dev->refcnt; - usbi_mutex_unlock(&dev->lock); - - if (refcnt == 0) { - usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address); - - libusb_unref_device(dev->parent_dev); - - if (usbi_backend.destroy_device) - usbi_backend.destroy_device(dev); - - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - /* backend does not support hotplug */ - usbi_disconnect_device(dev); - } - - usbi_mutex_destroy(&dev->lock); - free(dev); - } -} - -/* - * Signal the event pipe so that the event handling thread will be - * interrupted to process an internal event. - */ -int usbi_signal_event(struct libusb_context *ctx) -{ - unsigned char dummy = 1; - ssize_t r; - - /* write some data on event pipe to interrupt event handlers */ - r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy)); - if (r != sizeof(dummy)) { - usbi_warn(ctx, "internal signalling write failed"); - return LIBUSB_ERROR_IO; - } - - return 0; -} - -/* - * Clear the event pipe so that the event handling will no longer be - * interrupted. - */ -int usbi_clear_event(struct libusb_context *ctx) -{ - unsigned char dummy; - ssize_t r; - - /* read some data on event pipe to clear it */ - r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); - if (r != sizeof(dummy)) { - usbi_warn(ctx, "internal signalling read failed"); - return LIBUSB_ERROR_IO; - } - - return 0; -} - -/** \ingroup libusb_dev - * Open a device and obtain a device handle. A handle allows you to perform - * I/O on the device in question. - * - * Internally, this function adds a reference to the device and makes it - * available to you through libusb_get_device(). This reference is removed - * during libusb_close(). - * - * This is a non-blocking function; no requests are sent over the bus. - * - * \param dev the device to open - * \param dev_handle output location for the returned device handle pointer. Only - * populated when the return code is 0. - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure - * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_open(libusb_device *dev, - libusb_device_handle **dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct libusb_device_handle *_dev_handle; - size_t priv_size = usbi_backend.device_handle_priv_size; - int r; - usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); - - if (!dev->attached) { - return LIBUSB_ERROR_NO_DEVICE; - } - - _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); - if (!_dev_handle) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_mutex_init(&_dev_handle->lock); - if (r) { - free(_dev_handle); - return LIBUSB_ERROR_OTHER; - } - - _dev_handle->dev = libusb_ref_device(dev); - _dev_handle->auto_detach_kernel_driver = 0; - _dev_handle->claimed_interfaces = 0; - memset(&_dev_handle->os_priv, 0, priv_size); - - r = usbi_backend.open(_dev_handle); - if (r < 0) { - usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); - libusb_unref_device(dev); - usbi_mutex_destroy(&_dev_handle->lock); - free(_dev_handle); - return r; - } - - usbi_mutex_lock(&ctx->open_devs_lock); - list_add(&_dev_handle->list, &ctx->open_devs); - usbi_mutex_unlock(&ctx->open_devs_lock); - *dev_handle = _dev_handle; - - return 0; -} - -/** \ingroup libusb_dev - * Convenience function for finding a device with a particular - * idVendor/idProduct combination. This function is intended - * for those scenarios where you are using libusb to knock up a quick test - * application - it allows you to avoid calling libusb_get_device_list() and - * worrying about traversing/freeing the list. - * - * This function has limitations and is hence not intended for use in real - * applications: if multiple devices have the same IDs it will only - * give you the first one, etc. - * - * \param ctx the context to operate on, or NULL for the default context - * \param vendor_id the idVendor value to search for - * \param product_id the idProduct value to search for - * \returns a device handle for the first found device, or NULL on error - * or if the device could not be found. */ -DEFAULT_VISIBILITY -libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( - libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) -{ - struct libusb_device **devs; - struct libusb_device *found = NULL; - struct libusb_device *dev; - struct libusb_device_handle *dev_handle = NULL; - size_t i = 0; - int r; - - if (libusb_get_device_list(ctx, &devs) < 0) - return NULL; - - while ((dev = devs[i++]) != NULL) { - struct libusb_device_descriptor desc; - r = libusb_get_device_descriptor(dev, &desc); - if (r < 0) - goto out; - if (desc.idVendor == vendor_id && desc.idProduct == product_id) { - found = dev; - break; - } - } - - if (found) { - r = libusb_open(found, &dev_handle); - if (r < 0) - dev_handle = NULL; - } - -out: - libusb_free_device_list(devs, 1); - return dev_handle; -} - -static void do_close(struct libusb_context *ctx, - struct libusb_device_handle *dev_handle) -{ - struct usbi_transfer *itransfer; - struct usbi_transfer *tmp; - - /* remove any transfers in flight that are for this device */ - usbi_mutex_lock(&ctx->flying_transfers_lock); - - /* safe iteration because transfers may be being deleted */ - list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) { - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - if (transfer->dev_handle != dev_handle) - continue; - - usbi_mutex_lock(&itransfer->lock); - if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { - usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); - - if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) - usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); - else - usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); - } - usbi_mutex_unlock(&itransfer->lock); - - /* remove from the list of in-flight transfers and make sure - * we don't accidentally use the device handle in the future - * (or that such accesses will be easily caught and identified as a crash) - */ - list_del(&itransfer->list); - transfer->dev_handle = NULL; - - /* it is up to the user to free up the actual transfer struct. this is - * just making sure that we don't attempt to process the transfer after - * the device handle is invalid - */ - usbi_dbg("Removed transfer %p from the in-flight list because device handle %p closed", - transfer, dev_handle); - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - usbi_mutex_lock(&ctx->open_devs_lock); - list_del(&dev_handle->list); - usbi_mutex_unlock(&ctx->open_devs_lock); - - usbi_backend.close(dev_handle); - libusb_unref_device(dev_handle->dev); - usbi_mutex_destroy(&dev_handle->lock); - free(dev_handle); -} - -/** \ingroup libusb_dev - * Close a device handle. Should be called on all open handles before your - * application exits. - * - * Internally, this function destroys the reference that was added by - * libusb_open() on the given device. - * - * This is a non-blocking function; no requests are sent over the bus. - * - * \param dev_handle the device handle to close - */ -void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx; - int handling_events; - int pending_events; - - if (!dev_handle) - return; - usbi_dbg(""); - - ctx = HANDLE_CTX(dev_handle); - handling_events = usbi_handling_events(ctx); - - /* Similarly to libusb_open(), we want to interrupt all event handlers - * at this point. More importantly, we want to perform the actual close of - * the device while holding the event handling lock (preventing any other - * thread from doing event handling) because we will be removing a file - * descriptor from the polling loop. If this is being called by the current - * event handler, we can bypass the interruption code because we already - * hold the event handling lock. */ - - if (!handling_events) { - /* Record that we are closing a device. - * Only signal an event if there are no prior pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - ctx->device_close++; - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* take event handling lock */ - libusb_lock_events(ctx); - } - - /* Close the device */ - do_close(ctx, dev_handle); - - if (!handling_events) { - /* We're done with closing this device. - * Clear the event pipe if there are no further pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - ctx->device_close--; - pending_events = usbi_pending_events(ctx); - if (!pending_events) - usbi_clear_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* Release event handling lock and wake up event waiters */ - libusb_unlock_events(ctx); - } -} - -/** \ingroup libusb_dev - * Get the underlying device for a device handle. This function does not modify - * the reference count of the returned device, so do not feel compelled to - * unreference it when you are done. - * \param dev_handle a device handle - * \returns the underlying device - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) -{ - return dev_handle->dev; -} - -/** \ingroup libusb_dev - * Determine the bConfigurationValue of the currently active configuration. - * - * You could formulate your own control request to obtain this information, - * but this function has the advantage that it may be able to retrieve the - * information from operating system caches (no I/O involved). - * - * If the OS does not cache this information, then this function will block - * while a control transfer is submitted to retrieve the information. - * - * This function will return a value of 0 in the config output - * parameter if the device is in unconfigured state. - * - * \param dev_handle a device handle - * \param config output location for the bConfigurationValue of the active - * configuration (only valid for return code 0) - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, - int *config) -{ - int r = LIBUSB_ERROR_NOT_SUPPORTED; - - usbi_dbg(""); - if (usbi_backend.get_configuration) - r = usbi_backend.get_configuration(dev_handle, config); - - if (r == LIBUSB_ERROR_NOT_SUPPORTED) { - uint8_t tmp = 0; - usbi_dbg("falling back to control message"); - r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000); - if (r == 0) { - usbi_err(HANDLE_CTX(dev_handle), "zero bytes returned in ctrl transfer?"); - r = LIBUSB_ERROR_IO; - } else if (r == 1) { - r = 0; - *config = tmp; - } else { - usbi_dbg("control failed, error %d", r); - } - } - - if (r == 0) - usbi_dbg("active config %d", *config); - - return r; -} - -/** \ingroup libusb_dev - * Set the active configuration for a device. - * - * The operating system may or may not have already set an active - * configuration on the device. It is up to your application to ensure the - * correct configuration is selected before you attempt to claim interfaces - * and perform other operations. - * - * If you call this function on a device already configured with the selected - * configuration, then this function will act as a lightweight device reset: - * it will issue a SET_CONFIGURATION request using the current configuration, - * causing most USB-related device state to be reset (altsetting reset to zero, - * endpoint halts cleared, toggles reset). - * - * You cannot change/reset configuration if your application has claimed - * interfaces. It is advised to set the desired configuration before claiming - * interfaces. - * - * Alternatively you can call libusb_release_interface() first. Note if you - * do things this way you must ensure that auto_detach_kernel_driver for - * dev is 0, otherwise the kernel driver will be re-attached when you - * release the interface(s). - * - * You cannot change/reset configuration if other applications or drivers have - * claimed interfaces. - * - * A configuration value of -1 will put the device in unconfigured state. - * The USB specifications state that a configuration value of 0 does this, - * however buggy devices exist which actually have a configuration 0. - * - * You should always use this function rather than formulating your own - * SET_CONFIGURATION control request. This is because the underlying operating - * system needs to know when such changes happen. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param configuration the bConfigurationValue of the configuration you - * wish to activate, or -1 if you wish to put the device in an unconfigured - * state - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist - * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, - int configuration) -{ - usbi_dbg("configuration %d", configuration); - return usbi_backend.set_configuration(dev_handle, configuration); -} - -/** \ingroup libusb_dev - * Claim an interface on a given device handle. You must claim the interface - * you wish to use before you can perform I/O on any of its endpoints. - * - * It is legal to attempt to claim an already-claimed interface, in which - * case libusb just returns 0 without doing anything. - * - * If auto_detach_kernel_driver is set to 1 for dev, the kernel driver - * will be detached if necessary, on failure the detach error is returned. - * - * Claiming of interfaces is a purely logical operation; it does not cause - * any requests to be sent over the bus. Interface claiming is used to - * instruct the underlying operating system that your application wishes - * to take ownership of the interface. - * - * This is a non-blocking function. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the interface you - * wish to claim - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist - * \returns LIBUSB_ERROR_BUSY if another program or driver has claimed the - * interface - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns a LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, - int interface_number) -{ - int r = 0; - - usbi_dbg("interface %d", interface_number); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_mutex_lock(&dev_handle->lock); - if (dev_handle->claimed_interfaces & (1 << interface_number)) - goto out; - - r = usbi_backend.claim_interface(dev_handle, interface_number); - if (r == 0) - dev_handle->claimed_interfaces |= 1 << interface_number; - -out: - usbi_mutex_unlock(&dev_handle->lock); - return r; -} - -/** \ingroup libusb_dev - * Release an interface previously claimed with libusb_claim_interface(). You - * should release all claimed interfaces before closing a device handle. - * - * This is a blocking function. A SET_INTERFACE control request will be sent - * to the device, resetting interface state to the first alternate setting. - * - * If auto_detach_kernel_driver is set to 1 for dev, the kernel - * driver will be re-attached after releasing the interface. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the - * previously-claimed interface - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, - int interface_number) -{ - int r; - - usbi_dbg("interface %d", interface_number); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - usbi_mutex_lock(&dev_handle->lock); - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - r = usbi_backend.release_interface(dev_handle, interface_number); - if (r == 0) - dev_handle->claimed_interfaces &= ~(1 << interface_number); - -out: - usbi_mutex_unlock(&dev_handle->lock); - return r; -} - -/** \ingroup libusb_dev - * Activate an alternate setting for an interface. The interface must have - * been previously claimed with libusb_claim_interface(). - * - * You should always use this function rather than formulating your own - * SET_INTERFACE control request. This is because the underlying operating - * system needs to know when such changes happen. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the - * previously-claimed interface - * \param alternate_setting the bAlternateSetting of the alternate - * setting to activate - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the - * requested alternate setting does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, - int interface_number, int alternate_setting) -{ - usbi_dbg("interface %d altsetting %d", - interface_number, alternate_setting); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - usbi_mutex_lock(&dev_handle->lock); - if (!dev_handle->dev->attached) { - usbi_mutex_unlock(&dev_handle->lock); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { - usbi_mutex_unlock(&dev_handle->lock); - return LIBUSB_ERROR_NOT_FOUND; - } - usbi_mutex_unlock(&dev_handle->lock); - - return usbi_backend.set_interface_altsetting(dev_handle, interface_number, - alternate_setting); -} - -/** \ingroup libusb_dev - * Clear the halt/stall condition for an endpoint. Endpoints with halt status - * are unable to receive or transmit data until the halt condition is stalled. - * - * You should cancel all pending transfers before attempting to clear the halt - * condition. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param endpoint the endpoint to clear halt status - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, - unsigned char endpoint) -{ - usbi_dbg("endpoint %x", endpoint); - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - return usbi_backend.clear_halt(dev_handle, endpoint); -} - -/** \ingroup libusb_dev - * Perform a USB port reset to reinitialize a device. The system will attempt - * to restore the previous configuration and alternate settings after the - * reset has completed. - * - * If the reset fails, the descriptors change, or the previous state cannot be - * restored, the device will appear to be disconnected and reconnected. This - * means that the device handle is no longer valid (you should close it) and - * rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates - * when this is the case. - * - * This is a blocking function which usually incurs a noticeable delay. - * - * \param dev_handle a handle of the device to reset - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the - * device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) -{ - usbi_dbg(""); - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - return usbi_backend.reset_device(dev_handle); -} - -/** \ingroup libusb_asyncio - * Allocate up to num_streams usb bulk streams on the specified endpoints. This - * function takes an array of endpoints rather then a single endpoint because - * some protocols require that endpoints are setup with similar stream ids. - * All endpoints passed in must belong to the same interface. - * - * Note this function may return less streams then requested. Also note that the - * same number of streams are allocated for each endpoint in the endpoint array. - * - * Stream id 0 is reserved, and should not be used to communicate with devices. - * If libusb_alloc_streams() returns with a value of N, you may use stream ids - * 1 to N. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param dev_handle a device handle - * \param num_streams number of streams to try to allocate - * \param endpoints array of endpoints to allocate streams on - * \param num_endpoints length of the endpoints array - * \returns number of streams allocated, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend.alloc_streams) - return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints, - num_endpoints); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_asyncio - * Free usb bulk streams allocated with libusb_alloc_streams(). - * - * Note streams are automatically free-ed when releasing an interface. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param dev_handle a device handle - * \param endpoints array of endpoints to free streams on - * \param num_endpoints length of the endpoints array - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints) -{ - usbi_dbg("eps %d", num_endpoints); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend.free_streams) - return usbi_backend.free_streams(dev_handle, endpoints, - num_endpoints); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_asyncio - * Attempts to allocate a block of persistent DMA memory suitable for transfers - * against the given device. If successful, will return a block of memory - * that is suitable for use as "buffer" in \ref libusb_transfer against this - * device. Using this memory instead of regular memory means that the host - * controller can use DMA directly into the buffer to increase performance, and - * also that transfers can no longer fail due to kernel memory fragmentation. - * - * Note that this means you should not modify this memory (or even data on - * the same cache lines) when a transfer is in progress, although it is legal - * to have several transfers going on within the same memory block. - * - * Will return NULL on failure. Many systems do not support such zerocopy - * and will always return NULL. Memory allocated with this function must be - * freed with \ref libusb_dev_mem_free. Specifically, this means that the - * flag \ref LIBUSB_TRANSFER_FREE_BUFFER cannot be used to free memory allocated - * with this function. - * - * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 - * - * \param dev_handle a device handle - * \param length size of desired data buffer - * \returns a pointer to the newly allocated memory, or NULL on failure - */ -DEFAULT_VISIBILITY -unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, - size_t length) -{ - if (!dev_handle->dev->attached) - return NULL; - - if (usbi_backend.dev_mem_alloc) - return usbi_backend.dev_mem_alloc(dev_handle, length); - else - return NULL; -} - -/** \ingroup libusb_asyncio - * Free device memory allocated with libusb_dev_mem_alloc(). - * - * \param dev_handle a device handle - * \param buffer pointer to the previously allocated memory - * \param length size of previously allocated memory - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, - unsigned char *buffer, size_t length) -{ - if (usbi_backend.dev_mem_free) - return usbi_backend.dev_mem_free(dev_handle, buffer, length); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Determine if a kernel driver is active on an interface. If a kernel driver - * is active, you cannot claim the interface, and libusb will be unable to - * perform I/O. - * - * This functionality is not available on Windows. - * - * \param dev_handle a device handle - * \param interface_number the interface to check - * \returns 0 if no kernel driver is active - * \returns 1 if a kernel driver is active - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_detach_kernel_driver() - */ -int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend.kernel_driver_active) - return usbi_backend.kernel_driver_active(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Detach a kernel driver from an interface. If successful, you will then be - * able to claim the interface and perform I/O. - * - * This functionality is not available on Darwin or Windows. - * - * Note that libusb itself also talks to the device through a special kernel - * driver, if this driver is already attached to the device, this call will - * not detach it and return LIBUSB_ERROR_NOT_FOUND. - * - * \param dev_handle a device handle - * \param interface_number the interface to detach the driver from - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_kernel_driver_active() - */ -int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend.detach_kernel_driver) - return usbi_backend.detach_kernel_driver(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Re-attach an interface's kernel driver, which was previously detached - * using libusb_detach_kernel_driver(). This call is only effective on - * Linux and returns LIBUSB_ERROR_NOT_SUPPORTED on all other platforms. - * - * This functionality is not available on Darwin or Windows. - * - * \param dev_handle a device handle - * \param interface_number the interface to attach the driver from - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns LIBUSB_ERROR_BUSY if the driver cannot be attached because the - * interface is claimed by a program or driver - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_kernel_driver_active() - */ -int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend.attach_kernel_driver) - return usbi_backend.attach_kernel_driver(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Enable/disable libusb's automatic kernel driver detachment. When this is - * enabled libusb will automatically detach the kernel driver on an interface - * when claiming the interface, and attach it when releasing the interface. - * - * Automatic kernel driver detachment is disabled on newly opened device - * handles by default. - * - * On platforms which do not have LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER - * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will - * continue as if this function was never called. - * - * \param dev_handle a device handle - * \param enable whether to enable or disable auto kernel driver detachment - * - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \see libusb_claim_interface() - * \see libusb_release_interface() - * \see libusb_set_configuration() - */ -int API_EXPORTED libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev_handle, int enable) -{ - if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) - return LIBUSB_ERROR_NOT_SUPPORTED; - - dev_handle->auto_detach_kernel_driver = enable; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_lib - * \deprecated Use libusb_set_option() instead using the - * \ref LIBUSB_OPTION_LOG_LEVEL option. - */ -void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) -{ -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - USBI_GET_CONTEXT(ctx); - if (!ctx->debug_fixed) { - level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); - ctx->debug = (enum libusb_log_level)level; - } -#else - UNUSED(ctx); - UNUSED(level); -#endif -} - -/** \ingroup libusb_lib - * Set an option in the library. - * - * Use this function to configure a specific option within the library. - * - * Some options require one or more arguments to be provided. Consult each - * option's documentation for specific requirements. - * - * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106 - * - * \param ctx context on which to operate - * \param option which option to set - * \param ... any required arguments for the specified option - * - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported - * on this platform - */ -int API_EXPORTED libusb_set_option(libusb_context *ctx, - enum libusb_option option, ...) -{ - int arg, r = LIBUSB_SUCCESS; - va_list ap; - - USBI_GET_CONTEXT(ctx); - - va_start(ap, option); - switch (option) { - case LIBUSB_OPTION_LOG_LEVEL: - arg = va_arg(ap, int); - if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) { - r = LIBUSB_ERROR_INVALID_PARAM; - break; - } -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - if (!ctx->debug_fixed) - ctx->debug = (enum libusb_log_level)arg; -#endif - break; - - /* Handle all backend-specific options here */ - case LIBUSB_OPTION_USE_USBDK: - if (usbi_backend.set_option) - r = usbi_backend.set_option(ctx, option, ap); - else - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; - - default: - r = LIBUSB_ERROR_INVALID_PARAM; - } - va_end(ap); - - return r; -} - -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) -/* returns the log level as defined in the LIBUSB_DEBUG environment variable. - * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE. - * value is clamped to ensure it is within the valid range of possibilities. - */ -static enum libusb_log_level get_env_debug_level(void) -{ - const char *dbg = getenv("LIBUSB_DEBUG"); - enum libusb_log_level level; - if (dbg) { - int dbg_level = atoi(dbg); - dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); - level = (enum libusb_log_level)dbg_level; - } else { - level = LIBUSB_LOG_LEVEL_NONE; - } - return level; -} -#endif - -/** \ingroup libusb_lib - * Initialize libusb. This function must be called before calling any other - * libusb function. - * - * If you do not provide an output location for a context pointer, a default - * context will be created. If there was already a default context, it will - * be reused (and nothing will be initialized/reinitialized). - * - * \param context Optional output location for context pointer. - * Only valid on return code 0. - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \see libusb_contexts - */ -int API_EXPORTED libusb_init(libusb_context **context) -{ - struct libusb_device *dev, *next; - size_t priv_size = usbi_backend.context_priv_size; - struct libusb_context *ctx; - static int first_init = 1; - int r = 0; - - usbi_mutex_static_lock(&default_context_lock); - - if (!timestamp_origin.tv_sec) { - usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); - } - - if (!context && usbi_default_context) { - usbi_dbg("reusing default context"); - default_context_refcnt++; - usbi_mutex_static_unlock(&default_context_lock); - return 0; - } - - ctx = calloc(1, sizeof(*ctx) + priv_size); - if (!ctx) { - r = LIBUSB_ERROR_NO_MEM; - goto err_unlock; - } - -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - ctx->debug = get_env_debug_level(); - if (ctx->debug != LIBUSB_LOG_LEVEL_NONE) - ctx->debug_fixed = 1; -#endif - - /* default context should be initialized before calling usbi_dbg */ - if (!usbi_default_context) { - usbi_default_context = ctx; - default_context_refcnt++; - usbi_dbg("created default context"); - } - - usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor, - libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc); - - usbi_mutex_init(&ctx->usb_devs_lock); - usbi_mutex_init(&ctx->open_devs_lock); - usbi_mutex_init(&ctx->hotplug_cbs_lock); - list_init(&ctx->usb_devs); - list_init(&ctx->open_devs); - list_init(&ctx->hotplug_cbs); - ctx->next_hotplug_cb_handle = 1; - - usbi_mutex_static_lock(&active_contexts_lock); - if (first_init) { - first_init = 0; - list_init (&active_contexts_list); - } - list_add (&ctx->list, &active_contexts_list); - usbi_mutex_static_unlock(&active_contexts_lock); - - if (usbi_backend.init) { - r = usbi_backend.init(ctx); - if (r) - goto err_free_ctx; - } - - r = usbi_io_init(ctx); - if (r < 0) - goto err_backend_exit; - - usbi_mutex_static_unlock(&default_context_lock); - - if (context) - *context = ctx; - - return 0; - -err_backend_exit: - if (usbi_backend.exit) - usbi_backend.exit(ctx); -err_free_ctx: - if (ctx == usbi_default_context) { - usbi_default_context = NULL; - default_context_refcnt--; - } - - usbi_mutex_static_lock(&active_contexts_lock); - list_del (&ctx->list); - usbi_mutex_static_unlock(&active_contexts_lock); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { - list_del(&dev->list); - libusb_unref_device(dev); - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - usbi_mutex_destroy(&ctx->open_devs_lock); - usbi_mutex_destroy(&ctx->usb_devs_lock); - usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - - free(ctx); -err_unlock: - usbi_mutex_static_unlock(&default_context_lock); - return r; -} - -/** \ingroup libusb_lib - * Deinitialize libusb. Should be called after closing all open devices and - * before your application terminates. - * \param ctx the context to deinitialize, or NULL for the default context - */ -void API_EXPORTED libusb_exit(struct libusb_context *ctx) -{ - struct libusb_device *dev, *next; - struct timeval tv = { 0, 0 }; - - usbi_dbg(""); - USBI_GET_CONTEXT(ctx); - - /* if working with default context, only actually do the deinitialization - * if we're the last user */ - usbi_mutex_static_lock(&default_context_lock); - if (ctx == usbi_default_context) { - if (--default_context_refcnt > 0) { - usbi_dbg("not destroying default context"); - usbi_mutex_static_unlock(&default_context_lock); - return; - } - usbi_dbg("destroying default context"); - usbi_default_context = NULL; - } - usbi_mutex_static_unlock(&default_context_lock); - - usbi_mutex_static_lock(&active_contexts_lock); - list_del (&ctx->list); - usbi_mutex_static_unlock(&active_contexts_lock); - - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_hotplug_deregister(ctx, 1); - - /* - * Ensure any pending unplug events are read from the hotplug - * pipe. The usb_device-s hold in the events are no longer part - * of usb_devs, but the events still hold a reference! - * - * Note we don't do this if the application has left devices - * open (which implies a buggy app) to avoid packet completion - * handlers running when the app does not expect them to run. - */ - if (list_empty(&ctx->open_devs)) - libusb_handle_events_timeout(ctx, &tv); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { - list_del(&dev->list); - libusb_unref_device(dev); - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - } - - /* a few sanity checks. don't bother with locking because unless - * there is an application bug, nobody will be accessing these. */ - if (!list_empty(&ctx->usb_devs)) - usbi_warn(ctx, "some libusb_devices were leaked"); - if (!list_empty(&ctx->open_devs)) - usbi_warn(ctx, "application left some devices open"); - - usbi_io_exit(ctx); - if (usbi_backend.exit) - usbi_backend.exit(ctx); - - usbi_mutex_destroy(&ctx->open_devs_lock); - usbi_mutex_destroy(&ctx->usb_devs_lock); - usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - free(ctx); -} - -/** \ingroup libusb_misc - * Check at runtime if the loaded library has a given capability. - * This call should be performed after \ref libusb_init(), to ensure the - * backend has updated its capability set. - * - * \param capability the \ref libusb_capability to check for - * \returns nonzero if the running library has the capability, 0 otherwise - */ -int API_EXPORTED libusb_has_capability(uint32_t capability) -{ - switch (capability) { - case LIBUSB_CAP_HAS_CAPABILITY: - return 1; - case LIBUSB_CAP_HAS_HOTPLUG: - return !(usbi_backend.get_device_list); - case LIBUSB_CAP_HAS_HID_ACCESS: - return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS); - case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: - return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); - } - return 0; -} - -#ifdef ENABLE_LOGGING - -/* this is defined in libusbi.h if needed */ -#ifdef LIBUSB_PRINTF_WIN32 -/* - * Prior to VS2015, Microsoft did not provide the snprintf() function and - * provided a vsnprintf() that did not guarantee NULL-terminated output. - * Microsoft did provide a _snprintf() function, but again it did not - * guarantee NULL-terminated output. - * - * The below implementations guarantee NULL-terminated output and are - * C99 compliant. - */ - -int usbi_snprintf(char *str, size_t size, const char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = usbi_vsnprintf(str, size, format, ap); - va_end(ap); - - return ret; -} - -int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - int ret; - - ret = _vsnprintf(str, size, format, ap); - if (ret < 0 || ret == (int)size) { - /* Output is truncated, ensure buffer is NULL-terminated and - * determine how many characters would have been written. */ - str[size - 1] = '\0'; - if (ret < 0) - ret = _vsnprintf(NULL, 0, format, ap); - } - - return ret; -} -#endif /* LIBUSB_PRINTF_WIN32 */ - -static void usbi_log_str(enum libusb_log_level level, const char *str) -{ -#if defined(USE_SYSTEM_LOGGING_FACILITY) -#if defined(OS_WINDOWS) - OutputDebugString(str); -#elif defined(OS_WINCE) - /* Windows CE only supports the Unicode version of OutputDebugString. */ - WCHAR wbuf[USBI_MAX_LOG_LEN]; - MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf)); - OutputDebugStringW(wbuf); -#elif defined(__ANDROID__) - int priority = ANDROID_LOG_UNKNOWN; - switch (level) { - case LIBUSB_LOG_LEVEL_NONE: return; - case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break; - case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; - case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; - case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break; - } - __android_log_write(priority, "libusb", str); -#elif defined(HAVE_SYSLOG_FUNC) - int syslog_level = LOG_INFO; - switch (level) { - case LIBUSB_LOG_LEVEL_NONE: return; - case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break; - case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; - case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; - case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break; - } - syslog(syslog_level, "%s", str); -#else /* All of gcc, Clang, XCode seem to use #warning */ -#warning System logging is not supported on this platform. Logging to stderr will be used instead. - fputs(str, stderr); -#endif -#else - fputs(str, stderr); -#endif /* USE_SYSTEM_LOGGING_FACILITY */ - UNUSED(level); -} - -void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, va_list args) -{ - const char *prefix; - char buf[USBI_MAX_LOG_LEN]; - struct timespec now; - int global_debug, header_len, text_len; - static int has_debug_header_been_displayed = 0; - -#ifdef ENABLE_DEBUG_LOGGING - global_debug = 1; - UNUSED(ctx); -#else - enum libusb_log_level ctx_level = LIBUSB_LOG_LEVEL_NONE; - - USBI_GET_CONTEXT(ctx); - if (ctx) - ctx_level = ctx->debug; - else - ctx_level = get_env_debug_level(); - - if (ctx_level == LIBUSB_LOG_LEVEL_NONE) - return; - if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING) - return; - if (level == LIBUSB_LOG_LEVEL_INFO && ctx_level < LIBUSB_LOG_LEVEL_INFO) - return; - if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG) - return; - - global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); -#endif - - usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &now); - if ((global_debug) && (!has_debug_header_been_displayed)) { - has_debug_header_been_displayed = 1; - usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); - usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); - } - if (now.tv_nsec < timestamp_origin.tv_nsec) { - now.tv_sec--; - now.tv_nsec += 1000000000L; - } - now.tv_sec -= timestamp_origin.tv_sec; - now.tv_nsec -= timestamp_origin.tv_nsec; - - switch (level) { - case LIBUSB_LOG_LEVEL_NONE: - return; - case LIBUSB_LOG_LEVEL_ERROR: - prefix = "error"; - break; - case LIBUSB_LOG_LEVEL_WARNING: - prefix = "warning"; - break; - case LIBUSB_LOG_LEVEL_INFO: - prefix = "info"; - break; - case LIBUSB_LOG_LEVEL_DEBUG: - prefix = "debug"; - break; - default: - prefix = "unknown"; - break; - } - - if (global_debug) { - header_len = snprintf(buf, sizeof(buf), - "[%2d.%06d] [%08x] libusb: %s [%s] ", - (int)now.tv_sec, (int)(now.tv_nsec / 1000L), usbi_get_tid(), prefix, function); - } else { - header_len = snprintf(buf, sizeof(buf), - "libusb: %s [%s] ", prefix, function); - } - - if (header_len < 0 || header_len >= (int)sizeof(buf)) { - /* Somehow snprintf failed to write to the buffer, - * remove the header so something useful is output. */ - header_len = 0; - } - /* Make sure buffer is NUL terminated */ - buf[header_len] = '\0'; - text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len, - format, args); - if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { - /* Truncated log output. On some platforms a -1 return value means - * that the output was truncated. */ - text_len = sizeof(buf) - header_len; - } - if (header_len + text_len + sizeof(USBI_LOG_LINE_END) >= sizeof(buf)) { - /* Need to truncate the text slightly to fit on the terminator. */ - text_len -= (header_len + text_len + sizeof(USBI_LOG_LINE_END)) - sizeof(buf); - } - strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); - - usbi_log_str(level, buf); -} - -void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, ...) -{ - va_list args; - - va_start (args, format); - usbi_log_v(ctx, level, function, format, args); - va_end (args); -} - -#endif /* ENABLE_LOGGING */ - -/** \ingroup libusb_misc - * Returns a constant NULL-terminated string with the ASCII name of a libusb - * error or transfer status code. The caller must not free() the returned - * string. - * - * \param error_code The \ref libusb_error or libusb_transfer_status code to - * return the name of. - * \returns The error name, or the string **UNKNOWN** if the value of - * error_code is not a known error / status code. - */ -DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_error_name(int error_code) -{ - switch (error_code) { - case LIBUSB_ERROR_IO: - return "LIBUSB_ERROR_IO"; - case LIBUSB_ERROR_INVALID_PARAM: - return "LIBUSB_ERROR_INVALID_PARAM"; - case LIBUSB_ERROR_ACCESS: - return "LIBUSB_ERROR_ACCESS"; - case LIBUSB_ERROR_NO_DEVICE: - return "LIBUSB_ERROR_NO_DEVICE"; - case LIBUSB_ERROR_NOT_FOUND: - return "LIBUSB_ERROR_NOT_FOUND"; - case LIBUSB_ERROR_BUSY: - return "LIBUSB_ERROR_BUSY"; - case LIBUSB_ERROR_TIMEOUT: - return "LIBUSB_ERROR_TIMEOUT"; - case LIBUSB_ERROR_OVERFLOW: - return "LIBUSB_ERROR_OVERFLOW"; - case LIBUSB_ERROR_PIPE: - return "LIBUSB_ERROR_PIPE"; - case LIBUSB_ERROR_INTERRUPTED: - return "LIBUSB_ERROR_INTERRUPTED"; - case LIBUSB_ERROR_NO_MEM: - return "LIBUSB_ERROR_NO_MEM"; - case LIBUSB_ERROR_NOT_SUPPORTED: - return "LIBUSB_ERROR_NOT_SUPPORTED"; - case LIBUSB_ERROR_OTHER: - return "LIBUSB_ERROR_OTHER"; - - case LIBUSB_TRANSFER_ERROR: - return "LIBUSB_TRANSFER_ERROR"; - case LIBUSB_TRANSFER_TIMED_OUT: - return "LIBUSB_TRANSFER_TIMED_OUT"; - case LIBUSB_TRANSFER_CANCELLED: - return "LIBUSB_TRANSFER_CANCELLED"; - case LIBUSB_TRANSFER_STALL: - return "LIBUSB_TRANSFER_STALL"; - case LIBUSB_TRANSFER_NO_DEVICE: - return "LIBUSB_TRANSFER_NO_DEVICE"; - case LIBUSB_TRANSFER_OVERFLOW: - return "LIBUSB_TRANSFER_OVERFLOW"; - - case 0: - return "LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED"; - default: - return "**UNKNOWN**"; - } -} - -/** \ingroup libusb_misc - * Returns a pointer to const struct libusb_version with the version - * (major, minor, micro, nano and rc) of the running library. - */ -DEFAULT_VISIBILITY -const struct libusb_version * LIBUSB_CALL libusb_get_version(void) -{ - return &libusb_version_internal; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c b/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c deleted file mode 100644 index 74d6de557e..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * USB descriptor handling functions for libusb - * Copyright © 2007 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -#define DESC_HEADER_LENGTH 2 -#define DEVICE_DESC_LENGTH 18 -#define CONFIG_DESC_LENGTH 9 -#define INTERFACE_DESC_LENGTH 9 -#define ENDPOINT_DESC_LENGTH 7 -#define ENDPOINT_AUDIO_DESC_LENGTH 9 - -/** @defgroup libusb_desc USB descriptors - * This page details how to examine the various standard USB descriptors - * for detected devices - */ - -/* set host_endian if the w values are already in host endian format, - * as opposed to bus endian. */ -int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, - void *dest, int host_endian) -{ - const unsigned char *sp = source; - unsigned char *dp = dest; - uint16_t w; - const char *cp; - uint32_t d; - - for (cp = descriptor; *cp; cp++) { - switch (*cp) { - case 'b': /* 8-bit byte */ - *dp++ = *sp++; - break; - case 'w': /* 16-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - - if (host_endian) { - memcpy(dp, sp, 2); - } else { - w = (sp[1] << 8) | sp[0]; - *((uint16_t *)dp) = w; - } - sp += 2; - dp += 2; - break; - case 'd': /* 32-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - - if (host_endian) { - memcpy(dp, sp, 4); - } else { - d = (sp[3] << 24) | (sp[2] << 16) | - (sp[1] << 8) | sp[0]; - *((uint32_t *)dp) = d; - } - sp += 4; - dp += 4; - break; - case 'u': /* 16 byte UUID */ - memcpy(dp, sp, 16); - sp += 16; - dp += 16; - break; - } - } - - return (int) (sp - source); -} - -static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint) -{ - free((void *) endpoint->extra); -} - -static int parse_endpoint(struct libusb_context *ctx, - struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer, - int size, int host_endian) -{ - struct usb_descriptor_header header; - unsigned char *extra; - unsigned char *begin; - int parsed = 0; - int len; - - if (size < DESC_HEADER_LENGTH) { - usbi_err(ctx, "short endpoint descriptor read %d/%d", - size, DESC_HEADER_LENGTH); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - header.bDescriptorType, LIBUSB_DT_ENDPOINT); - return parsed; - } - if (header.bLength > size) { - usbi_warn(ctx, "short endpoint descriptor read %d/%d", - size, header.bLength); - return parsed; - } - if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH) - usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian); - else if (header.bLength >= ENDPOINT_DESC_LENGTH) - usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian); - else { - usbi_err(ctx, "invalid endpoint bLength (%d)", header.bLength); - return LIBUSB_ERROR_IO; - } - - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - - /* Skip over the rest of the Class Specific or Vendor Specific */ - /* descriptors */ - begin = buffer; - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, "invalid extra ep desc len (%d)", - header.bLength); - return LIBUSB_ERROR_IO; - } else if (header.bLength > size) { - usbi_warn(ctx, "short extra ep desc read %d/%d", - size, header.bLength); - return parsed; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - usbi_dbg("skipping descriptor %x", header.bDescriptorType); - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - } - - /* Copy any unknown descriptors into a storage area for drivers */ - /* to later parse */ - len = (int)(buffer - begin); - if (!len) { - endpoint->extra = NULL; - endpoint->extra_length = 0; - return parsed; - } - - extra = malloc(len); - endpoint->extra = extra; - if (!extra) { - endpoint->extra_length = 0; - return LIBUSB_ERROR_NO_MEM; - } - - memcpy(extra, begin, len); - endpoint->extra_length = len; - - return parsed; -} - -static void clear_interface(struct libusb_interface *usb_interface) -{ - int i; - int j; - - if (usb_interface->altsetting) { - for (i = 0; i < usb_interface->num_altsetting; i++) { - struct libusb_interface_descriptor *ifp = - (struct libusb_interface_descriptor *) - usb_interface->altsetting + i; - free((void *) ifp->extra); - if (ifp->endpoint) { - for (j = 0; j < ifp->bNumEndpoints; j++) - clear_endpoint((struct libusb_endpoint_descriptor *) - ifp->endpoint + j); - } - free((void *) ifp->endpoint); - } - } - free((void *) usb_interface->altsetting); - usb_interface->altsetting = NULL; -} - -static int parse_interface(libusb_context *ctx, - struct libusb_interface *usb_interface, unsigned char *buffer, int size, - int host_endian) -{ - int i; - int len; - int r; - int parsed = 0; - int interface_number = -1; - struct usb_descriptor_header header; - struct libusb_interface_descriptor *ifp; - unsigned char *begin; - - usb_interface->num_altsetting = 0; - - while (size >= INTERFACE_DESC_LENGTH) { - struct libusb_interface_descriptor *altsetting = - (struct libusb_interface_descriptor *) usb_interface->altsetting; - altsetting = usbi_reallocf(altsetting, - sizeof(struct libusb_interface_descriptor) * - (usb_interface->num_altsetting + 1)); - if (!altsetting) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - usb_interface->altsetting = altsetting; - - ifp = altsetting + usb_interface->num_altsetting; - usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0); - if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - ifp->bDescriptorType, LIBUSB_DT_INTERFACE); - return parsed; - } - if (ifp->bLength < INTERFACE_DESC_LENGTH) { - usbi_err(ctx, "invalid interface bLength (%d)", - ifp->bLength); - r = LIBUSB_ERROR_IO; - goto err; - } - if (ifp->bLength > size) { - usbi_warn(ctx, "short intf descriptor read %d/%d", - size, ifp->bLength); - return parsed; - } - if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { - usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints); - r = LIBUSB_ERROR_IO; - goto err; - } - - usb_interface->num_altsetting++; - ifp->extra = NULL; - ifp->extra_length = 0; - ifp->endpoint = NULL; - - if (interface_number == -1) - interface_number = ifp->bInterfaceNumber; - - /* Skip over the interface */ - buffer += ifp->bLength; - parsed += ifp->bLength; - size -= ifp->bLength; - - begin = buffer; - - /* Skip over any interface, class or vendor descriptors */ - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, - "invalid extra intf desc len (%d)", - header.bLength); - r = LIBUSB_ERROR_IO; - goto err; - } else if (header.bLength > size) { - usbi_warn(ctx, - "short extra intf desc read %d/%d", - size, header.bLength); - return parsed; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - buffer += header.bLength; - parsed += header.bLength; - size -= header.bLength; - } - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - ifp->extra = malloc(len); - if (!ifp->extra) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - memcpy((unsigned char *) ifp->extra, begin, len); - ifp->extra_length = len; - } - - if (ifp->bNumEndpoints > 0) { - struct libusb_endpoint_descriptor *endpoint; - endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor)); - ifp->endpoint = endpoint; - if (!endpoint) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - - for (i = 0; i < ifp->bNumEndpoints; i++) { - r = parse_endpoint(ctx, endpoint + i, buffer, size, - host_endian); - if (r < 0) - goto err; - if (r == 0) { - ifp->bNumEndpoints = (uint8_t)i; - break; - } - - buffer += r; - parsed += r; - size -= r; - } - } - - /* We check to see if it's an alternate to this one */ - ifp = (struct libusb_interface_descriptor *) buffer; - if (size < LIBUSB_DT_INTERFACE_SIZE || - ifp->bDescriptorType != LIBUSB_DT_INTERFACE || - ifp->bInterfaceNumber != interface_number) - return parsed; - } - - return parsed; -err: - clear_interface(usb_interface); - return r; -} - -static void clear_configuration(struct libusb_config_descriptor *config) -{ - int i; - if (config->interface) { - for (i = 0; i < config->bNumInterfaces; i++) - clear_interface((struct libusb_interface *) - config->interface + i); - } - free((void *) config->interface); - free((void *) config->extra); -} - -static int parse_configuration(struct libusb_context *ctx, - struct libusb_config_descriptor *config, unsigned char *buffer, - int size, int host_endian) -{ - int i; - int r; - struct usb_descriptor_header header; - struct libusb_interface *usb_interface; - - if (size < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "short config descriptor read %d/%d", - size, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian); - if (config->bDescriptorType != LIBUSB_DT_CONFIG) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - config->bDescriptorType, LIBUSB_DT_CONFIG); - return LIBUSB_ERROR_IO; - } - if (config->bLength < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "invalid config bLength (%d)", config->bLength); - return LIBUSB_ERROR_IO; - } - if (config->bLength > size) { - usbi_err(ctx, "short config descriptor read %d/%d", - size, config->bLength); - return LIBUSB_ERROR_IO; - } - if (config->bNumInterfaces > USB_MAXINTERFACES) { - usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces); - return LIBUSB_ERROR_IO; - } - - usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface)); - config->interface = usb_interface; - if (!usb_interface) - return LIBUSB_ERROR_NO_MEM; - - buffer += config->bLength; - size -= config->bLength; - - config->extra = NULL; - config->extra_length = 0; - - for (i = 0; i < config->bNumInterfaces; i++) { - int len; - unsigned char *begin; - - /* Skip over the rest of the Class Specific or Vendor */ - /* Specific descriptors */ - begin = buffer; - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, - "invalid extra config desc len (%d)", - header.bLength); - r = LIBUSB_ERROR_IO; - goto err; - } else if (header.bLength > size) { - usbi_warn(ctx, - "short extra config desc read %d/%d", - size, header.bLength); - config->bNumInterfaces = (uint8_t)i; - return size; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType); - buffer += header.bLength; - size -= header.bLength; - } - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - /* FIXME: We should realloc and append here */ - if (!config->extra_length) { - config->extra = malloc(len); - if (!config->extra) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - - memcpy((unsigned char *) config->extra, begin, len); - config->extra_length = len; - } - } - - r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian); - if (r < 0) - goto err; - if (r == 0) { - config->bNumInterfaces = (uint8_t)i; - break; - } - - buffer += r; - size -= r; - } - - return size; - -err: - clear_configuration(config); - return r; -} - -static int raw_desc_to_config(struct libusb_context *ctx, - unsigned char *buf, int size, int host_endian, - struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor *_config = malloc(sizeof(*_config)); - int r; - - if (!_config) - return LIBUSB_ERROR_NO_MEM; - - r = parse_configuration(ctx, _config, buf, size, host_endian); - if (r < 0) { - usbi_err(ctx, "parse_configuration failed with error %d", r); - free(_config); - return r; - } else if (r > 0) { - usbi_warn(ctx, "still %d bytes of descriptor data left", r); - } - - *config = _config; - return LIBUSB_SUCCESS; -} - -int usbi_device_cache_descriptor(libusb_device *dev) -{ - int r, host_endian = 0; - - r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, - &host_endian); - if (r < 0) - return r; - - if (!host_endian) { - dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB); - dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor); - dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct); - dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice); - } - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Get the USB device descriptor for a given device. - * - * This is a non-blocking function; the device descriptor is cached in memory. - * - * Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this - * function always succeeds. - * - * \param dev the device - * \param desc output location for the descriptor data - * \returns 0 on success or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, - struct libusb_device_descriptor *desc) -{ - usbi_dbg(""); - memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor, - sizeof (dev->device_descriptor)); - return 0; -} - -/** \ingroup libusb_desc - * Get the USB configuration descriptor for the currently active configuration. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_config_descriptor - */ -int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, - struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor _config; - unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; - unsigned char *buf = NULL; - int host_endian = 0; - int r; - - r = usbi_backend.get_active_config_descriptor(dev, tmp, - LIBUSB_DT_CONFIG_SIZE, &host_endian); - if (r < 0) - return r; - if (r < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(dev->ctx, "short config descriptor read %d/%d", - r, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); - buf = malloc(_config.wTotalLength); - if (!buf) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_backend.get_active_config_descriptor(dev, buf, - _config.wTotalLength, &host_endian); - if (r >= 0) - r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - - free(buf); - return r; -} - -/** \ingroup libusb_desc - * Get a USB configuration descriptor based on its index. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param config_index the index of the configuration you wish to retrieve - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_active_config_descriptor() - * \see libusb_get_config_descriptor_by_value() - */ -int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, - uint8_t config_index, struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor _config; - unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; - unsigned char *buf = NULL; - int host_endian = 0; - int r; - - usbi_dbg("index %d", config_index); - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_NOT_FOUND; - - r = usbi_backend.get_config_descriptor(dev, config_index, tmp, - LIBUSB_DT_CONFIG_SIZE, &host_endian); - if (r < 0) - return r; - if (r < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(dev->ctx, "short config descriptor read %d/%d", - r, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); - buf = malloc(_config.wTotalLength); - if (!buf) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_backend.get_config_descriptor(dev, config_index, buf, - _config.wTotalLength, &host_endian); - if (r >= 0) - r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - - free(buf); - return r; -} - -/* iterate through all configurations, returning the index of the configuration - * matching a specific bConfigurationValue in the idx output parameter, or -1 - * if the config was not found. - * returns 0 on success or a LIBUSB_ERROR code - */ -int usbi_get_config_index_by_value(struct libusb_device *dev, - uint8_t bConfigurationValue, int *idx) -{ - uint8_t i; - - usbi_dbg("value %d", bConfigurationValue); - for (i = 0; i < dev->num_configurations; i++) { - unsigned char tmp[6]; - int host_endian; - int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp), - &host_endian); - if (r < 0) { - *idx = -1; - return r; - } - if (tmp[5] == bConfigurationValue) { - *idx = i; - return 0; - } - } - - *idx = -1; - return 0; -} - -/** \ingroup libusb_desc - * Get a USB configuration descriptor with a specific bConfigurationValue. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param bConfigurationValue the bConfigurationValue of the configuration you - * wish to retrieve - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_active_config_descriptor() - * \see libusb_get_config_descriptor() - */ -int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, - uint8_t bConfigurationValue, struct libusb_config_descriptor **config) -{ - int r, idx, host_endian; - unsigned char *buf = NULL; - - if (usbi_backend.get_config_descriptor_by_value) { - r = usbi_backend.get_config_descriptor_by_value(dev, - bConfigurationValue, &buf, &host_endian); - if (r < 0) - return r; - return raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - } - - r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx); - if (r < 0) - return r; - else if (idx == -1) - return LIBUSB_ERROR_NOT_FOUND; - else - return libusb_get_config_descriptor(dev, (uint8_t) idx, config); -} - -/** \ingroup libusb_desc - * Free a configuration descriptor obtained from - * libusb_get_active_config_descriptor() or libusb_get_config_descriptor(). - * It is safe to call this function with a NULL config parameter, in which - * case the function simply returns. - * - * \param config the configuration descriptor to free - */ -void API_EXPORTED libusb_free_config_descriptor( - struct libusb_config_descriptor *config) -{ - if (!config) - return; - - clear_configuration(config); - free(config); -} - -/** \ingroup libusb_desc - * Get an endpoints superspeed endpoint companion descriptor (if any) - * - * \param ctx the context to operate on, or NULL for the default context - * \param endpoint endpoint descriptor from which to get the superspeed - * endpoint companion descriptor - * \param ep_comp output location for the superspeed endpoint companion - * descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_ss_endpoint_companion_descriptor() after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor( - struct libusb_context *ctx, - const struct libusb_endpoint_descriptor *endpoint, - struct libusb_ss_endpoint_companion_descriptor **ep_comp) -{ - struct usb_descriptor_header header; - int size = endpoint->extra_length; - const unsigned char *buffer = endpoint->extra; - - *ep_comp = NULL; - - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < 2 || header.bLength > size) { - usbi_err(ctx, "invalid descriptor length %d", - header.bLength); - return LIBUSB_ERROR_IO; - } - if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) { - buffer += header.bLength; - size -= header.bLength; - continue; - } - if (header.bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) { - usbi_err(ctx, "invalid ss-ep-comp-desc length %d", - header.bLength); - return LIBUSB_ERROR_IO; - } - *ep_comp = malloc(sizeof(**ep_comp)); - if (*ep_comp == NULL) - return LIBUSB_ERROR_NO_MEM; - usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0); - return LIBUSB_SUCCESS; - } - return LIBUSB_ERROR_NOT_FOUND; -} - -/** \ingroup libusb_desc - * Free a superspeed endpoint companion descriptor obtained from - * libusb_get_ss_endpoint_companion_descriptor(). - * It is safe to call this function with a NULL ep_comp parameter, in which - * case the function simply returns. - * - * \param ep_comp the superspeed endpoint companion descriptor to free - */ -void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor( - struct libusb_ss_endpoint_companion_descriptor *ep_comp) -{ - free(ep_comp); -} - -static int parse_bos(struct libusb_context *ctx, - struct libusb_bos_descriptor **bos, - unsigned char *buffer, int size, int host_endian) -{ - struct libusb_bos_descriptor bos_header, *_bos; - struct libusb_bos_dev_capability_descriptor dev_cap; - int i; - - if (size < LIBUSB_DT_BOS_SIZE) { - usbi_err(ctx, "short bos descriptor read %d/%d", - size, LIBUSB_DT_BOS_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian); - if (bos_header.bDescriptorType != LIBUSB_DT_BOS) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - bos_header.bDescriptorType, LIBUSB_DT_BOS); - return LIBUSB_ERROR_IO; - } - if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) { - usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength); - return LIBUSB_ERROR_IO; - } - if (bos_header.bLength > size) { - usbi_err(ctx, "short bos descriptor read %d/%d", - size, bos_header.bLength); - return LIBUSB_ERROR_IO; - } - - _bos = calloc (1, - sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *)); - if (!_bos) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian); - buffer += bos_header.bLength; - size -= bos_header.bLength; - - /* Get the device capability descriptors */ - for (i = 0; i < bos_header.bNumDeviceCaps; i++) { - if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { - usbi_warn(ctx, "short dev-cap descriptor read %d/%d", - size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE); - break; - } - usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian); - if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) { - usbi_warn(ctx, "unexpected descriptor %x (expected %x)", - dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY); - break; - } - if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { - usbi_err(ctx, "invalid dev-cap bLength (%d)", - dev_cap.bLength); - libusb_free_bos_descriptor(_bos); - return LIBUSB_ERROR_IO; - } - if (dev_cap.bLength > size) { - usbi_warn(ctx, "short dev-cap descriptor read %d/%d", - size, dev_cap.bLength); - break; - } - - _bos->dev_capability[i] = malloc(dev_cap.bLength); - if (!_bos->dev_capability[i]) { - libusb_free_bos_descriptor(_bos); - return LIBUSB_ERROR_NO_MEM; - } - memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength); - buffer += dev_cap.bLength; - size -= dev_cap.bLength; - } - _bos->bNumDeviceCaps = (uint8_t)i; - *bos = _bos; - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Get a Binary Object Store (BOS) descriptor - * This is a BLOCKING function, which will send requests to the device. - * - * \param dev_handle the handle of an open libusb device - * \param bos output location for the BOS descriptor. Only valid if 0 was returned. - * Must be freed with \ref libusb_free_bos_descriptor() after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor - * \returns another LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, - struct libusb_bos_descriptor **bos) -{ - struct libusb_bos_descriptor _bos; - uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0}; - unsigned char *bos_data = NULL; - const int host_endian = 0; - int r; - - /* Read the BOS. This generates 2 requests on the bus, - * one for the header, and one for the full BOS */ - r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header, - LIBUSB_DT_BOS_SIZE); - if (r < 0) { - if (r != LIBUSB_ERROR_PIPE) - usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); - return r; - } - if (r < LIBUSB_DT_BOS_SIZE) { - usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d", - r, LIBUSB_DT_BOS_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian); - usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities", - _bos.wTotalLength, _bos.bNumDeviceCaps); - bos_data = calloc(_bos.wTotalLength, 1); - if (bos_data == NULL) - return LIBUSB_ERROR_NO_MEM; - - r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, - _bos.wTotalLength); - if (r >= 0) - r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian); - else - usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); - - free(bos_data); - return r; -} - -/** \ingroup libusb_desc - * Free a BOS descriptor obtained from libusb_get_bos_descriptor(). - * It is safe to call this function with a NULL bos parameter, in which - * case the function simply returns. - * - * \param bos the BOS descriptor to free - */ -void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) -{ - int i; - - if (!bos) - return; - - for (i = 0; i < bos->bNumDeviceCaps; i++) - free(bos->dev_capability[i]); - free(bos); -} - -/** \ingroup libusb_desc - * Get an USB 2.0 Extension descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION - * LIBUSB_BT_USB_2_0_EXTENSION - * \param usb_2_0_extension output location for the USB 2.0 Extension - * descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_usb_2_0_extension_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_usb_2_0_extension_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) -{ - struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_USB_2_0_EXTENSION); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE); - return LIBUSB_ERROR_IO; - } - - _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension)); - if (!_usb_2_0_extension) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd", - _usb_2_0_extension, host_endian); - - *usb_2_0_extension = _usb_2_0_extension; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a USB 2.0 Extension descriptor obtained from - * libusb_get_usb_2_0_extension_descriptor(). - * It is safe to call this function with a NULL usb_2_0_extension parameter, - * in which case the function simply returns. - * - * \param usb_2_0_extension the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_usb_2_0_extension_descriptor( - struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) -{ - free(usb_2_0_extension); -} - -/** \ingroup libusb_desc - * Get a SuperSpeed USB Device Capability descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * \param ss_usb_device_cap output location for the SuperSpeed USB Device - * Capability descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_ss_usb_device_capability_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap) -{ - struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_SS_USB_DEVICE_CAPABILITY); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE); - return LIBUSB_ERROR_IO; - } - - _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap)); - if (!_ss_usb_device_cap) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw", - _ss_usb_device_cap, host_endian); - - *ss_usb_device_cap = _ss_usb_device_cap; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a SuperSpeed USB Device Capability descriptor obtained from - * libusb_get_ss_usb_device_capability_descriptor(). - * It is safe to call this function with a NULL ss_usb_device_cap - * parameter, in which case the function simply returns. - * - * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( - struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap) -{ - free(ss_usb_device_cap); -} - -/** \ingroup libusb_desc - * Get a Container ID descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID - * LIBUSB_BT_CONTAINER_ID - * \param container_id output location for the Container ID descriptor. - * Only valid if 0 was returned. Must be freed with - * libusb_free_container_id_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_container_id_descriptor **container_id) -{ - struct libusb_container_id_descriptor *_container_id; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_CONTAINER_ID); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE); - return LIBUSB_ERROR_IO; - } - - _container_id = malloc(sizeof(*_container_id)); - if (!_container_id) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu", - _container_id, host_endian); - - *container_id = _container_id; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a Container ID descriptor obtained from - * libusb_get_container_id_descriptor(). - * It is safe to call this function with a NULL container_id parameter, - * in which case the function simply returns. - * - * \param container_id the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_container_id_descriptor( - struct libusb_container_id_descriptor *container_id) -{ - free(container_id); -} - -/** \ingroup libusb_desc - * Retrieve a string descriptor in C style ASCII. - * - * Wrapper around libusb_get_string_descriptor(). Uses the first language - * supported by the device. - * - * \param dev_handle a device handle - * \param desc_index the index of the descriptor to retrieve - * \param data output buffer for ASCII string descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, - uint8_t desc_index, unsigned char *data, int length) -{ - unsigned char tbuf[255]; /* Some devices choke on size > 255 */ - int r, si, di; - uint16_t langid; - - /* Asking for the zero'th index is special - it returns a string - * descriptor that contains all the language IDs supported by the - * device. Typically there aren't many - often only one. Language - * IDs are 16 bit numbers, and they start at the third byte in the - * descriptor. There's also no point in trying to read descriptor 0 - * with this function. See USB 2.0 specification section 9.6.7 for - * more information. - */ - - if (desc_index == 0) - return LIBUSB_ERROR_INVALID_PARAM; - - r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf)); - if (r < 0) - return r; - - if (r < 4) - return LIBUSB_ERROR_IO; - - langid = tbuf[2] | (tbuf[3] << 8); - - r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf, - sizeof(tbuf)); - if (r < 0) - return r; - - if (tbuf[1] != LIBUSB_DT_STRING) - return LIBUSB_ERROR_IO; - - if (tbuf[0] > r) - return LIBUSB_ERROR_IO; - - di = 0; - for (si = 2; si < tbuf[0]; si += 2) { - if (di >= (length - 1)) - break; - - if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */ - data[di++] = '?'; - else - data[di++] = tbuf[si]; - } - - data[di] = 0; - return di; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c deleted file mode 100644 index a4320bc42e..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Hotplug functions for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2012-2013 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include - -#include "libusbi.h" -#include "hotplug.h" - -/** - * @defgroup libusb_hotplug Device hotplug event notification - * This page details how to use the libusb hotplug interface, where available. - * - * Be mindful that not all platforms currently implement hotplug notification and - * that you should first call on \ref libusb_has_capability() with parameter - * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available. - * - * \page libusb_hotplug Device hotplug event notification - * - * \section hotplug_intro Introduction - * - * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support - * for hotplug events on some platforms (you should test if your platform - * supports hotplug notification by calling \ref libusb_has_capability() with - * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). - * - * This interface allows you to request notification for the arrival and departure - * of matching USB devices. - * - * To receive hotplug notification you register a callback by calling - * \ref libusb_hotplug_register_callback(). This function will optionally return - * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback(). - * - * A callback function must return an int (0 or 1) indicating whether the callback is - * expecting additional events. Returning 0 will rearm the callback and 1 will cause - * the callback to be deregistered. Note that when callbacks are called from - * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE - * flag, the callback return value is ignored, iow you cannot cause a callback - * to be deregistered by returning 1 when it is called from - * libusb_hotplug_register_callback(). - * - * Callbacks for a particular context are automatically deregistered by libusb_exit(). - * - * As of 1.0.16 there are two supported hotplug events: - * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use - * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available - * - * A hotplug event can listen for either or both of these events. - * - * Note: If you receive notification that a device has left and you have any - * a libusb_device_handles for the device it is up to you to call libusb_close() - * on each device handle to free up any remaining resources associated with the device. - * Once a device has left any libusb_device_handle associated with the device - * are invalid and will remain so even if the device comes back. - * - * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered - * safe to call any libusb function that takes a libusb_device. It also safe to - * open a device and submit asynchronous transfers. However, most other functions - * that take a libusb_device_handle are not safe to call. Examples of such - * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking - * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must - * be used outside of the context of the hotplug callback. - * - * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function - * is libusb_get_device_descriptor(). - * - * The following code provides an example of the usage of the hotplug interface: -\code -#include -#include -#include -#include - -static int count = 0; - -int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event, void *user_data) { - static libusb_device_handle *dev_handle = NULL; - struct libusb_device_descriptor desc; - int rc; - - (void)libusb_get_device_descriptor(dev, &desc); - - if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { - rc = libusb_open(dev, &dev_handle); - if (LIBUSB_SUCCESS != rc) { - printf("Could not open USB device\n"); - } - } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { - if (dev_handle) { - libusb_close(dev_handle); - dev_handle = NULL; - } - } else { - printf("Unhandled event %d\n", event); - } - count++; - - return 0; -} - -int main (void) { - libusb_hotplug_callback_handle callback_handle; - int rc; - - libusb_init(NULL); - - rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, - LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, - &callback_handle); - if (LIBUSB_SUCCESS != rc) { - printf("Error creating a hotplug callback\n"); - libusb_exit(NULL); - return EXIT_FAILURE; - } - - while (count < 2) { - libusb_handle_events_completed(NULL, NULL); - nanosleep(&(struct timespec){0, 10000000UL}, NULL); - } - - libusb_hotplug_deregister_callback(NULL, callback_handle); - libusb_exit(NULL); - - return 0; -} -\endcode - */ - -static int usbi_hotplug_match_cb(struct libusb_context *ctx, - struct libusb_device *dev, libusb_hotplug_event event, - struct libusb_hotplug_callback *hotplug_cb) -{ - if (!(hotplug_cb->flags & event)) { - return 0; - } - - if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) && - hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { - return 0; - } - - if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) && - hotplug_cb->product_id != dev->device_descriptor.idProduct) { - return 0; - } - - if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) && - hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { - return 0; - } - - return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data); -} - -void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event) -{ - struct libusb_hotplug_callback *hotplug_cb, *next; - int ret; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { - if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) { - /* process deregistration in usbi_hotplug_deregister() */ - continue; - } - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb); - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - if (ret) { - list_del(&hotplug_cb->list); - free(hotplug_cb); - } - } - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); -} - -void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event) -{ - int pending_events; - struct libusb_hotplug_message *message = calloc(1, sizeof(*message)); - - if (!message) { - usbi_err(ctx, "error allocating hotplug message"); - return; - } - - message->event = event; - message->device = dev; - - /* Take the event data lock and add this message to the list. - * Only signal an event if there are no prior pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - list_add_tail(&message->list, &ctx->hotplug_msgs); - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); -} - -int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, - libusb_hotplug_event events, libusb_hotplug_flag flags, - int vendor_id, int product_id, int dev_class, - libusb_hotplug_callback_fn cb_fn, void *user_data, - libusb_hotplug_callback_handle *callback_handle) -{ - struct libusb_hotplug_callback *new_callback; - - /* check for sane values */ - if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) || - (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) || - (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || - (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || - (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || - !cb_fn) { - return LIBUSB_ERROR_INVALID_PARAM; - } - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - USBI_GET_CONTEXT(ctx); - - new_callback = calloc(1, sizeof(*new_callback)); - if (!new_callback) { - return LIBUSB_ERROR_NO_MEM; - } - - new_callback->flags = (uint8_t)events; - if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) { - new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID; - new_callback->vendor_id = (uint16_t)vendor_id; - } - if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) { - new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID; - new_callback->product_id = (uint16_t)product_id; - } - if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) { - new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID; - new_callback->dev_class = (uint8_t)dev_class; - } - new_callback->cb = cb_fn; - new_callback->user_data = user_data; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - /* protect the handle by the context hotplug lock */ - new_callback->handle = ctx->next_hotplug_cb_handle++; - - /* handle the unlikely case of overflow */ - if (ctx->next_hotplug_cb_handle < 0) - ctx->next_hotplug_cb_handle = 1; - - list_add(&new_callback->list, &ctx->hotplug_cbs); - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle); - - if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) { - ssize_t i, len; - struct libusb_device **devs; - - len = libusb_get_device_list(ctx, &devs); - if (len < 0) { - libusb_hotplug_deregister_callback(ctx, - new_callback->handle); - return (int)len; - } - - for (i = 0; i < len; i++) { - usbi_hotplug_match_cb(ctx, devs[i], - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, - new_callback); - } - - libusb_free_device_list(devs, 1); - } - - - if (callback_handle) - *callback_handle = new_callback->handle; - - return LIBUSB_SUCCESS; -} - -void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx, - libusb_hotplug_callback_handle callback_handle) -{ - struct libusb_hotplug_callback *hotplug_cb; - int deregistered = 0; - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return; - } - - USBI_GET_CONTEXT(ctx); - - usbi_dbg("deregister hotplug cb %d", callback_handle); - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { - if (callback_handle == hotplug_cb->handle) { - /* Mark this callback for deregistration */ - hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE; - deregistered = 1; - } - } - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - if (deregistered) { - int pending_events; - - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED; - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - } -} - -void usbi_hotplug_deregister(struct libusb_context *ctx, int forced) -{ - struct libusb_hotplug_callback *hotplug_cb, *next; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { - if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) { - usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb, - hotplug_cb->handle); - list_del(&hotplug_cb->list); - free(hotplug_cb); - } - } - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h deleted file mode 100644 index dbadbcb93d..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Hotplug support for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2012-2013 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef USBI_HOTPLUG_H -#define USBI_HOTPLUG_H - -#include "libusbi.h" - -enum usbi_hotplug_flags { - /* This callback is interested in device arrivals */ - USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, - - /* This callback is interested in device removals */ - USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, - - /* IMPORTANT: The values for the below entries must start *after* - * the highest value of the above entries!!! - */ - - /* The vendor_id field is valid for matching */ - USBI_HOTPLUG_VENDOR_ID_VALID = (1 << 3), - - /* The product_id field is valid for matching */ - USBI_HOTPLUG_PRODUCT_ID_VALID = (1 << 4), - - /* The dev_class field is valid for matching */ - USBI_HOTPLUG_DEV_CLASS_VALID = (1 << 5), - - /* This callback has been unregistered and needs to be freed */ - USBI_HOTPLUG_NEEDS_FREE = (1 << 6), -}; - -/** \ingroup hotplug - * The hotplug callback structure. The user populates this structure with - * libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback() - * to receive notification of hotplug events. - */ -struct libusb_hotplug_callback { - /** Flags that control how this callback behaves */ - uint8_t flags; - - /** Vendor ID to match (if flags says this is valid) */ - uint16_t vendor_id; - - /** Product ID to match (if flags says this is valid) */ - uint16_t product_id; - - /** Device class to match (if flags says this is valid) */ - uint8_t dev_class; - - /** Callback function to invoke for matching event/device */ - libusb_hotplug_callback_fn cb; - - /** Handle for this callback (used to match on deregister) */ - libusb_hotplug_callback_handle handle; - - /** User data that will be passed to the callback function */ - void *user_data; - - /** List this callback is registered in (ctx->hotplug_cbs) */ - struct list_head list; -}; - -struct libusb_hotplug_message { - /** The hotplug event that occurred */ - libusb_hotplug_event event; - - /** The device for which this hotplug event occurred */ - struct libusb_device *device; - - /** List this message is contained in (ctx->hotplug_msgs) */ - struct list_head list; -}; - -void usbi_hotplug_deregister(struct libusb_context *ctx, int forced); -void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event); -void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event); - -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/io.c b/vendor/github.com/karalabe/usb/libusb/libusb/io.c deleted file mode 100644 index a03bfaae1a..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/io.c +++ /dev/null @@ -1,2822 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * I/O functions for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef USBI_TIMERFD_AVAILABLE -#include -#endif - -#include "libusbi.h" -#include "hotplug.h" - -/** - * \page libusb_io Synchronous and asynchronous device I/O - * - * \section io_intro Introduction - * - * If you're using libusb in your application, you're probably wanting to - * perform I/O with devices - you want to perform USB data transfers. - * - * libusb offers two separate interfaces for device I/O. This page aims to - * introduce the two in order to help you decide which one is more suitable - * for your application. You can also choose to use both interfaces in your - * application by considering each transfer on a case-by-case basis. - * - * Once you have read through the following discussion, you should consult the - * detailed API documentation pages for the details: - * - \ref libusb_syncio - * - \ref libusb_asyncio - * - * \section theory Transfers at a logical level - * - * At a logical level, USB transfers typically happen in two parts. For - * example, when reading data from a endpoint: - * -# A request for data is sent to the device - * -# Some time later, the incoming data is received by the host - * - * or when writing data to an endpoint: - * - * -# The data is sent to the device - * -# Some time later, the host receives acknowledgement from the device that - * the data has been transferred. - * - * There may be an indefinite delay between the two steps. Consider a - * fictional USB input device with a button that the user can press. In order - * to determine when the button is pressed, you would likely submit a request - * to read data on a bulk or interrupt endpoint and wait for data to arrive. - * Data will arrive when the button is pressed by the user, which is - * potentially hours later. - * - * libusb offers both a synchronous and an asynchronous interface to performing - * USB transfers. The main difference is that the synchronous interface - * combines both steps indicated above into a single function call, whereas - * the asynchronous interface separates them. - * - * \section sync The synchronous interface - * - * The synchronous I/O interface allows you to perform a USB transfer with - * a single function call. When the function call returns, the transfer has - * completed and you can parse the results. - * - * If you have used the libusb-0.1 before, this I/O style will seem familar to - * you. libusb-0.1 only offered a synchronous interface. - * - * In our input device example, to read button presses you might write code - * in the following style: -\code -unsigned char data[4]; -int actual_length; -int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); -if (r == 0 && actual_length == sizeof(data)) { - // results of the transaction can now be found in the data buffer - // parse them here and report button press -} else { - error(); -} -\endcode - * - * The main advantage of this model is simplicity: you did everything with - * a single simple function call. - * - * However, this interface has its limitations. Your application will sleep - * inside libusb_bulk_transfer() until the transaction has completed. If it - * takes the user 3 hours to press the button, your application will be - * sleeping for that long. Execution will be tied up inside the library - - * the entire thread will be useless for that duration. - * - * Another issue is that by tieing up the thread with that single transaction - * there is no possibility of performing I/O with multiple endpoints and/or - * multiple devices simultaneously, unless you resort to creating one thread - * per transaction. - * - * Additionally, there is no opportunity to cancel the transfer after the - * request has been submitted. - * - * For details on how to use the synchronous API, see the - * \ref libusb_syncio "synchronous I/O API documentation" pages. - * - * \section async The asynchronous interface - * - * Asynchronous I/O is the most significant new feature in libusb-1.0. - * Although it is a more complex interface, it solves all the issues detailed - * above. - * - * Instead of providing which functions that block until the I/O has complete, - * libusb's asynchronous interface presents non-blocking functions which - * begin a transfer and then return immediately. Your application passes a - * callback function pointer to this non-blocking function, which libusb will - * call with the results of the transaction when it has completed. - * - * Transfers which have been submitted through the non-blocking functions - * can be cancelled with a separate function call. - * - * The non-blocking nature of this interface allows you to be simultaneously - * performing I/O to multiple endpoints on multiple devices, without having - * to use threads. - * - * This added flexibility does come with some complications though: - * - In the interest of being a lightweight library, libusb does not create - * threads and can only operate when your application is calling into it. Your - * application must call into libusb from it's main loop when events are ready - * to be handled, or you must use some other scheme to allow libusb to - * undertake whatever work needs to be done. - * - libusb also needs to be called into at certain fixed points in time in - * order to accurately handle transfer timeouts. - * - Memory handling becomes more complex. You cannot use stack memory unless - * the function with that stack is guaranteed not to return until the transfer - * callback has finished executing. - * - You generally lose some linearity from your code flow because submitting - * the transfer request is done in a separate function from where the transfer - * results are handled. This becomes particularly obvious when you want to - * submit a second transfer based on the results of an earlier transfer. - * - * Internally, libusb's synchronous interface is expressed in terms of function - * calls to the asynchronous interface. - * - * For details on how to use the asynchronous API, see the - * \ref libusb_asyncio "asynchronous I/O API" documentation pages. - */ - - -/** - * \page libusb_packetoverflow Packets and overflows - * - * \section packets Packet abstraction - * - * The USB specifications describe how data is transmitted in packets, with - * constraints on packet size defined by endpoint descriptors. The host must - * not send data payloads larger than the endpoint's maximum packet size. - * - * libusb and the underlying OS abstract out the packet concept, allowing you - * to request transfers of any size. Internally, the request will be divided - * up into correctly-sized packets. You do not have to be concerned with - * packet sizes, but there is one exception when considering overflows. - * - * \section overflow Bulk/interrupt transfer overflows - * - * When requesting data on a bulk endpoint, libusb requires you to supply a - * buffer and the maximum number of bytes of data that libusb can put in that - * buffer. However, the size of the buffer is not communicated to the device - - * the device is just asked to send any amount of data. - * - * There is no problem if the device sends an amount of data that is less than - * or equal to the buffer size. libusb reports this condition to you through - * the \ref libusb_transfer::actual_length "libusb_transfer.actual_length" - * field. - * - * Problems may occur if the device attempts to send more data than can fit in - * the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but - * other behaviour is largely undefined: actual_length may or may not be - * accurate, the chunk of data that can fit in the buffer (before overflow) - * may or may not have been transferred. - * - * Overflows are nasty, but can be avoided. Even though you were told to - * ignore packets above, think about the lower level details: each transfer is - * split into packets (typically small, with a maximum size of 512 bytes). - * Overflows can only happen if the final packet in an incoming data transfer - * is smaller than the actual packet that the device wants to transfer. - * Therefore, you will never see an overflow if your transfer buffer size is a - * multiple of the endpoint's packet size: the final packet will either - * fill up completely or will be only partially filled. - */ - -/** - * @defgroup libusb_asyncio Asynchronous device I/O - * - * This page details libusb's asynchronous (non-blocking) API for USB device - * I/O. This interface is very powerful but is also quite complex - you will - * need to read this page carefully to understand the necessary considerations - * and issues surrounding use of this interface. Simplistic applications - * may wish to consider the \ref libusb_syncio "synchronous I/O API" instead. - * - * The asynchronous interface is built around the idea of separating transfer - * submission and handling of transfer completion (the synchronous model - * combines both of these into one). There may be a long delay between - * submission and completion, however the asynchronous submission function - * is non-blocking so will return control to your application during that - * potentially long delay. - * - * \section asyncabstraction Transfer abstraction - * - * For the asynchronous I/O, libusb implements the concept of a generic - * transfer entity for all types of I/O (control, bulk, interrupt, - * isochronous). The generic transfer object must be treated slightly - * differently depending on which type of I/O you are performing with it. - * - * This is represented by the public libusb_transfer structure type. - * - * \section asynctrf Asynchronous transfers - * - * We can view asynchronous I/O as a 5 step process: - * -# Allocation: allocate a libusb_transfer - * -# Filling: populate the libusb_transfer instance with information - * about the transfer you wish to perform - * -# Submission: ask libusb to submit the transfer - * -# Completion handling: examine transfer results in the - * libusb_transfer structure - * -# Deallocation: clean up resources - * - * - * \subsection asyncalloc Allocation - * - * This step involves allocating memory for a USB transfer. This is the - * generic transfer object mentioned above. At this stage, the transfer - * is "blank" with no details about what type of I/O it will be used for. - * - * Allocation is done with the libusb_alloc_transfer() function. You must use - * this function rather than allocating your own transfers. - * - * \subsection asyncfill Filling - * - * This step is where you take a previously allocated transfer and fill it - * with information to determine the message type and direction, data buffer, - * callback function, etc. - * - * You can either fill the required fields yourself or you can use the - * helper functions: libusb_fill_control_transfer(), libusb_fill_bulk_transfer() - * and libusb_fill_interrupt_transfer(). - * - * \subsection asyncsubmit Submission - * - * When you have allocated a transfer and filled it, you can submit it using - * libusb_submit_transfer(). This function returns immediately but can be - * regarded as firing off the I/O request in the background. - * - * \subsection asynccomplete Completion handling - * - * After a transfer has been submitted, one of four things can happen to it: - * - * - The transfer completes (i.e. some data was transferred) - * - The transfer has a timeout and the timeout expires before all data is - * transferred - * - The transfer fails due to an error - * - The transfer is cancelled - * - * Each of these will cause the user-specified transfer callback function to - * be invoked. It is up to the callback function to determine which of the - * above actually happened and to act accordingly. - * - * The user-specified callback is passed a pointer to the libusb_transfer - * structure which was used to setup and submit the transfer. At completion - * time, libusb has populated this structure with results of the transfer: - * success or failure reason, number of bytes of data transferred, etc. See - * the libusb_transfer structure documentation for more information. - * - * Important Note: The user-specified callback is called from an event - * handling context. It is therefore important that no calls are made into - * libusb that will attempt to perform any event handling. Examples of such - * functions are any listed in the \ref libusb_syncio "synchronous API" and any of - * the blocking functions that retrieve \ref libusb_desc "USB descriptors". - * - * \subsection Deallocation - * - * When a transfer has completed (i.e. the callback function has been invoked), - * you are advised to free the transfer (unless you wish to resubmit it, see - * below). Transfers are deallocated with libusb_free_transfer(). - * - * It is undefined behaviour to free a transfer which has not completed. - * - * \section asyncresubmit Resubmission - * - * You may be wondering why allocation, filling, and submission are all - * separated above where they could reasonably be combined into a single - * operation. - * - * The reason for separation is to allow you to resubmit transfers without - * having to allocate new ones every time. This is especially useful for - * common situations dealing with interrupt endpoints - you allocate one - * transfer, fill and submit it, and when it returns with results you just - * resubmit it for the next interrupt. - * - * \section asynccancel Cancellation - * - * Another advantage of using the asynchronous interface is that you have - * the ability to cancel transfers which have not yet completed. This is - * done by calling the libusb_cancel_transfer() function. - * - * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the - * cancellation actually completes, the transfer's callback function will - * be invoked, and the callback function should check the transfer status to - * determine that it was cancelled. - * - * Freeing the transfer after it has been cancelled but before cancellation - * has completed will result in undefined behaviour. - * - * When a transfer is cancelled, some of the data may have been transferred. - * libusb will communicate this to you in the transfer callback. Do not assume - * that no data was transferred. - * - * \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints - * - * If your device does not have predictable transfer sizes (or it misbehaves), - * your application may submit a request for data on an IN endpoint which is - * smaller than the data that the device wishes to send. In some circumstances - * this will cause an overflow, which is a nasty condition to deal with. See - * the \ref libusb_packetoverflow page for discussion. - * - * \section asyncctrl Considerations for control transfers - * - * The libusb_transfer structure is generic and hence does not - * include specific fields for the control-specific setup packet structure. - * - * In order to perform a control transfer, you must place the 8-byte setup - * packet at the start of the data buffer. To simplify this, you could - * cast the buffer pointer to type struct libusb_control_setup, or you can - * use the helper function libusb_fill_control_setup(). - * - * The wLength field placed in the setup packet must be the length you would - * expect to be sent in the setup packet: the length of the payload that - * follows (or the expected maximum number of bytes to receive). However, - * the length field of the libusb_transfer object must be the length of - * the data buffer - i.e. it should be wLength plus the size of - * the setup packet (LIBUSB_CONTROL_SETUP_SIZE). - * - * If you use the helper functions, this is simplified for you: - * -# Allocate a buffer of size LIBUSB_CONTROL_SETUP_SIZE plus the size of the - * data you are sending/requesting. - * -# Call libusb_fill_control_setup() on the data buffer, using the transfer - * request size as the wLength value (i.e. do not include the extra space you - * allocated for the control setup). - * -# If this is a host-to-device transfer, place the data to be transferred - * in the data buffer, starting at offset LIBUSB_CONTROL_SETUP_SIZE. - * -# Call libusb_fill_control_transfer() to associate the data buffer with - * the transfer (and to set the remaining details such as callback and timeout). - * - Note that there is no parameter to set the length field of the transfer. - * The length is automatically inferred from the wLength field of the setup - * packet. - * -# Submit the transfer. - * - * The multi-byte control setup fields (wValue, wIndex and wLength) must - * be given in little-endian byte order (the endianness of the USB bus). - * Endianness conversion is transparently handled by - * libusb_fill_control_setup() which is documented to accept host-endian - * values. - * - * Further considerations are needed when handling transfer completion in - * your callback function: - * - As you might expect, the setup packet will still be sitting at the start - * of the data buffer. - * - If this was a device-to-host transfer, the received data will be sitting - * at offset LIBUSB_CONTROL_SETUP_SIZE into the buffer. - * - The actual_length field of the transfer structure is relative to the - * wLength of the setup packet, rather than the size of the data buffer. So, - * if your wLength was 4, your transfer's length was 12, then you - * should expect an actual_length of 4 to indicate that the data was - * transferred in entirity. - * - * To simplify parsing of setup packets and obtaining the data from the - * correct offset, you may wish to use the libusb_control_transfer_get_data() - * and libusb_control_transfer_get_setup() functions within your transfer - * callback. - * - * Even though control endpoints do not halt, a completed control transfer - * may have a LIBUSB_TRANSFER_STALL status code. This indicates the control - * request was not supported. - * - * \section asyncintr Considerations for interrupt transfers - * - * All interrupt transfers are performed using the polling interval presented - * by the bInterval value of the endpoint descriptor. - * - * \section asynciso Considerations for isochronous transfers - * - * Isochronous transfers are more complicated than transfers to - * non-isochronous endpoints. - * - * To perform I/O to an isochronous endpoint, allocate the transfer by calling - * libusb_alloc_transfer() with an appropriate number of isochronous packets. - * - * During filling, set \ref libusb_transfer::type "type" to - * \ref libusb_transfer_type::LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - * "LIBUSB_TRANSFER_TYPE_ISOCHRONOUS", and set - * \ref libusb_transfer::num_iso_packets "num_iso_packets" to a value less than - * or equal to the number of packets you requested during allocation. - * libusb_alloc_transfer() does not set either of these fields for you, given - * that you might not even use the transfer on an isochronous endpoint. - * - * Next, populate the length field for the first num_iso_packets entries in - * the \ref libusb_transfer::iso_packet_desc "iso_packet_desc" array. Section - * 5.6.3 of the USB2 specifications describe how the maximum isochronous - * packet length is determined by the wMaxPacketSize field in the endpoint - * descriptor. - * Two functions can help you here: - * - * - libusb_get_max_iso_packet_size() is an easy way to determine the max - * packet size for an isochronous endpoint. Note that the maximum packet - * size is actually the maximum number of bytes that can be transmitted in - * a single microframe, therefore this function multiplies the maximum number - * of bytes per transaction by the number of transaction opportunities per - * microframe. - * - libusb_set_iso_packet_lengths() assigns the same length to all packets - * within a transfer, which is usually what you want. - * - * For outgoing transfers, you'll obviously fill the buffer and populate the - * packet descriptors in hope that all the data gets transferred. For incoming - * transfers, you must ensure the buffer has sufficient capacity for - * the situation where all packets transfer the full amount of requested data. - * - * Completion handling requires some extra consideration. The - * \ref libusb_transfer::actual_length "actual_length" field of the transfer - * is meaningless and should not be examined; instead you must refer to the - * \ref libusb_iso_packet_descriptor::actual_length "actual_length" field of - * each individual packet. - * - * The \ref libusb_transfer::status "status" field of the transfer is also a - * little misleading: - * - If the packets were submitted and the isochronous data microframes - * completed normally, status will have value - * \ref libusb_transfer_status::LIBUSB_TRANSFER_COMPLETED - * "LIBUSB_TRANSFER_COMPLETED". Note that bus errors and software-incurred - * delays are not counted as transfer errors; the transfer.status field may - * indicate COMPLETED even if some or all of the packets failed. Refer to - * the \ref libusb_iso_packet_descriptor::status "status" field of each - * individual packet to determine packet failures. - * - The status field will have value - * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR - * "LIBUSB_TRANSFER_ERROR" only when serious errors were encountered. - * - Other transfer status codes occur with normal behaviour. - * - * The data for each packet will be found at an offset into the buffer that - * can be calculated as if each prior packet completed in full. The - * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple() - * functions may help you here. - * - * Note: Some operating systems (e.g. Linux) may impose limits on the - * length of individual isochronous packets and/or the total length of the - * isochronous transfer. Such limits can be difficult for libusb to detect, - * so the library will simply try and submit the transfer as set up by you. - * If the transfer fails to submit because it is too large, - * libusb_submit_transfer() will return - * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM". - * - * \section asyncmem Memory caveats - * - * In most circumstances, it is not safe to use stack memory for transfer - * buffers. This is because the function that fired off the asynchronous - * transfer may return before libusb has finished using the buffer, and when - * the function returns it's stack gets destroyed. This is true for both - * host-to-device and device-to-host transfers. - * - * The only case in which it is safe to use stack memory is where you can - * guarantee that the function owning the stack space for the buffer does not - * return until after the transfer's callback function has completed. In every - * other case, you need to use heap memory instead. - * - * \section asyncflags Fine control - * - * Through using this asynchronous interface, you may find yourself repeating - * a few simple operations many times. You can apply a bitwise OR of certain - * flags to a transfer to simplify certain things: - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_SHORT_NOT_OK - * "LIBUSB_TRANSFER_SHORT_NOT_OK" results in transfers which transferred - * less than the requested amount of data being marked with status - * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR "LIBUSB_TRANSFER_ERROR" - * (they would normally be regarded as COMPLETED) - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER - * "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusb to free the transfer - * buffer when freeing the transfer. - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_TRANSFER - * "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusb to automatically free the - * transfer after the transfer callback returns. - * - * \section asyncevent Event handling - * - * An asynchronous model requires that libusb perform work at various - * points in time - namely processing the results of previously-submitted - * transfers and invoking the user-supplied callback function. - * - * This gives rise to the libusb_handle_events() function which your - * application must call into when libusb has work do to. This gives libusb - * the opportunity to reap pending transfers, invoke callbacks, etc. - * - * There are 2 different approaches to dealing with libusb_handle_events: - * - * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated - * thread. - * -# Integrate libusb with your application's main event loop. libusb - * exposes a set of file descriptors which allow you to do this. - * - * The first approach has the big advantage that it will also work on Windows - * were libusb' poll API for select / poll integration is not available. So - * if you want to support Windows and use the async API, you must use this - * approach, see the \ref eventthread "Using an event handling thread" section - * below for details. - * - * If you prefer a single threaded approach with a single central event loop, - * see the \ref libusb_poll "polling and timing" section for how to integrate libusb - * into your application's main event loop. - * - * \section eventthread Using an event handling thread - * - * Lets begin with stating the obvious: If you're going to use a separate - * thread for libusb event handling, your callback functions MUST be - * threadsafe. - * - * Other then that doing event handling from a separate thread, is mostly - * simple. You can use an event thread function as follows: -\code -void *event_thread_func(void *ctx) -{ - while (event_thread_run) - libusb_handle_events(ctx); - - return NULL; -} -\endcode - * - * There is one caveat though, stopping this thread requires setting the - * event_thread_run variable to 0, and after that libusb_handle_events() needs - * to return control to event_thread_func. But unless some event happens, - * libusb_handle_events() will not return. - * - * There are 2 different ways of dealing with this, depending on if your - * application uses libusb' \ref libusb_hotplug "hotplug" support or not. - * - * Applications which do not use hotplug support, should not start the event - * thread until after their first call to libusb_open(), and should stop the - * thread when closing the last open device as follows: -\code -void my_close_handle(libusb_device_handle *dev_handle) -{ - if (open_devs == 1) - event_thread_run = 0; - - libusb_close(dev_handle); // This wakes up libusb_handle_events() - - if (open_devs == 1) - pthread_join(event_thread); - - open_devs--; -} -\endcode - * - * Applications using hotplug support should start the thread at program init, - * after having successfully called libusb_hotplug_register_callback(), and - * should stop the thread at program exit as follows: -\code -void my_libusb_exit(void) -{ - event_thread_run = 0; - libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events() - pthread_join(event_thread); - libusb_exit(ctx); -} -\endcode - */ - -/** - * @defgroup libusb_poll Polling and timing - * - * This page documents libusb's functions for polling events and timing. - * These functions are only necessary for users of the - * \ref libusb_asyncio "asynchronous API". If you are only using the simpler - * \ref libusb_syncio "synchronous API" then you do not need to ever call these - * functions. - * - * The justification for the functionality described here has already been - * discussed in the \ref asyncevent "event handling" section of the - * asynchronous API documentation. In summary, libusb does not create internal - * threads for event processing and hence relies on your application calling - * into libusb at certain points in time so that pending events can be handled. - * - * Your main loop is probably already calling poll() or select() or a - * variant on a set of file descriptors for other event sources (e.g. keyboard - * button presses, mouse movements, network sockets, etc). You then add - * libusb's file descriptors to your poll()/select() calls, and when activity - * is detected on such descriptors you know it is time to call - * libusb_handle_events(). - * - * There is one final event handling complication. libusb supports - * asynchronous transfers which time out after a specified time period. - * - * On some platforms a timerfd is used, so the timeout handling is just another - * fd, on other platforms this requires that libusb is called into at or after - * the timeout to handle it. So, in addition to considering libusb's file - * descriptors in your main event loop, you must also consider that libusb - * sometimes needs to be called into at fixed points in time even when there - * is no file descriptor activity, see \ref polltime details. - * - * In order to know precisely when libusb needs to be called into, libusb - * offers you a set of pollable file descriptors and information about when - * the next timeout expires. - * - * If you are using the asynchronous I/O API, you must take one of the two - * following options, otherwise your I/O will not complete. - * - * \section pollsimple The simple option - * - * If your application revolves solely around libusb and does not need to - * handle other event sources, you can have a program structure as follows: -\code -// initialize libusb -// find and open device -// maybe fire off some initial async I/O - -while (user_has_not_requested_exit) - libusb_handle_events(ctx); - -// clean up and exit -\endcode - * - * With such a simple main loop, you do not have to worry about managing - * sets of file descriptors or handling timeouts. libusb_handle_events() will - * handle those details internally. - * - * \section libusb_pollmain The more advanced option - * - * \note This functionality is currently only available on Unix-like platforms. - * On Windows, libusb_get_pollfds() simply returns NULL. Applications which - * want to support Windows are advised to use an \ref eventthread - * "event handling thread" instead. - * - * In more advanced applications, you will already have a main loop which - * is monitoring other event sources: network sockets, X11 events, mouse - * movements, etc. Through exposing a set of file descriptors, libusb is - * designed to cleanly integrate into such main loops. - * - * In addition to polling file descriptors for the other event sources, you - * take a set of file descriptors from libusb and monitor those too. When you - * detect activity on libusb's file descriptors, you call - * libusb_handle_events_timeout() in non-blocking mode. - * - * What's more, libusb may also need to handle events at specific moments in - * time. No file descriptor activity is generated at these times, so your - * own application needs to be continually aware of when the next one of these - * moments occurs (through calling libusb_get_next_timeout()), and then it - * needs to call libusb_handle_events_timeout() in non-blocking mode when - * these moments occur. This means that you need to adjust your - * poll()/select() timeout accordingly. - * - * libusb provides you with a set of file descriptors to poll and expects you - * to poll all of them, treating them as a single entity. The meaning of each - * file descriptor in the set is an internal implementation detail, - * platform-dependent and may vary from release to release. Don't try and - * interpret the meaning of the file descriptors, just do as libusb indicates, - * polling all of them at once. - * - * In pseudo-code, you want something that looks like: -\code -// initialise libusb - -libusb_get_pollfds(ctx) -while (user has not requested application exit) { - libusb_get_next_timeout(ctx); - poll(on libusb file descriptors plus any other event sources of interest, - using a timeout no larger than the value libusb just suggested) - if (poll() indicated activity on libusb file descriptors) - libusb_handle_events_timeout(ctx, &zero_tv); - if (time has elapsed to or beyond the libusb timeout) - libusb_handle_events_timeout(ctx, &zero_tv); - // handle events from other sources here -} - -// clean up and exit -\endcode - * - * \subsection polltime Notes on time-based events - * - * The above complication with having to track time and call into libusb at - * specific moments is a bit of a headache. For maximum compatibility, you do - * need to write your main loop as above, but you may decide that you can - * restrict the supported platforms of your application and get away with - * a more simplistic scheme. - * - * These time-based event complications are \b not required on the following - * platforms: - * - Darwin - * - Linux, provided that the following version requirements are satisfied: - * - Linux v2.6.27 or newer, compiled with timerfd support - * - glibc v2.9 or newer - * - libusb v1.0.5 or newer - * - * Under these configurations, libusb_get_next_timeout() will \em always return - * 0, so your main loop can be simplified to: -\code -// initialise libusb - -libusb_get_pollfds(ctx) -while (user has not requested application exit) { - poll(on libusb file descriptors plus any other event sources of interest, - using any timeout that you like) - if (poll() indicated activity on libusb file descriptors) - libusb_handle_events_timeout(ctx, &zero_tv); - // handle events from other sources here -} - -// clean up and exit -\endcode - * - * Do remember that if you simplify your main loop to the above, you will - * lose compatibility with some platforms (including legacy Linux platforms, - * and any future platforms supported by libusb which may have time-based - * event requirements). The resultant problems will likely appear as - * strange bugs in your application. - * - * You can use the libusb_pollfds_handle_timeouts() function to do a runtime - * check to see if it is safe to ignore the time-based event complications. - * If your application has taken the shortcut of ignoring libusb's next timeout - * in your main loop, then you are advised to check the return value of - * libusb_pollfds_handle_timeouts() during application startup, and to abort - * if the platform does suffer from these timing complications. - * - * \subsection fdsetchange Changes in the file descriptor set - * - * The set of file descriptors that libusb uses as event sources may change - * during the life of your application. Rather than having to repeatedly - * call libusb_get_pollfds(), you can set up notification functions for when - * the file descriptor set changes using libusb_set_pollfd_notifiers(). - * - * \subsection mtissues Multi-threaded considerations - * - * Unfortunately, the situation is complicated further when multiple threads - * come into play. If two threads are monitoring the same file descriptors, - * the fact that only one thread will be woken up when an event occurs causes - * some headaches. - * - * The events lock, event waiters lock, and libusb_handle_events_locked() - * entities are added to solve these problems. You do not need to be concerned - * with these entities otherwise. - * - * See the extra documentation: \ref libusb_mtasync - */ - -/** \page libusb_mtasync Multi-threaded applications and asynchronous I/O - * - * libusb is a thread-safe library, but extra considerations must be applied - * to applications which interact with libusb from multiple threads. - * - * The underlying issue that must be addressed is that all libusb I/O - * revolves around monitoring file descriptors through the poll()/select() - * system calls. This is directly exposed at the - * \ref libusb_asyncio "asynchronous interface" but it is important to note that the - * \ref libusb_syncio "synchronous interface" is implemented on top of the - * asynchonrous interface, therefore the same considerations apply. - * - * The issue is that if two or more threads are concurrently calling poll() - * or select() on libusb's file descriptors then only one of those threads - * will be woken up when an event arrives. The others will be completely - * oblivious that anything has happened. - * - * Consider the following pseudo-code, which submits an asynchronous transfer - * then waits for its completion. This style is one way you could implement a - * synchronous interface on top of the asynchronous interface (and libusb - * does something similar, albeit more advanced due to the complications - * explained on this page). - * -\code -void cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; -} - -void myfunc() { - struct libusb_transfer *transfer; - unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2))); - int completed = 0; - - transfer = libusb_alloc_transfer(0); - libusb_fill_control_setup(buffer, - LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x04, 0x01, 0, 0); - libusb_fill_control_transfer(transfer, dev, buffer, cb, &completed, 1000); - libusb_submit_transfer(transfer); - - while (!completed) { - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_timeout(ctx, &zero_tv); - } - printf("completed!"); - // other code here -} -\endcode - * - * Here we are serializing completion of an asynchronous event - * against a condition - the condition being completion of a specific transfer. - * The poll() loop has a long timeout to minimize CPU usage during situations - * when nothing is happening (it could reasonably be unlimited). - * - * If this is the only thread that is polling libusb's file descriptors, there - * is no problem: there is no danger that another thread will swallow up the - * event that we are interested in. On the other hand, if there is another - * thread polling the same descriptors, there is a chance that it will receive - * the event that we were interested in. In this situation, myfunc() - * will only realise that the transfer has completed on the next iteration of - * the loop, up to 120 seconds later. Clearly a two-minute delay is - * undesirable, and don't even think about using short timeouts to circumvent - * this issue! - * - * The solution here is to ensure that no two threads are ever polling the - * file descriptors at the same time. A naive implementation of this would - * impact the capabilities of the library, so libusb offers the scheme - * documented below to ensure no loss of functionality. - * - * Before we go any further, it is worth mentioning that all libusb-wrapped - * event handling procedures fully adhere to the scheme documented below. - * This includes libusb_handle_events() and its variants, and all the - * synchronous I/O functions - libusb hides this headache from you. - * - * \section Using libusb_handle_events() from multiple threads - * - * Even when only using libusb_handle_events() and synchronous I/O functions, - * you can still have a race condition. You might be tempted to solve the - * above with libusb_handle_events() like so: - * -\code - libusb_submit_transfer(transfer); - - while (!completed) { - libusb_handle_events(ctx); - } - printf("completed!"); -\endcode - * - * This however has a race between the checking of completed and - * libusb_handle_events() acquiring the events lock, so another thread - * could have completed the transfer, resulting in this thread hanging - * until either a timeout or another event occurs. See also commit - * 6696512aade99bb15d6792af90ae329af270eba6 which fixes this in the - * synchronous API implementation of libusb. - * - * Fixing this race requires checking the variable completed only after - * taking the event lock, which defeats the concept of just calling - * libusb_handle_events() without worrying about locking. This is why - * libusb-1.0.9 introduces the new libusb_handle_events_timeout_completed() - * and libusb_handle_events_completed() functions, which handles doing the - * completion check for you after they have acquired the lock: - * -\code - libusb_submit_transfer(transfer); - - while (!completed) { - libusb_handle_events_completed(ctx, &completed); - } - printf("completed!"); -\endcode - * - * This nicely fixes the race in our example. Note that if all you want to - * do is submit a single transfer and wait for its completion, then using - * one of the synchronous I/O functions is much easier. - * - * \section eventlock The events lock - * - * The problem is when we consider the fact that libusb exposes file - * descriptors to allow for you to integrate asynchronous USB I/O into - * existing main loops, effectively allowing you to do some work behind - * libusb's back. If you do take libusb's file descriptors and pass them to - * poll()/select() yourself, you need to be aware of the associated issues. - * - * The first concept to be introduced is the events lock. The events lock - * is used to serialize threads that want to handle events, such that only - * one thread is handling events at any one time. - * - * You must take the events lock before polling libusb file descriptors, - * using libusb_lock_events(). You must release the lock as soon as you have - * aborted your poll()/select() loop, using libusb_unlock_events(). - * - * \section threadwait Letting other threads do the work for you - * - * Although the events lock is a critical part of the solution, it is not - * enough on it's own. You might wonder if the following is sufficient... -\code - libusb_lock_events(ctx); - while (!completed) { - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_timeout(ctx, &zero_tv); - } - libusb_unlock_events(ctx); -\endcode - * ...and the answer is that it is not. This is because the transfer in the - * code shown above may take a long time (say 30 seconds) to complete, and - * the lock is not released until the transfer is completed. - * - * Another thread with similar code that wants to do event handling may be - * working with a transfer that completes after a few milliseconds. Despite - * having such a quick completion time, the other thread cannot check that - * status of its transfer until the code above has finished (30 seconds later) - * due to contention on the lock. - * - * To solve this, libusb offers you a mechanism to determine when another - * thread is handling events. It also offers a mechanism to block your thread - * until the event handling thread has completed an event (and this mechanism - * does not involve polling of file descriptors). - * - * After determining that another thread is currently handling events, you - * obtain the event waiters lock using libusb_lock_event_waiters(). - * You then re-check that some other thread is still handling events, and if - * so, you call libusb_wait_for_event(). - * - * libusb_wait_for_event() puts your application to sleep until an event - * occurs, or until a thread releases the events lock. When either of these - * things happen, your thread is woken up, and should re-check the condition - * it was waiting on. It should also re-check that another thread is handling - * events, and if not, it should start handling events itself. - * - * This looks like the following, as pseudo-code: -\code -retry: -if (libusb_try_lock_events(ctx) == 0) { - // we obtained the event lock: do our own event handling - while (!completed) { - if (!libusb_event_handling_ok(ctx)) { - libusb_unlock_events(ctx); - goto retry; - } - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_locked(ctx, 0); - } - libusb_unlock_events(ctx); -} else { - // another thread is doing event handling. wait for it to signal us that - // an event has completed - libusb_lock_event_waiters(ctx); - - while (!completed) { - // now that we have the event waiters lock, double check that another - // thread is still handling events for us. (it may have ceased handling - // events in the time it took us to reach this point) - if (!libusb_event_handler_active(ctx)) { - // whoever was handling events is no longer doing so, try again - libusb_unlock_event_waiters(ctx); - goto retry; - } - - libusb_wait_for_event(ctx, NULL); - } - libusb_unlock_event_waiters(ctx); -} -printf("completed!\n"); -\endcode - * - * A naive look at the above code may suggest that this can only support - * one event waiter (hence a total of 2 competing threads, the other doing - * event handling), because the event waiter seems to have taken the event - * waiters lock while waiting for an event. However, the system does support - * multiple event waiters, because libusb_wait_for_event() actually drops - * the lock while waiting, and reaquires it before continuing. - * - * We have now implemented code which can dynamically handle situations where - * nobody is handling events (so we should do it ourselves), and it can also - * handle situations where another thread is doing event handling (so we can - * piggyback onto them). It is also equipped to handle a combination of - * the two, for example, another thread is doing event handling, but for - * whatever reason it stops doing so before our condition is met, so we take - * over the event handling. - * - * Four functions were introduced in the above pseudo-code. Their importance - * should be apparent from the code shown above. - * -# libusb_try_lock_events() is a non-blocking function which attempts - * to acquire the events lock but returns a failure code if it is contended. - * -# libusb_event_handling_ok() checks that libusb is still happy for your - * thread to be performing event handling. Sometimes, libusb needs to - * interrupt the event handler, and this is how you can check if you have - * been interrupted. If this function returns 0, the correct behaviour is - * for you to give up the event handling lock, and then to repeat the cycle. - * The following libusb_try_lock_events() will fail, so you will become an - * events waiter. For more information on this, read \ref fullstory below. - * -# libusb_handle_events_locked() is a variant of - * libusb_handle_events_timeout() that you can call while holding the - * events lock. libusb_handle_events_timeout() itself implements similar - * logic to the above, so be sure not to call it when you are - * "working behind libusb's back", as is the case here. - * -# libusb_event_handler_active() determines if someone is currently - * holding the events lock - * - * You might be wondering why there is no function to wake up all threads - * blocked on libusb_wait_for_event(). This is because libusb can do this - * internally: it will wake up all such threads when someone calls - * libusb_unlock_events() or when a transfer completes (at the point after its - * callback has returned). - * - * \subsection fullstory The full story - * - * The above explanation should be enough to get you going, but if you're - * really thinking through the issues then you may be left with some more - * questions regarding libusb's internals. If you're curious, read on, and if - * not, skip to the next section to avoid confusing yourself! - * - * The immediate question that may spring to mind is: what if one thread - * modifies the set of file descriptors that need to be polled while another - * thread is doing event handling? - * - * There are 2 situations in which this may happen. - * -# libusb_open() will add another file descriptor to the poll set, - * therefore it is desirable to interrupt the event handler so that it - * restarts, picking up the new descriptor. - * -# libusb_close() will remove a file descriptor from the poll set. There - * are all kinds of race conditions that could arise here, so it is - * important that nobody is doing event handling at this time. - * - * libusb handles these issues internally, so application developers do not - * have to stop their event handlers while opening/closing devices. Here's how - * it works, focusing on the libusb_close() situation first: - * - * -# During initialization, libusb opens an internal pipe, and it adds the read - * end of this pipe to the set of file descriptors to be polled. - * -# During libusb_close(), libusb writes some dummy data on this event pipe. - * This immediately interrupts the event handler. libusb also records - * internally that it is trying to interrupt event handlers for this - * high-priority event. - * -# At this point, some of the functions described above start behaving - * differently: - * - libusb_event_handling_ok() starts returning 1, indicating that it is NOT - * OK for event handling to continue. - * - libusb_try_lock_events() starts returning 1, indicating that another - * thread holds the event handling lock, even if the lock is uncontended. - * - libusb_event_handler_active() starts returning 1, indicating that - * another thread is doing event handling, even if that is not true. - * -# The above changes in behaviour result in the event handler stopping and - * giving up the events lock very quickly, giving the high-priority - * libusb_close() operation a "free ride" to acquire the events lock. All - * threads that are competing to do event handling become event waiters. - * -# With the events lock held inside libusb_close(), libusb can safely remove - * a file descriptor from the poll set, in the safety of knowledge that - * nobody is polling those descriptors or trying to access the poll set. - * -# After obtaining the events lock, the close operation completes very - * quickly (usually a matter of milliseconds) and then immediately releases - * the events lock. - * -# At the same time, the behaviour of libusb_event_handling_ok() and friends - * reverts to the original, documented behaviour. - * -# The release of the events lock causes the threads that are waiting for - * events to be woken up and to start competing to become event handlers - * again. One of them will succeed; it will then re-obtain the list of poll - * descriptors, and USB I/O will then continue as normal. - * - * libusb_open() is similar, and is actually a more simplistic case. Upon a - * call to libusb_open(): - * - * -# The device is opened and a file descriptor is added to the poll set. - * -# libusb sends some dummy data on the event pipe, and records that it - * is trying to modify the poll descriptor set. - * -# The event handler is interrupted, and the same behaviour change as for - * libusb_close() takes effect, causing all event handling threads to become - * event waiters. - * -# The libusb_open() implementation takes its free ride to the events lock. - * -# Happy that it has successfully paused the events handler, libusb_open() - * releases the events lock. - * -# The event waiter threads are all woken up and compete to become event - * handlers again. The one that succeeds will obtain the list of poll - * descriptors again, which will include the addition of the new device. - * - * \subsection concl Closing remarks - * - * The above may seem a little complicated, but hopefully I have made it clear - * why such complications are necessary. Also, do not forget that this only - * applies to applications that take libusb's file descriptors and integrate - * them into their own polling loops. - * - * You may decide that it is OK for your multi-threaded application to ignore - * some of the rules and locks detailed above, because you don't think that - * two threads can ever be polling the descriptors at the same time. If that - * is the case, then that's good news for you because you don't have to worry. - * But be careful here; remember that the synchronous I/O functions do event - * handling internally. If you have one thread doing event handling in a loop - * (without implementing the rules and locking semantics documented above) - * and another trying to send a synchronous USB transfer, you will end up with - * two threads monitoring the same descriptors, and the above-described - * undesirable behaviour occurring. The solution is for your polling thread to - * play by the rules; the synchronous I/O functions do so, and this will result - * in them getting along in perfect harmony. - * - * If you do have a dedicated thread doing event handling, it is perfectly - * legal for it to take the event handling lock for long periods of time. Any - * synchronous I/O functions you call from other threads will transparently - * fall back to the "event waiters" mechanism detailed above. The only - * consideration that your event handling thread must apply is the one related - * to libusb_event_handling_ok(): you must call this before every poll(), and - * give up the events lock if instructed. - */ - -int usbi_io_init(struct libusb_context *ctx) -{ - int r; - - usbi_mutex_init(&ctx->flying_transfers_lock); - usbi_mutex_init(&ctx->events_lock); - usbi_mutex_init(&ctx->event_waiters_lock); - usbi_cond_init(&ctx->event_waiters_cond); - usbi_mutex_init(&ctx->event_data_lock); - usbi_tls_key_create(&ctx->event_handling_key); - list_init(&ctx->flying_transfers); - list_init(&ctx->ipollfds); - list_init(&ctx->hotplug_msgs); - list_init(&ctx->completed_transfers); - - /* FIXME should use an eventfd on kernels that support it */ - r = usbi_pipe(ctx->event_pipe); - if (r < 0) { - r = LIBUSB_ERROR_OTHER; - goto err; - } - - r = usbi_add_pollfd(ctx, ctx->event_pipe[0], POLLIN); - if (r < 0) - goto err_close_pipe; - -#ifdef USBI_TIMERFD_AVAILABLE - ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(), - TFD_NONBLOCK | TFD_CLOEXEC); - if (ctx->timerfd >= 0) { - usbi_dbg("using timerfd for timeouts"); - r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); - if (r < 0) - goto err_close_timerfd; - } else { - usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); - ctx->timerfd = -1; - } -#endif - - return 0; - -#ifdef USBI_TIMERFD_AVAILABLE -err_close_timerfd: - close(ctx->timerfd); - usbi_remove_pollfd(ctx, ctx->event_pipe[0]); -#endif -err_close_pipe: - usbi_close(ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[1]); -err: - usbi_mutex_destroy(&ctx->flying_transfers_lock); - usbi_mutex_destroy(&ctx->events_lock); - usbi_mutex_destroy(&ctx->event_waiters_lock); - usbi_cond_destroy(&ctx->event_waiters_cond); - usbi_mutex_destroy(&ctx->event_data_lock); - usbi_tls_key_delete(ctx->event_handling_key); - return r; -} - -void usbi_io_exit(struct libusb_context *ctx) -{ - usbi_remove_pollfd(ctx, ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[1]); -#ifdef USBI_TIMERFD_AVAILABLE - if (usbi_using_timerfd(ctx)) { - usbi_remove_pollfd(ctx, ctx->timerfd); - close(ctx->timerfd); - } -#endif - usbi_mutex_destroy(&ctx->flying_transfers_lock); - usbi_mutex_destroy(&ctx->events_lock); - usbi_mutex_destroy(&ctx->event_waiters_lock); - usbi_cond_destroy(&ctx->event_waiters_cond); - usbi_mutex_destroy(&ctx->event_data_lock); - usbi_tls_key_delete(ctx->event_handling_key); - if (ctx->pollfds) - free(ctx->pollfds); -} - -static int calculate_timeout(struct usbi_transfer *transfer) -{ - int r; - struct timespec current_time; - unsigned int timeout = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; - - if (!timeout) { - timerclear(&transfer->timeout); - return 0; - } - - r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); - if (r < 0) { - usbi_err(ITRANSFER_CTX(transfer), - "failed to read monotonic clock, errno=%d", errno); - return r; - } - - current_time.tv_sec += timeout / 1000; - current_time.tv_nsec += (timeout % 1000) * 1000000; - - while (current_time.tv_nsec >= 1000000000) { - current_time.tv_nsec -= 1000000000; - current_time.tv_sec++; - } - - TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time); - return 0; -} - -/** \ingroup libusb_asyncio - * Allocate a libusb transfer with a specified number of isochronous packet - * descriptors. The returned transfer is pre-initialized for you. When the new - * transfer is no longer needed, it should be freed with - * libusb_free_transfer(). - * - * Transfers intended for non-isochronous endpoints (e.g. control, bulk, - * interrupt) should specify an iso_packets count of zero. - * - * For transfers intended for isochronous endpoints, specify an appropriate - * number of packet descriptors to be allocated as part of the transfer. - * The returned transfer is not specially initialized for isochronous I/O; - * you are still required to set the - * \ref libusb_transfer::num_iso_packets "num_iso_packets" and - * \ref libusb_transfer::type "type" fields accordingly. - * - * It is safe to allocate a transfer with some isochronous packets and then - * use it on a non-isochronous endpoint. If you do this, ensure that at time - * of submission, num_iso_packets is 0 and that type is set appropriately. - * - * \param iso_packets number of isochronous packet descriptors to allocate - * \returns a newly allocated transfer, or NULL on error - */ -DEFAULT_VISIBILITY -struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( - int iso_packets) -{ - struct libusb_transfer *transfer; - size_t os_alloc_size = usbi_backend.transfer_priv_size; - size_t alloc_size = sizeof(struct usbi_transfer) - + sizeof(struct libusb_transfer) - + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) - + os_alloc_size; - struct usbi_transfer *itransfer = calloc(1, alloc_size); - if (!itransfer) - return NULL; - - itransfer->num_iso_packets = iso_packets; - usbi_mutex_init(&itransfer->lock); - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - usbi_dbg("transfer %p", transfer); - return transfer; -} - -/** \ingroup libusb_asyncio - * Free a transfer structure. This should be called for all transfers - * allocated with libusb_alloc_transfer(). - * - * If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER - * "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is - * non-NULL, this function will also free the transfer buffer using the - * standard system memory allocator (e.g. free()). - * - * It is legal to call this function with a NULL transfer. In this case, - * the function will simply return safely. - * - * It is not legal to free an active transfer (one which has been submitted - * and has not yet completed). - * - * \param transfer the transfer to free - */ -void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer; - if (!transfer) - return; - - usbi_dbg("transfer %p", transfer); - if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) - free(transfer->buffer); - - itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - usbi_mutex_destroy(&itransfer->lock); - free(itransfer); -} - -#ifdef USBI_TIMERFD_AVAILABLE -static int disarm_timerfd(struct libusb_context *ctx) -{ - const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } }; - int r; - - usbi_dbg(""); - r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL); - if (r < 0) - return LIBUSB_ERROR_OTHER; - else - return 0; -} - -/* iterates through the flying transfers, and rearms the timerfd based on the - * next upcoming timeout. - * must be called with flying_list locked. - * returns 0 on success or a LIBUSB_ERROR code on failure. - */ -static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) -{ - struct usbi_transfer *transfer; - - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - struct timeval *cur_tv = &transfer->timeout; - - /* if we've reached transfers of infinite timeout, then we have no - * arming to do */ - if (!timerisset(cur_tv)) - goto disarm; - - /* act on first transfer that has not already been handled */ - if (!(transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) { - int r; - const struct itimerspec it = { {0, 0}, - { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; - usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); - r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); - if (r < 0) - return LIBUSB_ERROR_OTHER; - return 0; - } - } - -disarm: - return disarm_timerfd(ctx); -} -#else -static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) -{ - UNUSED(ctx); - return 0; -} -#endif - -/* add a transfer to the (timeout-sorted) active transfers list. - * This function will return non 0 if fails to update the timer, - * in which case the transfer is *not* on the flying_transfers list. */ -static int add_to_flying_list(struct usbi_transfer *transfer) -{ - struct usbi_transfer *cur; - struct timeval *timeout = &transfer->timeout; - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int r; - int first = 1; - - r = calculate_timeout(transfer); - if (r) - return r; - - /* if we have no other flying transfers, start the list with this one */ - if (list_empty(&ctx->flying_transfers)) { - list_add(&transfer->list, &ctx->flying_transfers); - goto out; - } - - /* if we have infinite timeout, append to end of list */ - if (!timerisset(timeout)) { - list_add_tail(&transfer->list, &ctx->flying_transfers); - /* first is irrelevant in this case */ - goto out; - } - - /* otherwise, find appropriate place in list */ - list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) { - /* find first timeout that occurs after the transfer in question */ - struct timeval *cur_tv = &cur->timeout; - - if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) || - (cur_tv->tv_sec == timeout->tv_sec && - cur_tv->tv_usec > timeout->tv_usec)) { - list_add_tail(&transfer->list, &cur->list); - goto out; - } - first = 0; - } - /* first is 0 at this stage (list not empty) */ - - /* otherwise we need to be inserted at the end */ - list_add_tail(&transfer->list, &ctx->flying_transfers); -out: -#ifdef USBI_TIMERFD_AVAILABLE - if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) { - /* if this transfer has the lowest timeout of all active transfers, - * rearm the timerfd with this transfer's timeout */ - const struct itimerspec it = { {0, 0}, - { timeout->tv_sec, timeout->tv_usec * 1000 } }; - usbi_dbg("arm timerfd for timeout in %dms (first in line)", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); - r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); - if (r < 0) { - usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno); - r = LIBUSB_ERROR_OTHER; - } - } -#else - UNUSED(first); -#endif - - if (r) - list_del(&transfer->list); - - return r; -} - -/* remove a transfer from the active transfers list. - * This function will *always* remove the transfer from the - * flying_transfers list. It will return a LIBUSB_ERROR code - * if it fails to update the timer for the next timeout. */ -static int remove_from_flying_list(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int rearm_timerfd; - int r = 0; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - rearm_timerfd = (timerisset(&transfer->timeout) && - list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == transfer); - list_del(&transfer->list); - if (usbi_using_timerfd(ctx) && rearm_timerfd) - r = arm_timerfd_for_next_timeout(ctx); - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - return r; -} - -/** \ingroup libusb_asyncio - * Submit a transfer. This function will fire off the USB transfer and then - * return immediately. - * - * \param transfer the transfer to submit - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported - * by the operating system. - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than - * the operating system and/or hardware can support - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - int r; - - usbi_dbg("transfer %p", transfer); - - /* - * Important note on locking, this function takes / releases locks - * in the following order: - * take flying_transfers_lock - * take itransfer->lock - * clear transfer - * add to flying_transfers list - * release flying_transfers_lock - * submit transfer - * release itransfer->lock - * if submit failed: - * take flying_transfers_lock - * remove from flying_transfers list - * release flying_transfers_lock - * - * Note that it takes locks in the order a-b and then releases them - * in the same order a-b. This is somewhat unusual but not wrong, - * release order is not important as long as *all* locks are released - * before re-acquiring any locks. - * - * This means that the ordering of first releasing itransfer->lock - * and then re-acquiring the flying_transfers_list on error is - * important and must not be changed! - * - * This is done this way because when we take both locks we must always - * take flying_transfers_lock first to avoid ab-ba style deadlocks with - * the timeout handling and usbi_handle_disconnect paths. - * - * And we cannot release itransfer->lock before the submission is - * complete otherwise timeout handling for transfers with short - * timeouts may run before submission. - */ - usbi_mutex_lock(&ctx->flying_transfers_lock); - usbi_mutex_lock(&itransfer->lock); - if (itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_mutex_unlock(&itransfer->lock); - return LIBUSB_ERROR_BUSY; - } - itransfer->transferred = 0; - itransfer->state_flags = 0; - itransfer->timeout_flags = 0; - r = add_to_flying_list(itransfer); - if (r) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_mutex_unlock(&itransfer->lock); - return r; - } - /* - * We must release the flying transfers lock here, because with - * some backends the submit_transfer method is synchroneous. - */ - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - r = usbi_backend.submit_transfer(itransfer); - if (r == LIBUSB_SUCCESS) { - itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; - /* keep a reference to this device */ - libusb_ref_device(transfer->dev_handle->dev); - } - usbi_mutex_unlock(&itransfer->lock); - - if (r != LIBUSB_SUCCESS) - remove_from_flying_list(itransfer); - - return r; -} - -/** \ingroup libusb_asyncio - * Asynchronously cancel a previously submitted transfer. - * This function returns immediately, but this does not indicate cancellation - * is complete. Your callback function will be invoked at some later time - * with a transfer status of - * \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED - * "LIBUSB_TRANSFER_CANCELLED." - * - * \param transfer the transfer to cancel - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, - * already complete, or already cancelled. - * \returns a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - int r; - - usbi_dbg("transfer %p", transfer ); - usbi_mutex_lock(&itransfer->lock); - if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) - || (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - r = usbi_backend.cancel_transfer(itransfer); - if (r < 0) { - if (r != LIBUSB_ERROR_NOT_FOUND && - r != LIBUSB_ERROR_NO_DEVICE) - usbi_err(TRANSFER_CTX(transfer), - "cancel transfer failed error %d", r); - else - usbi_dbg("cancel transfer failed error %d", r); - - if (r == LIBUSB_ERROR_NO_DEVICE) - itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; - } - - itransfer->state_flags |= USBI_TRANSFER_CANCELLING; - -out: - usbi_mutex_unlock(&itransfer->lock); - return r; -} - -/** \ingroup libusb_asyncio - * Set a transfers bulk stream id. Note users are advised to use - * libusb_fill_bulk_stream_transfer() instead of calling this function - * directly. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to set the stream id for - * \param stream_id the stream id to set - * \see libusb_alloc_streams() - */ -void API_EXPORTED libusb_transfer_set_stream_id( - struct libusb_transfer *transfer, uint32_t stream_id) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - - itransfer->stream_id = stream_id; -} - -/** \ingroup libusb_asyncio - * Get a transfers bulk stream id. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to get the stream id for - * \returns the stream id for the transfer - */ -uint32_t API_EXPORTED libusb_transfer_get_stream_id( - struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - - return itransfer->stream_id; -} - -/* Handle completion of a transfer (completion might be an error condition). - * This will invoke the user-supplied callback function, which may end up - * freeing the transfer. Therefore you cannot use the transfer structure - * after calling this function, and you should free all backend-specific - * data before calling it. - * Do not call this function with the usbi_transfer lock held. User-specified - * callback functions may attempt to directly resubmit the transfer, which - * will attempt to take the lock. */ -int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, - enum libusb_transfer_status status) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_device_handle *dev_handle = transfer->dev_handle; - uint8_t flags; - int r; - - r = remove_from_flying_list(itransfer); - if (r < 0) - usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno); - - usbi_mutex_lock(&itransfer->lock); - itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT; - usbi_mutex_unlock(&itransfer->lock); - - if (status == LIBUSB_TRANSFER_COMPLETED - && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { - int rqlen = transfer->length; - if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) - rqlen -= LIBUSB_CONTROL_SETUP_SIZE; - if (rqlen != itransfer->transferred) { - usbi_dbg("interpreting short transfer as error"); - status = LIBUSB_TRANSFER_ERROR; - } - } - - flags = transfer->flags; - transfer->status = status; - transfer->actual_length = itransfer->transferred; - usbi_dbg("transfer %p has callback %p", transfer, transfer->callback); - if (transfer->callback) - transfer->callback(transfer); - /* transfer might have been freed by the above call, do not use from - * this point. */ - if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) - libusb_free_transfer(transfer); - libusb_unref_device(dev_handle->dev); - return r; -} - -/* Similar to usbi_handle_transfer_completion() but exclusively for transfers - * that were asynchronously cancelled. The same concerns w.r.t. freeing of - * transfers exist here. - * Do not call this function with the usbi_transfer lock held. User-specified - * callback functions may attempt to directly resubmit the transfer, which - * will attempt to take the lock. */ -int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - uint8_t timed_out; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT; - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - /* if the URB was cancelled due to timeout, report timeout to the user */ - if (timed_out) { - usbi_dbg("detected timeout cancellation"); - return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); - } - - /* otherwise its a normal async cancel */ - return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED); -} - -/* Add a completed transfer to the completed_transfers list of the - * context and signal the event. The backend's handle_transfer_completion() - * function will be called the next time an event handler runs. */ -void usbi_signal_transfer_completion(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int pending_events; - - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - list_add_tail(&transfer->completed_list, &ctx->completed_transfers); - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); -} - -/** \ingroup libusb_poll - * Attempt to acquire the event handling lock. This lock is used to ensure that - * only one thread is monitoring libusb event sources at any one time. - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * While holding this lock, you are trusted to actually be handling events. - * If you are no longer handling events, you must call libusb_unlock_events() - * as soon as possible. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 if the lock was obtained successfully - * \returns 1 if the lock was not obtained (i.e. another thread holds the lock) - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) -{ - int r; - unsigned int ru; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * start event handling */ - usbi_mutex_lock(&ctx->event_data_lock); - ru = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (ru) { - usbi_dbg("someone else is closing a device"); - return 1; - } - - r = usbi_mutex_trylock(&ctx->events_lock); - if (r) - return 1; - - ctx->event_handler_active = 1; - return 0; -} - -/** \ingroup libusb_poll - * Acquire the event handling lock, blocking until successful acquisition if - * it is contended. This lock is used to ensure that only one thread is - * monitoring libusb event sources at any one time. - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * While holding this lock, you are trusted to actually be handling events. - * If you are no longer handling events, you must call libusb_unlock_events() - * as soon as possible. - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_lock_events(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->events_lock); - ctx->event_handler_active = 1; -} - -/** \ingroup libusb_poll - * Release the lock previously acquired with libusb_try_lock_events() or - * libusb_lock_events(). Releasing this lock will wake up any threads blocked - * on libusb_wait_for_event(). - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_unlock_events(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - ctx->event_handler_active = 0; - usbi_mutex_unlock(&ctx->events_lock); - - /* FIXME: perhaps we should be a bit more efficient by not broadcasting - * the availability of the events lock when we are modifying pollfds - * (check ctx->device_close)? */ - usbi_mutex_lock(&ctx->event_waiters_lock); - usbi_cond_broadcast(&ctx->event_waiters_cond); - usbi_mutex_unlock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Determine if it is still OK for this thread to be doing event handling. - * - * Sometimes, libusb needs to temporarily pause all event handlers, and this - * is the function you should use before polling file descriptors to see if - * this is the case. - * - * If this function instructs your thread to give up the events lock, you - * should just continue the usual logic that is documented in \ref libusb_mtasync. - * On the next iteration, your thread will fail to obtain the events lock, - * and will hence become an event waiter. - * - * This function should be called while the events lock is held: you don't - * need to worry about the results of this function if your thread is not - * the current event handler. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 1 if event handling can start or continue - * \returns 0 if this thread must give up the events lock - * \ref fullstory "Multi-threaded I/O: the full story" - */ -int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx) -{ - unsigned int r; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * continue event handling */ - usbi_mutex_lock(&ctx->event_data_lock); - r = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (r) { - usbi_dbg("someone else is closing a device"); - return 0; - } - - return 1; -} - - -/** \ingroup libusb_poll - * Determine if an active thread is handling events (i.e. if anyone is holding - * the event handling lock). - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 1 if a thread is handling events - * \returns 0 if there are no threads currently handling events - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) -{ - unsigned int r; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * start event handling -- indicate that event handling is happening */ - usbi_mutex_lock(&ctx->event_data_lock); - r = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (r) { - usbi_dbg("someone else is closing a device"); - return 1; - } - - return ctx->event_handler_active; -} - -/** \ingroup libusb_poll - * Interrupt any active thread that is handling events. This is mainly useful - * for interrupting a dedicated event handling thread when an application - * wishes to call libusb_exit(). - * - * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) -{ - int pending_events; - USBI_GET_CONTEXT(ctx); - - usbi_dbg(""); - usbi_mutex_lock(&ctx->event_data_lock); - - pending_events = usbi_pending_events(ctx); - ctx->event_flags |= USBI_EVENT_USER_INTERRUPT; - if (!pending_events) - usbi_signal_event(ctx); - - usbi_mutex_unlock(&ctx->event_data_lock); -} - -/** \ingroup libusb_poll - * Acquire the event waiters lock. This lock is designed to be obtained under - * the situation where you want to be aware when events are completed, but - * some other thread is event handling so calling libusb_handle_events() is not - * allowed. - * - * You then obtain this lock, re-check that another thread is still handling - * events, then call libusb_wait_for_event(). - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly, - * and may potentially be handling events from 2 threads simultaenously. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Release the event waiters lock. - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_unlock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Wait for another thread to signal completion of an event. Must be called - * with the event waiters lock held, see libusb_lock_event_waiters(). - * - * This function will block until any of the following conditions are met: - * -# The timeout expires - * -# A transfer completes - * -# A thread releases the event handling lock through libusb_unlock_events() - * - * Condition 1 is obvious. Condition 2 unblocks your thread after - * the callback for the transfer has completed. Condition 3 is important - * because it means that the thread that was previously handling events is no - * longer doing so, so if any events are to complete, another thread needs to - * step up and start event handling. - * - * This function releases the event waiters lock before putting your thread - * to sleep, and reacquires the lock as it is being woken up. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv maximum timeout for this blocking function. A NULL value - * indicates unlimited timeout. - * \returns 0 after a transfer completes or another thread stops event handling - * \returns 1 if the timeout expired - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) -{ - int r; - - USBI_GET_CONTEXT(ctx); - if (tv == NULL) { - usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); - return 0; - } - - r = usbi_cond_timedwait(&ctx->event_waiters_cond, - &ctx->event_waiters_lock, tv); - - if (r < 0) - return r; - else - return (r == ETIMEDOUT); -} - -static void handle_timeout(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int r; - - itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED; - r = libusb_cancel_transfer(transfer); - if (r == LIBUSB_SUCCESS) - itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; - else - usbi_warn(TRANSFER_CTX(transfer), - "async cancel failed %d errno=%d", r, errno); -} - -static int handle_timeouts_locked(struct libusb_context *ctx) -{ - int r; - struct timespec systime_ts; - struct timeval systime; - struct usbi_transfer *transfer; - - if (list_empty(&ctx->flying_transfers)) - return 0; - - /* get current time */ - r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); - if (r < 0) - return r; - - TIMESPEC_TO_TIMEVAL(&systime, &systime_ts); - - /* iterate through flying transfers list, finding all transfers that - * have expired timeouts */ - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - struct timeval *cur_tv = &transfer->timeout; - - /* if we've reached transfers of infinite timeout, we're all done */ - if (!timerisset(cur_tv)) - return 0; - - /* ignore timeouts we've already handled */ - if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) - continue; - - /* if transfer has non-expired timeout, nothing more to do */ - if ((cur_tv->tv_sec > systime.tv_sec) || - (cur_tv->tv_sec == systime.tv_sec && - cur_tv->tv_usec > systime.tv_usec)) - return 0; - - /* otherwise, we've got an expired timeout to handle */ - handle_timeout(transfer); - } - return 0; -} - -static int handle_timeouts(struct libusb_context *ctx) -{ - int r; - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->flying_transfers_lock); - r = handle_timeouts_locked(ctx); - usbi_mutex_unlock(&ctx->flying_transfers_lock); - return r; -} - -#ifdef USBI_TIMERFD_AVAILABLE -static int handle_timerfd_trigger(struct libusb_context *ctx) -{ - int r; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - - /* process the timeout that just happened */ - r = handle_timeouts_locked(ctx); - if (r < 0) - goto out; - - /* arm for next timeout*/ - r = arm_timerfd_for_next_timeout(ctx); - -out: - usbi_mutex_unlock(&ctx->flying_transfers_lock); - return r; -} -#endif - -/* do the actual event handling. assumes that no other thread is concurrently - * doing the same thing. */ -static int handle_events(struct libusb_context *ctx, struct timeval *tv) -{ - int r; - struct usbi_pollfd *ipollfd; - POLL_NFDS_TYPE nfds = 0; - POLL_NFDS_TYPE internal_nfds; - struct pollfd *fds = NULL; - int i = -1; - int timeout_ms; - - /* prevent attempts to recursively handle events (e.g. calling into - * libusb_handle_events() from within a hotplug or transfer callback) */ - if (usbi_handling_events(ctx)) - return LIBUSB_ERROR_BUSY; - usbi_start_event_handling(ctx); - - /* there are certain fds that libusb uses internally, currently: - * - * 1) event pipe - * 2) timerfd - * - * the backend will never need to attempt to handle events on these fds, so - * we determine how many fds are in use internally for this context and when - * handle_events() is called in the backend, the pollfd list and count will - * be adjusted to skip over these internal fds */ - if (usbi_using_timerfd(ctx)) - internal_nfds = 2; - else - internal_nfds = 1; - - /* only reallocate the poll fds when the list of poll fds has been modified - * since the last poll, otherwise reuse them to save the additional overhead */ - usbi_mutex_lock(&ctx->event_data_lock); - if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) { - usbi_dbg("poll fds modified, reallocating"); - - if (ctx->pollfds) { - free(ctx->pollfds); - ctx->pollfds = NULL; - } - - /* sanity check - it is invalid for a context to have fewer than the - * required internal fds (memory corruption?) */ - assert(ctx->pollfds_cnt >= internal_nfds); - - ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds)); - if (!ctx->pollfds) { - usbi_mutex_unlock(&ctx->event_data_lock); - r = LIBUSB_ERROR_NO_MEM; - goto done; - } - - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) { - struct libusb_pollfd *pollfd = &ipollfd->pollfd; - i++; - ctx->pollfds[i].fd = pollfd->fd; - ctx->pollfds[i].events = pollfd->events; - } - - /* reset the flag now that we have the updated list */ - ctx->event_flags &= ~USBI_EVENT_POLLFDS_MODIFIED; - - /* if no further pending events, clear the event pipe so that we do - * not immediately return from poll */ - if (!usbi_pending_events(ctx)) - usbi_clear_event(ctx); - } - fds = ctx->pollfds; - nfds = ctx->pollfds_cnt; - usbi_mutex_unlock(&ctx->event_data_lock); - - timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); - - /* round up to next millisecond */ - if (tv->tv_usec % 1000) - timeout_ms++; - - usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); - r = usbi_poll(fds, nfds, timeout_ms); - usbi_dbg("poll() returned %d", r); - if (r == 0) { - r = handle_timeouts(ctx); - goto done; - } else if (r == -1 && errno == EINTR) { - r = LIBUSB_ERROR_INTERRUPTED; - goto done; - } else if (r < 0) { - usbi_err(ctx, "poll failed %d err=%d", r, errno); - r = LIBUSB_ERROR_IO; - goto done; - } - - /* fds[0] is always the event pipe */ - if (fds[0].revents) { - struct list_head hotplug_msgs; - struct usbi_transfer *itransfer; - int hotplug_cb_deregistered = 0; - int ret = 0; - - list_init(&hotplug_msgs); - - usbi_dbg("caught a fish on the event pipe"); - - /* take the the event data lock while processing events */ - usbi_mutex_lock(&ctx->event_data_lock); - - /* check if someone added a new poll fd */ - if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) - usbi_dbg("someone updated the poll fds"); - - if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) { - usbi_dbg("someone purposely interrupted"); - ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; - } - - if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) { - usbi_dbg("someone unregistered a hotplug cb"); - ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED; - hotplug_cb_deregistered = 1; - } - - /* check if someone is closing a device */ - if (ctx->device_close) - usbi_dbg("someone is closing a device"); - - /* check for any pending hotplug messages */ - if (!list_empty(&ctx->hotplug_msgs)) { - usbi_dbg("hotplug message received"); - list_cut(&hotplug_msgs, &ctx->hotplug_msgs); - } - - /* complete any pending transfers */ - while (ret == 0 && !list_empty(&ctx->completed_transfers)) { - itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); - list_del(&itransfer->completed_list); - usbi_mutex_unlock(&ctx->event_data_lock); - ret = usbi_backend.handle_transfer_completion(itransfer); - if (ret) - usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); - usbi_mutex_lock(&ctx->event_data_lock); - } - - /* if no further pending events, clear the event pipe */ - if (!usbi_pending_events(ctx)) - usbi_clear_event(ctx); - - usbi_mutex_unlock(&ctx->event_data_lock); - - if (hotplug_cb_deregistered) - usbi_hotplug_deregister(ctx, 0); - - /* process the hotplug messages, if any */ - while (!list_empty(&hotplug_msgs)) { - struct libusb_hotplug_message *message = - list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list); - - usbi_hotplug_match(ctx, message->device, message->event); - - /* the device left, dereference the device */ - if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) - libusb_unref_device(message->device); - - list_del(&message->list); - free(message); - } - - if (ret) { - /* return error code */ - r = ret; - goto done; - } - - if (0 == --r) - goto done; - } - -#ifdef USBI_TIMERFD_AVAILABLE - /* on timerfd configurations, fds[1] is the timerfd */ - if (usbi_using_timerfd(ctx) && fds[1].revents) { - /* timerfd indicates that a timeout has expired */ - int ret; - usbi_dbg("timerfd triggered"); - - ret = handle_timerfd_trigger(ctx); - if (ret < 0) { - /* return error code */ - r = ret; - goto done; - } - - if (0 == --r) - goto done; - } -#endif - - r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); - if (r) - usbi_err(ctx, "backend handle_events failed with error %d", r); - -done: - usbi_end_event_handling(ctx); - return r; -} - -/* returns the smallest of: - * 1. timeout of next URB - * 2. user-supplied timeout - * returns 1 if there is an already-expired timeout, otherwise returns 0 - * and populates out - */ -static int get_next_timeout(libusb_context *ctx, struct timeval *tv, - struct timeval *out) -{ - struct timeval timeout; - int r = libusb_get_next_timeout(ctx, &timeout); - if (r) { - /* timeout already expired? */ - if (!timerisset(&timeout)) - return 1; - - /* choose the smallest of next URB timeout or user specified timeout */ - if (timercmp(&timeout, tv, <)) - *out = timeout; - else - *out = *tv; - } else { - *out = *tv; - } - return 0; -} - -/** \ingroup libusb_poll - * Handle any pending events. - * - * libusb determines "pending events" by checking if any timeouts have expired - * and by checking the set of file descriptors for activity. - * - * If a zero timeval is passed, this function will handle any already-pending - * events and then immediately return in non-blocking style. - * - * If a non-zero timeval is passed and no events are currently pending, this - * function will block waiting for events to handle up until the specified - * timeout. If an event arrives or a signal is raised, this function will - * return early. - * - * If the parameter completed is not NULL then after obtaining the event - * handling lock this function will return immediately if the integer - * pointed to is not 0. This allows for race free waiting for the completion - * of a specific transfer. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or an all zero - * timeval struct for non-blocking mode - * \param completed pointer to completion integer to check, or NULL - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, - struct timeval *tv, int *completed) -{ - int r; - struct timeval poll_timeout; - - USBI_GET_CONTEXT(ctx); - r = get_next_timeout(ctx, tv, &poll_timeout); - if (r) { - /* timeout already expired */ - return handle_timeouts(ctx); - } - -retry: - if (libusb_try_lock_events(ctx) == 0) { - if (completed == NULL || !*completed) { - /* we obtained the event lock: do our own event handling */ - usbi_dbg("doing our own event handling"); - r = handle_events(ctx, &poll_timeout); - } - libusb_unlock_events(ctx); - return r; - } - - /* another thread is doing event handling. wait for thread events that - * notify event completion. */ - libusb_lock_event_waiters(ctx); - - if (completed && *completed) - goto already_done; - - if (!libusb_event_handler_active(ctx)) { - /* we hit a race: whoever was event handling earlier finished in the - * time it took us to reach this point. try the cycle again. */ - libusb_unlock_event_waiters(ctx); - usbi_dbg("event handler was active but went away, retrying"); - goto retry; - } - - usbi_dbg("another thread is doing event handling"); - r = libusb_wait_for_event(ctx, &poll_timeout); - -already_done: - libusb_unlock_event_waiters(ctx); - - if (r < 0) - return r; - else if (r == 1) - return handle_timeouts(ctx); - else - return 0; -} - -/** \ingroup libusb_poll - * Handle any pending events - * - * Like libusb_handle_events_timeout_completed(), but without the completed - * parameter, calling this function is equivalent to calling - * libusb_handle_events_timeout_completed() with a NULL completed parameter. - * - * This function is kept primarily for backwards compatibility. - * All new code should call libusb_handle_events_completed() or - * libusb_handle_events_timeout_completed() to avoid race conditions. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or an all zero - * timeval struct for non-blocking mode - * \returns 0 on success, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv) -{ - return libusb_handle_events_timeout_completed(ctx, tv, NULL); -} - -/** \ingroup libusb_poll - * Handle any pending events in blocking mode. There is currently a timeout - * hardcoded at 60 seconds but we plan to make it unlimited in future. For - * finer control over whether this function is blocking or non-blocking, or - * for control over the timeout, use libusb_handle_events_timeout_completed() - * instead. - * - * This function is kept primarily for backwards compatibility. - * All new code should call libusb_handle_events_completed() or - * libusb_handle_events_timeout_completed() to avoid race conditions. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 on success, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_handle_events(libusb_context *ctx) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_completed(ctx, &tv, NULL); -} - -/** \ingroup libusb_poll - * Handle any pending events in blocking mode. - * - * Like libusb_handle_events(), with the addition of a completed parameter - * to allow for race free waiting for the completion of a specific transfer. - * - * See libusb_handle_events_timeout_completed() for details on the completed - * parameter. - * - * \param ctx the context to operate on, or NULL for the default context - * \param completed pointer to completion integer to check, or NULL - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, - int *completed) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_completed(ctx, &tv, completed); -} - -/** \ingroup libusb_poll - * Handle any pending events by polling file descriptors, without checking if - * any other threads are already doing so. Must be called with the event lock - * held, see libusb_lock_events(). - * - * This function is designed to be called under the situation where you have - * taken the event lock and are calling poll()/select() directly on libusb's - * file descriptors (as opposed to using libusb_handle_events() or similar). - * You detect events on libusb's descriptors, so you then call this function - * with a zero timeout value (while still holding the event lock). - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or zero for - * non-blocking mode - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, - struct timeval *tv) -{ - int r; - struct timeval poll_timeout; - - USBI_GET_CONTEXT(ctx); - r = get_next_timeout(ctx, tv, &poll_timeout); - if (r) { - /* timeout already expired */ - return handle_timeouts(ctx); - } - - return handle_events(ctx, &poll_timeout); -} - -/** \ingroup libusb_poll - * Determines whether your application must apply special timing considerations - * when monitoring libusb's file descriptors. - * - * This function is only useful for applications which retrieve and poll - * libusb's file descriptors in their own main loop (\ref libusb_pollmain). - * - * Ordinarily, libusb's event handler needs to be called into at specific - * moments in time (in addition to times when there is activity on the file - * descriptor set). The usual approach is to use libusb_get_next_timeout() - * to learn about when the next timeout occurs, and to adjust your - * poll()/select() timeout accordingly so that you can make a call into the - * library at that time. - * - * Some platforms supported by libusb do not come with this baggage - any - * events relevant to timing will be represented by activity on the file - * descriptor set, and libusb_get_next_timeout() will always return 0. - * This function allows you to detect whether you are running on such a - * platform. - * - * Since v1.0.5. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 if you must call into libusb at times determined by - * libusb_get_next_timeout(), or 1 if all timeout events are handled internally - * or through regular activity on the file descriptors. - * \ref libusb_pollmain "Polling libusb file descriptors for event handling" - */ -int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) -{ -#if defined(USBI_TIMERFD_AVAILABLE) - USBI_GET_CONTEXT(ctx); - return usbi_using_timerfd(ctx); -#else - UNUSED(ctx); - return 0; -#endif -} - -/** \ingroup libusb_poll - * Determine the next internal timeout that libusb needs to handle. You only - * need to use this function if you are calling poll() or select() or similar - * on libusb's file descriptors yourself - you do not need to use it if you - * are calling libusb_handle_events() or a variant directly. - * - * You should call this function in your main loop in order to determine how - * long to wait for select() or poll() to return results. libusb needs to be - * called into at this timeout, so you should use it as an upper bound on - * your select() or poll() call. - * - * When the timeout has expired, call into libusb_handle_events_timeout() - * (perhaps in non-blocking mode) so that libusb can handle the timeout. - * - * This function may return 1 (success) and an all-zero timeval. If this is - * the case, it indicates that libusb has a timeout that has already expired - * so you should call libusb_handle_events_timeout() or similar immediately. - * A return code of 0 indicates that there are no pending timeouts. - * - * On some platforms, this function will always returns 0 (no pending - * timeouts). See \ref polltime. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv output location for a relative time against the current - * clock in which libusb must be called into in order to process timeout events - * \returns 0 if there are no pending timeouts, 1 if a timeout was returned, - * or LIBUSB_ERROR_OTHER on failure - */ -int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, - struct timeval *tv) -{ - struct usbi_transfer *transfer; - struct timespec cur_ts; - struct timeval cur_tv; - struct timeval next_timeout = { 0, 0 }; - int r; - - USBI_GET_CONTEXT(ctx); - if (usbi_using_timerfd(ctx)) - return 0; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - if (list_empty(&ctx->flying_transfers)) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_dbg("no URBs, no timeout!"); - return 0; - } - - /* find next transfer which hasn't already been processed as timed out */ - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) - continue; - - /* if we've reached transfers of infinte timeout, we're done looking */ - if (!timerisset(&transfer->timeout)) - break; - - next_timeout = transfer->timeout; - break; - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (!timerisset(&next_timeout)) { - usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); - return 0; - } - - r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); - if (r < 0) { - usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); - return 0; - } - TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); - - if (!timercmp(&cur_tv, &next_timeout, <)) { - usbi_dbg("first timeout already expired"); - timerclear(tv); - } else { - timersub(&next_timeout, &cur_tv, tv); - usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec); - } - - return 1; -} - -/** \ingroup libusb_poll - * Register notification functions for file descriptor additions/removals. - * These functions will be invoked for every new or removed file descriptor - * that libusb uses as an event source. - * - * To remove notifiers, pass NULL values for the function pointers. - * - * Note that file descriptors may have been added even before you register - * these notifiers (e.g. at libusb_init() time). - * - * Additionally, note that the removal notifier may be called during - * libusb_exit() (e.g. when it is closing file descriptors that were opened - * and added to the poll set at libusb_init() time). If you don't want this, - * remove the notifiers immediately before calling libusb_exit(). - * - * \param ctx the context to operate on, or NULL for the default context - * \param added_cb pointer to function for addition notifications - * \param removed_cb pointer to function for removal notifications - * \param user_data User data to be passed back to callbacks (useful for - * passing context information) - */ -void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, - libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, - void *user_data) -{ - USBI_GET_CONTEXT(ctx); - ctx->fd_added_cb = added_cb; - ctx->fd_removed_cb = removed_cb; - ctx->fd_cb_user_data = user_data; -} - -/* - * Interrupt the iteration of the event handling thread, so that it picks - * up the fd change. Callers of this function must hold the event_data_lock. - */ -static void usbi_fd_notification(struct libusb_context *ctx) -{ - int pending_events; - - /* Record that there is a new poll fd. - * Only signal an event if there are no prior pending events. */ - pending_events = usbi_pending_events(ctx); - ctx->event_flags |= USBI_EVENT_POLLFDS_MODIFIED; - if (!pending_events) - usbi_signal_event(ctx); -} - -/* Add a file descriptor to the list of file descriptors to be monitored. - * events should be specified as a bitmask of events passed to poll(), e.g. - * POLLIN and/or POLLOUT. */ -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) -{ - struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd)); - if (!ipollfd) - return LIBUSB_ERROR_NO_MEM; - - usbi_dbg("add fd %d events %d", fd, events); - ipollfd->pollfd.fd = fd; - ipollfd->pollfd.events = events; - usbi_mutex_lock(&ctx->event_data_lock); - list_add_tail(&ipollfd->list, &ctx->ipollfds); - ctx->pollfds_cnt++; - usbi_fd_notification(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - if (ctx->fd_added_cb) - ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); - return 0; -} - -/* Remove a file descriptor from the list of file descriptors to be polled. */ -void usbi_remove_pollfd(struct libusb_context *ctx, int fd) -{ - struct usbi_pollfd *ipollfd; - int found = 0; - - usbi_dbg("remove fd %d", fd); - usbi_mutex_lock(&ctx->event_data_lock); - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) - if (ipollfd->pollfd.fd == fd) { - found = 1; - break; - } - - if (!found) { - usbi_dbg("couldn't find fd %d to remove", fd); - usbi_mutex_unlock(&ctx->event_data_lock); - return; - } - - list_del(&ipollfd->list); - ctx->pollfds_cnt--; - usbi_fd_notification(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - free(ipollfd); - if (ctx->fd_removed_cb) - ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); -} - -/** \ingroup libusb_poll - * Retrieve a list of file descriptors that should be polled by your main loop - * as libusb event sources. - * - * The returned list is NULL-terminated and should be freed with libusb_free_pollfds() - * when done. The actual list contents must not be touched. - * - * As file descriptors are a Unix-specific concept, this function is not - * available on Windows and will always return NULL. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns a NULL-terminated list of libusb_pollfd structures - * \returns NULL on error - * \returns NULL on platforms where the functionality is not available - */ -DEFAULT_VISIBILITY -const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( - libusb_context *ctx) -{ -#ifndef OS_WINDOWS - struct libusb_pollfd **ret = NULL; - struct usbi_pollfd *ipollfd; - size_t i = 0; - USBI_GET_CONTEXT(ctx); - - usbi_mutex_lock(&ctx->event_data_lock); - - ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *)); - if (!ret) - goto out; - - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) - ret[i++] = (struct libusb_pollfd *) ipollfd; - ret[ctx->pollfds_cnt] = NULL; - -out: - usbi_mutex_unlock(&ctx->event_data_lock); - return (const struct libusb_pollfd **) ret; -#else - usbi_err(ctx, "external polling of libusb's internal descriptors "\ - "is not yet supported on Windows platforms"); - return NULL; -#endif -} - -/** \ingroup libusb_poll - * Free a list of libusb_pollfd structures. This should be called for all - * pollfd lists allocated with libusb_get_pollfds(). - * - * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104 - * - * It is legal to call this function with a NULL pollfd list. In this case, - * the function will simply return safely. - * - * \param pollfds the list of libusb_pollfd structures to free - */ -void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) -{ - if (!pollfds) - return; - - free((void *)pollfds); -} - -/* Backends may call this from handle_events to report disconnection of a - * device. This function ensures transfers get cancelled appropriately. - * Callers of this function must hold the events_lock. - */ -void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) -{ - struct usbi_transfer *cur; - struct usbi_transfer *to_cancel; - - usbi_dbg("device %d.%d", - dev_handle->dev->bus_number, dev_handle->dev->device_address); - - /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE - * status code. - * - * when we find a transfer for this device on the list, there are two - * possible scenarios: - * 1. the transfer is currently in-flight, in which case we terminate the - * transfer here - * 2. the transfer has been added to the flying transfer list by - * libusb_submit_transfer, has failed to submit and - * libusb_submit_transfer is waiting for us to release the - * flying_transfers_lock to remove it, so we ignore it - */ - - while (1) { - to_cancel = NULL; - usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); - list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer) - if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { - usbi_mutex_lock(&cur->lock); - if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT) - to_cancel = cur; - usbi_mutex_unlock(&cur->lock); - - if (to_cancel) - break; - } - usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); - - if (!to_cancel) - break; - - usbi_dbg("cancelling transfer %p from disconnect", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); - - usbi_mutex_lock(&to_cancel->lock); - usbi_backend.clear_transfer_priv(to_cancel); - usbi_mutex_unlock(&to_cancel->lock); - usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); - } - -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h deleted file mode 100644 index 430136b2e2..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h +++ /dev/null @@ -1,2039 +0,0 @@ -/* - * Public libusb header file - * Copyright © 2001 Johannes Erdfelt - * Copyright © 2007-2008 Daniel Drake - * Copyright © 2012 Pete Batard - * Copyright © 2012 Nathan Hjelm - * For more information, please visit: http://libusb.info - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_H -#define LIBUSB_H - -#ifdef _MSC_VER -/* on MS environments, the inline keyword is available in C++ only */ -#if !defined(__cplusplus) -#define inline __inline -#endif -/* ssize_t is also not available (copy/paste from MinGW) */ -#ifndef _SSIZE_T_DEFINED -#define _SSIZE_T_DEFINED -#undef ssize_t -#ifdef _WIN64 - typedef __int64 ssize_t; -#else - typedef int ssize_t; -#endif /* _WIN64 */ -#endif /* _SSIZE_T_DEFINED */ -#endif /* _MSC_VER */ - -/* stdint.h is not available on older MSVC */ -#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H)) -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -#else -#include -#endif - -#if !defined(_WIN32_WCE) -#include -#endif - -#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) -#include -#endif - -#include -#include - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ -#else -#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ -#endif - -/* 'interface' might be defined as a macro on Windows, so we need to - * undefine it so as not to break the current libusb API, because - * libusb_config_descriptor has an 'interface' member - * As this can be problematic if you include windows.h after libusb.h - * in your sources, we force windows.h to be included first. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#include -#if defined(interface) -#undef interface -#endif -#if !defined(__CYGWIN__) -#include -#endif -#endif - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#define LIBUSB_DEPRECATED_FOR(f) \ - __attribute__((deprecated("Use " #f " instead"))) -#elif __GNUC__ >= 3 -#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated)) -#else -#define LIBUSB_DEPRECATED_FOR(f) -#endif /* __GNUC__ */ - -/** \def LIBUSB_CALL - * \ingroup libusb_misc - * libusb's Windows calling convention. - * - * Under Windows, the selection of available compilers and configurations - * means that, unlike other platforms, there is not one true calling - * convention (calling convention: the manner in which parameters are - * passed to functions in the generated assembly code). - * - * Matching the Windows API itself, libusb uses the WINAPI convention (which - * translates to the stdcall convention) and guarantees that the - * library is compiled in this way. The public header file also includes - * appropriate annotations so that your own software will use the right - * convention, even if another convention is being used by default within - * your codebase. - * - * The one consideration that you must apply in your software is to mark - * all functions which you use as libusb callbacks with this LIBUSB_CALL - * annotation, so that they too get compiled for the correct calling - * convention. - * - * On non-Windows operating systems, this macro is defined as nothing. This - * means that you can apply it to your code without worrying about - * cross-platform compatibility. - */ -/* LIBUSB_CALL must be defined on both definition and declaration of libusb - * functions. You'd think that declaration would be enough, but cygwin will - * complain about conflicting types unless both are marked this way. - * The placement of this macro is important too; it must appear after the - * return type, before the function name. See internal documentation for - * API_EXPORTED. - */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#define LIBUSB_CALL WINAPI -#else -#define LIBUSB_CALL -#endif - -/** \def LIBUSB_API_VERSION - * \ingroup libusb_misc - * libusb's API version. - * - * Since version 1.0.13, to help with feature detection, libusb defines - * a LIBUSB_API_VERSION macro that gets increased every time there is a - * significant change to the API, such as the introduction of a new call, - * the definition of a new macro/enum member, or any other element that - * libusb applications may want to detect at compilation time. - * - * The macro is typically used in an application as follows: - * \code - * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) - * // Use one of the newer features from the libusb API - * #endif - * \endcode - * - * Internally, LIBUSB_API_VERSION is defined as follows: - * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) - */ -#define LIBUSB_API_VERSION 0x01000106 - -/* The following is kept for compatibility, but will be deprecated in the future */ -#define LIBUSBX_API_VERSION LIBUSB_API_VERSION - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \ingroup libusb_misc - * Convert a 16-bit value from host-endian to little-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the host-endian value to convert - * \returns the value in little-endian byte order - */ -static inline uint16_t libusb_cpu_to_le16(const uint16_t x) -{ - union { - uint8_t b8[2]; - uint16_t b16; - } _tmp; - _tmp.b8[1] = (uint8_t) (x >> 8); - _tmp.b8[0] = (uint8_t) (x & 0xff); - return _tmp.b16; -} - -/** \def libusb_le16_to_cpu - * \ingroup libusb_misc - * Convert a 16-bit value from little-endian to host-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the little-endian value to convert - * \returns the value in host-endian byte order - */ -#define libusb_le16_to_cpu libusb_cpu_to_le16 - -/* standard USB stuff */ - -/** \ingroup libusb_desc - * Device and/or Interface Class codes */ -enum libusb_class_code { - /** In the context of a \ref libusb_device_descriptor "device descriptor", - * this bDeviceClass value indicates that each interface specifies its - * own class information and all interfaces operate independently. - */ - LIBUSB_CLASS_PER_INTERFACE = 0, - - /** Audio class */ - LIBUSB_CLASS_AUDIO = 1, - - /** Communications class */ - LIBUSB_CLASS_COMM = 2, - - /** Human Interface Device class */ - LIBUSB_CLASS_HID = 3, - - /** Physical */ - LIBUSB_CLASS_PHYSICAL = 5, - - /** Printer class */ - LIBUSB_CLASS_PRINTER = 7, - - /** Image class */ - LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ - LIBUSB_CLASS_IMAGE = 6, - - /** Mass storage class */ - LIBUSB_CLASS_MASS_STORAGE = 8, - - /** Hub class */ - LIBUSB_CLASS_HUB = 9, - - /** Data class */ - LIBUSB_CLASS_DATA = 10, - - /** Smart Card */ - LIBUSB_CLASS_SMART_CARD = 0x0b, - - /** Content Security */ - LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, - - /** Video */ - LIBUSB_CLASS_VIDEO = 0x0e, - - /** Personal Healthcare */ - LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, - - /** Diagnostic Device */ - LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, - - /** Wireless class */ - LIBUSB_CLASS_WIRELESS = 0xe0, - - /** Application class */ - LIBUSB_CLASS_APPLICATION = 0xfe, - - /** Class is vendor-specific */ - LIBUSB_CLASS_VENDOR_SPEC = 0xff -}; - -/** \ingroup libusb_desc - * Descriptor types as defined by the USB specification. */ -enum libusb_descriptor_type { - /** Device descriptor. See libusb_device_descriptor. */ - LIBUSB_DT_DEVICE = 0x01, - - /** Configuration descriptor. See libusb_config_descriptor. */ - LIBUSB_DT_CONFIG = 0x02, - - /** String descriptor */ - LIBUSB_DT_STRING = 0x03, - - /** Interface descriptor. See libusb_interface_descriptor. */ - LIBUSB_DT_INTERFACE = 0x04, - - /** Endpoint descriptor. See libusb_endpoint_descriptor. */ - LIBUSB_DT_ENDPOINT = 0x05, - - /** BOS descriptor */ - LIBUSB_DT_BOS = 0x0f, - - /** Device Capability descriptor */ - LIBUSB_DT_DEVICE_CAPABILITY = 0x10, - - /** HID descriptor */ - LIBUSB_DT_HID = 0x21, - - /** HID report descriptor */ - LIBUSB_DT_REPORT = 0x22, - - /** Physical descriptor */ - LIBUSB_DT_PHYSICAL = 0x23, - - /** Hub descriptor */ - LIBUSB_DT_HUB = 0x29, - - /** SuperSpeed Hub descriptor */ - LIBUSB_DT_SUPERSPEED_HUB = 0x2a, - - /** SuperSpeed Endpoint Companion descriptor */ - LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30 -}; - -/* Descriptor sizes per descriptor type */ -#define LIBUSB_DT_DEVICE_SIZE 18 -#define LIBUSB_DT_CONFIG_SIZE 9 -#define LIBUSB_DT_INTERFACE_SIZE 9 -#define LIBUSB_DT_ENDPOINT_SIZE 7 -#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ -#define LIBUSB_DT_HUB_NONVAR_SIZE 7 -#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 -#define LIBUSB_DT_BOS_SIZE 5 -#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3 - -/* BOS descriptor sizes */ -#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 -#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 -#define LIBUSB_BT_CONTAINER_ID_SIZE 20 - -/* We unwrap the BOS => define its max size */ -#define LIBUSB_DT_BOS_MAX_SIZE ((LIBUSB_DT_BOS_SIZE) +\ - (LIBUSB_BT_USB_2_0_EXTENSION_SIZE) +\ - (LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) +\ - (LIBUSB_BT_CONTAINER_ID_SIZE)) - -#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ -#define LIBUSB_ENDPOINT_DIR_MASK 0x80 - -/** \ingroup libusb_desc - * Endpoint direction. Values for bit 7 of the - * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. - */ -enum libusb_endpoint_direction { - /** In: device-to-host */ - LIBUSB_ENDPOINT_IN = 0x80, - - /** Out: host-to-device */ - LIBUSB_ENDPOINT_OUT = 0x00 -}; - -#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ - -/** \ingroup libusb_desc - * Endpoint transfer type. Values for bits 0:1 of the - * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. - */ -enum libusb_transfer_type { - /** Control endpoint */ - LIBUSB_TRANSFER_TYPE_CONTROL = 0, - - /** Isochronous endpoint */ - LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, - - /** Bulk endpoint */ - LIBUSB_TRANSFER_TYPE_BULK = 2, - - /** Interrupt endpoint */ - LIBUSB_TRANSFER_TYPE_INTERRUPT = 3, - - /** Stream endpoint */ - LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, -}; - -/** \ingroup libusb_misc - * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ -enum libusb_standard_request { - /** Request status of the specific recipient */ - LIBUSB_REQUEST_GET_STATUS = 0x00, - - /** Clear or disable a specific feature */ - LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, - - /* 0x02 is reserved */ - - /** Set or enable a specific feature */ - LIBUSB_REQUEST_SET_FEATURE = 0x03, - - /* 0x04 is reserved */ - - /** Set device address for all future accesses */ - LIBUSB_REQUEST_SET_ADDRESS = 0x05, - - /** Get the specified descriptor */ - LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, - - /** Used to update existing descriptors or add new descriptors */ - LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, - - /** Get the current device configuration value */ - LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, - - /** Set device configuration */ - LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, - - /** Return the selected alternate setting for the specified interface */ - LIBUSB_REQUEST_GET_INTERFACE = 0x0A, - - /** Select an alternate interface for the specified interface */ - LIBUSB_REQUEST_SET_INTERFACE = 0x0B, - - /** Set then report an endpoint's synchronization frame */ - LIBUSB_REQUEST_SYNCH_FRAME = 0x0C, - - /** Sets both the U1 and U2 Exit Latency */ - LIBUSB_REQUEST_SET_SEL = 0x30, - - /** Delay from the time a host transmits a packet to the time it is - * received by the device. */ - LIBUSB_SET_ISOCH_DELAY = 0x31, -}; - -/** \ingroup libusb_misc - * Request type bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. */ -enum libusb_request_type { - /** Standard */ - LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), - - /** Class */ - LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), - - /** Vendor */ - LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), - - /** Reserved */ - LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) -}; - -/** \ingroup libusb_misc - * Recipient bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. Values 4 through 31 are reserved. */ -enum libusb_request_recipient { - /** Device */ - LIBUSB_RECIPIENT_DEVICE = 0x00, - - /** Interface */ - LIBUSB_RECIPIENT_INTERFACE = 0x01, - - /** Endpoint */ - LIBUSB_RECIPIENT_ENDPOINT = 0x02, - - /** Other */ - LIBUSB_RECIPIENT_OTHER = 0x03, -}; - -#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C - -/** \ingroup libusb_desc - * Synchronization type for isochronous endpoints. Values for bits 2:3 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_sync_type { - /** No synchronization */ - LIBUSB_ISO_SYNC_TYPE_NONE = 0, - - /** Asynchronous */ - LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, - - /** Adaptive */ - LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, - - /** Synchronous */ - LIBUSB_ISO_SYNC_TYPE_SYNC = 3 -}; - -#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 - -/** \ingroup libusb_desc - * Usage type for isochronous endpoints. Values for bits 4:5 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_usage_type { - /** Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_DATA = 0, - - /** Feedback endpoint */ - LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, - - /** Implicit feedback Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB device descriptor. This - * descriptor is documented in section 9.6.1 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_device_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this - * context. */ - uint8_t bDescriptorType; - - /** USB specification release number in binary-coded decimal. A value of - * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ - uint16_t bcdUSB; - - /** USB-IF class code for the device. See \ref libusb_class_code. */ - uint8_t bDeviceClass; - - /** USB-IF subclass code for the device, qualified by the bDeviceClass - * value */ - uint8_t bDeviceSubClass; - - /** USB-IF protocol code for the device, qualified by the bDeviceClass and - * bDeviceSubClass values */ - uint8_t bDeviceProtocol; - - /** Maximum packet size for endpoint 0 */ - uint8_t bMaxPacketSize0; - - /** USB-IF vendor ID */ - uint16_t idVendor; - - /** USB-IF product ID */ - uint16_t idProduct; - - /** Device release number in binary-coded decimal */ - uint16_t bcdDevice; - - /** Index of string descriptor describing manufacturer */ - uint8_t iManufacturer; - - /** Index of string descriptor describing product */ - uint8_t iProduct; - - /** Index of string descriptor containing device serial number */ - uint8_t iSerialNumber; - - /** Number of possible configurations */ - uint8_t bNumConfigurations; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB endpoint descriptor. This - * descriptor is documented in section 9.6.6 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_endpoint_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in - * this context. */ - uint8_t bDescriptorType; - - /** The address of the endpoint described by this descriptor. Bits 0:3 are - * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, - * see \ref libusb_endpoint_direction. - */ - uint8_t bEndpointAddress; - - /** Attributes which apply to the endpoint when it is configured using - * the bConfigurationValue. Bits 0:1 determine the transfer type and - * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for - * isochronous endpoints and correspond to \ref libusb_iso_sync_type. - * Bits 4:5 are also only used for isochronous endpoints and correspond to - * \ref libusb_iso_usage_type. Bits 6:7 are reserved. - */ - uint8_t bmAttributes; - - /** Maximum packet size this endpoint is capable of sending/receiving. */ - uint16_t wMaxPacketSize; - - /** Interval for polling endpoint for data transfers. */ - uint8_t bInterval; - - /** For audio devices only: the rate at which synchronization feedback - * is provided. */ - uint8_t bRefresh; - - /** For audio devices only: the address if the synch endpoint */ - uint8_t bSynchAddress; - - /** Extra descriptors. If libusb encounters unknown endpoint descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB interface descriptor. This - * descriptor is documented in section 9.6.5 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_interface_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE - * in this context. */ - uint8_t bDescriptorType; - - /** Number of this interface */ - uint8_t bInterfaceNumber; - - /** Value used to select this alternate setting for this interface */ - uint8_t bAlternateSetting; - - /** Number of endpoints used by this interface (excluding the control - * endpoint). */ - uint8_t bNumEndpoints; - - /** USB-IF class code for this interface. See \ref libusb_class_code. */ - uint8_t bInterfaceClass; - - /** USB-IF subclass code for this interface, qualified by the - * bInterfaceClass value */ - uint8_t bInterfaceSubClass; - - /** USB-IF protocol code for this interface, qualified by the - * bInterfaceClass and bInterfaceSubClass values */ - uint8_t bInterfaceProtocol; - - /** Index of string descriptor describing this interface */ - uint8_t iInterface; - - /** Array of endpoint descriptors. This length of this array is determined - * by the bNumEndpoints field. */ - const struct libusb_endpoint_descriptor *endpoint; - - /** Extra descriptors. If libusb encounters unknown interface descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A collection of alternate settings for a particular USB interface. - */ -struct libusb_interface { - /** Array of interface descriptors. The length of this array is determined - * by the num_altsetting field. */ - const struct libusb_interface_descriptor *altsetting; - - /** The number of alternate settings that belong to this interface */ - int num_altsetting; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB configuration descriptor. This - * descriptor is documented in section 9.6.3 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_config_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG - * in this context. */ - uint8_t bDescriptorType; - - /** Total length of data returned for this configuration */ - uint16_t wTotalLength; - - /** Number of interfaces supported by this configuration */ - uint8_t bNumInterfaces; - - /** Identifier value for this configuration */ - uint8_t bConfigurationValue; - - /** Index of string descriptor describing this configuration */ - uint8_t iConfiguration; - - /** Configuration characteristics */ - uint8_t bmAttributes; - - /** Maximum power consumption of the USB device from this bus in this - * configuration when the device is fully operation. Expressed in units - * of 2 mA when the device is operating in high-speed mode and in units - * of 8 mA when the device is operating in super-speed mode. */ - uint8_t MaxPower; - - /** Array of interfaces supported by this configuration. The length of - * this array is determined by the bNumInterfaces field. */ - const struct libusb_interface *interface; - - /** Extra descriptors. If libusb encounters unknown configuration - * descriptors, it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A structure representing the superspeed endpoint companion - * descriptor. This descriptor is documented in section 9.6.7 of - * the USB 3.0 specification. All multiple-byte fields are represented in - * host-endian format. - */ -struct libusb_ss_endpoint_companion_descriptor { - - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in - * this context. */ - uint8_t bDescriptorType; - - - /** The maximum number of packets the endpoint can send or - * receive as part of a burst. */ - uint8_t bMaxBurst; - - /** In bulk EP: bits 4:0 represents the maximum number of - * streams the EP supports. In isochronous EP: bits 1:0 - * represents the Mult - a zero based value that determines - * the maximum number of packets within a service interval */ - uint8_t bmAttributes; - - /** The total number of bytes this EP will transfer every - * service interval. valid only for periodic EPs. */ - uint16_t wBytesPerInterval; -}; - -/** \ingroup libusb_desc - * A generic representation of a BOS Device Capability descriptor. It is - * advised to check bDevCapabilityType and call the matching - * libusb_get_*_descriptor function to get a structure fully matching the type. - */ -struct libusb_bos_dev_capability_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - /** Device Capability type */ - uint8_t bDevCapabilityType; - /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; -}; - -/** \ingroup libusb_desc - * A structure representing the Binary Device Object Store (BOS) descriptor. - * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_bos_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS - * in this context. */ - uint8_t bDescriptorType; - - /** Length of this descriptor and all of its sub descriptors */ - uint16_t wTotalLength; - - /** The number of separate device capability descriptors in - * the BOS */ - uint8_t bNumDeviceCaps; - - /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; -}; - -/** \ingroup libusb_desc - * A structure representing the USB 2.0 Extension descriptor - * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_usb_2_0_extension_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION - * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ - uint8_t bDevCapabilityType; - - /** Bitmap encoding of supported device level features. - * A value of one in a bit location indicates a feature is - * supported; a value of zero indicates it is not supported. - * See \ref libusb_usb_2_0_extension_attributes. */ - uint32_t bmAttributes; -}; - -/** \ingroup libusb_desc - * A structure representing the SuperSpeed USB Device Capability descriptor - * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_ss_usb_device_capability_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ - uint8_t bDevCapabilityType; - - /** Bitmap encoding of supported device level features. - * A value of one in a bit location indicates a feature is - * supported; a value of zero indicates it is not supported. - * See \ref libusb_ss_usb_device_capability_attributes. */ - uint8_t bmAttributes; - - /** Bitmap encoding of the speed supported by this device when - * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ - uint16_t wSpeedSupported; - - /** The lowest speed at which all the functionality supported - * by the device is available to the user. For example if the - * device supports all its functionality when connected at - * full speed and above then it sets this value to 1. */ - uint8_t bFunctionalitySupport; - - /** U1 Device Exit Latency. */ - uint8_t bU1DevExitLat; - - /** U2 Device Exit Latency. */ - uint16_t bU2DevExitLat; -}; - -/** \ingroup libusb_desc - * A structure representing the Container ID descriptor. - * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. - * All multiple-byte fields, except UUIDs, are represented in host-endian format. - */ -struct libusb_container_id_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID - * LIBUSB_BT_CONTAINER_ID in this context. */ - uint8_t bDevCapabilityType; - - /** Reserved field */ - uint8_t bReserved; - - /** 128 bit UUID */ - uint8_t ContainerID[16]; -}; - -/** \ingroup libusb_asyncio - * Setup packet for control transfers. */ -struct libusb_control_setup { - /** Request type. Bits 0:4 determine recipient, see - * \ref libusb_request_recipient. Bits 5:6 determine type, see - * \ref libusb_request_type. Bit 7 determines data transfer direction, see - * \ref libusb_endpoint_direction. - */ - uint8_t bmRequestType; - - /** Request. If the type bits of bmRequestType are equal to - * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD - * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to - * \ref libusb_standard_request. For other cases, use of this field is - * application-specific. */ - uint8_t bRequest; - - /** Value. Varies according to request */ - uint16_t wValue; - - /** Index. Varies according to request, typically used to pass an index - * or offset */ - uint16_t wIndex; - - /** Number of bytes to transfer */ - uint16_t wLength; -}; - -#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) - -/* libusb */ - -struct libusb_context; -struct libusb_device; -struct libusb_device_handle; - -/** \ingroup libusb_lib - * Structure providing the version of the libusb runtime - */ -struct libusb_version { - /** Library major version. */ - const uint16_t major; - - /** Library minor version. */ - const uint16_t minor; - - /** Library micro version. */ - const uint16_t micro; - - /** Library nano version. */ - const uint16_t nano; - - /** Library release candidate suffix string, e.g. "-rc4". */ - const char *rc; - - /** For ABI compatibility only. */ - const char* describe; -}; - -/** \ingroup libusb_lib - * Structure representing a libusb session. The concept of individual libusb - * sessions allows for your program to use two libraries (or dynamically - * load two modules) which both independently use libusb. This will prevent - * interference between the individual libusb users - for example - * libusb_set_option() will not affect the other user of the library, and - * libusb_exit() will not destroy resources that the other user is still - * using. - * - * Sessions are created by libusb_init() and destroyed through libusb_exit(). - * If your application is guaranteed to only ever include a single libusb - * user (i.e. you), you do not have to worry about contexts: pass NULL in - * every function call where a context is required. The default context - * will be used. - * - * For more information, see \ref libusb_contexts. - */ -typedef struct libusb_context libusb_context; - -/** \ingroup libusb_dev - * Structure representing a USB device detected on the system. This is an - * opaque type for which you are only ever provided with a pointer, usually - * originating from libusb_get_device_list(). - * - * Certain operations can be performed on a device, but in order to do any - * I/O you will have to first obtain a device handle using libusb_open(). - * - * Devices are reference counted with libusb_ref_device() and - * libusb_unref_device(), and are freed when the reference count reaches 0. - * New devices presented by libusb_get_device_list() have a reference count of - * 1, and libusb_free_device_list() can optionally decrease the reference count - * on all devices in the list. libusb_open() adds another reference which is - * later destroyed by libusb_close(). - */ -typedef struct libusb_device libusb_device; - - -/** \ingroup libusb_dev - * Structure representing a handle on a USB device. This is an opaque type for - * which you are only ever provided with a pointer, usually originating from - * libusb_open(). - * - * A device handle is used to perform I/O and other operations. When finished - * with a device handle, you should call libusb_close(). - */ -typedef struct libusb_device_handle libusb_device_handle; - -/** \ingroup libusb_dev - * Speed codes. Indicates the speed at which the device is operating. - */ -enum libusb_speed { - /** The OS doesn't report or know the device speed. */ - LIBUSB_SPEED_UNKNOWN = 0, - - /** The device is operating at low speed (1.5MBit/s). */ - LIBUSB_SPEED_LOW = 1, - - /** The device is operating at full speed (12MBit/s). */ - LIBUSB_SPEED_FULL = 2, - - /** The device is operating at high speed (480MBit/s). */ - LIBUSB_SPEED_HIGH = 3, - - /** The device is operating at super speed (5000MBit/s). */ - LIBUSB_SPEED_SUPER = 4, - - /** The device is operating at super speed plus (10000MBit/s). */ - LIBUSB_SPEED_SUPER_PLUS = 5, -}; - -/** \ingroup libusb_dev - * Supported speeds (wSpeedSupported) bitfield. Indicates what - * speeds the device supports. - */ -enum libusb_supported_speed { - /** Low speed operation supported (1.5MBit/s). */ - LIBUSB_LOW_SPEED_OPERATION = 1, - - /** Full speed operation supported (12MBit/s). */ - LIBUSB_FULL_SPEED_OPERATION = 2, - - /** High speed operation supported (480MBit/s). */ - LIBUSB_HIGH_SPEED_OPERATION = 4, - - /** Superspeed operation supported (5000MBit/s). */ - LIBUSB_SUPER_SPEED_OPERATION = 8, -}; - -/** \ingroup libusb_dev - * Masks for the bits of the - * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field - * of the USB 2.0 Extension descriptor. - */ -enum libusb_usb_2_0_extension_attributes { - /** Supports Link Power Management (LPM) */ - LIBUSB_BM_LPM_SUPPORT = 2, -}; - -/** \ingroup libusb_dev - * Masks for the bits of the - * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field - * field of the SuperSpeed USB Device Capability descriptor. - */ -enum libusb_ss_usb_device_capability_attributes { - /** Supports Latency Tolerance Messages (LTM) */ - LIBUSB_BM_LTM_SUPPORT = 2, -}; - -/** \ingroup libusb_dev - * USB capability types - */ -enum libusb_bos_type { - /** Wireless USB device capability */ - LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1, - - /** USB 2.0 extensions */ - LIBUSB_BT_USB_2_0_EXTENSION = 2, - - /** SuperSpeed USB device capability */ - LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3, - - /** Container ID type */ - LIBUSB_BT_CONTAINER_ID = 4, -}; - -/** \ingroup libusb_misc - * Error codes. Most libusb functions return 0 on success or one of these - * codes on failure. - * You can call libusb_error_name() to retrieve a string representation of an - * error code or libusb_strerror() to get an end-user suitable description of - * an error code. - */ -enum libusb_error { - /** Success (no error) */ - LIBUSB_SUCCESS = 0, - - /** Input/output error */ - LIBUSB_ERROR_IO = -1, - - /** Invalid parameter */ - LIBUSB_ERROR_INVALID_PARAM = -2, - - /** Access denied (insufficient permissions) */ - LIBUSB_ERROR_ACCESS = -3, - - /** No such device (it may have been disconnected) */ - LIBUSB_ERROR_NO_DEVICE = -4, - - /** Entity not found */ - LIBUSB_ERROR_NOT_FOUND = -5, - - /** Resource busy */ - LIBUSB_ERROR_BUSY = -6, - - /** Operation timed out */ - LIBUSB_ERROR_TIMEOUT = -7, - - /** Overflow */ - LIBUSB_ERROR_OVERFLOW = -8, - - /** Pipe error */ - LIBUSB_ERROR_PIPE = -9, - - /** System call interrupted (perhaps due to signal) */ - LIBUSB_ERROR_INTERRUPTED = -10, - - /** Insufficient memory */ - LIBUSB_ERROR_NO_MEM = -11, - - /** Operation not supported or unimplemented on this platform */ - LIBUSB_ERROR_NOT_SUPPORTED = -12, - - /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the - message strings in strerror.c when adding new error codes here. */ - - /** Other error */ - LIBUSB_ERROR_OTHER = -99, -}; - -/* Total number of error codes in enum libusb_error */ -#define LIBUSB_ERROR_COUNT 14 - -/** \ingroup libusb_asyncio - * Transfer status codes */ -enum libusb_transfer_status { - /** Transfer completed without error. Note that this does not indicate - * that the entire amount of requested data was transferred. */ - LIBUSB_TRANSFER_COMPLETED, - - /** Transfer failed */ - LIBUSB_TRANSFER_ERROR, - - /** Transfer timed out */ - LIBUSB_TRANSFER_TIMED_OUT, - - /** Transfer was cancelled */ - LIBUSB_TRANSFER_CANCELLED, - - /** For bulk/interrupt endpoints: halt condition detected (endpoint - * stalled). For control endpoints: control request not supported. */ - LIBUSB_TRANSFER_STALL, - - /** Device was disconnected */ - LIBUSB_TRANSFER_NO_DEVICE, - - /** Device sent more data than requested */ - LIBUSB_TRANSFER_OVERFLOW, - - /* NB! Remember to update libusb_error_name() - when adding new status codes here. */ -}; - -/** \ingroup libusb_asyncio - * libusb_transfer.flags values */ -enum libusb_transfer_flags { - /** Report short frames as errors */ - LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, - - /** Automatically free() transfer buffer during libusb_free_transfer(). - * Note that buffers allocated with libusb_dev_mem_alloc() should not - * be attempted freed in this way, since free() is not an appropriate - * way to release such memory. */ - LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, - - /** Automatically call libusb_free_transfer() after callback returns. - * If this flag is set, it is illegal to call libusb_free_transfer() - * from your transfer callback, as this will result in a double-free - * when this flag is acted upon. */ - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, - - /** Terminate transfers that are a multiple of the endpoint's - * wMaxPacketSize with an extra zero length packet. This is useful - * when a device protocol mandates that each logical request is - * terminated by an incomplete packet (i.e. the logical requests are - * not separated by other means). - * - * This flag only affects host-to-device transfers to bulk and interrupt - * endpoints. In other situations, it is ignored. - * - * This flag only affects transfers with a length that is a multiple of - * the endpoint's wMaxPacketSize. On transfers of other lengths, this - * flag has no effect. Therefore, if you are working with a device that - * needs a ZLP whenever the end of the logical request falls on a packet - * boundary, then it is sensible to set this flag on every - * transfer (you do not have to worry about only setting it on transfers - * that end on the boundary). - * - * This flag is currently only supported on Linux. - * On other systems, libusb_submit_transfer() will return - * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. - * - * Available since libusb-1.0.9. - */ - LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, -}; - -/** \ingroup libusb_asyncio - * Isochronous packet descriptor. */ -struct libusb_iso_packet_descriptor { - /** Length of data to request in this packet */ - unsigned int length; - - /** Amount of data that was actually transferred */ - unsigned int actual_length; - - /** Status code for this packet */ - enum libusb_transfer_status status; -}; - -struct libusb_transfer; - -/** \ingroup libusb_asyncio - * Asynchronous transfer callback function type. When submitting asynchronous - * transfers, you pass a pointer to a callback function of this type via the - * \ref libusb_transfer::callback "callback" member of the libusb_transfer - * structure. libusb will call this function later, when the transfer has - * completed or failed. See \ref libusb_asyncio for more information. - * \param transfer The libusb_transfer struct the callback function is being - * notified about. - */ -typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); - -/** \ingroup libusb_asyncio - * The generic USB transfer structure. The user populates this structure and - * then submits it in order to request a transfer. After the transfer has - * completed, the library populates the transfer with the results and passes - * it back to the user. - */ -struct libusb_transfer { - /** Handle of the device that this transfer will be submitted to */ - libusb_device_handle *dev_handle; - - /** A bitwise OR combination of \ref libusb_transfer_flags. */ - uint8_t flags; - - /** Address of the endpoint where this transfer will be sent. */ - unsigned char endpoint; - - /** Type of the endpoint from \ref libusb_transfer_type */ - unsigned char type; - - /** Timeout for this transfer in milliseconds. A value of 0 indicates no - * timeout. */ - unsigned int timeout; - - /** The status of the transfer. Read-only, and only for use within - * transfer callback function. - * - * If this is an isochronous transfer, this field may read COMPLETED even - * if there were errors in the frames. Use the - * \ref libusb_iso_packet_descriptor::status "status" field in each packet - * to determine if errors occurred. */ - enum libusb_transfer_status status; - - /** Length of the data buffer */ - int length; - - /** Actual length of data that was transferred. Read-only, and only for - * use within transfer callback function. Not valid for isochronous - * endpoint transfers. */ - int actual_length; - - /** Callback function. This will be invoked when the transfer completes, - * fails, or is cancelled. */ - libusb_transfer_cb_fn callback; - - /** User context data to pass to the callback function. */ - void *user_data; - - /** Data buffer */ - unsigned char *buffer; - - /** Number of isochronous packets. Only used for I/O with isochronous - * endpoints. */ - int num_iso_packets; - - /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; -}; - -/** \ingroup libusb_misc - * Capabilities supported by an instance of libusb on the current running - * platform. Test if the loaded library supports a given capability by calling - * \ref libusb_has_capability(). - */ -enum libusb_capability { - /** The libusb_has_capability() API is available. */ - LIBUSB_CAP_HAS_CAPABILITY = 0x0000, - /** Hotplug support is available on this platform. */ - LIBUSB_CAP_HAS_HOTPLUG = 0x0001, - /** The library can access HID devices without requiring user intervention. - * Note that before being able to actually access an HID device, you may - * still have to call additional libusb functions such as - * \ref libusb_detach_kernel_driver(). */ - LIBUSB_CAP_HAS_HID_ACCESS = 0x0100, - /** The library supports detaching of the default USB driver, using - * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ - LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 -}; - -/** \ingroup libusb_lib - * Log message levels. - * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) - * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr - */ -enum libusb_log_level { - LIBUSB_LOG_LEVEL_NONE = 0, - LIBUSB_LOG_LEVEL_ERROR = 1, - LIBUSB_LOG_LEVEL_WARNING = 2, - LIBUSB_LOG_LEVEL_INFO = 3, - LIBUSB_LOG_LEVEL_DEBUG = 4, -}; - -int LIBUSB_CALL libusb_init(libusb_context **ctx); -void LIBUSB_CALL libusb_exit(libusb_context *ctx); -LIBUSB_DEPRECATED_FOR(libusb_set_option) -void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); -const struct libusb_version * LIBUSB_CALL libusb_get_version(void); -int LIBUSB_CALL libusb_has_capability(uint32_t capability); -const char * LIBUSB_CALL libusb_error_name(int errcode); -int LIBUSB_CALL libusb_setlocale(const char *locale); -const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode); - -ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, - libusb_device ***list); -void LIBUSB_CALL libusb_free_device_list(libusb_device **list, - int unref_devices); -libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); -void LIBUSB_CALL libusb_unref_device(libusb_device *dev); - -int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, - int *config); -int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, - struct libusb_device_descriptor *desc); -int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, - struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, - uint8_t config_index, struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, - uint8_t bConfigurationValue, struct libusb_config_descriptor **config); -void LIBUSB_CALL libusb_free_config_descriptor( - struct libusb_config_descriptor *config); -int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( - struct libusb_context *ctx, - const struct libusb_endpoint_descriptor *endpoint, - struct libusb_ss_endpoint_companion_descriptor **ep_comp); -void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( - struct libusb_ss_endpoint_companion_descriptor *ep_comp); -int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, - struct libusb_bos_descriptor **bos); -void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); -int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension); -void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor( - struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension); -int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap); -void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor( - struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap); -int LIBUSB_CALL libusb_get_container_id_descriptor(struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_container_id_descriptor **container_id); -void LIBUSB_CALL libusb_free_container_id_descriptor( - struct libusb_container_id_descriptor *container_id); -uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); -uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); -int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len); -LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers) -int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length); -libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev); -uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); -int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); -int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, - unsigned char endpoint); -int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, - unsigned char endpoint); - -int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); -void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); -libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); - -int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, - int configuration); -int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, - int interface_number); - -libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( - libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); - -int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, - int interface_number, int alternate_setting); -int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, - unsigned char endpoint); -int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); - -int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints); - -unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, - size_t length); -int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, - unsigned char *buffer, size_t length); - -int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev_handle, int enable); - -/* async I/O */ - -/** \ingroup libusb_asyncio - * Get the data section of a control transfer. This convenience function is here - * to remind you that the data does not start until 8 bytes into the actual - * buffer, as the setup packet comes first. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns pointer to the first byte of the data section - */ -static inline unsigned char *libusb_control_transfer_get_data( - struct libusb_transfer *transfer) -{ - return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; -} - -/** \ingroup libusb_asyncio - * Get the control setup packet of a control transfer. This convenience - * function is here to remind you that the control setup occupies the first - * 8 bytes of the transfer data buffer. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns a casted pointer to the start of the transfer data buffer - */ -static inline struct libusb_control_setup *libusb_control_transfer_get_setup( - struct libusb_transfer *transfer) -{ - return (struct libusb_control_setup *)(void *) transfer->buffer; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the setup packet (first 8 bytes of the data - * buffer) for a control transfer. The wIndex, wValue and wLength values should - * be given in host-endian byte order. - * - * \param buffer buffer to output the setup packet into - * This pointer must be aligned to at least 2 bytes boundary. - * \param bmRequestType see the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field of - * \ref libusb_control_setup - * \param bRequest see the - * \ref libusb_control_setup::bRequest "bRequest" field of - * \ref libusb_control_setup - * \param wValue see the - * \ref libusb_control_setup::wValue "wValue" field of - * \ref libusb_control_setup - * \param wIndex see the - * \ref libusb_control_setup::wIndex "wIndex" field of - * \ref libusb_control_setup - * \param wLength see the - * \ref libusb_control_setup::wLength "wLength" field of - * \ref libusb_control_setup - */ -static inline void libusb_fill_control_setup(unsigned char *buffer, - uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - uint16_t wLength) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; - setup->bmRequestType = bmRequestType; - setup->bRequest = bRequest; - setup->wValue = libusb_cpu_to_le16(wValue); - setup->wIndex = libusb_cpu_to_le16(wIndex); - setup->wLength = libusb_cpu_to_le16(wLength); -} - -struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); -int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); -int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); -void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); -void LIBUSB_CALL libusb_transfer_set_stream_id( - struct libusb_transfer *transfer, uint32_t stream_id); -uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( - struct libusb_transfer *transfer); - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a control transfer. - * - * If you pass a transfer buffer to this function, the first 8 bytes will - * be interpreted as a control setup packet, and the wLength field will be - * used to automatically populate the \ref libusb_transfer::length "length" - * field of the transfer. Therefore the recommended approach is: - * -# Allocate a suitably sized data buffer (including space for control setup) - * -# Call libusb_fill_control_setup() - * -# If this is a host-to-device transfer with a data stage, put the data - * in place after the setup packet - * -# Call this function - * -# Call libusb_submit_transfer() - * - * It is also legal to pass a NULL buffer to this function, in which case this - * function will not attempt to populate the length field. Remember that you - * must then populate the buffer and length fields later. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param buffer data buffer. If provided, this function will interpret the - * first 8 bytes as a setup packet and infer the transfer length from that. - * This pointer must be aligned to at least 2 bytes boundary. - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_control_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, - unsigned int timeout) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; - transfer->dev_handle = dev_handle; - transfer->endpoint = 0; - transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; - transfer->timeout = timeout; - transfer->buffer = buffer; - if (setup) - transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE - + libusb_le16_to_cpu(setup->wLength)); - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a bulk transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, libusb_transfer_cb_fn callback, - void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_BULK; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a bulk transfer using bulk streams. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param stream_id bulk stream id for this transfer - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_bulk_stream_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char endpoint, uint32_t stream_id, - unsigned char *buffer, int length, libusb_transfer_cb_fn callback, - void *user_data, unsigned int timeout) -{ - libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, - length, callback, user_data, timeout); - transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; - libusb_transfer_set_stream_id(transfer, stream_id); -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an interrupt transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_interrupt_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an isochronous transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param num_iso_packets the number of isochronous packets - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, int num_iso_packets, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->num_iso_packets = num_iso_packets; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Convenience function to set the length of all packets in an isochronous - * transfer, based on the num_iso_packets field in the transfer structure. - * - * \param transfer a transfer - * \param length the length to set in each isochronous packet descriptor - * \see libusb_get_max_packet_size() - */ -static inline void libusb_set_iso_packet_lengths( - struct libusb_transfer *transfer, unsigned int length) -{ - int i; - for (i = 0; i < transfer->num_iso_packets; i++) - transfer->iso_packet_desc[i].length = length; -} - -/** \ingroup libusb_asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer. - * - * This is a thorough function which loops through all preceding packets, - * accumulating their lengths to find the position of the specified packet. - * Typically you will assign equal lengths to each packet in the transfer, - * and hence the above method is sub-optimal. You may wish to use - * libusb_get_iso_packet_buffer_simple() instead. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer_simple() - */ -static inline unsigned char *libusb_get_iso_packet_buffer( - struct libusb_transfer *transfer, unsigned int packet) -{ - int i; - size_t offset = 0; - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = (int) packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - for (i = 0; i < _packet; i++) - offset += transfer->iso_packet_desc[i].length; - - return transfer->buffer + offset; -} - -/** \ingroup libusb_asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer, for transfers where each - * packet is of identical size. - * - * This function relies on the assumption that every packet within the transfer - * is of identical size to the first packet. Calculating the location of - * the packet buffer is then just a simple calculation: - * buffer + (packet_size * packet) - * - * Do not use this function on transfers other than those that have identical - * packet lengths for each packet. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer() - */ -static inline unsigned char *libusb_get_iso_packet_buffer_simple( - struct libusb_transfer *transfer, unsigned int packet) -{ - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = (int) packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet); -} - -/* sync I/O */ - -int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout); - -int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -/** \ingroup libusb_desc - * Retrieve a descriptor from the default control pipe. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. - * - * \param dev_handle a device handle - * \param desc_type the descriptor type, see \ref libusb_descriptor_type - * \param desc_index the index of the descriptor to retrieve - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - */ -static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, - uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) -{ - return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), - 0, data, (uint16_t) length, 1000); -} - -/** \ingroup libusb_desc - * Retrieve a descriptor from a device. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. The string returned is Unicode, as - * detailed in the USB specifications. - * - * \param dev_handle a device handle - * \param desc_index the index of the descriptor to retrieve - * \param langid the language ID for the string descriptor - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - * \see libusb_get_string_descriptor_ascii() - */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, - uint8_t desc_index, uint16_t langid, unsigned char *data, int length) -{ - return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), - langid, data, (uint16_t) length, 1000); -} - -int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, - uint8_t desc_index, unsigned char *data, int length); - -/* polling and timeouts */ - -int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); -void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); -int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); - -int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, - struct timeval *tv, int *completed); -int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); -int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); -int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); -int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, - struct timeval *tv); - -/** \ingroup libusb_poll - * File descriptor for polling - */ -struct libusb_pollfd { - /** Numeric file descriptor */ - int fd; - - /** Event flags to poll for from . POLLIN indicates that you - * should monitor this file descriptor for becoming ready to read from, - * and POLLOUT indicates that you should monitor this file descriptor for - * nonblocking write readiness. */ - short events; -}; - -/** \ingroup libusb_poll - * Callback function, invoked when a new file descriptor should be added - * to the set of file descriptors monitored for events. - * \param fd the new file descriptor - * \param events events to monitor for, see \ref libusb_pollfd for a - * description - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, - void *user_data); - -/** \ingroup libusb_poll - * Callback function, invoked when a file descriptor should be removed from - * the set of file descriptors being monitored for events. After returning - * from this callback, do not use that file descriptor again. - * \param fd the file descriptor to stop monitoring - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); - -const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( - libusb_context *ctx); -void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds); -void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, - libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, - void *user_data); - -/** \ingroup libusb_hotplug - * Callback handle. - * - * Callbacks handles are generated by libusb_hotplug_register_callback() - * and can be used to deregister callbacks. Callback handles are unique - * per libusb_context and it is safe to call libusb_hotplug_deregister_callback() - * on an already deregisted callback. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * For more information, see \ref libusb_hotplug. - */ -typedef int libusb_hotplug_callback_handle; - -/** \ingroup libusb_hotplug - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * Flags for hotplug events */ -typedef enum { - /** Default value when not using any flags. */ - LIBUSB_HOTPLUG_NO_FLAGS = 0, - - /** Arm the callback and fire it for all matching currently attached devices. */ - LIBUSB_HOTPLUG_ENUMERATE = 1<<0, -} libusb_hotplug_flag; - -/** \ingroup libusb_hotplug - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * Hotplug events */ -typedef enum { - /** A device has been plugged in and is ready to use */ - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01, - - /** A device has left and is no longer available. - * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. - * It is safe to call libusb_get_device_descriptor on a device that has left */ - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, -} libusb_hotplug_event; - -/** \ingroup libusb_hotplug - * Wildcard matching for hotplug events */ -#define LIBUSB_HOTPLUG_MATCH_ANY -1 - -/** \ingroup libusb_hotplug - * Hotplug callback function type. When requesting hotplug event notifications, - * you pass a pointer to a callback function of this type. - * - * This callback may be called by an internal event thread and as such it is - * recommended the callback do minimal processing before returning. - * - * libusb will call this function later, when a matching event had happened on - * a matching device. See \ref libusb_hotplug for more information. - * - * It is safe to call either libusb_hotplug_register_callback() or - * libusb_hotplug_deregister_callback() from within a callback function. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param ctx context of this notification - * \param device libusb_device this event occurred on - * \param event event that occurred - * \param user_data user data provided when this callback was registered - * \returns bool whether this callback is finished processing events. - * returning 1 will cause this callback to be deregistered - */ -typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, - libusb_device *device, - libusb_hotplug_event event, - void *user_data); - -/** \ingroup libusb_hotplug - * Register a hotplug callback function - * - * Register a callback with the libusb_context. The callback will fire - * when a matching event occurs on a matching device. The callback is - * armed until either it is deregistered with libusb_hotplug_deregister_callback() - * or the supplied callback returns 1 to indicate it is finished processing events. - * - * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be - * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices - * already plugged into the machine. Note that libusb modifies its internal - * device list from a separate thread, while calling hotplug callbacks from - * libusb_handle_events(), so it is possible for a device to already be present - * on, or removed from, its internal device list, while the hotplug callbacks - * still need to be dispatched. This means that when using \ref - * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival - * of the same device, once from libusb_hotplug_register_callback() and once - * from libusb_handle_events(); and/or your callback may be called for the - * removal of a device for which an arrived call was never made. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param[in] ctx context to register this callback with - * \param[in] events bitwise or of events that will trigger this callback. See \ref - * libusb_hotplug_event - * \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag - * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] cb_fn the function to be invoked on a matching event/device - * \param[in] user_data user data to pass to the callback function - * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) - * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure - */ -int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, - libusb_hotplug_event events, - libusb_hotplug_flag flags, - int vendor_id, int product_id, - int dev_class, - libusb_hotplug_callback_fn cb_fn, - void *user_data, - libusb_hotplug_callback_handle *callback_handle); - -/** \ingroup libusb_hotplug - * Deregisters a hotplug callback. - * - * Deregister a callback from a libusb_context. This function is safe to call from within - * a hotplug callback. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param[in] ctx context this callback is registered with - * \param[in] callback_handle the handle of the callback to deregister - */ -void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, - libusb_hotplug_callback_handle callback_handle); - -/** \ingroup libusb_lib - * Available option values for libusb_set_option(). - */ -enum libusb_option { - /** Set the log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stderr file descriptor. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - */ - LIBUSB_OPTION_LOG_LEVEL, - - /** Use the UsbDk backend for a specific context, if available. - * - * This option should be set immediately after calling libusb_init(), otherwise - * unspecified behavior may occur. - * - * Only valid on Windows. - */ - LIBUSB_OPTION_USE_USBDK, -}; - -int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h deleted file mode 100644 index 31d6ce98d4..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * Internal header for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSBI_H -#define LIBUSBI_H - -#include - -#include - -#include -#include -#include -#include -#ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_MISSING_H -#include -#endif - -#include "libusb.h" -#include "version.h" - -/* Attribute to ensure that a structure member is aligned to a natural - * pointer alignment. Used for os_priv member. */ -#if defined(_MSC_VER) -#if defined(_WIN64) -#define PTR_ALIGNED __declspec(align(8)) -#else -#define PTR_ALIGNED __declspec(align(4)) -#endif -#elif defined(__GNUC__) -#define PTR_ALIGNED __attribute__((aligned(sizeof(void *)))) -#else -#define PTR_ALIGNED -#endif - -/* Inside the libusb code, mark all public functions as follows: - * return_type API_EXPORTED function_name(params) { ... } - * But if the function returns a pointer, mark it as follows: - * DEFAULT_VISIBILITY return_type * LIBUSB_CALL function_name(params) { ... } - * In the libusb public header, mark all declarations as: - * return_type LIBUSB_CALL function_name(params); - */ -#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY - -#ifdef __cplusplus -extern "C" { -#endif - -#define DEVICE_DESC_LENGTH 18 - -#define USB_MAXENDPOINTS 32 -#define USB_MAXINTERFACES 32 -#define USB_MAXCONFIG 8 - -/* Backend specific capabilities */ -#define USBI_CAP_HAS_HID_ACCESS 0x00010000 -#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 - -/* Maximum number of bytes in a log line */ -#define USBI_MAX_LOG_LEN 1024 -/* Terminator for log lines */ -#define USBI_LOG_LINE_END "\n" - -/* The following is used to silence warnings for unused variables */ -#define UNUSED(var) do { (void)(var); } while(0) - -#if !defined(ARRAYSIZE) -#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0])) -#endif - -struct list_head { - struct list_head *prev, *next; -}; - -/* Get an entry from the list - * ptr - the address of this list_head element in "type" - * type - the data type that contains "member" - * member - the list_head element in "type" - */ -#define list_entry(ptr, type, member) \ - ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) - -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/* Get each entry from a list - * pos - A structure pointer has a "member" element - * head - list head - * member - the list_head element in "pos" - * type - the type of the first parameter - */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) - -#define list_for_each_entry_safe(pos, n, head, member, type) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) - -#define list_empty(entry) ((entry)->next == (entry)) - -static inline void list_init(struct list_head *entry) -{ - entry->prev = entry->next = entry; -} - -static inline void list_add(struct list_head *entry, struct list_head *head) -{ - entry->next = head->next; - entry->prev = head; - - head->next->prev = entry; - head->next = entry; -} - -static inline void list_add_tail(struct list_head *entry, - struct list_head *head) -{ - entry->next = head; - entry->prev = head->prev; - - head->prev->next = entry; - head->prev = entry; -} - -static inline void list_del(struct list_head *entry) -{ - entry->next->prev = entry->prev; - entry->prev->next = entry->next; - entry->next = entry->prev = NULL; -} - -static inline void list_cut(struct list_head *list, struct list_head *head) -{ - if (list_empty(head)) - return; - - list->next = head->next; - list->next->prev = list; - list->prev = head->prev; - list->prev->next = list; - - list_init(head); -} - -static inline void *usbi_reallocf(void *ptr, size_t size) -{ - void *ret = realloc(ptr, size); - if (!ret) - free(ptr); - return ret; -} - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *mptr = (ptr); \ - (type *)( (char *)mptr - offsetof(type,member) );}) - -#ifndef CLAMP -#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) -#endif -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0) - -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#define TIMEVAL_TV_SEC_TYPE long -#else -#define TIMEVAL_TV_SEC_TYPE time_t -#endif - -/* Some platforms don't have this define */ -#ifndef TIMESPEC_TO_TIMEVAL -#define TIMESPEC_TO_TIMEVAL(tv, ts) \ - do { \ - (tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ - } while (0) -#endif - -#ifdef ENABLE_LOGGING - -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define snprintf usbi_snprintf -#define vsnprintf usbi_vsnprintf -int usbi_snprintf(char *dst, size_t size, const char *format, ...); -int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); -#define LIBUSB_PRINTF_WIN32 -#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */ - -void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, ...); - -void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, va_list args); - -#if !defined(_MSC_VER) || (_MSC_VER >= 1400) - -#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) - -#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) -#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) -#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) -#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) - -#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ - -#define LOG_BODY(ctxt, level) \ -{ \ - va_list args; \ - va_start(args, format); \ - usbi_log_v(ctxt, level, "", format, args); \ - va_end(args); \ -} - -static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) -static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) -static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) -static inline void usbi_dbg(const char *format, ...) - LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) - -#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ - -#else /* ENABLE_LOGGING */ - -#define usbi_err(ctx, ...) do { (void)ctx; } while (0) -#define usbi_warn(ctx, ...) do { (void)ctx; } while (0) -#define usbi_info(ctx, ...) do { (void)ctx; } while (0) -#define usbi_dbg(...) do {} while (0) - -#endif /* ENABLE_LOGGING */ - -#define USBI_GET_CONTEXT(ctx) \ - do { \ - if (!(ctx)) \ - (ctx) = usbi_default_context; \ - } while(0) - -#define DEVICE_CTX(dev) ((dev)->ctx) -#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) -#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) -#define ITRANSFER_CTX(transfer) \ - (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) - -#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) -#define IS_EPOUT(ep) (!IS_EPIN(ep)) -#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) -#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) - -/* Internal abstraction for thread synchronization */ -#if defined(THREADS_POSIX) -#include "os/threads_posix.h" -#elif defined(OS_WINDOWS) || defined(OS_WINCE) -#include "os/threads_windows.h" -#endif - -extern struct libusb_context *usbi_default_context; - -/* Forward declaration for use in context (fully defined inside poll abstraction) */ -struct pollfd; - -struct libusb_context { -#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) - enum libusb_log_level debug; - int debug_fixed; -#endif - - /* internal event pipe, used for signalling occurrence of an internal event. */ - int event_pipe[2]; - - struct list_head usb_devs; - usbi_mutex_t usb_devs_lock; - - /* A list of open handles. Backends are free to traverse this if required. - */ - struct list_head open_devs; - usbi_mutex_t open_devs_lock; - - /* A list of registered hotplug callbacks */ - struct list_head hotplug_cbs; - libusb_hotplug_callback_handle next_hotplug_cb_handle; - usbi_mutex_t hotplug_cbs_lock; - - /* this is a list of in-flight transfer handles, sorted by timeout - * expiration. URBs to timeout the soonest are placed at the beginning of - * the list, URBs that will time out later are placed after, and urbs with - * infinite timeout are always placed at the very end. */ - struct list_head flying_transfers; - /* Note paths taking both this and usbi_transfer->lock must always - * take this lock first */ - usbi_mutex_t flying_transfers_lock; - - /* user callbacks for pollfd changes */ - libusb_pollfd_added_cb fd_added_cb; - libusb_pollfd_removed_cb fd_removed_cb; - void *fd_cb_user_data; - - /* ensures that only one thread is handling events at any one time */ - usbi_mutex_t events_lock; - - /* used to see if there is an active thread doing event handling */ - int event_handler_active; - - /* A thread-local storage key to track which thread is performing event - * handling */ - usbi_tls_key_t event_handling_key; - - /* used to wait for event completion in threads other than the one that is - * event handling */ - usbi_mutex_t event_waiters_lock; - usbi_cond_t event_waiters_cond; - - /* A lock to protect internal context event data. */ - usbi_mutex_t event_data_lock; - - /* A bitmask of flags that are set to indicate specific events that need to - * be handled. Protected by event_data_lock. */ - unsigned int event_flags; - - /* A counter that is set when we want to interrupt and prevent event handling, - * in order to safely close a device. Protected by event_data_lock. */ - unsigned int device_close; - - /* list and count of poll fds and an array of poll fd structures that is - * (re)allocated as necessary prior to polling. Protected by event_data_lock. */ - struct list_head ipollfds; - struct pollfd *pollfds; - POLL_NFDS_TYPE pollfds_cnt; - - /* A list of pending hotplug messages. Protected by event_data_lock. */ - struct list_head hotplug_msgs; - - /* A list of pending completed transfers. Protected by event_data_lock. */ - struct list_head completed_transfers; - -#ifdef USBI_TIMERFD_AVAILABLE - /* used for timeout handling, if supported by OS. - * this timerfd is maintained to trigger on the next pending timeout */ - int timerfd; -#endif - - struct list_head list; - - PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; -}; - -enum usbi_event_flags { - /* The list of pollfds has been modified */ - USBI_EVENT_POLLFDS_MODIFIED = 1 << 0, - - /* The user has interrupted the event handler */ - USBI_EVENT_USER_INTERRUPT = 1 << 1, - - /* A hotplug callback deregistration is pending */ - USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1 << 2, -}; - -/* Macros for managing event handling state */ -#define usbi_handling_events(ctx) \ - (usbi_tls_key_get((ctx)->event_handling_key) != NULL) - -#define usbi_start_event_handling(ctx) \ - usbi_tls_key_set((ctx)->event_handling_key, ctx) - -#define usbi_end_event_handling(ctx) \ - usbi_tls_key_set((ctx)->event_handling_key, NULL) - -/* Update the following macro if new event sources are added */ -#define usbi_pending_events(ctx) \ - ((ctx)->event_flags || (ctx)->device_close \ - || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers)) - -#ifdef USBI_TIMERFD_AVAILABLE -#define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) -#else -#define usbi_using_timerfd(ctx) (0) -#endif - -struct libusb_device { - /* lock protects refcnt, everything else is finalized at initialization - * time */ - usbi_mutex_t lock; - int refcnt; - - struct libusb_context *ctx; - - uint8_t bus_number; - uint8_t port_number; - struct libusb_device* parent_dev; - uint8_t device_address; - uint8_t num_configurations; - enum libusb_speed speed; - - struct list_head list; - unsigned long session_data; - - struct libusb_device_descriptor device_descriptor; - int attached; - - PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; -}; - -struct libusb_device_handle { - /* lock protects claimed_interfaces */ - usbi_mutex_t lock; - unsigned long claimed_interfaces; - - struct list_head list; - struct libusb_device *dev; - int auto_detach_kernel_driver; - - PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; -}; - -enum { - USBI_CLOCK_MONOTONIC, - USBI_CLOCK_REALTIME -}; - -/* in-memory transfer layout: - * - * 1. struct usbi_transfer - * 2. struct libusb_transfer (which includes iso packets) [variable size] - * 3. os private data [variable size] - * - * from a libusb_transfer, you can get the usbi_transfer by rewinding the - * appropriate number of bytes. - * the usbi_transfer includes the number of allocated packets, so you can - * determine the size of the transfer and hence the start and length of the - * OS-private data. - */ - -struct usbi_transfer { - int num_iso_packets; - struct list_head list; - struct list_head completed_list; - struct timeval timeout; - int transferred; - uint32_t stream_id; - uint8_t state_flags; /* Protected by usbi_transfer->lock */ - uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */ - - /* this lock is held during libusb_submit_transfer() and - * libusb_cancel_transfer() (allowing the OS backend to prevent duplicate - * cancellation, submission-during-cancellation, etc). the OS backend - * should also take this lock in the handle_events path, to prevent the user - * cancelling the transfer from another thread while you are processing - * its completion (presumably there would be races within your OS backend - * if this were possible). - * Note paths taking both this and the flying_transfers_lock must - * always take the flying_transfers_lock first */ - usbi_mutex_t lock; -}; - -enum usbi_transfer_state_flags { - /* Transfer successfully submitted by backend */ - USBI_TRANSFER_IN_FLIGHT = 1 << 0, - - /* Cancellation was requested via libusb_cancel_transfer() */ - USBI_TRANSFER_CANCELLING = 1 << 1, - - /* Operation on the transfer failed because the device disappeared */ - USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2, -}; - -enum usbi_transfer_timeout_flags { - /* Set by backend submit_transfer() if the OS handles timeout */ - USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0, - - /* The transfer timeout has been handled */ - USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, - - /* The transfer timeout was successfully processed */ - USBI_TRANSFER_TIMED_OUT = 1 << 2, -}; - -#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ - ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ - + sizeof(struct usbi_transfer))) -#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ - ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ - - sizeof(struct usbi_transfer))) - -static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) -{ - return ((unsigned char *)transfer) + sizeof(struct usbi_transfer) - + sizeof(struct libusb_transfer) - + (transfer->num_iso_packets - * sizeof(struct libusb_iso_packet_descriptor)); -} - -/* bus structures */ - -/* All standard descriptors have these 2 fields in common */ -struct usb_descriptor_header { - uint8_t bLength; - uint8_t bDescriptorType; -}; - -/* shared data and functions */ - -int usbi_io_init(struct libusb_context *ctx); -void usbi_io_exit(struct libusb_context *ctx); - -struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, - unsigned long session_id); -struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, - unsigned long session_id); -int usbi_sanitize_device(struct libusb_device *dev); -void usbi_handle_disconnect(struct libusb_device_handle *dev_handle); - -int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, - enum libusb_transfer_status status); -int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); -void usbi_signal_transfer_completion(struct usbi_transfer *transfer); - -int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, - void *dest, int host_endian); -int usbi_device_cache_descriptor(libusb_device *dev); -int usbi_get_config_index_by_value(struct libusb_device *dev, - uint8_t bConfigurationValue, int *idx); - -void usbi_connect_device (struct libusb_device *dev); -void usbi_disconnect_device (struct libusb_device *dev); - -int usbi_signal_event(struct libusb_context *ctx); -int usbi_clear_event(struct libusb_context *ctx); - -/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ - defined(OS_HAIKU) || defined(OS_SUNOS) -#include -#include "os/poll_posix.h" -#elif defined(OS_WINDOWS) || defined(OS_WINCE) -#include "os/poll_windows.h" -#endif - -struct usbi_pollfd { - /* must come first */ - struct libusb_pollfd pollfd; - - struct list_head list; -}; - -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); -void usbi_remove_pollfd(struct libusb_context *ctx, int fd); - -/* device discovery */ - -/* we traverse usbfs without knowing how many devices we are going to find. - * so we create this discovered_devs model which is similar to a linked-list - * which grows when required. it can be freed once discovery has completed, - * eliminating the need for a list node in the libusb_device structure - * itself. */ -struct discovered_devs { - size_t len; - size_t capacity; - struct libusb_device *devices[ZERO_SIZED_ARRAY]; -}; - -struct discovered_devs *discovered_devs_append( - struct discovered_devs *discdevs, struct libusb_device *dev); - -/* OS abstraction */ - -/* This is the interface that OS backends need to implement. - * All fields are mandatory, except ones explicitly noted as optional. */ -struct usbi_os_backend { - /* A human-readable name for your backend, e.g. "Linux usbfs" */ - const char *name; - - /* Binary mask for backend specific capabilities */ - uint32_t caps; - - /* Perform initialization of your backend. You might use this function - * to determine specific capabilities of the system, allocate required - * data structures for later, etc. - * - * This function is called when a libusb user initializes the library - * prior to use. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*init)(struct libusb_context *ctx); - - /* Deinitialization. Optional. This function should destroy anything - * that was set up by init. - * - * This function is called when the user deinitializes the library. - */ - void (*exit)(struct libusb_context *ctx); - - /* Set a backend-specific option. Optional. - * - * This function is called when the user calls libusb_set_option() and - * the option is not handled by the core library. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*set_option)(struct libusb_context *ctx, enum libusb_option option, - va_list args); - - /* Enumerate all the USB devices on the system, returning them in a list - * of discovered devices. - * - * Your implementation should enumerate all devices on the system, - * regardless of whether they have been seen before or not. - * - * When you have found a device, compute a session ID for it. The session - * ID should uniquely represent that particular device for that particular - * connection session since boot (i.e. if you disconnect and reconnect a - * device immediately after, it should be assigned a different session ID). - * If your OS cannot provide a unique session ID as described above, - * presenting a session ID of (bus_number << 8 | device_address) should - * be sufficient. Bus numbers and device addresses wrap and get reused, - * but that is an unlikely case. - * - * After computing a session ID for a device, call - * usbi_get_device_by_session_id(). This function checks if libusb already - * knows about the device, and if so, it provides you with a reference - * to a libusb_device structure for it. - * - * If usbi_get_device_by_session_id() returns NULL, it is time to allocate - * a new device structure for the device. Call usbi_alloc_device() to - * obtain a new libusb_device structure with reference count 1. Populate - * the bus_number and device_address attributes of the new device, and - * perform any other internal backend initialization you need to do. At - * this point, you should be ready to provide device descriptors and so - * on through the get_*_descriptor functions. Finally, call - * usbi_sanitize_device() to perform some final sanity checks on the - * device. Assuming all of the above succeeded, we can now continue. - * If any of the above failed, remember to unreference the device that - * was returned by usbi_alloc_device(). - * - * At this stage we have a populated libusb_device structure (either one - * that was found earlier, or one that we have just allocated and - * populated). This can now be added to the discovered devices list - * using discovered_devs_append(). Note that discovered_devs_append() - * may reallocate the list, returning a new location for it, and also - * note that reallocation can fail. Your backend should handle these - * error conditions appropriately. - * - * This function should not generate any bus I/O and should not block. - * If I/O is required (e.g. reading the active configuration value), it is - * OK to ignore these suggestions :) - * - * This function is executed when the user wishes to retrieve a list - * of USB devices connected to the system. - * - * If the backend has hotplug support, this function is not used! - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*get_device_list)(struct libusb_context *ctx, - struct discovered_devs **discdevs); - - /* Apps which were written before hotplug support, may listen for - * hotplug events on their own and call libusb_get_device_list on - * device addition. In this case libusb_get_device_list will likely - * return a list without the new device in there, as the hotplug - * event thread will still be busy enumerating the device, which may - * take a while, or may not even have seen the event yet. - * - * To avoid this libusb_get_device_list will call this optional - * function for backends with hotplug support before copying - * ctx->usb_devs to the user. In this function the backend should - * ensure any pending hotplug events are fully processed before - * returning. - * - * Optional, should be implemented by backends with hotplug support. - */ - void (*hotplug_poll)(void); - - /* Open a device for I/O and other USB operations. The device handle - * is preallocated for you, you can retrieve the device in question - * through handle->dev. - * - * Your backend should allocate any internal resources required for I/O - * and other operations so that those operations can happen (hopefully) - * without hiccup. This is also a good place to inform libusb that it - * should monitor certain file descriptors related to this device - - * see the usbi_add_pollfd() function. - * - * This function should not generate any bus I/O and should not block. - * - * This function is called when the user attempts to obtain a device - * handle for a device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since - * discovery - * - another LIBUSB_ERROR code on other failure - * - * Do not worry about freeing the handle on failed open, the upper layers - * do this for you. - */ - int (*open)(struct libusb_device_handle *dev_handle); - - /* Close a device such that the handle cannot be used again. Your backend - * should destroy any resources that were allocated in the open path. - * This may also be a good place to call usbi_remove_pollfd() to inform - * libusb of any file descriptors associated with this device that should - * no longer be monitored. - * - * This function is called when the user closes a device handle. - */ - void (*close)(struct libusb_device_handle *dev_handle); - - /* Retrieve the device descriptor from a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. Alternatively, you may be able - * to retrieve it from a kernel interface (some Linux setups can do this) - * still without generating bus I/O. - * - * This function is expected to write DEVICE_DESC_LENGTH (18) bytes into - * buffer, which is guaranteed to be big enough. - * - * This function is called when sanity-checking a device before adding - * it to the list of discovered devices, and also when the user requests - * to read the device descriptor. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return 0 on success or a LIBUSB_ERROR code on failure. - */ - int (*get_device_descriptor)(struct libusb_device *device, - unsigned char *buffer, int *host_endian); - - /* Get the ACTIVE configuration descriptor for a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. You may also have to keep track - * of which configuration is active when the user changes it. - * - * This function is expected to write len bytes of data into buffer, which - * is guaranteed to be big enough. If you can only do a partial write, - * return an error code. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state - * - another LIBUSB_ERROR code on other failure - */ - int (*get_active_config_descriptor)(struct libusb_device *device, - unsigned char *buffer, size_t len, int *host_endian); - - /* Get a specific configuration descriptor for a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. - * - * The requested descriptor is expressed as a zero-based index (i.e. 0 - * indicates that we are requesting the first descriptor). The index does - * not (necessarily) equal the bConfigurationValue of the configuration - * being requested. - * - * This function is expected to write len bytes of data into buffer, which - * is guaranteed to be big enough. If you can only do a partial write, - * return an error code. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return the length read on success or a LIBUSB_ERROR code on failure. - */ - int (*get_config_descriptor)(struct libusb_device *device, - uint8_t config_index, unsigned char *buffer, size_t len, - int *host_endian); - - /* Like get_config_descriptor but then by bConfigurationValue instead - * of by index. - * - * Optional, if not present the core will call get_config_descriptor - * for all configs until it finds the desired bConfigurationValue. - * - * Returns a pointer to the raw-descriptor in *buffer, this memory - * is valid as long as device is valid. - * - * Returns the length of the returned raw-descriptor on success, - * or a LIBUSB_ERROR code on failure. - */ - int (*get_config_descriptor_by_value)(struct libusb_device *device, - uint8_t bConfigurationValue, unsigned char **buffer, - int *host_endian); - - /* Get the bConfigurationValue for the active configuration for a device. - * Optional. This should only be implemented if you can retrieve it from - * cache (don't generate I/O). - * - * If you cannot retrieve this from cache, either do not implement this - * function, or return LIBUSB_ERROR_NOT_SUPPORTED. This will cause - * libusb to retrieve the information through a standard control transfer. - * - * This function must be non-blocking. - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - LIBUSB_ERROR_NOT_SUPPORTED if the value cannot be retrieved without - * blocking - * - another LIBUSB_ERROR code on other failure. - */ - int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); - - /* Set the active configuration for a device. - * - * A configuration value of -1 should put the device in unconfigured state. - * - * This function can block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * - LIBUSB_ERROR_BUSY if interfaces are currently claimed (and hence - * configuration cannot be changed) - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure. - */ - int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); - - /* Claim an interface. When claimed, the application can then perform - * I/O to an interface's endpoints. - * - * This function should not generate any bus I/O and should not block. - * Interface claiming is a logical operation that simply ensures that - * no other drivers/applications are using the interface, and after - * claiming, no other drivers/applications can use the interface because - * we now "own" it. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the interface does not exist - * - LIBUSB_ERROR_BUSY if the interface is in use by another driver/app - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); - - /* Release a previously claimed interface. - * - * This function should also generate a SET_INTERFACE control request, - * resetting the alternate setting of that interface to 0. It's OK for - * this function to block as a result. - * - * You will only ever be asked to release an interface which was - * successfully claimed earlier. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); - - /* Set the alternate setting for an interface. - * - * You will only ever be asked to set the alternate setting for an - * interface which was successfully claimed earlier. - * - * It's OK for this function to block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the alternate setting does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, - int interface_number, int altsetting); - - /* Clear a halt/stall condition on an endpoint. - * - * It's OK for this function to block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*clear_halt)(struct libusb_device_handle *dev_handle, - unsigned char endpoint); - - /* Perform a USB port reset to reinitialize a device. - * - * If possible, the device handle should still be usable after the reset - * completes, assuming that the device descriptors did not change during - * reset and all previous interface state can be restored. - * - * If something changes, or you cannot easily locate/verify the resetted - * device, return LIBUSB_ERROR_NOT_FOUND. This prompts the application - * to close the old handle and re-enumerate the device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the device - * has been disconnected since it was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*reset_device)(struct libusb_device_handle *dev_handle); - - /* Alloc num_streams usb3 bulk streams on the passed in endpoints */ - int (*alloc_streams)(struct libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints); - - /* Free usb3 bulk streams allocated with alloc_streams */ - int (*free_streams)(struct libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints); - - /* Allocate persistent DMA memory for the given device, suitable for - * zerocopy. May return NULL on failure. Optional to implement. - */ - unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle, - size_t len); - - /* Free memory allocated by dev_mem_alloc. */ - int (*dev_mem_free)(struct libusb_device_handle *handle, - unsigned char *buffer, size_t len); - - /* Determine if a kernel driver is active on an interface. Optional. - * - * The presence of a kernel driver on an interface indicates that any - * calls to claim_interface would fail with the LIBUSB_ERROR_BUSY code. - * - * Return: - * - 0 if no driver is active - * - 1 if a driver is active - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*kernel_driver_active)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Detach a kernel driver from an interface. Optional. - * - * After detaching a kernel driver, the interface should be available - * for claim. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Attach a kernel driver to an interface. Optional. - * - * Reattach a kernel driver to the device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - LIBUSB_ERROR_BUSY if a program or driver has claimed the interface, - * preventing reattachment - * - another LIBUSB_ERROR code on other failure - */ - int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Destroy a device. Optional. - * - * This function is called when the last reference to a device is - * destroyed. It should free any resources allocated in the get_device_list - * path. - */ - void (*destroy_device)(struct libusb_device *dev); - - /* Submit a transfer. Your implementation should take the transfer, - * morph it into whatever form your platform requires, and submit it - * asynchronously. - * - * This function must not block. - * - * This function gets called with the flying_transfers_lock locked! - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * - another LIBUSB_ERROR code on other failure - */ - int (*submit_transfer)(struct usbi_transfer *itransfer); - - /* Cancel a previously submitted transfer. - * - * This function must not block. The transfer cancellation must complete - * later, resulting in a call to usbi_handle_transfer_cancellation() - * from the context of handle_events. - */ - int (*cancel_transfer)(struct usbi_transfer *itransfer); - - /* Clear a transfer as if it has completed or cancelled, but do not - * report any completion/cancellation to the library. You should free - * all private data from the transfer as if you were just about to report - * completion or cancellation. - * - * This function might seem a bit out of place. It is used when libusb - * detects a disconnected device - it calls this function for all pending - * transfers before reporting completion (with the disconnect code) to - * the user. Maybe we can improve upon this internal interface in future. - */ - void (*clear_transfer_priv)(struct usbi_transfer *itransfer); - - /* Handle any pending events on file descriptors. Optional. - * - * Provide this function when file descriptors directly indicate device - * or transfer activity. If your backend does not have such file descriptors, - * implement the handle_transfer_completion function below. - * - * This involves monitoring any active transfers and processing their - * completion or cancellation. - * - * The function is passed an array of pollfd structures (size nfds) - * as a result of the poll() system call. The num_ready parameter - * indicates the number of file descriptors that have reported events - * (i.e. the poll() return value). This should be enough information - * for you to determine which actions need to be taken on the currently - * active transfers. - * - * For any cancelled transfers, call usbi_handle_transfer_cancellation(). - * For completed transfers, call usbi_handle_transfer_completion(). - * For control/bulk/interrupt transfers, populate the "transferred" - * element of the appropriate usbi_transfer structure before calling the - * above functions. For isochronous transfers, populate the status and - * transferred fields of the iso packet descriptors of the transfer. - * - * This function should also be able to detect disconnection of the - * device, reporting that situation with usbi_handle_disconnect(). - * - * When processing an event related to a transfer, you probably want to - * take usbi_transfer.lock to prevent races. See the documentation for - * the usbi_transfer structure. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*handle_events)(struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); - - /* Handle transfer completion. Optional. - * - * Provide this function when there are no file descriptors available - * that directly indicate device or transfer activity. If your backend does - * have such file descriptors, implement the handle_events function above. - * - * Your backend must tell the library when a transfer has completed by - * calling usbi_signal_transfer_completion(). You should store any private - * information about the transfer and its completion status in the transfer's - * private backend data. - * - * During event handling, this function will be called on each transfer for - * which usbi_signal_transfer_completion() was called. - * - * For any cancelled transfers, call usbi_handle_transfer_cancellation(). - * For completed transfers, call usbi_handle_transfer_completion(). - * For control/bulk/interrupt transfers, populate the "transferred" - * element of the appropriate usbi_transfer structure before calling the - * above functions. For isochronous transfers, populate the status and - * transferred fields of the iso packet descriptors of the transfer. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*handle_transfer_completion)(struct usbi_transfer *itransfer); - - /* Get time from specified clock. At least two clocks must be implemented - by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. - - Description of clocks: - USBI_CLOCK_REALTIME : clock returns time since system epoch. - USBI_CLOCK_MONOTONIC: clock returns time since unspecified start - time (usually boot). - */ - int (*clock_gettime)(int clkid, struct timespec *tp); - -#ifdef USBI_TIMERFD_AVAILABLE - /* clock ID of the clock that should be used for timerfd */ - clockid_t (*get_timerfd_clockid)(void); -#endif - - /* Number of bytes to reserve for per-context private backend data. - * This private data area is accessible through the "os_priv" field of - * struct libusb_context. */ - size_t context_priv_size; - - /* Number of bytes to reserve for per-device private backend data. - * This private data area is accessible through the "os_priv" field of - * struct libusb_device. */ - size_t device_priv_size; - - /* Number of bytes to reserve for per-handle private backend data. - * This private data area is accessible through the "os_priv" field of - * struct libusb_device. */ - size_t device_handle_priv_size; - - /* Number of bytes to reserve for per-transfer private backend data. - * This private data area is accessible by calling - * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance. - */ - size_t transfer_priv_size; -}; - -extern const struct usbi_os_backend usbi_backend; - -extern struct list_head active_contexts_list; -extern usbi_mutex_static_t active_contexts_lock; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c deleted file mode 100644 index 35ea1c321e..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c +++ /dev/null @@ -1,2142 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:nil -*- */ -/* - * darwin backend for libusb 1.0 - * Copyright © 2008-2017 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector - * function. Its use is also conditionalized to only older deployment targets. */ -#define OBJC_SILENCE_GC_DEPRECATIONS 1 - -#include -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #include -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 -/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */ -#include -#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y) - -_Atomic int32_t initCount = ATOMIC_VAR_INIT(0); -#else -/* use darwin atomics if the target is older than 10.12 */ -#include - -/* OSAtomicAdd32Barrier returns the new value */ -#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y) - -static volatile int32_t initCount = 0; - -#endif - -/* On 10.12 and later, use newly available clock_*() functions */ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 -#define OSX_USE_CLOCK_GETTIME 1 -#else -#define OSX_USE_CLOCK_GETTIME 0 -#endif - -#include "darwin_usb.h" - -/* async event thread */ -static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; - -static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT; - -#if !OSX_USE_CLOCK_GETTIME -static clock_serv_t clock_realtime; -static clock_serv_t clock_monotonic; -#endif - -static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ -static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ - -static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; -static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; -static const char *darwin_device_class = kIOUSBDeviceClassName; - -#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) - -/* async event thread */ -static pthread_t libusb_darwin_at; - -static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian); -static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface); -static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface); -static int darwin_reset_device(struct libusb_device_handle *dev_handle); -static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0); - -static int darwin_scan_devices(struct libusb_context *ctx); -static int process_new_device (struct libusb_context *ctx, io_service_t service); - -#if defined(ENABLE_LOGGING) -static const char *darwin_error_str (int result) { - static char string_buffer[50]; - switch (result) { - case kIOReturnSuccess: - return "no error"; - case kIOReturnNotOpen: - return "device not opened for exclusive access"; - case kIOReturnNoDevice: - return "no connection to an IOService"; - case kIOUSBNoAsyncPortErr: - return "no async port has been opened for interface"; - case kIOReturnExclusiveAccess: - return "another process has device opened for exclusive access"; - case kIOUSBPipeStalled: - return "pipe is stalled"; - case kIOReturnError: - return "could not establish a connection to the Darwin kernel"; - case kIOUSBTransactionTimeout: - return "transaction timed out"; - case kIOReturnBadArgument: - return "invalid argument"; - case kIOReturnAborted: - return "transaction aborted"; - case kIOReturnNotResponding: - return "device not responding"; - case kIOReturnOverrun: - return "data overrun"; - case kIOReturnCannotWire: - return "physical memory can not be wired down"; - case kIOReturnNoResources: - return "out of resources"; - case kIOUSBHighSpeedSplitError: - return "high speed split error"; - default: - snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result); - return string_buffer; - } -} -#endif - -static int darwin_to_libusb (int result) { - switch (result) { - case kIOReturnUnderrun: - case kIOReturnSuccess: - return LIBUSB_SUCCESS; - case kIOReturnNotOpen: - case kIOReturnNoDevice: - return LIBUSB_ERROR_NO_DEVICE; - case kIOReturnExclusiveAccess: - return LIBUSB_ERROR_ACCESS; - case kIOUSBPipeStalled: - return LIBUSB_ERROR_PIPE; - case kIOReturnBadArgument: - return LIBUSB_ERROR_INVALID_PARAM; - case kIOUSBTransactionTimeout: - return LIBUSB_ERROR_TIMEOUT; - case kIOReturnNotResponding: - case kIOReturnAborted: - case kIOReturnError: - case kIOUSBNoAsyncPortErr: - default: - return LIBUSB_ERROR_OTHER; - } -} - -/* this function must be called with the darwin_cached_devices_lock held */ -static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { - cached_dev->refcount--; - /* free the device and remove it from the cache */ - if (0 == cached_dev->refcount) { - list_del(&cached_dev->list); - - (*(cached_dev->device))->Release(cached_dev->device); - free (cached_dev); - } -} - -static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) { - cached_dev->refcount++; -} - -static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - - /* current interface */ - struct darwin_interface *cInterface; - - int8_t i, iface; - - usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep); - - for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { - cInterface = &priv->interfaces[iface]; - - if (dev_handle->claimed_interfaces & (1 << iface)) { - for (i = 0 ; i < cInterface->num_endpoints ; i++) { - if (cInterface->endpoint_addrs[i] == ep) { - *pipep = i + 1; - - if (ifcp) - *ifcp = iface; - - if (interface_out) - *interface_out = cInterface; - - usbi_dbg ("pipe %d on interface %d matches", *pipep, iface); - return 0; - } - } - } - } - - /* No pipe found with the correct endpoint address */ - usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); - - return LIBUSB_ERROR_NOT_FOUND; -} - -static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { - CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class); - - if (!matchingDict) - return kIOReturnError; - - if (location) { - CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this - internally (CFNumberType of locationID is kCFNumberSInt32Type) */ - CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); - - if (propertyMatchDict && locationCF) { - CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); - CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); - } - /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ - - /* release our references as per the Create Rule */ - if (propertyMatchDict) - CFRelease (propertyMatchDict); - if (locationCF) - CFRelease (locationCF); - } - - return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); -} - -/* Returns 1 on success, 0 on failure. */ -static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { - CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; - - if (cfNumber) { - if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) { - ret = CFNumberGetValue(cfNumber, type, p); - } - - CFRelease (cfNumber); - } - - return ret; -} - -static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { - CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; - - if (cfData) { - if (CFGetTypeID (cfData) == CFDataGetTypeID ()) { - CFIndex length = CFDataGetLength (cfData); - if (length < size) { - size = length; - } - - CFDataGetBytes (cfData, CFRangeMake(0, size), p); - ret = 1; - } - - CFRelease (cfData); - } - - return ret; -} - -static usb_device_t **darwin_device_from_service (io_service_t service) -{ - io_cf_plugin_ref_t *plugInInterface = NULL; - usb_device_t **device; - kern_return_t result; - SInt32 score; - - result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, - &score); - - if (kIOReturnSuccess != result || !plugInInterface) { - usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result)); - return NULL; - } - - (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), - (LPVOID)&device); - /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ - (*plugInInterface)->Release (plugInInterface); - - return device; -} - -static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { - UNUSED(ptr); - struct libusb_context *ctx; - io_service_t service; - - usbi_mutex_lock(&active_contexts_lock); - - while ((service = IOIteratorNext(add_devices))) { - /* add this device to each active context's device list */ - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - process_new_device (ctx, service); - } - - IOObjectRelease(service); - } - - usbi_mutex_unlock(&active_contexts_lock); -} - -static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { - UNUSED(ptr); - struct libusb_device *dev = NULL; - struct libusb_context *ctx; - struct darwin_cached_device *old_device; - - io_service_t device; - UInt64 session; - int ret; - - usbi_mutex_lock(&active_contexts_lock); - - while ((device = IOIteratorNext (rem_devices)) != 0) { - /* get the location from the i/o registry */ - ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); - IOObjectRelease (device); - if (!ret) - continue; - - /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function - otherwise no cached device will ever get freed */ - usbi_mutex_lock(&darwin_cached_devices_lock); - list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) { - if (old_device->session == session) { - darwin_deref_cached_device (old_device); - break; - } - } - usbi_mutex_unlock(&darwin_cached_devices_lock); - - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - usbi_dbg ("notifying context %p of device disconnect", ctx); - - dev = usbi_get_device_by_session_id(ctx, (unsigned long) session); - if (dev) { - /* signal the core that this device has been disconnected. the core will tear down this device - when the reference count reaches 0 */ - usbi_disconnect_device(dev); - libusb_unref_device(dev); - } - } - } - - usbi_mutex_unlock(&active_contexts_lock); -} - -static void darwin_hotplug_poll (void) -{ - /* not sure if 5 seconds will be too long/short but it should work ok */ - mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0}; - - /* since a kernel thread may nodify the IOInterators used for - * hotplug notidication we can't just clear the iterators. - * instead just wait until all IOService providers are quiet */ - (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout); -} - -static void darwin_clear_iterator (io_iterator_t iter) { - io_service_t device; - - while ((device = IOIteratorNext (iter)) != 0) - IOObjectRelease (device); -} - -static void *darwin_event_thread_main (void *arg0) { - IOReturn kresult; - struct libusb_context *ctx = (struct libusb_context *)arg0; - CFRunLoopRef runloop; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - /* Set this thread's name, so it can be seen in the debugger - and crash reports. */ - pthread_setname_np ("org.libusb.device-hotplug"); -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - /* Tell the Objective-C garbage collector about this thread. - This is required because, unlike NSThreads, pthreads are - not automatically registered. Although we don't use - Objective-C, we use CoreFoundation, which does. - Garbage collection support was entirely removed in 10.12, - so don't bother there. */ - objc_registerThreadWithCollector(); -#endif - - /* hotplug (device arrival/removal) sources */ - CFRunLoopSourceContext libusb_shutdown_cfsourcectx; - CFRunLoopSourceRef libusb_notification_cfsource; - io_notification_port_t libusb_notification_port; - io_iterator_t libusb_rem_device_iterator; - io_iterator_t libusb_add_device_iterator; - - usbi_dbg ("creating hotplug event source"); - - runloop = CFRunLoopGetCurrent (); - CFRetain (runloop); - - /* add the shutdown cfsource to the run loop */ - memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx)); - libusb_shutdown_cfsourcectx.info = runloop; - libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop; - libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx); - CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); - - /* add the notification port to the run loop */ - libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault); - libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port); - CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); - - /* create notifications for removed devices */ - kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification, - IOServiceMatching(darwin_device_class), - darwin_devices_detached, - ctx, &libusb_rem_device_iterator); - - if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); - - pthread_exit (NULL); - } - - /* create notifications for attached devices */ - kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification, - IOServiceMatching(darwin_device_class), - darwin_devices_attached, - ctx, &libusb_add_device_iterator); - - if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); - - pthread_exit (NULL); - } - - /* arm notifiers */ - darwin_clear_iterator (libusb_rem_device_iterator); - darwin_clear_iterator (libusb_add_device_iterator); - - usbi_dbg ("darwin event thread ready to receive events"); - - /* signal the main thread that the hotplug runloop has been created. */ - pthread_mutex_lock (&libusb_darwin_at_mutex); - libusb_darwin_acfl = runloop; - pthread_cond_signal (&libusb_darwin_at_cond); - pthread_mutex_unlock (&libusb_darwin_at_mutex); - - /* run the runloop */ - CFRunLoopRun(); - - usbi_dbg ("darwin event thread exiting"); - - /* remove the notification cfsource */ - CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); - - /* remove the shutdown cfsource */ - CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); - - /* delete notification port */ - IONotificationPortDestroy (libusb_notification_port); - - /* delete iterators */ - IOObjectRelease (libusb_rem_device_iterator); - IOObjectRelease (libusb_add_device_iterator); - - CFRelease (libusb_darwin_acfls); - CFRelease (runloop); - - libusb_darwin_acfls = NULL; - libusb_darwin_acfl = NULL; - - pthread_exit (NULL); -} - -/* cleanup function to destroy cached devices */ -static void __attribute__((destructor)) _darwin_finalize(void) { - struct darwin_cached_device *dev, *next; - - usbi_mutex_lock(&darwin_cached_devices_lock); - list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) { - darwin_deref_cached_device(dev); - } - usbi_mutex_unlock(&darwin_cached_devices_lock); -} - -static void darwin_check_version (void) { - /* adjust for changes in the USB stack in xnu 15 */ - int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE}; - long version; - char version_string[256] = {'\0',}; - size_t length = 256; - - sysctl(sysctl_args, 2, version_string, &length, NULL, 0); - - errno = 0; - version = strtol (version_string, NULL, 10); - if (0 == errno && version >= 15) { - darwin_device_class = "IOUSBHostDevice"; - } -} - -static int darwin_init(struct libusb_context *ctx) { - int rc; - - rc = pthread_once (&darwin_init_once, darwin_check_version); - if (rc) { - return LIBUSB_ERROR_OTHER; - } - - rc = darwin_scan_devices (ctx); - if (LIBUSB_SUCCESS != rc) { - return rc; - } - - if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) { -#if !OSX_USE_CLOCK_GETTIME - /* create the clocks that will be used if clock_gettime() is not available */ - host_name_port_t host_self; - - host_self = mach_host_self(); - host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); - host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); - mach_port_deallocate(mach_task_self(), host_self); -#endif - - pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); - - pthread_mutex_lock (&libusb_darwin_at_mutex); - while (!libusb_darwin_acfl) - pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); - pthread_mutex_unlock (&libusb_darwin_at_mutex); - } - - return rc; -} - -static void darwin_exit (struct libusb_context *ctx) { - UNUSED(ctx); - if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) { -#if !OSX_USE_CLOCK_GETTIME - mach_port_deallocate(mach_task_self(), clock_realtime); - mach_port_deallocate(mach_task_self(), clock_monotonic); -#endif - - /* stop the event runloop and wait for the thread to terminate. */ - CFRunLoopSourceSignal(libusb_darwin_acfls); - CFRunLoopWakeUp (libusb_darwin_acfl); - pthread_join (libusb_darwin_at, NULL); - } -} - -static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - - /* return cached copy */ - memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return 0; -} - -static int get_configuration_index (struct libusb_device *dev, int config_value) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - UInt8 i, numConfig; - IOUSBConfigurationDescriptorPtr desc; - IOReturn kresult; - - /* is there a simpler way to determine the index? */ - kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - for (i = 0 ; i < numConfig ; i++) { - (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc); - - if (desc->bConfigurationValue == config_value) - return i; - } - - /* configuration not found */ - return LIBUSB_ERROR_NOT_FOUND; -} - -static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - int config_index; - - if (0 == priv->active_config) - return LIBUSB_ERROR_NOT_FOUND; - - config_index = get_configuration_index (dev, priv->active_config); - if (config_index < 0) - return config_index; - - return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian); -} - -static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - IOUSBConfigurationDescriptorPtr desc; - IOReturn kresult; - int ret; - - if (!priv || !priv->device) - return LIBUSB_ERROR_OTHER; - - kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc); - if (kresult == kIOReturnSuccess) { - /* copy descriptor */ - if (libusb_le16_to_cpu(desc->wTotalLength) < len) - len = libusb_le16_to_cpu(desc->wTotalLength); - - memmove (buffer, desc, len); - - /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */ - *host_endian = 0; - } - - ret = darwin_to_libusb (kresult); - if (ret != LIBUSB_SUCCESS) - return ret; - - return (int) len; -} - -/* check whether the os has configured the device */ -static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **darwin_device = dev->device; - - IOUSBConfigurationDescriptorPtr configDesc; - IOUSBFindInterfaceRequest request; - kern_return_t kresult; - io_iterator_t interface_iterator; - io_service_t firstInterface; - - if (dev->dev_descriptor.bNumConfigurations < 1) { - usbi_err (ctx, "device has no configurations"); - return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */ - } - - /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is - not usable anyway */ - if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) { - usbi_dbg ("ignoring configuration on root hub simulation"); - dev->active_config = 0; - return 0; - } - - /* find the first configuration */ - kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc); - dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1; - - /* check if the device is already configured. there is probably a better way than iterating over the - to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices - might lock up on the device request) */ - - /* Setup the Interface Request */ - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) - return darwin_to_libusb (kresult); - - /* iterate once */ - firstInterface = IOIteratorNext(interface_iterator); - - /* done with the interface iterator */ - IOObjectRelease(interface_iterator); - - if (firstInterface) { - IOObjectRelease (firstInterface); - - /* device is configured */ - if (dev->dev_descriptor.bNumConfigurations == 1) - /* to avoid problems with some devices get the configurations value from the configuration descriptor */ - dev->active_config = dev->first_config; - else - /* devices with more than one configuration should work with GetConfiguration */ - (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config); - } else - /* not configured */ - dev->active_config = 0; - - usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config); - - return 0; -} - -static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { - IOUSBDevRequestTO req; - - memset (buffer, 0, buffer_size); - - /* Set up request for descriptor/ */ - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = desc << 8; - req.wIndex = desc_index; - req.wLength = buffer_size; - req.pData = buffer; - req.noDataTimeout = 20; - req.completionTimeout = 100; - - return (*device)->DeviceRequestTO (device, &req); -} - -static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **device = dev->device; - int retries = 1, delay = 30000; - int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; - int is_open = 0; - int ret = 0, ret2; - UInt8 bDeviceClass; - UInt16 idProduct, idVendor; - - dev->can_enumerate = 0; - - (*device)->GetDeviceClass (device, &bDeviceClass); - (*device)->GetDeviceProduct (device, &idProduct); - (*device)->GetDeviceVendor (device, &idVendor); - - /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some - * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still, - * to follow the spec as closely as possible, try opening the device */ - is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess); - - do { - /**** retrieve device descriptor ****/ - ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor)); - - if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType) - /* received an overrun error but we still received a device descriptor */ - ret = kIOReturnSuccess; - - if (kIOUSBVendorIDAppleComputer == idVendor) { - /* NTH: don't bother retrying or unsuspending Apple devices */ - break; - } - - if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations || - 0 == dev->dev_descriptor.bcdUSB)) { - /* work around for incorrectly configured devices */ - if (try_reconfigure && is_open) { - usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again..."); - - /* set the first configuration */ - (*device)->SetConfiguration(device, 1); - - /* don't try to reconfigure again */ - try_reconfigure = 0; - } - - ret = kIOUSBPipeStalled; - } - - if (kIOReturnSuccess != ret && is_open && try_unsuspend) { - /* device may be suspended. unsuspend it and try again */ -#if DeviceVersion >= 320 - UInt32 info = 0; - - /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ - (void)(*device)->GetUSBDeviceInformation (device, &info); - - /* note that the device was suspended */ - if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info) - try_unsuspend = 1; -#endif - - if (try_unsuspend) { - /* try to unsuspend the device */ - ret2 = (*device)->USBDeviceSuspend (device, 0); - if (kIOReturnSuccess != ret2) { - /* prevent log spew from poorly behaving devices. this indicates the - os actually had trouble communicating with the device */ - usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2)); - } else - unsuspended = 1; - - try_unsuspend = 0; - } - } - - if (kIOReturnSuccess != ret) { - usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); - /* sleep for a little while before trying again */ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - } - } while (kIOReturnSuccess != ret && retries--); - - if (unsuspended) - /* resuspend the device */ - (void)(*device)->USBDeviceSuspend (device, 1); - - if (is_open) - (void) (*device)->USBDeviceClose (device); - - if (ret != kIOReturnSuccess) { - /* a debug message was already printed out for this error */ - if (LIBUSB_CLASS_HUB == bDeviceClass) - usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", - idVendor, idProduct, darwin_error_str (ret), ret); - else - usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", - idVendor, idProduct, darwin_error_str (ret), ret); - return darwin_to_libusb (ret); - } - - /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ - if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) { - /* not a valid device */ - usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", - idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct)); - return LIBUSB_ERROR_NO_DEVICE; - } - - usbi_dbg ("cached device descriptor:"); - usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType); - usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB); - usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass); - usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass); - usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol); - usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0); - usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor); - usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct); - usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice); - usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer); - usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct); - usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber); - usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations); - - dev->can_enumerate = 1; - - return LIBUSB_SUCCESS; -} - -static int get_device_port (io_service_t service, UInt8 *port) { - kern_return_t result; - io_service_t parent; - int ret = 0; - - if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) { - return 1; - } - - result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent); - if (kIOReturnSuccess == result) { - ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port); - IOObjectRelease (parent); - } - - return ret; -} - -static int get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) { - kern_return_t result; - io_service_t parent; - - /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */ - parent = service; - while((result = IORegistryEntryGetParentEntry (parent, kIOServicePlane, &parent)) == kIOReturnSuccess) { - if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) { - /* Success */ - return 1; - } - } - - /* We ran out of parents */ - return 0; -} - -static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, - struct darwin_cached_device **cached_out) { - struct darwin_cached_device *new_device; - UInt64 sessionID = 0, parent_sessionID = 0; - int ret = LIBUSB_SUCCESS; - usb_device_t **device; - UInt8 port = 0; - - /* get some info from the io registry */ - (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID); - if (!get_device_port (service, &port)) { - usbi_dbg("could not get connected port number"); - } - - usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); - - if (get_device_parent_sessionID(service, &parent_sessionID)) { - usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID); - } - - usbi_mutex_lock(&darwin_cached_devices_lock); - do { - *cached_out = NULL; - - list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { - usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session); - if (new_device->session == sessionID) { - usbi_dbg("using cached device for device"); - *cached_out = new_device; - break; - } - } - - if (*cached_out) - break; - - usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID); - - device = darwin_device_from_service (service); - if (!device) { - ret = LIBUSB_ERROR_NO_DEVICE; - break; - } - - new_device = calloc (1, sizeof (*new_device)); - if (!new_device) { - ret = LIBUSB_ERROR_NO_MEM; - break; - } - - /* add this device to the cached device list */ - list_add(&new_device->list, &darwin_cached_devices); - - (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); - - /* keep a reference to this device */ - darwin_ref_cached_device(new_device); - - new_device->device = device; - new_device->session = sessionID; - (*device)->GetLocationID (device, &new_device->location); - new_device->port = port; - new_device->parent_session = parent_sessionID; - - /* cache the device descriptor */ - ret = darwin_cache_device_descriptor(ctx, new_device); - if (ret) - break; - - if (new_device->can_enumerate) { - snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address, - new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct, - new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass); - } - } while (0); - - usbi_mutex_unlock(&darwin_cached_devices_lock); - - /* keep track of devices regardless of if we successfully enumerate them to - prevent them from being enumerated multiple times */ - - *cached_out = new_device; - - return ret; -} - -static int process_new_device (struct libusb_context *ctx, io_service_t service) { - struct darwin_device_priv *priv; - struct libusb_device *dev = NULL; - struct darwin_cached_device *cached_device; - UInt8 devSpeed; - int ret = 0; - - do { - ret = darwin_get_cached_device (ctx, service, &cached_device); - - if (ret < 0 || !cached_device->can_enumerate) { - return ret; - } - - /* check current active configuration (and cache the first configuration value-- - which may be used by claim_interface) */ - ret = darwin_check_configuration (ctx, cached_device); - if (ret) - break; - - usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64, - ctx, cached_device->session); - - dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session); - if (!dev) { - return LIBUSB_ERROR_NO_MEM; - } - - priv = (struct darwin_device_priv *)dev->os_priv; - - priv->dev = cached_device; - darwin_ref_cached_device (priv->dev); - - if (cached_device->parent_session > 0) { - dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session); - } else { - dev->parent_dev = NULL; - } - dev->port_number = cached_device->port; - dev->bus_number = cached_device->location >> 24; - dev->device_address = cached_device->address; - - (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); - - switch (devSpeed) { - case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; - case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; - case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; -#endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 - case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; -#endif - default: - usbi_warn (ctx, "Got unknown device speed %d", devSpeed); - } - - ret = usbi_sanitize_device (dev); - if (ret < 0) - break; - - usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address, - dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path); - } while (0); - - if (0 == ret) { - usbi_connect_device (dev); - } else { - libusb_unref_device (dev); - } - - return ret; -} - -static int darwin_scan_devices(struct libusb_context *ctx) { - io_iterator_t deviceIterator; - io_service_t service; - kern_return_t kresult; - - kresult = usb_setup_device_iterator (&deviceIterator, 0); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - while ((service = IOIteratorNext (deviceIterator))) { - (void) process_new_device (ctx, service); - - IOObjectRelease(service); - } - - IOObjectRelease(deviceIterator); - - return 0; -} - -static int darwin_open (struct libusb_device_handle *dev_handle) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - - if (0 == dpriv->open_count) { - /* try to open the device */ - kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); - if (kresult != kIOReturnSuccess) { - usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); - - if (kIOReturnExclusiveAccess != kresult) { - return darwin_to_libusb (kresult); - } - - /* it is possible to perform some actions on a device that is not open so do not return an error */ - priv->is_open = 0; - } else { - priv->is_open = 1; - } - - /* create async event source */ - kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); - if (kresult != kIOReturnSuccess) { - usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); - - if (priv->is_open) { - (*(dpriv->device))->USBDeviceClose (dpriv->device); - } - - priv->is_open = 0; - - return darwin_to_libusb (kresult); - } - - CFRetain (libusb_darwin_acfl); - - /* add the cfSource to the aync run loop */ - CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes); - } - - /* device opened successfully */ - dpriv->open_count++; - - usbi_dbg ("device open for access"); - - return 0; -} - -static void darwin_close (struct libusb_device_handle *dev_handle) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - int i; - - if (dpriv->open_count == 0) { - /* something is probably very wrong if this is the case */ - usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!"); - return; - } - - dpriv->open_count--; - - /* make sure all interfaces are released */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - libusb_release_interface (dev_handle, i); - - if (0 == dpriv->open_count) { - /* delete the device's async event source */ - if (priv->cfSource) { - CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode); - CFRelease (priv->cfSource); - priv->cfSource = NULL; - CFRelease (libusb_darwin_acfl); - } - - if (priv->is_open) { - /* close the device */ - kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); - if (kresult) { - /* Log the fact that we had a problem closing the file, however failing a - * close isn't really an error, so return success anyway */ - usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); - } - } - } -} - -static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - - *config = (int) dpriv->active_config; - - return 0; -} - -static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - int i; - - /* Setting configuration will invalidate the interface, so we need - to reclaim it. First, dispose of existing interfaces, if any. */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - darwin_release_interface (dev_handle, i); - - kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - /* Reclaim any interfaces. */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - darwin_claim_interface (dev_handle, i); - - dpriv->active_config = config; - - return 0; -} - -static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { - IOUSBFindInterfaceRequest request; - kern_return_t kresult; - io_iterator_t interface_iterator; - UInt8 bInterfaceNumber; - int ret; - - *usbInterfacep = IO_OBJECT_NULL; - - /* Setup the Interface Request */ - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) - return kresult; - - while ((*usbInterfacep = IOIteratorNext(interface_iterator))) { - /* find the interface number */ - ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type, - &bInterfaceNumber); - - if (ret && bInterfaceNumber == ifc) { - break; - } - - (void) IOObjectRelease (*usbInterfacep); - } - - /* done with the interface iterator */ - IOObjectRelease(interface_iterator); - - return 0; -} - -static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - kern_return_t kresult; - - UInt8 numep, direction, number; - UInt8 dont_care1, dont_care3; - UInt16 dont_care2; - int rc; - - usbi_dbg ("building table of endpoints."); - - /* retrieve the total number of endpoints on this interface */ - kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* iterate through pipe references */ - for (int i = 1 ; i <= numep ; i++) { - kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, - &dont_care2, &dont_care3); - - if (kresult != kIOReturnSuccess) { - /* probably a buggy device. try to get the endpoint address from the descriptors */ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *endpoint_desc; - UInt8 alt_setting; - - kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface"); - return darwin_to_libusb (kresult); - } - - rc = libusb_get_active_config_descriptor (dev_handle->dev, &config); - if (LIBUSB_SUCCESS != rc) { - return rc; - } - - endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1; - - cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; - } else { - cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); - } - - usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift, - cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK); - } - - cInterface->num_endpoints = numep; - - return 0; -} - -static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - io_service_t usbInterface = IO_OBJECT_NULL; - IOReturn kresult; - IOCFPlugInInterface **plugInInterface = NULL; - SInt32 score; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - /* make sure we have an interface */ - if (!usbInterface && dpriv->first_config != 0) { - usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config); - - /* set the configuration */ - kresult = darwin_set_configuration (dev_handle, dpriv->first_config); - if (kresult != LIBUSB_SUCCESS) { - usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); - return kresult; - } - - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - } - - if (!usbInterface) { - usbi_err (HANDLE_CTX (dev_handle), "interface not found"); - return LIBUSB_ERROR_NOT_FOUND; - } - - /* get an interface to the device's interface */ - kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, &score); - - /* ignore release error */ - (void)IOObjectRelease (usbInterface); - - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - if (!plugInInterface) { - usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); - return LIBUSB_ERROR_NOT_FOUND; - } - - /* Do the actual claim */ - kresult = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - (LPVOID)&cInterface->interface); - /* We no longer need the intermediate plug-in */ - /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ - (*plugInInterface)->Release (plugInInterface); - if (kresult || !cInterface->interface) { - usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* claim the interface */ - kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { - /* this should not happen */ - darwin_release_interface (dev_handle, iface); - usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; - } - - cInterface->cfSource = NULL; - - /* create async event source */ - kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); - if (kresult != kIOReturnSuccess) { - usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); - - /* can't continue without an async event source */ - (void)darwin_release_interface (dev_handle, iface); - - return darwin_to_libusb (kresult); - } - - /* add the cfSource to the async thread's run loop */ - CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - - usbi_dbg ("interface opened"); - - return 0; -} - -static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - IOReturn kresult; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - /* Check to see if an interface is open */ - if (!cInterface->interface) - return LIBUSB_SUCCESS; - - /* clean up endpoint data */ - cInterface->num_endpoints = 0; - - /* delete the interface's async event source */ - if (cInterface->cfSource) { - CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - CFRelease (cInterface->cfSource); - } - - kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); - if (kresult) - usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); - - kresult = (*(cInterface->interface))->Release(cInterface->interface); - if (kresult != kIOReturnSuccess) - usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); - - cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL; - - return darwin_to_libusb (kresult); -} - -static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - IOReturn kresult; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - if (!cInterface->interface) - return LIBUSB_ERROR_NO_DEVICE; - - kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); - if (kresult != kIOReturnSuccess) - darwin_reset_device (dev_handle); - - /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { - /* this should not happen */ - darwin_release_interface (dev_handle, iface); - usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; - } - - return darwin_to_libusb (kresult); -} - -static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - /* current interface */ - struct darwin_interface *cInterface; - IOReturn kresult; - uint8_t pipeRef; - - /* determine the interface/endpoint to use */ - if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - /* newer versions of darwin support clearing additional bits on the device's endpoint */ - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); - if (kresult) - usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); - - return darwin_to_libusb (kresult); -} - -static int darwin_reset_device(struct libusb_device_handle *dev_handle) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOUSBDeviceDescriptor descriptor; - IOUSBConfigurationDescriptorPtr cached_configuration; - IOUSBConfigurationDescriptor configuration; - bool reenumerate = false; - IOReturn kresult; - int i; - - kresult = (*(dpriv->device))->ResetDevice (dpriv->device); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); - return darwin_to_libusb (kresult); - } - - do { - usbi_dbg ("darwin/reset_device: checking if device descriptor changed"); - - /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */ - (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor)); - - /* check if the device descriptor has changed */ - if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) { - reenumerate = true; - break; - } - - /* check if any configuration descriptor has changed */ - for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i); - - (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration)); - (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); - - if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) { - reenumerate = true; - break; - } - } - } while (0); - - if (reenumerate) { - usbi_dbg ("darwin/reset_device: device requires reenumeration"); - (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg ("darwin/reset_device: device reset complete"); - - return LIBUSB_SUCCESS; -} - -static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - io_service_t usbInterface; - CFTypeRef driver; - IOReturn kresult; - - kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); - - return darwin_to_libusb (kresult); - } - - driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0); - IOObjectRelease (usbInterface); - - if (driver) { - CFRelease (driver); - - return 1; - } - - /* no driver */ - return 0; -} - -/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */ -static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { - UNUSED(dev_handle); - UNUSED(interface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { - UNUSED(dev_handle); - UNUSED(interface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void darwin_destroy_device(struct libusb_device *dev) { - struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv; - - if (dpriv->dev) { - /* need to hold the lock in case this is the last reference to the device */ - usbi_mutex_lock(&darwin_cached_devices_lock); - darwin_deref_cached_device (dpriv->dev); - dpriv->dev = NULL; - usbi_mutex_unlock(&darwin_cached_devices_lock); - } -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - IOReturn ret; - uint8_t transferType; - /* None of the values below are used in libusbx for bulk transfers */ - uint8_t direction, number, interval, pipeRef; - uint16_t maxPacketSize; - - struct darwin_interface *cInterface; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - if (ret) { - usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - return darwin_to_libusb (ret); - } - - if (0 != (transfer->length % maxPacketSize)) { - /* do not need a zero packet */ - transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET; - } - - /* submit the request */ - /* timeouts are unavailable on interrupt endpoints */ - if (transferType == kUSBInterrupt) { - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); - else - ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); - } else { - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); - else - ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); - } - - if (ret) - usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - - return darwin_to_libusb (ret); -} - -#if InterfaceVersion >= 550 -static int submit_stream_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_interface *cInterface; - uint8_t pipeRef; - IOReturn ret; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); - else - ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); - - if (ret) - usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - - return darwin_to_libusb (ret); -} -#endif - -static int submit_iso_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - IOReturn kresult; - uint8_t direction, number, interval, pipeRef, transferType; - uint16_t maxPacketSize; - UInt64 frame; - AbsoluteTime atTime; - int i; - - struct darwin_interface *cInterface; - - /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ - if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { - free(tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } - - if (!tpriv->isoc_framelist) { - tpriv->num_iso_packets = transfer->num_iso_packets; - tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); - if (!tpriv->isoc_framelist) - return LIBUSB_ERROR_NO_MEM; - } - - /* copy the frame list from the libusb descriptor (the structures differ only is member order) */ - for (i = 0 ; i < transfer->num_iso_packets ; i++) - tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length; - - /* determine the interface/endpoint to use */ - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - /* determine the properties of this endpoint and the speed of the device */ - (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - /* Last but not least we need the bus frame number */ - kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); - if (kresult) { - usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); - free(tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - - return darwin_to_libusb (kresult); - } - - (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - /* schedule for a frame a little in the future */ - frame += 4; - - if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) - frame = cInterface->frames[transfer->endpoint]; - - /* submit the request */ - if (IS_XFERIN(transfer)) - kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); - else - kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); - - if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) - /* Full speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)); - else - /* High/super speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8; - - if (kresult != kIOReturnSuccess) { - usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(kresult)); - free (tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } - - return darwin_to_libusb (kresult); -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - IOReturn kresult; - - memset(&tpriv->req, 0, sizeof(tpriv->req)); - - /* IOUSBDeviceInterface expects the request in cpu endianness */ - tpriv->req.bmRequestType = setup->bmRequestType; - tpriv->req.bRequest = setup->bRequest; - /* these values should be in bus order from libusb_fill_control_setup */ - tpriv->req.wValue = OSSwapLittleToHostInt16 (setup->wValue); - tpriv->req.wIndex = OSSwapLittleToHostInt16 (setup->wIndex); - tpriv->req.wLength = OSSwapLittleToHostInt16 (setup->wLength); - /* data is stored after the libusb control block */ - tpriv->req.pData = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - tpriv->req.completionTimeout = transfer->timeout; - tpriv->req.noDataTimeout = transfer->timeout; - - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - /* all transfers in libusb-1.0 are async */ - - if (transfer->endpoint) { - struct darwin_interface *cInterface; - uint8_t pipeRef; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); - } else - /* control request on endpoint 0 */ - kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); - - if (kresult != kIOReturnSuccess) - usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); - - return darwin_to_libusb (kresult); -} - -static int darwin_submit_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: -#if InterfaceVersion >= 550 - return submit_stream_transfer(itransfer); -#else - usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers"); - return LIBUSB_ERROR_NOT_SUPPORTED; -#endif - default: - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int cancel_control_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - IOReturn kresult; - - usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe"); - - if (!dpriv->device) - return LIBUSB_ERROR_NO_DEVICE; - - kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); - - return darwin_to_libusb (kresult); -} - -static int darwin_abort_transfers (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - struct darwin_interface *cInterface; - uint8_t pipeRef, iface; - IOReturn kresult; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!dpriv->device) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef); - - /* abort transactions */ -#if InterfaceVersion >= 550 - if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) - (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); - else -#endif - (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - - usbi_dbg ("calling clear pipe stall to clear the data toggle bit"); - - /* newer versions of darwin support clearing additional bits on the device's endpoint */ - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); - - return darwin_to_libusb (kresult); -} - -static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return cancel_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return darwin_abort_transfers (itransfer); - default: - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) { - free (tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } -} - -static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) { - struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon; - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - usbi_dbg ("an async io operation has completed"); - - /* if requested write a zero packet */ - if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - struct darwin_interface *cInterface; - uint8_t pipeRef; - - (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface); - - (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); - } - - tpriv->result = result; - tpriv->size = (UInt32) (uintptr_t) arg0; - - /* signal the core that this transfer is complete */ - usbi_signal_transfer_completion(itransfer); -} - -static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { - if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) - result = kIOUSBTransactionTimeout; - - switch (result) { - case kIOReturnUnderrun: - case kIOReturnSuccess: - return LIBUSB_TRANSFER_COMPLETED; - case kIOReturnAborted: - return LIBUSB_TRANSFER_CANCELLED; - case kIOUSBPipeStalled: - usbi_dbg ("transfer error: pipe is stalled"); - return LIBUSB_TRANSFER_STALL; - case kIOReturnOverrun: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun"); - return LIBUSB_TRANSFER_OVERFLOW; - case kIOUSBTransactionTimeout: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out"); - itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; - return LIBUSB_TRANSFER_TIMED_OUT; - default: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result); - return LIBUSB_TRANSFER_ERROR; - } -} - -static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; - int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; - int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; - int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; - int i; - - if (!isIsoc && !isBulk && !isControl && !isInterrupt) { - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_dbg ("handling %s completion with kernel status %d", - isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result); - - if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) { - if (isIsoc && tpriv->isoc_framelist) { - /* copy isochronous results back */ - - for (i = 0; i < transfer->num_iso_packets ; i++) { - struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; - lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus); - lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; - } - } else if (!isIsoc) - itransfer->transferred += tpriv->size; - } - - /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */ - return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result)); -} - -static int darwin_clock_gettime(int clk_id, struct timespec *tp) { -#if !OSX_USE_CLOCK_GETTIME - mach_timespec_t sys_time; - clock_serv_t clock_ref; - - switch (clk_id) { - case USBI_CLOCK_REALTIME: - /* CLOCK_REALTIME represents time since the epoch */ - clock_ref = clock_realtime; - break; - case USBI_CLOCK_MONOTONIC: - /* use system boot time as reference for the monotonic clock */ - clock_ref = clock_monotonic; - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } - - clock_get_time (clock_ref, &sys_time); - - tp->tv_sec = sys_time.tv_sec; - tp->tv_nsec = sys_time.tv_nsec; - - return 0; -#else - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - return clock_gettime(CLOCK_MONOTONIC, tp); - case USBI_CLOCK_REALTIME: - return clock_gettime(CLOCK_REALTIME, tp); - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -#endif -} - -#if InterfaceVersion >= 550 -static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, - int num_endpoints) { - struct darwin_interface *cInterface; - UInt32 supportsStreams; - uint8_t pipeRef; - int rc, i; - - /* find the mimimum number of supported streams on the endpoint list */ - for (i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) { - return rc; - } - - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); - if (num_streams > supportsStreams) - num_streams = supportsStreams; - } - - /* it is an error if any endpoint in endpoints does not support streams */ - if (0 == num_streams) - return LIBUSB_ERROR_INVALID_PARAM; - - /* create the streams */ - for (i = 0 ; i < num_endpoints ; ++i) { - (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); - - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams); - if (kIOReturnSuccess != rc) - return darwin_to_libusb(rc); - } - - return num_streams; -} - -static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { - struct darwin_interface *cInterface; - UInt32 supportsStreams; - uint8_t pipeRef; - int rc; - - for (int i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) - return rc; - - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); - if (0 == supportsStreams) - return LIBUSB_ERROR_INVALID_PARAM; - - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0); - if (kIOReturnSuccess != rc) - return darwin_to_libusb(rc); - } - - return LIBUSB_SUCCESS; -} -#endif - -const struct usbi_os_backend usbi_backend = { - .name = "Darwin", - .caps = 0, - .init = darwin_init, - .exit = darwin_exit, - .get_device_list = NULL, /* not needed */ - .get_device_descriptor = darwin_get_device_descriptor, - .get_active_config_descriptor = darwin_get_active_config_descriptor, - .get_config_descriptor = darwin_get_config_descriptor, - .hotplug_poll = darwin_hotplug_poll, - - .open = darwin_open, - .close = darwin_close, - .get_configuration = darwin_get_configuration, - .set_configuration = darwin_set_configuration, - .claim_interface = darwin_claim_interface, - .release_interface = darwin_release_interface, - - .set_interface_altsetting = darwin_set_interface_altsetting, - .clear_halt = darwin_clear_halt, - .reset_device = darwin_reset_device, - -#if InterfaceVersion >= 550 - .alloc_streams = darwin_alloc_streams, - .free_streams = darwin_free_streams, -#endif - - .kernel_driver_active = darwin_kernel_driver_active, - .detach_kernel_driver = darwin_detach_kernel_driver, - .attach_kernel_driver = darwin_attach_kernel_driver, - - .destroy_device = darwin_destroy_device, - - .submit_transfer = darwin_submit_transfer, - .cancel_transfer = darwin_cancel_transfer, - .clear_transfer_priv = darwin_clear_transfer_priv, - - .handle_transfer_completion = darwin_handle_transfer_completion, - - .clock_gettime = darwin_clock_gettime, - - .device_priv_size = sizeof(struct darwin_device_priv), - .device_handle_priv_size = sizeof(struct darwin_device_handle_priv), - .transfer_priv_size = sizeof(struct darwin_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h deleted file mode 100644 index 474567f6ac..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * darwin backend for libusb 1.0 - * Copyright © 2008-2015 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined(LIBUSB_DARWIN_H) -#define LIBUSB_DARWIN_H - -#include "libusbi.h" - -#include -#include -#include -#include - -/* IOUSBInterfaceInferface */ - -/* New in OS 10.12.0. */ -#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - -#define usb_interface_t IOUSBInterfaceInterface800 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800 -#define InterfaceVersion 800 - -/* New in OS 10.10.0. */ -#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) - -#define usb_interface_t IOUSBInterfaceInterface700 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 -#define InterfaceVersion 700 - -/* New in OS 10.9.0. */ -#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) - -#define usb_interface_t IOUSBInterfaceInterface650 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650 -#define InterfaceVersion 650 - -/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) - -#define usb_interface_t IOUSBInterfaceInterface550 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 -#define InterfaceVersion 550 - -/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) - -#define usb_interface_t IOUSBInterfaceInterface500 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 -#define InterfaceVersion 500 - -/* New in OS 10.5.0. */ -#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) - -#define usb_interface_t IOUSBInterfaceInterface300 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 -#define InterfaceVersion 300 - -/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) - -#define usb_interface_t IOUSBInterfaceInterface245 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 -#define InterfaceVersion 245 - -/* New in OS 10.4.0. */ -#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040) - -#define usb_interface_t IOUSBInterfaceInterface220 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 -#define InterfaceVersion 220 - -#else - -#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" - -#endif - -/* IOUSBDeviceInterface */ - -/* New in OS 10.9.0. */ -#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) - -#define usb_device_t IOUSBDeviceInterface650 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID650 -#define DeviceVersion 650 - -/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) - -#define usb_device_t IOUSBDeviceInterface500 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 -#define DeviceVersion 500 - -/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) - -#define usb_device_t IOUSBDeviceInterface320 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID320 -#define DeviceVersion 320 - -/* New in OS 10.5.0. */ -#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) - -#define usb_device_t IOUSBDeviceInterface300 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID300 -#define DeviceVersion 300 - -/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) - -#define usb_device_t IOUSBDeviceInterface245 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID245 -#define DeviceVersion 245 - -/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */ -#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) - -#define usb_device_t IOUSBDeviceInterface197 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 -#define DeviceVersion 197 - -#else - -#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" - -#endif - -#if !defined(IO_OBJECT_NULL) -#define IO_OBJECT_NULL ((io_object_t) 0) -#endif - -typedef IOCFPlugInInterface *io_cf_plugin_ref_t; -typedef IONotificationPortRef io_notification_port_t; - -/* private structures */ -struct darwin_cached_device { - struct list_head list; - IOUSBDeviceDescriptor dev_descriptor; - UInt32 location; - UInt64 parent_session; - UInt64 session; - UInt16 address; - char sys_path[21]; - usb_device_t **device; - int open_count; - UInt8 first_config, active_config, port; - int can_enumerate; - int refcount; -}; - -struct darwin_device_priv { - struct darwin_cached_device *dev; -}; - -struct darwin_device_handle_priv { - int is_open; - CFRunLoopSourceRef cfSource; - - struct darwin_interface { - usb_interface_t **interface; - uint8_t num_endpoints; - CFRunLoopSourceRef cfSource; - uint64_t frames[256]; - uint8_t endpoint_addrs[USB_MAXENDPOINTS]; - } interfaces[USB_MAXINTERFACES]; -}; - -struct darwin_transfer_priv { - /* Isoc */ - IOUSBIsocFrame *isoc_framelist; - int num_iso_packets; - - /* Control */ - IOUSBDevRequestTO req; - - /* Bulk */ - - /* Completion status */ - IOReturn result; - UInt32 size; -}; - -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp deleted file mode 100644 index e0c7713206..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2007-2008, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Lotz - */ - -#include "haiku_usb.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class WatchedEntry { -public: - WatchedEntry(BMessenger *, entry_ref *); - ~WatchedEntry(); - bool EntryCreated(entry_ref *ref); - bool EntryRemoved(ino_t node); - bool InitCheck(); - -private: - BMessenger* fMessenger; - node_ref fNode; - bool fIsDirectory; - USBDevice* fDevice; - WatchedEntry* fEntries; - WatchedEntry* fLink; - bool fInitCheck; -}; - - -class RosterLooper : public BLooper { -public: - RosterLooper(USBRoster *); - void Stop(); - virtual void MessageReceived(BMessage *); - bool InitCheck(); - -private: - USBRoster* fRoster; - WatchedEntry* fRoot; - BMessenger* fMessenger; - bool fInitCheck; -}; - - -WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref) - : fMessenger(messenger), - fIsDirectory(false), - fDevice(NULL), - fEntries(NULL), - fLink(NULL), - fInitCheck(false) -{ - BEntry entry(ref); - entry.GetNodeRef(&fNode); - - BDirectory directory; - if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) { - fIsDirectory = true; - - while (directory.GetNextEntry(&entry) >= B_OK) { - if (entry.GetRef(ref) < B_OK) - continue; - - WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); - if (child == NULL) - continue; - if (child->InitCheck() == false) { - delete child; - continue; - } - - child->fLink = fEntries; - fEntries = child; - } - - watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger); - } - else { - if (strncmp(ref->name, "raw", 3) == 0) - return; - - BPath path, parent_path; - entry.GetPath(&path); - fDevice = new(std::nothrow) USBDevice(path.Path()); - if (fDevice != NULL && fDevice->InitCheck() == true) { - // Add this new device to each active context's device list - struct libusb_context *ctx; - unsigned long session_id = (unsigned long)&fDevice; - - usbi_mutex_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - usbi_dbg("using previously allocated device with location %lu", session_id); - libusb_unref_device(dev); - continue; - } - usbi_dbg("allocating new device with location %lu", session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) { - usbi_dbg("device allocation failed"); - continue; - } - *((USBDevice **)dev->os_priv) = fDevice; - - // Calculate pseudo-device-address - int addr, tmp; - if (strcmp(path.Leaf(), "hub") == 0) - tmp = 100; //Random Number - else - sscanf(path.Leaf(), "%d", &tmp); - addr = tmp + 1; - path.GetParent(&parent_path); - while (strcmp(parent_path.Leaf(), "usb") != 0) { - sscanf(parent_path.Leaf(), "%d", &tmp); - addr += tmp + 1; - parent_path.GetParent(&parent_path); - } - sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number); - dev->device_address = addr - (dev->bus_number + 1); - - if (usbi_sanitize_device(dev) < 0) { - usbi_dbg("device sanitization failed"); - libusb_unref_device(dev); - continue; - } - usbi_connect_device(dev); - } - usbi_mutex_unlock(&active_contexts_lock); - } - else if (fDevice) { - delete fDevice; - fDevice = NULL; - return; - } - } - fInitCheck = true; -} - - -WatchedEntry::~WatchedEntry() -{ - if (fIsDirectory) { - watch_node(&fNode, B_STOP_WATCHING, *fMessenger); - - WatchedEntry *child = fEntries; - while (child) { - WatchedEntry *next = child->fLink; - delete child; - child = next; - } - } - - if (fDevice) { - // Remove this device from each active context's device list - struct libusb_context *ctx; - struct libusb_device *dev; - unsigned long session_id = (unsigned long)&fDevice; - - usbi_mutex_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev != NULL) { - usbi_disconnect_device(dev); - libusb_unref_device(dev); - } else { - usbi_dbg("device with location %lu not found", session_id); - } - } - usbi_mutex_static_unlock(&active_contexts_lock); - delete fDevice; - } -} - - -bool -WatchedEntry::EntryCreated(entry_ref *ref) -{ - if (!fIsDirectory) - return false; - - if (ref->directory != fNode.node) { - WatchedEntry *child = fEntries; - while (child) { - if (child->EntryCreated(ref)) - return true; - child = child->fLink; - } - return false; - } - - WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); - if (child == NULL) - return false; - child->fLink = fEntries; - fEntries = child; - return true; -} - - -bool -WatchedEntry::EntryRemoved(ino_t node) -{ - if (!fIsDirectory) - return false; - - WatchedEntry *child = fEntries; - WatchedEntry *lastChild = NULL; - while (child) { - if (child->fNode.node == node) { - if (lastChild) - lastChild->fLink = child->fLink; - else - fEntries = child->fLink; - delete child; - return true; - } - - if (child->EntryRemoved(node)) - return true; - - lastChild = child; - child = child->fLink; - } - return false; -} - - -bool -WatchedEntry::InitCheck() -{ - return fInitCheck; -} - - -RosterLooper::RosterLooper(USBRoster *roster) - : BLooper("LibusbRoster Looper"), - fRoster(roster), - fRoot(NULL), - fMessenger(NULL), - fInitCheck(false) -{ - BEntry entry("/dev/bus/usb"); - if (!entry.Exists()) { - usbi_err(NULL, "usb_raw not published"); - return; - } - - Run(); - fMessenger = new(std::nothrow) BMessenger(this); - if (fMessenger == NULL) { - usbi_err(NULL, "error creating BMessenger object"); - return; - } - - if (Lock()) { - entry_ref ref; - entry.GetRef(&ref); - fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref); - Unlock(); - if (fRoot == NULL) - return; - if (fRoot->InitCheck() == false) { - delete fRoot; - fRoot = NULL; - return; - } - } - fInitCheck = true; -} - - -void -RosterLooper::Stop() -{ - Lock(); - delete fRoot; - delete fMessenger; - Quit(); -} - - -void -RosterLooper::MessageReceived(BMessage *message) -{ - int32 opcode; - if (message->FindInt32("opcode", &opcode) < B_OK) - return; - - switch (opcode) { - case B_ENTRY_CREATED: - { - dev_t device; - ino_t directory; - const char *name; - if (message->FindInt32("device", &device) < B_OK || - message->FindInt64("directory", &directory) < B_OK || - message->FindString("name", &name) < B_OK) - break; - - entry_ref ref(device, directory, name); - fRoot->EntryCreated(&ref); - break; - } - case B_ENTRY_REMOVED: - { - ino_t node; - if (message->FindInt64("node", &node) < B_OK) - break; - fRoot->EntryRemoved(node); - break; - } - } -} - - -bool -RosterLooper::InitCheck() -{ - return fInitCheck; -} - - -USBRoster::USBRoster() - : fLooper(NULL) -{ -} - - -USBRoster::~USBRoster() -{ - Stop(); -} - - -int -USBRoster::Start() -{ - if (fLooper == NULL) { - fLooper = new(std::nothrow) RosterLooper(this); - if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) { - if (fLooper) - fLooper = NULL; - return LIBUSB_ERROR_OTHER; - } - } - return LIBUSB_SUCCESS; -} - - -void -USBRoster::Stop() -{ - if (fLooper) { - ((RosterLooper *)fLooper)->Stop(); - fLooper = NULL; - } -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h deleted file mode 100644 index d51ae9eae8..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include "libusbi.h" -#include "haiku_usb_raw.h" - -using namespace std; - -class USBDevice; -class USBDeviceHandle; -class USBTransfer; - -class USBDevice { -public: - USBDevice(const char *); - virtual ~USBDevice(); - const char* Location() const; - uint8 CountConfigurations() const; - const usb_device_descriptor* Descriptor() const; - const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const; - const usb_configuration_descriptor* ActiveConfiguration() const; - uint8 EndpointToIndex(uint8) const; - uint8 EndpointToInterface(uint8) const; - int ClaimInterface(int); - int ReleaseInterface(int); - int CheckInterfacesFree(int); - int SetActiveConfiguration(int); - int ActiveConfigurationIndex() const; - bool InitCheck(); -private: - int Initialise(); - unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask - usb_device_descriptor fDeviceDescriptor; - unsigned char** fConfigurationDescriptors; - int fActiveConfiguration; - char* fPath; - map fConfigToIndex; - map* fEndpointToIndex; - map* fEndpointToInterface; - bool fInitCheck; -}; - -class USBDeviceHandle { -public: - USBDeviceHandle(USBDevice *dev); - virtual ~USBDeviceHandle(); - int ClaimInterface(int); - int ReleaseInterface(int); - int SetConfiguration(int); - int SetAltSetting(int, int); - status_t SubmitTransfer(struct usbi_transfer *); - status_t CancelTransfer(USBTransfer *); - bool InitCheck(); -private: - int fRawFD; - static status_t TransfersThread(void *); - void TransfersWorker(); - USBDevice* fUSBDevice; - unsigned int fClaimedInterfaces; - BList fTransfers; - BLocker fTransfersLock; - sem_id fTransfersSem; - thread_id fTransfersThread; - bool fInitCheck; -}; - -class USBTransfer { -public: - USBTransfer(struct usbi_transfer *, USBDevice *); - virtual ~USBTransfer(); - void Do(int); - struct usbi_transfer* UsbiTransfer(); - void SetCancelled(); - bool IsCancelled(); -private: - struct usbi_transfer* fUsbiTransfer; - struct libusb_transfer* fLibusbTransfer; - USBDevice* fUSBDevice; - BLocker fStatusLock; - bool fCancelled; -}; - -class USBRoster { -public: - USBRoster(); - virtual ~USBRoster(); - int Start(); - void Stop(); -private: - void* fLooper; -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp deleted file mode 100644 index d3de8cc080..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include -#include -#include -#include - -#include "haiku_usb.h" - -int _errno_to_libusb(int status) -{ - return status; -} - -USBTransfer::USBTransfer(struct usbi_transfer *itransfer, USBDevice *device) -{ - fUsbiTransfer = itransfer; - fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - fUSBDevice = device; - fCancelled = false; -} - -USBTransfer::~USBTransfer() -{ -} - -struct usbi_transfer * -USBTransfer::UsbiTransfer() -{ - return fUsbiTransfer; -} - -void -USBTransfer::SetCancelled() -{ - fCancelled = true; -} - -bool -USBTransfer::IsCancelled() -{ - return fCancelled; -} - -void -USBTransfer::Do(int fRawFD) -{ - switch (fLibusbTransfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - { - struct libusb_control_setup *setup = (struct libusb_control_setup *)fLibusbTransfer->buffer; - usb_raw_command command; - command.control.request_type = setup->bmRequestType; - command.control.request = setup->bRequest; - command.control.value = setup->wValue; - command.control.index = setup->wIndex; - command.control.length = setup->wLength; - command.control.data = fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - if (fCancelled) - break; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || - command.control.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed control transfer"); - break; - } - fUsbiTransfer->transferred = command.control.length; - } - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - { - usb_raw_command command; - command.transfer.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); - command.transfer.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); - command.transfer.data = fLibusbTransfer->buffer; - command.transfer.length = fLibusbTransfer->length; - if (fCancelled) - break; - if (fLibusbTransfer->type == LIBUSB_TRANSFER_TYPE_BULK) { - if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command)) || - command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed bulk transfer"); - break; - } - } - else { - if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command)) || - command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed interrupt transfer"); - break; - } - } - fUsbiTransfer->transferred = command.transfer.length; - } - break; - // IsochronousTransfers not tested - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - { - usb_raw_command command; - command.isochronous.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); - command.isochronous.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); - command.isochronous.data = fLibusbTransfer->buffer; - command.isochronous.length = fLibusbTransfer->length; - command.isochronous.packet_count = fLibusbTransfer->num_iso_packets; - int i; - usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets]; - for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { - if ((int16)(fLibusbTransfer->iso_packet_desc[i]).length != (fLibusbTransfer->iso_packet_desc[i]).length) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); - break; - } - packetDescriptors[i].request_length = (int16)(fLibusbTransfer->iso_packet_desc[i]).length; - } - if (i < fLibusbTransfer->num_iso_packets) - break; // TODO Handle this error - command.isochronous.packet_descriptors = packetDescriptors; - if (fCancelled) - break; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, sizeof(command)) || - command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); - break; - } - for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { - (fLibusbTransfer->iso_packet_desc[i]).actual_length = packetDescriptors[i].actual_length; - switch (packetDescriptors[i].status) { - case B_OK: - (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_COMPLETED; - break; - default: - (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_ERROR; - break; - } - } - delete[] packetDescriptors; - // Do we put the length of transfer here, for isochronous transfers? - fUsbiTransfer->transferred = command.transfer.length; - } - break; - default: - usbi_err(TRANSFER_CTX(fLibusbTransfer), "Unknown type of transfer"); - } -} - -bool -USBDeviceHandle::InitCheck() -{ - return fInitCheck; -} - -status_t -USBDeviceHandle::TransfersThread(void *self) -{ - USBDeviceHandle *handle = (USBDeviceHandle *)self; - handle->TransfersWorker(); - return B_OK; -} - -void -USBDeviceHandle::TransfersWorker() -{ - while (true) { - status_t status = acquire_sem(fTransfersSem); - if (status == B_BAD_SEM_ID) - break; - if (status == B_INTERRUPTED) - continue; - fTransfersLock.Lock(); - USBTransfer *fPendingTransfer = (USBTransfer *) fTransfers.RemoveItem((int32)0); - fTransfersLock.Unlock(); - fPendingTransfer->Do(fRawFD); - usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer()); - } -} - -status_t -USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice); - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer; - BAutolock locker(fTransfersLock); - fTransfers.AddItem(transfer); - release_sem(fTransfersSem); - return LIBUSB_SUCCESS; -} - -status_t -USBDeviceHandle::CancelTransfer(USBTransfer *transfer) -{ - transfer->SetCancelled(); - fTransfersLock.Lock(); - bool removed = fTransfers.RemoveItem(transfer); - fTransfersLock.Unlock(); - if(removed) - usbi_signal_transfer_completion(transfer->UsbiTransfer()); - return LIBUSB_SUCCESS; -} - -USBDeviceHandle::USBDeviceHandle(USBDevice *dev) - : - fTransfersThread(-1), - fUSBDevice(dev), - fClaimedInterfaces(0), - fInitCheck(false) -{ - fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC); - if (fRawFD < 0) { - usbi_err(NULL,"failed to open device"); - return; - } - fTransfersSem = create_sem(0, "Transfers Queue Sem"); - fTransfersThread = spawn_thread(TransfersThread, "Transfer Worker", B_NORMAL_PRIORITY, this); - resume_thread(fTransfersThread); - fInitCheck = true; -} - -USBDeviceHandle::~USBDeviceHandle() -{ - if (fRawFD > 0) - close(fRawFD); - for(int i = 0; i < 32; i++) { - if (fClaimedInterfaces & (1 << i)) - ReleaseInterface(i); - } - delete_sem(fTransfersSem); - if (fTransfersThread > 0) - wait_for_thread(fTransfersThread, NULL); -} - -int -USBDeviceHandle::ClaimInterface(int inumber) -{ - int status = fUSBDevice->ClaimInterface(inumber); - if (status == LIBUSB_SUCCESS) - fClaimedInterfaces |= (1 << inumber); - return status; -} - -int -USBDeviceHandle::ReleaseInterface(int inumber) -{ - fUSBDevice->ReleaseInterface(inumber); - fClaimedInterfaces &= ~(1 << inumber); - return LIBUSB_SUCCESS; -} - -int -USBDeviceHandle::SetConfiguration(int config) -{ - int config_index = fUSBDevice->CheckInterfacesFree(config); - if(config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND) - return config_index; - usb_raw_command command; - command.config.config_index = config_index; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - return _errno_to_libusb(command.config.status); - } - fUSBDevice->SetActiveConfiguration(config_index); - return LIBUSB_SUCCESS; -} - -int -USBDeviceHandle::SetAltSetting(int inumber, int alt) -{ - usb_raw_command command; - command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex(); - command.alternate.interface_index = inumber; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, sizeof(command)) || - command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "Error retrieving active alternate interface"); - return _errno_to_libusb(command.alternate.status); - } - if (command.alternate.alternate_info == alt) { - usbi_dbg("Setting alternate interface successful"); - return LIBUSB_SUCCESS; - } - command.alternate.alternate_info = alt; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, sizeof(command)) || - command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY - usbi_err(NULL, "Error setting alternate interface"); - return _errno_to_libusb(command.alternate.status); - } - usbi_dbg("Setting alternate interface successful"); - return LIBUSB_SUCCESS; -} - - -USBDevice::USBDevice(const char *path) - : - fPath(NULL), - fActiveConfiguration(0), //0? - fConfigurationDescriptors(NULL), - fClaimedInterfaces(0), - fEndpointToIndex(NULL), - fEndpointToInterface(NULL), - fInitCheck(false) -{ - fPath=strdup(path); - Initialise(); -} - -USBDevice::~USBDevice() -{ - free(fPath); - if (fConfigurationDescriptors) { - for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) { - if (fConfigurationDescriptors[i]) - delete fConfigurationDescriptors[i]; - } - delete[] fConfigurationDescriptors; - } - if (fEndpointToIndex) - delete[] fEndpointToIndex; - if (fEndpointToInterface) - delete[] fEndpointToInterface; -} - -bool -USBDevice::InitCheck() -{ - return fInitCheck; -} - -const char * -USBDevice::Location() const -{ - return fPath; -} - -uint8 -USBDevice::CountConfigurations() const -{ - return fDeviceDescriptor.num_configurations; -} - -const usb_device_descriptor * -USBDevice::Descriptor() const -{ - return &fDeviceDescriptor; -} - -const usb_configuration_descriptor * -USBDevice::ConfigurationDescriptor(uint32 index) const -{ - if (index > CountConfigurations()) - return NULL; - return (usb_configuration_descriptor *) fConfigurationDescriptors[index]; -} - -const usb_configuration_descriptor * -USBDevice::ActiveConfiguration() const -{ - return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration]; -} - -int -USBDevice::ActiveConfigurationIndex() const -{ - return fActiveConfiguration; -} - -int USBDevice::ClaimInterface(int interface) -{ - if (interface > ActiveConfiguration()->number_interfaces) - return LIBUSB_ERROR_NOT_FOUND; - if (fClaimedInterfaces & (1 << interface)) - return LIBUSB_ERROR_BUSY; - fClaimedInterfaces |= (1 << interface); - return LIBUSB_SUCCESS; -} - -int USBDevice::ReleaseInterface(int interface) -{ - fClaimedInterfaces &= ~(1 << interface); - return LIBUSB_SUCCESS; -} - -int -USBDevice::CheckInterfacesFree(int config) -{ - if (fConfigToIndex.count(config) == 0) - return LIBUSB_ERROR_NOT_FOUND; - if (fClaimedInterfaces == 0) - return fConfigToIndex[(uint8)config]; - return LIBUSB_ERROR_BUSY; -} - -int -USBDevice::SetActiveConfiguration(int config_index) -{ - fActiveConfiguration = config_index; - return LIBUSB_SUCCESS; -} - -uint8 -USBDevice::EndpointToIndex(uint8 address) const -{ - return fEndpointToIndex[fActiveConfiguration][address]; -} - -uint8 -USBDevice::EndpointToInterface(uint8 address) const -{ - return fEndpointToInterface[fActiveConfiguration][address]; -} - -int -USBDevice::Initialise() //Do we need more error checking, etc? How to report? -{ - int fRawFD = open(fPath, O_RDWR | O_CLOEXEC); - if (fRawFD < 0) - return B_ERROR; - usb_raw_command command; - command.device.descriptor = &fDeviceDescriptor; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command)) || - command.device.status != B_USB_RAW_STATUS_SUCCESS) { - close(fRawFD); - return B_ERROR; - } - - fConfigurationDescriptors = new(std::nothrow) unsigned char *[fDeviceDescriptor.num_configurations]; - fEndpointToIndex = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; - fEndpointToInterface = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; - for (int i = 0; i < fDeviceDescriptor.num_configurations; i++) { - usb_configuration_descriptor tmp_config; - command.config.descriptor = &tmp_config; - command.config.config_index = i; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving configuration descriptor"); - close(fRawFD); - return B_ERROR; - } - fConfigToIndex[tmp_config.configuration_value] = i; - fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length]; - command.control.request_type = 128; - command.control.request = 6; - command.control.value = (2 << 8) | i; - command.control.index = 0; - command.control.length = tmp_config.total_length; - command.control.data = fConfigurationDescriptors[i]; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || - command.control.status!=B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving full configuration descriptor"); - close(fRawFD); - return B_ERROR; - } - for (int j = 0; j < tmp_config.number_interfaces; j++) { - command.alternate.config_index = i; - command.alternate.interface_index = j; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving number of alternate interfaces"); - close(fRawFD); - return B_ERROR; - } - int num_alternate = command.alternate.alternate_info; - for (int k = 0; k < num_alternate; k++) { - usb_interface_descriptor tmp_interface; - command.interface_etc.config_index = i; - command.interface_etc.interface_index = j; - command.interface_etc.alternate_index = k; - command.interface_etc.descriptor = &tmp_interface; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving interface descriptor"); - close(fRawFD); - return B_ERROR; - } - for (int l = 0; l < tmp_interface.num_endpoints; l++) { - usb_endpoint_descriptor tmp_endpoint; - command.endpoint_etc.config_index = i; - command.endpoint_etc.interface_index = j; - command.endpoint_etc.alternate_index = k; - command.endpoint_etc.endpoint_index = l; - command.endpoint_etc.descriptor = &tmp_endpoint; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving endpoint descriptor"); - close(fRawFD); - return B_ERROR; - } - fEndpointToIndex[i][tmp_endpoint.endpoint_address] = l; - fEndpointToInterface[i][tmp_endpoint.endpoint_address] = j; - } - } - } - } - close(fRawFD); - fInitCheck = true; - return B_OK; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp deleted file mode 100644 index c701e34421..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include -#include -#include -#include - -#include "haiku_usb.h" - -USBRoster gUsbRoster; -int32 gInitCount = 0; - -static int -haiku_init(struct libusb_context *ctx) -{ - if (atomic_add(&gInitCount, 1) == 0) - return gUsbRoster.Start(); - return LIBUSB_SUCCESS; -} - -static void -haiku_exit(struct libusb_context *ctx) -{ - UNUSED(ctx); - if (atomic_add(&gInitCount, -1) == 1) - gUsbRoster.Stop(); -} - -static int -haiku_open(struct libusb_device_handle *dev_handle) -{ - USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv); - USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev); - if (handle == NULL) - return LIBUSB_ERROR_NO_MEM; - if (handle->InitCheck() == false) { - delete handle; - return LIBUSB_ERROR_NO_DEVICE; - } - *((USBDeviceHandle **)dev_handle->os_priv) = handle; - return LIBUSB_SUCCESS; -} - -static void -haiku_close(struct libusb_device_handle *dev_handle) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - if (handle == NULL) - return; - delete handle; - *((USBDeviceHandle **)dev_handle->os_priv) = NULL; -} - -static int -haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH); - *host_endian = 0; - return LIBUSB_SUCCESS; -} - -static int -haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - const usb_configuration_descriptor *act_config = dev->ActiveConfiguration(); - if (len > act_config->total_length) - return LIBUSB_ERROR_OVERFLOW; - memcpy(buffer, act_config, len); - *host_endian = 0; - return LIBUSB_SUCCESS; -} - -static int -haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index); - if (config == NULL) { - usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor"); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (len > config->total_length) - len = config->total_length; - memcpy(buffer, config, len); - *host_endian = 0; - return len; -} - -static int -haiku_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv); - return handle->SetConfiguration(config); -} - -static int -haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - return handle->ClaimInterface(interface_number); -} - -static int -haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - return handle->SetAltSetting(interface_number, altsetting); -} - -static int -haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - haiku_set_altsetting(dev_handle,interface_number, 0); - return handle->ReleaseInterface(interface_number); -} - -static int -haiku_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); - return fDeviceHandle->SubmitTransfer(itransfer); -} - -static int -haiku_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); - return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer))); -} - -static void -haiku_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; -} - -static int -haiku_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); - - usbi_mutex_lock(&itransfer->lock); - if (transfer->IsCancelled()) { - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; - usbi_mutex_unlock(&itransfer->lock); - if (itransfer->transferred < 0) - itransfer->transferred = 0; - return usbi_handle_transfer_cancellation(itransfer); - } - libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; - if (itransfer->transferred < 0) { - usbi_err(ITRANSFER_CTX(itransfer), "error in transfer"); - status = LIBUSB_TRANSFER_ERROR; - itransfer->transferred = 0; - } - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); -} - -static int -haiku_clock_gettime(int clkid, struct timespec *tp) -{ - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - return LIBUSB_ERROR_INVALID_PARAM; -} - -const struct usbi_os_backend usbi_backend = { - /*.name =*/ "Haiku usbfs", - /*.caps =*/ 0, - /*.init =*/ haiku_init, - /*.exit =*/ haiku_exit, - /*.set_option =*/ NULL, - /*.get_device_list =*/ NULL, - /*.hotplug_poll =*/ NULL, - /*.open =*/ haiku_open, - /*.close =*/ haiku_close, - /*.get_device_descriptor =*/ haiku_get_device_descriptor, - /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, - /*.get_config_descriptor =*/ haiku_get_config_descriptor, - /*.get_config_descriptor_by_value =*/ NULL, - - - /*.get_configuration =*/ NULL, - /*.set_configuration =*/ haiku_set_configuration, - /*.claim_interface =*/ haiku_claim_interface, - /*.release_interface =*/ haiku_release_interface, - - /*.set_interface_altsetting =*/ haiku_set_altsetting, - /*.clear_halt =*/ NULL, - /*.reset_device =*/ NULL, - - /*.alloc_streams =*/ NULL, - /*.free_streams =*/ NULL, - - /*.dev_mem_alloc =*/ NULL, - /*.dev_mem_free =*/ NULL, - - /*.kernel_driver_active =*/ NULL, - /*.detach_kernel_driver =*/ NULL, - /*.attach_kernel_driver =*/ NULL, - - /*.destroy_device =*/ NULL, - - /*.submit_transfer =*/ haiku_submit_transfer, - /*.cancel_transfer =*/ haiku_cancel_transfer, - /*.clear_transfer_priv =*/ haiku_clear_transfer_priv, - - /*.handle_events =*/ NULL, - /*.handle_transfer_completion =*/ haiku_handle_transfer_completion, - - /*.clock_gettime =*/ haiku_clock_gettime, - -#ifdef USBI_TIMERFD_AVAILABLE - /*.get_timerfd_clockid =*/ NULL, -#endif - - /*.context_priv_size=*/ 0, - /*.device_priv_size =*/ sizeof(USBDevice *), - /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *), - /*.transfer_priv_size =*/ sizeof(USBTransfer *), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h deleted file mode 100644 index 5baf53d7c9..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2006-2008, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - */ - -#ifndef _USB_RAW_H_ -#define _USB_RAW_H_ - -#include - -#define B_USB_RAW_PROTOCOL_VERSION 0x0015 -#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff - -typedef enum { - B_USB_RAW_COMMAND_GET_VERSION = 0x1000, - - B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000, - B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, - B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, - B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, - B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, - B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, - - B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000, - B_USB_RAW_COMMAND_SET_FEATURE, - B_USB_RAW_COMMAND_CLEAR_FEATURE, - B_USB_RAW_COMMAND_GET_STATUS, - B_USB_RAW_COMMAND_GET_DESCRIPTOR, - B_USB_RAW_COMMAND_SET_ALT_INTERFACE, - - B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000, - B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, - B_USB_RAW_COMMAND_BULK_TRANSFER, - B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER -} usb_raw_command_id; - - -typedef enum { - B_USB_RAW_STATUS_SUCCESS = 0, - - B_USB_RAW_STATUS_FAILED, - B_USB_RAW_STATUS_ABORTED, - B_USB_RAW_STATUS_STALLED, - B_USB_RAW_STATUS_CRC_ERROR, - B_USB_RAW_STATUS_TIMEOUT, - - B_USB_RAW_STATUS_INVALID_CONFIGURATION, - B_USB_RAW_STATUS_INVALID_INTERFACE, - B_USB_RAW_STATUS_INVALID_ENDPOINT, - B_USB_RAW_STATUS_INVALID_STRING, - - B_USB_RAW_STATUS_NO_MEMORY -} usb_raw_command_status; - - -typedef union { - struct { - status_t status; - } version; - - struct { - status_t status; - usb_device_descriptor *descriptor; - } device; - - struct { - status_t status; - usb_configuration_descriptor *descriptor; - uint32 config_index; - } config; - - struct { - status_t status; - uint32 alternate_info; - uint32 config_index; - uint32 interface_index; - } alternate; - - struct { - status_t status; - usb_interface_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - } interface; - - struct { - status_t status; - usb_interface_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - } interface_etc; - - struct { - status_t status; - usb_endpoint_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 endpoint_index; - } endpoint; - - struct { - status_t status; - usb_endpoint_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - uint32 endpoint_index; - } endpoint_etc; - - struct { - status_t status; - usb_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 generic_index; - size_t length; - } generic; - - struct { - status_t status; - usb_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - uint32 generic_index; - size_t length; - } generic_etc; - - struct { - status_t status; - usb_string_descriptor *descriptor; - uint32 string_index; - size_t length; - } string; - - struct { - status_t status; - uint8 type; - uint8 index; - uint16 language_id; - void *data; - size_t length; - } descriptor; - - struct { - status_t status; - uint8 request_type; - uint8 request; - uint16 value; - uint16 index; - uint16 length; - void *data; - } control; - - struct { - status_t status; - uint32 interface; - uint32 endpoint; - void *data; - size_t length; - } transfer; - - struct { - status_t status; - uint32 interface; - uint32 endpoint; - void *data; - size_t length; - usb_iso_packet_descriptor *packet_descriptors; - uint32 packet_count; - } isochronous; -} usb_raw_command; - -#endif // _USB_RAW_H_ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c deleted file mode 100644 index c1ad1ec51f..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c +++ /dev/null @@ -1,409 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright (C) 2007-2009 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt - * Copyright (c) 2013 Nathan Hjelm - * Copyright (c) 2016 Chris Dickens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_ASM_TYPES_H -#include -#endif - -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -#define NL_GROUP_KERNEL 1 - -#ifndef SOCK_CLOEXEC -#define SOCK_CLOEXEC 0 -#endif - -#ifndef SOCK_NONBLOCK -#define SOCK_NONBLOCK 0 -#endif - -static int linux_netlink_socket = -1; -static int netlink_control_pipe[2] = { -1, -1 }; -static pthread_t libusb_linux_event_thread; - -static void *linux_netlink_event_thread_main(void *arg); - -static int set_fd_cloexec_nb(int fd, int socktype) -{ - int flags; - -#if defined(FD_CLOEXEC) - /* Make sure the netlink socket file descriptor is marked as CLOEXEC */ - if (!(socktype & SOCK_CLOEXEC)) { - flags = fcntl(fd, F_GETFD); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); - return -1; - } - - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { - usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); - return -1; - } - } -#endif - - /* Make sure the netlink socket is non-blocking */ - if (!(socktype & SOCK_NONBLOCK)) { - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); - return -1; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { - usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); - return -1; - } - } - - return 0; -} - -int linux_netlink_start_event_monitor(void) -{ - struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; - int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC; - int opt = 1; - int ret; - - linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); - if (linux_netlink_socket == -1 && errno == EINVAL) { - usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); - socktype = SOCK_RAW; - linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); - } - - if (linux_netlink_socket == -1) { - usbi_err(NULL, "failed to create netlink socket (%d)", errno); - goto err; - } - - ret = set_fd_cloexec_nb(linux_netlink_socket, socktype); - if (ret == -1) - goto err_close_socket; - - ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); - if (ret == -1) { - usbi_err(NULL, "failed to bind netlink socket (%d)", errno); - goto err_close_socket; - } - - ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); - if (ret == -1) { - usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno); - goto err_close_socket; - } - - ret = usbi_pipe(netlink_control_pipe); - if (ret) { - usbi_err(NULL, "failed to create netlink control pipe"); - goto err_close_socket; - } - - ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL); - if (ret != 0) { - usbi_err(NULL, "failed to create netlink event thread (%d)", ret); - goto err_close_pipe; - } - - return LIBUSB_SUCCESS; - -err_close_pipe: - close(netlink_control_pipe[0]); - close(netlink_control_pipe[1]); - netlink_control_pipe[0] = -1; - netlink_control_pipe[1] = -1; -err_close_socket: - close(linux_netlink_socket); - linux_netlink_socket = -1; -err: - return LIBUSB_ERROR_OTHER; -} - -int linux_netlink_stop_event_monitor(void) -{ - char dummy = 1; - ssize_t r; - - assert(linux_netlink_socket != -1); - - /* Write some dummy data to the control pipe and - * wait for the thread to exit */ - r = write(netlink_control_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) - usbi_warn(NULL, "netlink control pipe signal failed"); - - pthread_join(libusb_linux_event_thread, NULL); - - close(linux_netlink_socket); - linux_netlink_socket = -1; - - /* close and reset control pipe */ - close(netlink_control_pipe[0]); - close(netlink_control_pipe[1]); - netlink_control_pipe[0] = -1; - netlink_control_pipe[1] = -1; - - return LIBUSB_SUCCESS; -} - -static const char *netlink_message_parse(const char *buffer, size_t len, const char *key) -{ - const char *end = buffer + len; - size_t keylen = strlen(key); - - while (buffer < end && *buffer) { - if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=') - return buffer + keylen + 1; - buffer += strlen(buffer) + 1; - } - - return NULL; -} - -/* parse parts of netlink message common to both libudev and the kernel */ -static int linux_netlink_parse(const char *buffer, size_t len, int *detached, - const char **sys_name, uint8_t *busnum, uint8_t *devaddr) -{ - const char *tmp, *slash; - - errno = 0; - - *sys_name = NULL; - *detached = 0; - *busnum = 0; - *devaddr = 0; - - tmp = netlink_message_parse(buffer, len, "ACTION"); - if (!tmp) { - return -1; - } else if (strcmp(tmp, "remove") == 0) { - *detached = 1; - } else if (strcmp(tmp, "add") != 0) { - usbi_dbg("unknown device action %s", tmp); - return -1; - } - - /* check that this is a usb message */ - tmp = netlink_message_parse(buffer, len, "SUBSYSTEM"); - if (!tmp || strcmp(tmp, "usb") != 0) { - /* not usb. ignore */ - return -1; - } - - /* check that this is an actual usb device */ - tmp = netlink_message_parse(buffer, len, "DEVTYPE"); - if (!tmp || strcmp(tmp, "usb_device") != 0) { - /* not usb. ignore */ - return -1; - } - - tmp = netlink_message_parse(buffer, len, "BUSNUM"); - if (tmp) { - *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - tmp = netlink_message_parse(buffer, len, "DEVNUM"); - if (NULL == tmp) - return -1; - - *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - } else { - /* no bus number. try "DEVICE" */ - tmp = netlink_message_parse(buffer, len, "DEVICE"); - if (!tmp) { - /* not usb. ignore */ - return -1; - } - - /* Parse a device path such as /dev/bus/usb/003/004 */ - slash = strrchr(tmp, '/'); - if (!slash) - return -1; - - *busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - *devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - return 0; - } - - tmp = netlink_message_parse(buffer, len, "DEVPATH"); - if (!tmp) - return -1; - - slash = strrchr(tmp, '/'); - if (slash) - *sys_name = slash + 1; - - /* found a usb device */ - return 0; -} - -static int linux_netlink_read_message(void) -{ - char cred_buffer[CMSG_SPACE(sizeof(struct ucred))]; - char msg_buffer[2048]; - const char *sys_name = NULL; - uint8_t busnum, devaddr; - int detached, r; - ssize_t len; - struct cmsghdr *cmsg; - struct ucred *cred; - struct sockaddr_nl sa_nl; - struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) }; - struct msghdr msg = { - .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer), - .msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl) - }; - - /* read netlink message */ - len = recvmsg(linux_netlink_socket, &msg, 0); - if (len == -1) { - if (errno != EAGAIN && errno != EINTR) - usbi_err(NULL, "error receiving message from netlink (%d)", errno); - return -1; - } - - if (len < 32 || (msg.msg_flags & MSG_TRUNC)) { - usbi_err(NULL, "invalid netlink message length"); - return -1; - } - - if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) { - usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)", - (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid); - return -1; - } - - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { - usbi_dbg("ignoring netlink message with no sender credentials"); - return -1; - } - - cred = (struct ucred *)CMSG_DATA(cmsg); - if (cred->uid != 0) { - usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid); - return -1; - } - - r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); - if (r) - return r; - - usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", - busnum, devaddr, sys_name, detached ? "yes" : "no"); - - /* signal device is available (or not) to all contexts */ - if (detached) - linux_device_disconnected(busnum, devaddr); - else - linux_hotplug_enumerate(busnum, devaddr, sys_name); - - return 0; -} - -static void *linux_netlink_event_thread_main(void *arg) -{ - char dummy; - int r; - ssize_t nb; - struct pollfd fds[] = { - { .fd = netlink_control_pipe[0], - .events = POLLIN }, - { .fd = linux_netlink_socket, - .events = POLLIN }, - }; - - UNUSED(arg); - - usbi_dbg("netlink event thread entering"); - - while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { - if (r < 0) { - /* temporary failure */ - continue; - } - if (fds[0].revents & POLLIN) { - /* activity on control pipe, read the byte and exit */ - nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy)); - if (nb <= 0) - usbi_warn(NULL, "netlink control pipe read failed"); - break; - } - if (fds[1].revents & POLLIN) { - usbi_mutex_static_lock(&linux_hotplug_lock); - linux_netlink_read_message(); - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - } - - usbi_dbg("netlink event thread exiting"); - - return NULL; -} - -void linux_netlink_hotplug_poll(void) -{ - int r; - - usbi_mutex_static_lock(&linux_hotplug_lock); - do { - r = linux_netlink_read_message(); - } while (r == 0); - usbi_mutex_static_unlock(&linux_hotplug_lock); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c deleted file mode 100644 index c97806ba6b..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c +++ /dev/null @@ -1,329 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright (C) 2007-2009 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt - * Copyright (c) 2012-2013 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -/* udev context */ -static struct udev *udev_ctx = NULL; -static int udev_monitor_fd = -1; -static int udev_control_pipe[2] = {-1, -1}; -static struct udev_monitor *udev_monitor = NULL; -static pthread_t linux_event_thread; - -static void udev_hotplug_event(struct udev_device* udev_dev); -static void *linux_udev_event_thread_main(void *arg); - -int linux_udev_start_event_monitor(void) -{ - int r; - - assert(udev_ctx == NULL); - udev_ctx = udev_new(); - if (!udev_ctx) { - usbi_err(NULL, "could not create udev context"); - goto err; - } - - udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev"); - if (!udev_monitor) { - usbi_err(NULL, "could not initialize udev monitor"); - goto err_free_ctx; - } - - r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device"); - if (r) { - usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem"); - goto err_free_monitor; - } - - if (udev_monitor_enable_receiving(udev_monitor)) { - usbi_err(NULL, "failed to enable the udev monitor"); - goto err_free_monitor; - } - - udev_monitor_fd = udev_monitor_get_fd(udev_monitor); - -#if defined(FD_CLOEXEC) - /* Make sure the udev file descriptor is marked as CLOEXEC */ - r = fcntl(udev_monitor_fd, F_GETFD); - if (r == -1) { - usbi_err(NULL, "geting udev monitor fd flags (%d)", errno); - goto err_free_monitor; - } - if (!(r & FD_CLOEXEC)) { - if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) { - usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); - goto err_free_monitor; - } - } -#endif - - /* Some older versions of udev are not non-blocking by default, - * so make sure this is set */ - r = fcntl(udev_monitor_fd, F_GETFL); - if (r == -1) { - usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno); - goto err_free_monitor; - } - if (!(r & O_NONBLOCK)) { - if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) { - usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno); - goto err_free_monitor; - } - } - - r = usbi_pipe(udev_control_pipe); - if (r) { - usbi_err(NULL, "could not create udev control pipe"); - goto err_free_monitor; - } - - r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL); - if (r) { - usbi_err(NULL, "creating hotplug event thread (%d)", r); - goto err_close_pipe; - } - - return LIBUSB_SUCCESS; - -err_close_pipe: - close(udev_control_pipe[0]); - close(udev_control_pipe[1]); -err_free_monitor: - udev_monitor_unref(udev_monitor); - udev_monitor = NULL; - udev_monitor_fd = -1; -err_free_ctx: - udev_unref(udev_ctx); -err: - udev_ctx = NULL; - return LIBUSB_ERROR_OTHER; -} - -int linux_udev_stop_event_monitor(void) -{ - char dummy = 1; - int r; - - assert(udev_ctx != NULL); - assert(udev_monitor != NULL); - assert(udev_monitor_fd != -1); - - /* Write some dummy data to the control pipe and - * wait for the thread to exit */ - r = write(udev_control_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) { - usbi_warn(NULL, "udev control pipe signal failed"); - } - pthread_join(linux_event_thread, NULL); - - /* Release the udev monitor */ - udev_monitor_unref(udev_monitor); - udev_monitor = NULL; - udev_monitor_fd = -1; - - /* Clean up the udev context */ - udev_unref(udev_ctx); - udev_ctx = NULL; - - /* close and reset control pipe */ - close(udev_control_pipe[0]); - close(udev_control_pipe[1]); - udev_control_pipe[0] = -1; - udev_control_pipe[1] = -1; - - return LIBUSB_SUCCESS; -} - -static void *linux_udev_event_thread_main(void *arg) -{ - char dummy; - int r; - ssize_t nb; - struct udev_device* udev_dev; - struct pollfd fds[] = { - {.fd = udev_control_pipe[0], - .events = POLLIN}, - {.fd = udev_monitor_fd, - .events = POLLIN}, - }; - - usbi_dbg("udev event thread entering."); - - while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { - if (r < 0) { - /* temporary failure */ - continue; - } - if (fds[0].revents & POLLIN) { - /* activity on control pipe, read the byte and exit */ - nb = read(udev_control_pipe[0], &dummy, sizeof(dummy)); - if (nb <= 0) { - usbi_warn(NULL, "udev control pipe read failed"); - } - break; - } - if (fds[1].revents & POLLIN) { - usbi_mutex_static_lock(&linux_hotplug_lock); - udev_dev = udev_monitor_receive_device(udev_monitor); - if (udev_dev) - udev_hotplug_event(udev_dev); - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - } - - usbi_dbg("udev event thread exiting"); - - return NULL; -} - -static int udev_device_info(struct libusb_context *ctx, int detached, - struct udev_device *udev_dev, uint8_t *busnum, - uint8_t *devaddr, const char **sys_name) { - const char *dev_node; - - dev_node = udev_device_get_devnode(udev_dev); - if (!dev_node) { - return LIBUSB_ERROR_OTHER; - } - - *sys_name = udev_device_get_sysname(udev_dev); - if (!*sys_name) { - return LIBUSB_ERROR_OTHER; - } - - return linux_get_device_address(ctx, detached, busnum, devaddr, - dev_node, *sys_name); -} - -static void udev_hotplug_event(struct udev_device* udev_dev) -{ - const char* udev_action; - const char* sys_name = NULL; - uint8_t busnum = 0, devaddr = 0; - int detached; - int r; - - do { - udev_action = udev_device_get_action(udev_dev); - if (!udev_action) { - break; - } - - detached = !strncmp(udev_action, "remove", 6); - - r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name); - if (LIBUSB_SUCCESS != r) { - break; - } - - usbi_dbg("udev hotplug event. action: %s.", udev_action); - - if (strncmp(udev_action, "add", 3) == 0) { - linux_hotplug_enumerate(busnum, devaddr, sys_name); - } else if (detached) { - linux_device_disconnected(busnum, devaddr); - } else { - usbi_err(NULL, "ignoring udev action %s", udev_action); - } - } while (0); - - udev_device_unref(udev_dev); -} - -int linux_udev_scan_devices(struct libusb_context *ctx) -{ - struct udev_enumerate *enumerator; - struct udev_list_entry *devices, *entry; - struct udev_device *udev_dev; - const char *sys_name; - int r; - - assert(udev_ctx != NULL); - - enumerator = udev_enumerate_new(udev_ctx); - if (NULL == enumerator) { - usbi_err(ctx, "error creating udev enumerator"); - return LIBUSB_ERROR_OTHER; - } - - udev_enumerate_add_match_subsystem(enumerator, "usb"); - udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device"); - udev_enumerate_scan_devices(enumerator); - devices = udev_enumerate_get_list_entry(enumerator); - - entry = NULL; - udev_list_entry_foreach(entry, devices) { - const char *path = udev_list_entry_get_name(entry); - uint8_t busnum = 0, devaddr = 0; - - udev_dev = udev_device_new_from_syspath(udev_ctx, path); - - r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name); - if (r) { - udev_device_unref(udev_dev); - continue; - } - - linux_enumerate_device(ctx, busnum, devaddr, sys_name); - udev_device_unref(udev_dev); - } - - udev_enumerate_unref(enumerator); - - return LIBUSB_SUCCESS; -} - -void linux_udev_hotplug_poll(void) -{ - struct udev_device* udev_dev; - - usbi_mutex_static_lock(&linux_hotplug_lock); - do { - udev_dev = udev_monitor_receive_device(udev_monitor); - if (udev_dev) { - usbi_dbg("Handling hotplug event from hotplug_poll"); - udev_hotplug_event(udev_dev); - } - } while (udev_dev); - usbi_mutex_static_unlock(&linux_hotplug_lock); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c deleted file mode 100644 index 768e7d5a64..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c +++ /dev/null @@ -1,2800 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * Copyright © 2013 Nathan Hjelm - * Copyright © 2012-2013 Hans de Goede - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -/* sysfs vs usbfs: - * opening a usbfs node causes the device to be resumed, so we attempt to - * avoid this during enumeration. - * - * sysfs allows us to read the kernel's in-memory copies of device descriptors - * and so forth, avoiding the need to open the device: - * - The binary "descriptors" file contains all config descriptors since - * 2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed - * - The binary "descriptors" file was added in 2.6.23, commit - * 69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the - * active config descriptors - * - The "busnum" file was added in 2.6.22, commit - * 83f7d958eab2fbc6b159ee92bf1493924e1d0f72 - * - The "devnum" file has been present since pre-2.6.18 - * - the "bConfigurationValue" file has been present since pre-2.6.18 - * - * If we have bConfigurationValue, busnum, and devnum, then we can determine - * the active configuration without having to open the usbfs node in RDWR mode. - * The busnum file is important as that is the only way we can relate sysfs - * devices to usbfs nodes. - * - * If we also have all descriptors, we can obtain the device descriptor and - * configuration without touching usbfs at all. - */ - -/* endianness for multi-byte fields: - * - * Descriptors exposed by usbfs have the multi-byte fields in the device - * descriptor as host endian. Multi-byte fields in the other descriptors are - * bus-endian. The kernel documentation says otherwise, but it is wrong. - * - * In sysfs all descriptors are bus-endian. - */ - -static const char *usbfs_path = NULL; - -/* use usbdev*.* device names in /dev instead of the usbfs bus directories */ -static int usbdev_names = 0; - -/* Linux has changed the maximum length of an individual isochronous packet - * over time. Initially this limit was 1,023 bytes, but Linux 2.6.18 - * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to - * 8,192 bytes to support higher bandwidth devices. Linux 3.10 - * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this - * value to 49,152 bytes to support super speed devices. - */ -static unsigned int max_iso_packet_len = 0; - -/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the - * close-on-exec flag in the underlying file descriptor. */ -static int supports_flag_cloexec = -1; - -/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically - * allows us to mark URBs as being part of a specific logical transfer when - * we submit them to the kernel. then, on any error except a cancellation, all - * URBs within that transfer will be cancelled and no more URBs will be - * accepted for the transfer, meaning that no more data can creep in. - * - * The BULK_CONTINUATION flag must be set on all URBs within a bulk transfer - * (in either direction) except the first. - * For IN transfers, we must also set SHORT_NOT_OK on all URBs except the - * last; it means that the kernel should treat a short reply as an error. - * For OUT transfers, SHORT_NOT_OK must not be set. it isn't needed (OUT - * transfers can't be short unless there's already some sort of error), and - * setting this flag is disallowed (a kernel with USB debugging enabled will - * reject such URBs). - */ -static int supports_flag_bulk_continuation = -1; - -/* Linux 2.6.31 fixes support for the zero length packet URB flag. This - * allows us to mark URBs that should be followed by a zero length data - * packet, which can be required by device- or class-specific protocols. - */ -static int supports_flag_zero_packet = -1; - -/* clock ID for monotonic clock, as not all clock sources are available on all - * systems. appropriate choice made at initialization time. */ -static clockid_t monotonic_clkid = -1; - -/* Linux 2.6.22 (commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72) adds a busnum - * to sysfs, so we can relate devices. This also implies that we can read - * the active configuration through bConfigurationValue */ -static int sysfs_can_relate_devices = -1; - -/* Linux 2.6.26 (commit 217a9081d8e69026186067711131b77f0ce219ed) adds all - * config descriptors (rather then just the active config) to the sysfs - * descriptors file, so from then on we can use them. */ -static int sysfs_has_descriptors = -1; - -/* how many times have we initted (and not exited) ? */ -static int init_count = 0; - -/* Serialize hotplug start/stop */ -static usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER; -/* Serialize scan-devices, event-thread, and poll */ -usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER; - -static int linux_start_event_monitor(void); -static int linux_stop_event_monitor(void); -static int linux_scan_devices(struct libusb_context *ctx); -static int sysfs_scan_device(struct libusb_context *ctx, const char *devname); -static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int); - -#if !defined(USE_UDEV) -static int linux_default_scan_devices (struct libusb_context *ctx); -#endif - -struct kernel_version { - int major; - int minor; - int sublevel; -}; - -struct linux_device_priv { - char *sysfs_dir; - unsigned char *descriptors; - int descriptors_len; - int active_config; /* cache val for !sysfs_can_relate_devices */ -}; - -struct linux_device_handle_priv { - int fd; - int fd_removed; - uint32_t caps; -}; - -enum reap_action { - NORMAL = 0, - /* submission failed after the first URB, so await cancellation/completion - * of all the others */ - SUBMIT_FAILED, - - /* cancelled by user or timeout */ - CANCELLED, - - /* completed multi-URB transfer in non-final URB */ - COMPLETED_EARLY, - - /* one or more urbs encountered a low-level error */ - ERROR, -}; - -struct linux_transfer_priv { - union { - struct usbfs_urb *urbs; - struct usbfs_urb **iso_urbs; - }; - - enum reap_action reap_action; - int num_urbs; - int num_retired; - enum libusb_transfer_status reap_status; - - /* next iso packet in user-supplied transfer to be populated */ - int iso_packet_offset; -}; - -static int _open(const char *path, int flags) -{ -#if defined(O_CLOEXEC) - if (supports_flag_cloexec) - return open(path, flags | O_CLOEXEC); - else -#endif - return open(path, flags); -} - -static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - char path[PATH_MAX]; - int fd; - int delay = 10000; - - if (usbdev_names) - snprintf(path, PATH_MAX, "%s/usbdev%d.%d", - usbfs_path, dev->bus_number, dev->device_address); - else - snprintf(path, PATH_MAX, "%s/%03d/%03d", - usbfs_path, dev->bus_number, dev->device_address); - - fd = _open(path, mode); - if (fd != -1) - return fd; /* Success */ - - if (errno == ENOENT) { - if (!silent) - usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000); - - /* Wait 10ms for USB device path creation.*/ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - - fd = _open(path, mode); - if (fd != -1) - return fd; /* Success */ - } - - if (!silent) { - usbi_err(ctx, "libusb couldn't open USB device %s: %s", - path, strerror(errno)); - if (errno == EACCES && mode == O_RDWR) - usbi_err(ctx, "libusb requires write access to USB " - "device nodes."); - } - - if (errno == EACCES) - return LIBUSB_ERROR_ACCESS; - if (errno == ENOENT) - return LIBUSB_ERROR_NO_DEVICE; - return LIBUSB_ERROR_IO; -} - -static struct linux_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct linux_device_priv *) dev->os_priv; -} - -static struct linux_device_handle_priv *_device_handle_priv( - struct libusb_device_handle *handle) -{ - return (struct linux_device_handle_priv *) handle->os_priv; -} - -/* check dirent for a /dev/usbdev%d.%d name - * optionally return bus/device on success */ -static int _is_usbdev_entry(struct dirent *entry, int *bus_p, int *dev_p) -{ - int busnum, devnum; - - if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2) - return 0; - - usbi_dbg("found: %s", entry->d_name); - if (bus_p != NULL) - *bus_p = busnum; - if (dev_p != NULL) - *dev_p = devnum; - return 1; -} - -static int check_usb_vfs(const char *dirname) -{ - DIR *dir; - struct dirent *entry; - int found = 0; - - dir = opendir(dirname); - if (!dir) - return 0; - - while ((entry = readdir(dir)) != NULL) { - if (entry->d_name[0] == '.') - continue; - - /* We assume if we find any files that it must be the right place */ - found = 1; - break; - } - - closedir(dir); - return found; -} - -static const char *find_usbfs_path(void) -{ - const char *path = "/dev/bus/usb"; - const char *ret = NULL; - - if (check_usb_vfs(path)) { - ret = path; - } else { - path = "/proc/bus/usb"; - if (check_usb_vfs(path)) - ret = path; - } - - /* look for /dev/usbdev*.* if the normal places fail */ - if (ret == NULL) { - struct dirent *entry; - DIR *dir; - - path = "/dev"; - dir = opendir(path); - if (dir != NULL) { - while ((entry = readdir(dir)) != NULL) { - if (_is_usbdev_entry(entry, NULL, NULL)) { - /* found one; that's enough */ - ret = path; - usbdev_names = 1; - break; - } - } - closedir(dir); - } - } - -/* On udev based systems without any usb-devices /dev/bus/usb will not - * exist. So if we've not found anything and we're using udev for hotplug - * simply assume /dev/bus/usb rather then making libusb_init fail. */ -#if defined(USE_UDEV) - if (ret == NULL) - ret = "/dev/bus/usb"; -#endif - - if (ret != NULL) - usbi_dbg("found usbfs at %s", ret); - - return ret; -} - -/* the monotonic clock is not usable on all systems (e.g. embedded ones often - * seem to lack it). fall back to REALTIME if we have to. */ -static clockid_t find_monotonic_clock(void) -{ -#ifdef CLOCK_MONOTONIC - struct timespec ts; - int r; - - /* Linux 2.6.28 adds CLOCK_MONOTONIC_RAW but we don't use it - * because it's not available through timerfd */ - r = clock_gettime(CLOCK_MONOTONIC, &ts); - if (r == 0) - return CLOCK_MONOTONIC; - usbi_dbg("monotonic clock doesn't work, errno %d", errno); -#endif - - return CLOCK_REALTIME; -} - -static int get_kernel_version(struct libusb_context *ctx, - struct kernel_version *ver) -{ - struct utsname uts; - int atoms; - - if (uname(&uts) < 0) { - usbi_err(ctx, "uname failed, errno %d", errno); - return -1; - } - - atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel); - if (atoms < 1) { - usbi_err(ctx, "failed to parse uname release '%s'", uts.release); - return -1; - } - - if (atoms < 2) - ver->minor = -1; - if (atoms < 3) - ver->sublevel = -1; - - usbi_dbg("reported kernel version is %s", uts.release); - - return 0; -} - -static int kernel_version_ge(const struct kernel_version *ver, - int major, int minor, int sublevel) -{ - if (ver->major > major) - return 1; - else if (ver->major < major) - return 0; - - /* kmajor == major */ - if (ver->minor == -1 && ver->sublevel == -1) - return 0 == minor && 0 == sublevel; - else if (ver->minor > minor) - return 1; - else if (ver->minor < minor) - return 0; - - /* kminor == minor */ - if (ver->sublevel == -1) - return 0 == sublevel; - - return ver->sublevel >= sublevel; -} - -static int op_init(struct libusb_context *ctx) -{ - struct kernel_version kversion; - struct stat statbuf; - int r; - - usbfs_path = find_usbfs_path(); - if (!usbfs_path) { - usbi_err(ctx, "could not find usbfs"); - return LIBUSB_ERROR_OTHER; - } - - if (monotonic_clkid == -1) - monotonic_clkid = find_monotonic_clock(); - - if (get_kernel_version(ctx, &kversion) < 0) - return LIBUSB_ERROR_OTHER; - - if (supports_flag_cloexec == -1) { - /* O_CLOEXEC flag available from Linux 2.6.23 */ - supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23); - } - - if (supports_flag_bulk_continuation == -1) { - /* bulk continuation URB flag available from Linux 2.6.32 */ - supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32); - } - - if (supports_flag_bulk_continuation) - usbi_dbg("bulk continuation flag supported"); - - if (-1 == supports_flag_zero_packet) { - /* zero length packet URB flag fixed since Linux 2.6.31 */ - supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31); - } - - if (supports_flag_zero_packet) - usbi_dbg("zero length packet flag supported"); - - if (!max_iso_packet_len) { - if (kernel_version_ge(&kversion,3,10,0)) - max_iso_packet_len = 49152; - else if (kernel_version_ge(&kversion,2,6,18)) - max_iso_packet_len = 8192; - else - max_iso_packet_len = 1023; - } - - usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len); - - if (-1 == sysfs_has_descriptors) { - /* sysfs descriptors has all descriptors since Linux 2.6.26 */ - sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26); - } - - if (-1 == sysfs_can_relate_devices) { - /* sysfs has busnum since Linux 2.6.22 */ - sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22); - } - - if (sysfs_can_relate_devices || sysfs_has_descriptors) { - r = stat(SYSFS_DEVICE_PATH, &statbuf); - if (r != 0 || !S_ISDIR(statbuf.st_mode)) { - usbi_warn(ctx, "sysfs not mounted"); - sysfs_can_relate_devices = 0; - sysfs_has_descriptors = 0; - } - } - - if (sysfs_can_relate_devices) - usbi_dbg("sysfs can relate devices"); - - if (sysfs_has_descriptors) - usbi_dbg("sysfs has complete descriptors"); - - usbi_mutex_static_lock(&linux_hotplug_startstop_lock); - r = LIBUSB_SUCCESS; - if (init_count == 0) { - /* start up hotplug event handler */ - r = linux_start_event_monitor(); - } - if (r == LIBUSB_SUCCESS) { - r = linux_scan_devices(ctx); - if (r == LIBUSB_SUCCESS) - init_count++; - else if (init_count == 0) - linux_stop_event_monitor(); - } else - usbi_err(ctx, "error starting hotplug event monitor"); - usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); - - return r; -} - -static void op_exit(struct libusb_context *ctx) -{ - UNUSED(ctx); - usbi_mutex_static_lock(&linux_hotplug_startstop_lock); - assert(init_count != 0); - if (!--init_count) { - /* tear down event handler */ - (void)linux_stop_event_monitor(); - } - usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); -} - -static int linux_start_event_monitor(void) -{ -#if defined(USE_UDEV) - return linux_udev_start_event_monitor(); -#else - return linux_netlink_start_event_monitor(); -#endif -} - -static int linux_stop_event_monitor(void) -{ -#if defined(USE_UDEV) - return linux_udev_stop_event_monitor(); -#else - return linux_netlink_stop_event_monitor(); -#endif -} - -static int linux_scan_devices(struct libusb_context *ctx) -{ - int ret; - - usbi_mutex_static_lock(&linux_hotplug_lock); - -#if defined(USE_UDEV) - ret = linux_udev_scan_devices(ctx); -#else - ret = linux_default_scan_devices(ctx); -#endif - - usbi_mutex_static_unlock(&linux_hotplug_lock); - - return ret; -} - -static void op_hotplug_poll(void) -{ -#if defined(USE_UDEV) - linux_udev_hotplug_poll(); -#else - linux_netlink_hotplug_poll(); -#endif -} - -static int _open_sysfs_attr(struct libusb_device *dev, const char *attr) -{ - struct linux_device_priv *priv = _device_priv(dev); - char filename[PATH_MAX]; - int fd; - - snprintf(filename, PATH_MAX, "%s/%s/%s", - SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); - fd = _open(filename, O_RDONLY); - if (fd < 0) { - usbi_err(DEVICE_CTX(dev), - "open %s failed ret=%d errno=%d", filename, fd, errno); - return LIBUSB_ERROR_IO; - } - - return fd; -} - -/* Note only suitable for attributes which always read >= 0, < 0 is error */ -static int __read_sysfs_attr(struct libusb_context *ctx, - const char *devname, const char *attr) -{ - char filename[PATH_MAX]; - FILE *f; - int fd, r, value; - - snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, - devname, attr); - fd = _open(filename, O_RDONLY); - if (fd == -1) { - if (errno == ENOENT) { - /* File doesn't exist. Assume the device has been - disconnected (see trac ticket #70). */ - return LIBUSB_ERROR_NO_DEVICE; - } - usbi_err(ctx, "open %s failed errno=%d", filename, errno); - return LIBUSB_ERROR_IO; - } - - f = fdopen(fd, "r"); - if (f == NULL) { - usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno); - close(fd); - return LIBUSB_ERROR_OTHER; - } - - r = fscanf(f, "%d", &value); - fclose(f); - if (r != 1) { - usbi_err(ctx, "fscanf %s returned %d, errno=%d", attr, r, errno); - return LIBUSB_ERROR_NO_DEVICE; /* For unplug race (trac #70) */ - } - if (value < 0) { - usbi_err(ctx, "%s contains a negative value", filename); - return LIBUSB_ERROR_IO; - } - - return value; -} - -static int op_get_device_descriptor(struct libusb_device *dev, - unsigned char *buffer, int *host_endian) -{ - struct linux_device_priv *priv = _device_priv(dev); - - *host_endian = sysfs_has_descriptors ? 0 : 1; - memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH); - - return 0; -} - -/* read the bConfigurationValue for a device */ -static int sysfs_get_active_config(struct libusb_device *dev, int *config) -{ - char *endptr; - char tmp[5] = {0, 0, 0, 0, 0}; - long num; - int fd; - ssize_t r; - - fd = _open_sysfs_attr(dev, "bConfigurationValue"); - if (fd < 0) - return fd; - - r = read(fd, tmp, sizeof(tmp)); - close(fd); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "read bConfigurationValue failed ret=%d errno=%d", r, errno); - return LIBUSB_ERROR_IO; - } else if (r == 0) { - usbi_dbg("device unconfigured"); - *config = -1; - return 0; - } - - if (tmp[sizeof(tmp) - 1] != 0) { - usbi_err(DEVICE_CTX(dev), "not null-terminated?"); - return LIBUSB_ERROR_IO; - } else if (tmp[0] == 0) { - usbi_err(DEVICE_CTX(dev), "no configuration value?"); - return LIBUSB_ERROR_IO; - } - - num = strtol(tmp, &endptr, 10); - if (endptr == tmp) { - usbi_err(DEVICE_CTX(dev), "error converting '%s' to integer", tmp); - return LIBUSB_ERROR_IO; - } - - *config = (int) num; - return 0; -} - -int linux_get_device_address (struct libusb_context *ctx, int detached, - uint8_t *busnum, uint8_t *devaddr,const char *dev_node, - const char *sys_name) -{ - int sysfs_attr; - - usbi_dbg("getting address for device: %s detached: %d", sys_name, detached); - /* can't use sysfs to read the bus and device number if the - * device has been detached */ - if (!sysfs_can_relate_devices || detached || NULL == sys_name) { - if (NULL == dev_node) { - return LIBUSB_ERROR_OTHER; - } - - /* will this work with all supported kernel versions? */ - if (!strncmp(dev_node, "/dev/bus/usb", 12)) { - sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr); - } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { - sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr); - } - - return LIBUSB_SUCCESS; - } - - usbi_dbg("scan %s", sys_name); - - sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum"); - if (0 > sysfs_attr) - return sysfs_attr; - if (sysfs_attr > 255) - return LIBUSB_ERROR_INVALID_PARAM; - *busnum = (uint8_t) sysfs_attr; - - sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum"); - if (0 > sysfs_attr) - return sysfs_attr; - if (sysfs_attr > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - *devaddr = (uint8_t) sysfs_attr; - - usbi_dbg("bus=%d dev=%d", *busnum, *devaddr); - - return LIBUSB_SUCCESS; -} - -/* Return offset of the next descriptor with the given type */ -static int seek_to_next_descriptor(struct libusb_context *ctx, - uint8_t descriptor_type, unsigned char *buffer, int size) -{ - struct usb_descriptor_header header; - int i; - - for (i = 0; size >= 0; i += header.bLength, size -= header.bLength) { - if (size == 0) - return LIBUSB_ERROR_NOT_FOUND; - - if (size < 2) { - usbi_err(ctx, "short descriptor read %d/2", size); - return LIBUSB_ERROR_IO; - } - usbi_parse_descriptor(buffer + i, "bb", &header, 0); - - if (i && header.bDescriptorType == descriptor_type) - return i; - } - usbi_err(ctx, "bLength overflow by %d bytes", -size); - return LIBUSB_ERROR_IO; -} - -/* Return offset to next config */ -static int seek_to_next_config(struct libusb_context *ctx, - unsigned char *buffer, int size) -{ - struct libusb_config_descriptor config; - - if (size == 0) - return LIBUSB_ERROR_NOT_FOUND; - - if (size < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "short descriptor read %d/%d", - size, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwbbbbb", &config, 0); - if (config.bDescriptorType != LIBUSB_DT_CONFIG) { - usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)", - config.bDescriptorType); - return LIBUSB_ERROR_IO; - } - - /* - * In usbfs the config descriptors are config.wTotalLength bytes apart, - * with any short reads from the device appearing as holes in the file. - * - * In sysfs wTotalLength is ignored, instead the kernel returns a - * config descriptor with verified bLength fields, with descriptors - * with an invalid bLength removed. - */ - if (sysfs_has_descriptors) { - int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG, - buffer, size); - if (next == LIBUSB_ERROR_NOT_FOUND) - next = size; - if (next < 0) - return next; - - if (next != config.wTotalLength) - usbi_warn(ctx, "config length mismatch wTotalLength " - "%d real %d", config.wTotalLength, next); - return next; - } else { - if (config.wTotalLength < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "invalid wTotalLength %d", - config.wTotalLength); - return LIBUSB_ERROR_IO; - } else if (config.wTotalLength > size) { - usbi_warn(ctx, "short descriptor read %d/%d", - size, config.wTotalLength); - return size; - } else - return config.wTotalLength; - } -} - -static int op_get_config_descriptor_by_value(struct libusb_device *dev, - uint8_t value, unsigned char **buffer, int *host_endian) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct linux_device_priv *priv = _device_priv(dev); - unsigned char *descriptors = priv->descriptors; - int size = priv->descriptors_len; - struct libusb_config_descriptor *config; - - *buffer = NULL; - /* Unlike the device desc. config descs. are always in raw format */ - *host_endian = 0; - - /* Skip device header */ - descriptors += DEVICE_DESC_LENGTH; - size -= DEVICE_DESC_LENGTH; - - /* Seek till the config is found, or till "EOF" */ - while (1) { - int next = seek_to_next_config(ctx, descriptors, size); - if (next < 0) - return next; - config = (struct libusb_config_descriptor *)descriptors; - if (config->bConfigurationValue == value) { - *buffer = descriptors; - return next; - } - size -= next; - descriptors += next; - } -} - -static int op_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buffer, size_t len, int *host_endian) -{ - int r, config; - unsigned char *config_desc; - - if (sysfs_can_relate_devices) { - r = sysfs_get_active_config(dev, &config); - if (r < 0) - return r; - } else { - /* Use cached bConfigurationValue */ - struct linux_device_priv *priv = _device_priv(dev); - config = priv->active_config; - } - if (config == -1) - return LIBUSB_ERROR_NOT_FOUND; - - r = op_get_config_descriptor_by_value(dev, config, &config_desc, - host_endian); - if (r < 0) - return r; - - len = MIN(len, (size_t)r); - memcpy(buffer, config_desc, len); - return len; -} - -static int op_get_config_descriptor(struct libusb_device *dev, - uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct linux_device_priv *priv = _device_priv(dev); - unsigned char *descriptors = priv->descriptors; - int i, r, size = priv->descriptors_len; - - /* Unlike the device desc. config descs. are always in raw format */ - *host_endian = 0; - - /* Skip device header */ - descriptors += DEVICE_DESC_LENGTH; - size -= DEVICE_DESC_LENGTH; - - /* Seek till the config is found, or till "EOF" */ - for (i = 0; ; i++) { - r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size); - if (r < 0) - return r; - if (i == config_index) - break; - size -= r; - descriptors += r; - } - - len = MIN(len, (size_t)r); - memcpy(buffer, descriptors, len); - return len; -} - -/* send a control message to retrieve active configuration */ -static int usbfs_get_active_config(struct libusb_device *dev, int fd) -{ - struct linux_device_priv *priv = _device_priv(dev); - unsigned char active_config = 0; - int r; - - struct usbfs_ctrltransfer ctrl = { - .bmRequestType = LIBUSB_ENDPOINT_IN, - .bRequest = LIBUSB_REQUEST_GET_CONFIGURATION, - .wValue = 0, - .wIndex = 0, - .wLength = 1, - .timeout = 1000, - .data = &active_config - }; - - r = ioctl(fd, IOCTL_USBFS_CONTROL, &ctrl); - if (r < 0) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - /* we hit this error path frequently with buggy devices :( */ - usbi_warn(DEVICE_CTX(dev), - "get_configuration failed ret=%d errno=%d", r, errno); - priv->active_config = -1; - } else { - if (active_config > 0) { - priv->active_config = active_config; - } else { - /* some buggy devices have a configuration 0, but we're - * reaching into the corner of a corner case here, so let's - * not support buggy devices in these circumstances. - * stick to the specs: a configuration value of 0 means - * unconfigured. */ - usbi_warn(DEVICE_CTX(dev), - "active cfg 0? assuming unconfigured device"); - priv->active_config = -1; - } - } - - return LIBUSB_SUCCESS; -} - -static int initialize_device(struct libusb_device *dev, uint8_t busnum, - uint8_t devaddr, const char *sysfs_dir) -{ - struct linux_device_priv *priv = _device_priv(dev); - struct libusb_context *ctx = DEVICE_CTX(dev); - int descriptors_size = 512; /* Begin with a 1024 byte alloc */ - int fd, speed; - ssize_t r; - - dev->bus_number = busnum; - dev->device_address = devaddr; - - if (sysfs_dir) { - priv->sysfs_dir = strdup(sysfs_dir); - if (!priv->sysfs_dir) - return LIBUSB_ERROR_NO_MEM; - - /* Note speed can contain 1.5, in this case __read_sysfs_attr - will stop parsing at the '.' and return 1 */ - speed = __read_sysfs_attr(DEVICE_CTX(dev), sysfs_dir, "speed"); - if (speed >= 0) { - switch (speed) { - case 1: dev->speed = LIBUSB_SPEED_LOW; break; - case 12: dev->speed = LIBUSB_SPEED_FULL; break; - case 480: dev->speed = LIBUSB_SPEED_HIGH; break; - case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; - case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; - default: - usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); - } - } - } - - /* cache descriptors in memory */ - if (sysfs_has_descriptors) - fd = _open_sysfs_attr(dev, "descriptors"); - else - fd = _get_usbfs_fd(dev, O_RDONLY, 0); - if (fd < 0) - return fd; - - do { - descriptors_size *= 2; - priv->descriptors = usbi_reallocf(priv->descriptors, - descriptors_size); - if (!priv->descriptors) { - close(fd); - return LIBUSB_ERROR_NO_MEM; - } - /* usbfs has holes in the file */ - if (!sysfs_has_descriptors) { - memset(priv->descriptors + priv->descriptors_len, - 0, descriptors_size - priv->descriptors_len); - } - r = read(fd, priv->descriptors + priv->descriptors_len, - descriptors_size - priv->descriptors_len); - if (r < 0) { - usbi_err(ctx, "read descriptor failed ret=%d errno=%d", - fd, errno); - close(fd); - return LIBUSB_ERROR_IO; - } - priv->descriptors_len += r; - } while (priv->descriptors_len == descriptors_size); - - close(fd); - - if (priv->descriptors_len < DEVICE_DESC_LENGTH) { - usbi_err(ctx, "short descriptor read (%d)", - priv->descriptors_len); - return LIBUSB_ERROR_IO; - } - - if (sysfs_can_relate_devices) - return LIBUSB_SUCCESS; - - /* cache active config */ - fd = _get_usbfs_fd(dev, O_RDWR, 1); - if (fd < 0) { - /* cannot send a control message to determine the active - * config. just assume the first one is active. */ - usbi_warn(ctx, "Missing rw usbfs access; cannot determine " - "active configuration descriptor"); - if (priv->descriptors_len >= - (DEVICE_DESC_LENGTH + LIBUSB_DT_CONFIG_SIZE)) { - struct libusb_config_descriptor config; - usbi_parse_descriptor( - priv->descriptors + DEVICE_DESC_LENGTH, - "bbwbbbbb", &config, 0); - priv->active_config = config.bConfigurationValue; - } else - priv->active_config = -1; /* No config dt */ - - return LIBUSB_SUCCESS; - } - - r = usbfs_get_active_config(dev, fd); - close(fd); - - return r; -} - -static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct libusb_device *it; - char *parent_sysfs_dir, *tmp; - int ret, add_parent = 1; - - /* XXX -- can we figure out the topology when using usbfs? */ - if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) { - /* either using usbfs or finding the parent of a root hub */ - return LIBUSB_SUCCESS; - } - - parent_sysfs_dir = strdup(sysfs_dir); - if (NULL == parent_sysfs_dir) { - return LIBUSB_ERROR_NO_MEM; - } - if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) || - NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) { - dev->port_number = atoi(tmp + 1); - *tmp = '\0'; - } else { - usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info", - parent_sysfs_dir); - free (parent_sysfs_dir); - return LIBUSB_SUCCESS; - } - - /* is the parent a root hub? */ - if (NULL == strchr(parent_sysfs_dir, '-')) { - tmp = parent_sysfs_dir; - ret = asprintf (&parent_sysfs_dir, "usb%s", tmp); - free (tmp); - if (0 > ret) { - return LIBUSB_ERROR_NO_MEM; - } - } - -retry: - /* find the parent in the context */ - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) { - struct linux_device_priv *priv = _device_priv(it); - if (priv->sysfs_dir) { - if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { - dev->parent_dev = libusb_ref_device(it); - break; - } - } - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - if (!dev->parent_dev && add_parent) { - usbi_dbg("parent_dev %s not enumerated yet, enumerating now", - parent_sysfs_dir); - sysfs_scan_device(ctx, parent_sysfs_dir); - add_parent = 0; - goto retry; - } - - usbi_dbg("Dev %p (%s) has parent %p (%s) port %d", dev, sysfs_dir, - dev->parent_dev, parent_sysfs_dir, dev->port_number); - - free (parent_sysfs_dir); - - return LIBUSB_SUCCESS; -} - -int linux_enumerate_device(struct libusb_context *ctx, - uint8_t busnum, uint8_t devaddr, const char *sysfs_dir) -{ - unsigned long session_id; - struct libusb_device *dev; - int r = 0; - - /* FIXME: session ID is not guaranteed unique as addresses can wrap and - * will be reused. instead we should add a simple sysfs attribute with - * a session ID. */ - session_id = busnum << 8 | devaddr; - usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr, - session_id); - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - /* device already exists in the context */ - usbi_dbg("session_id %ld already exists", session_id); - libusb_unref_device(dev); - return LIBUSB_SUCCESS; - } - - usbi_dbg("allocating new device for %d/%d (session %ld)", - busnum, devaddr, session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) - return LIBUSB_ERROR_NO_MEM; - - r = initialize_device(dev, busnum, devaddr, sysfs_dir); - if (r < 0) - goto out; - r = usbi_sanitize_device(dev); - if (r < 0) - goto out; - - r = linux_get_parent_info(dev, sysfs_dir); - if (r < 0) - goto out; -out: - if (r < 0) - libusb_unref_device(dev); - else - usbi_connect_device(dev); - - return r; -} - -void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name) -{ - struct libusb_context *ctx; - - usbi_mutex_static_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - linux_enumerate_device(ctx, busnum, devaddr, sys_name); - } - usbi_mutex_static_unlock(&active_contexts_lock); -} - -void linux_device_disconnected(uint8_t busnum, uint8_t devaddr) -{ - struct libusb_context *ctx; - struct libusb_device *dev; - unsigned long session_id = busnum << 8 | devaddr; - - usbi_mutex_static_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - dev = usbi_get_device_by_session_id (ctx, session_id); - if (NULL != dev) { - usbi_disconnect_device (dev); - libusb_unref_device(dev); - } else { - usbi_dbg("device not found for session %x", session_id); - } - } - usbi_mutex_static_unlock(&active_contexts_lock); -} - -#if !defined(USE_UDEV) -/* open a bus directory and adds all discovered devices to the context */ -static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum) -{ - DIR *dir; - char dirpath[PATH_MAX]; - struct dirent *entry; - int r = LIBUSB_ERROR_IO; - - snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum); - usbi_dbg("%s", dirpath); - dir = opendir(dirpath); - if (!dir) { - usbi_err(ctx, "opendir '%s' failed, errno=%d", dirpath, errno); - /* FIXME: should handle valid race conditions like hub unplugged - * during directory iteration - this is not an error */ - return r; - } - - while ((entry = readdir(dir))) { - int devaddr; - - if (entry->d_name[0] == '.') - continue; - - devaddr = atoi(entry->d_name); - if (devaddr == 0) { - usbi_dbg("unknown dir entry %s", entry->d_name); - continue; - } - - if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - - r = 0; - } - - closedir(dir); - return r; -} - -static int usbfs_get_device_list(struct libusb_context *ctx) -{ - struct dirent *entry; - DIR *buses = opendir(usbfs_path); - int r = 0; - - if (!buses) { - usbi_err(ctx, "opendir buses failed errno=%d", errno); - return LIBUSB_ERROR_IO; - } - - while ((entry = readdir(buses))) { - int busnum; - - if (entry->d_name[0] == '.') - continue; - - if (usbdev_names) { - int devaddr; - if (!_is_usbdev_entry(entry, &busnum, &devaddr)) - continue; - - r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL); - if (r < 0) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - } else { - busnum = atoi(entry->d_name); - if (busnum == 0) { - usbi_dbg("unknown dir entry %s", entry->d_name); - continue; - } - - r = usbfs_scan_busdir(ctx, busnum); - if (r < 0) - break; - } - } - - closedir(buses); - return r; - -} -#endif - -static int sysfs_scan_device(struct libusb_context *ctx, const char *devname) -{ - uint8_t busnum, devaddr; - int ret; - - ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname); - if (LIBUSB_SUCCESS != ret) { - return ret; - } - - return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff, - devname); -} - -#if !defined(USE_UDEV) -static int sysfs_get_device_list(struct libusb_context *ctx) -{ - DIR *devices = opendir(SYSFS_DEVICE_PATH); - struct dirent *entry; - int num_devices = 0; - int num_enumerated = 0; - - if (!devices) { - usbi_err(ctx, "opendir devices failed errno=%d", errno); - return LIBUSB_ERROR_IO; - } - - while ((entry = readdir(devices))) { - if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3)) - || strchr(entry->d_name, ':')) - continue; - - num_devices++; - - if (sysfs_scan_device(ctx, entry->d_name)) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - - num_enumerated++; - } - - closedir(devices); - - /* successful if at least one device was enumerated or no devices were found */ - if (num_enumerated || !num_devices) - return LIBUSB_SUCCESS; - else - return LIBUSB_ERROR_IO; -} - -static int linux_default_scan_devices (struct libusb_context *ctx) -{ - /* we can retrieve device list and descriptors from sysfs or usbfs. - * sysfs is preferable, because if we use usbfs we end up resuming - * any autosuspended USB devices. however, sysfs is not available - * everywhere, so we need a usbfs fallback too. - * - * as described in the "sysfs vs usbfs" comment at the top of this - * file, sometimes we have sysfs but not enough information to - * relate sysfs devices to usbfs nodes. op_init() determines the - * adequacy of sysfs and sets sysfs_can_relate_devices. - */ - if (sysfs_can_relate_devices != 0) - return sysfs_get_device_list(ctx); - else - return usbfs_get_device_list(ctx); -} -#endif - -static int op_open(struct libusb_device_handle *handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - int r; - - hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); - if (hpriv->fd < 0) { - if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) { - /* device will still be marked as attached if hotplug monitor thread - * hasn't processed remove event yet */ - usbi_mutex_static_lock(&linux_hotplug_lock); - if (handle->dev->attached) { - usbi_dbg("open failed with no device, but device still attached"); - linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address); - } - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - return hpriv->fd; - } - - r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); - if (r < 0) { - if (errno == ENOTTY) - usbi_dbg("getcap not available"); - else - usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno); - hpriv->caps = 0; - if (supports_flag_zero_packet) - hpriv->caps |= USBFS_CAP_ZERO_PACKET; - if (supports_flag_bulk_continuation) - hpriv->caps |= USBFS_CAP_BULK_CONTINUATION; - } - - r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); - if (r < 0) - close(hpriv->fd); - - return r; -} - -static void op_close(struct libusb_device_handle *dev_handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(dev_handle); - /* fd may have already been removed by POLLERR condition in op_handle_events() */ - if (!hpriv->fd_removed) - usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd); - close(hpriv->fd); -} - -static int op_get_configuration(struct libusb_device_handle *handle, - int *config) -{ - int r; - - if (sysfs_can_relate_devices) { - r = sysfs_get_active_config(handle->dev, config); - } else { - r = usbfs_get_active_config(handle->dev, - _device_handle_priv(handle)->fd); - if (r == LIBUSB_SUCCESS) - *config = _device_priv(handle->dev)->active_config; - } - if (r < 0) - return r; - - if (*config == -1) { - usbi_err(HANDLE_CTX(handle), "device unconfigured"); - *config = 0; - } - - return 0; -} - -static int op_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct linux_device_priv *priv = _device_priv(handle->dev); - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_SETCONFIG, &config); - if (r) { - if (errno == EINVAL) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - /* update our cached active config descriptor */ - priv->active_config = config; - - return LIBUSB_SUCCESS; -} - -static int claim_interface(struct libusb_device_handle *handle, int iface) -{ - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface); - if (r) { - if (errno == ENOENT) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "claim interface failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return 0; -} - -static int release_interface(struct libusb_device_handle *handle, int iface) -{ - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface); - if (r) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "release interface failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return 0; -} - -static int op_set_interface(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_setinterface setintf; - int r; - - setintf.interface = iface; - setintf.altsetting = altsetting; - r = ioctl(fd, IOCTL_USBFS_SETINTF, &setintf); - if (r) { - if (errno == EINVAL) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "setintf failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_clear_halt(struct libusb_device_handle *handle, - unsigned char endpoint) -{ - int fd = _device_handle_priv(handle)->fd; - unsigned int _endpoint = endpoint; - int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint); - if (r) { - if (errno == ENOENT) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "clear_halt failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_reset_device(struct libusb_device_handle *handle) -{ - int fd = _device_handle_priv(handle)->fd; - int i, r, ret = 0; - - /* Doing a device reset will cause the usbfs driver to get unbound - from any interfaces it is bound to. By voluntarily unbinding - the usbfs driver ourself, we stop the kernel from rebinding - the interface after reset (which would end up with the interface - getting bound to the in kernel driver if any). */ - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (handle->claimed_interfaces & (1L << i)) { - release_interface(handle, i); - } - } - - usbi_mutex_lock(&handle->lock); - r = ioctl(fd, IOCTL_USBFS_RESET, NULL); - if (r) { - if (errno == ENODEV) { - ret = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - usbi_err(HANDLE_CTX(handle), - "reset failed error %d errno %d", r, errno); - ret = LIBUSB_ERROR_OTHER; - goto out; - } - - /* And re-claim any interfaces which were claimed before the reset */ - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (handle->claimed_interfaces & (1L << i)) { - /* - * A driver may have completed modprobing during - * IOCTL_USBFS_RESET, and bound itself as soon as - * IOCTL_USBFS_RESET released the device lock - */ - r = detach_kernel_driver_and_claim(handle, i); - if (r) { - usbi_warn(HANDLE_CTX(handle), - "failed to re-claim interface %d after reset: %s", - i, libusb_error_name(r)); - handle->claimed_interfaces &= ~(1L << i); - ret = LIBUSB_ERROR_NOT_FOUND; - } - } - } -out: - usbi_mutex_unlock(&handle->lock); - return ret; -} - -static int do_streams_ioctl(struct libusb_device_handle *handle, long req, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - int r, fd = _device_handle_priv(handle)->fd; - struct usbfs_streams *streams; - - if (num_endpoints > 30) /* Max 15 in + 15 out eps */ - return LIBUSB_ERROR_INVALID_PARAM; - - streams = malloc(sizeof(struct usbfs_streams) + num_endpoints); - if (!streams) - return LIBUSB_ERROR_NO_MEM; - - streams->num_streams = num_streams; - streams->num_eps = num_endpoints; - memcpy(streams->eps, endpoints, num_endpoints); - - r = ioctl(fd, req, streams); - - free(streams); - - if (r < 0) { - if (errno == ENOTTY) - return LIBUSB_ERROR_NOT_SUPPORTED; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "streams-ioctl failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return r; -} - -static int op_alloc_streams(struct libusb_device_handle *handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS, - num_streams, endpoints, num_endpoints); -} - -static int op_free_streams(struct libusb_device_handle *handle, - unsigned char *endpoints, int num_endpoints) -{ - return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0, - endpoints, num_endpoints); -} - -static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle, - size_t len) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - unsigned char *buffer = (unsigned char *)mmap(NULL, len, - PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0); - if (buffer == MAP_FAILED) { - usbi_err(HANDLE_CTX(handle), "alloc dev mem failed errno %d", - errno); - return NULL; - } - return buffer; -} - -static int op_dev_mem_free(struct libusb_device_handle *handle, - unsigned char *buffer, size_t len) -{ - if (munmap(buffer, len) != 0) { - usbi_err(HANDLE_CTX(handle), "free dev mem failed errno %d", - errno); - return LIBUSB_ERROR_OTHER; - } else { - return LIBUSB_SUCCESS; - } -} - -static int op_kernel_driver_active(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_getdriver getdrv; - int r; - - getdrv.interface = interface; - r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); - if (r) { - if (errno == ENODATA) - return 0; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "get driver failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1; -} - -static int op_detach_kernel_driver(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_ioctl command; - struct usbfs_getdriver getdrv; - int r; - - command.ifno = interface; - command.ioctl_code = IOCTL_USBFS_DISCONNECT; - command.data = NULL; - - getdrv.interface = interface; - r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); - if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0) - return LIBUSB_ERROR_NOT_FOUND; - - r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); - if (r) { - if (errno == ENODATA) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "detach failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_attach_kernel_driver(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_ioctl command; - int r; - - command.ifno = interface; - command.ioctl_code = IOCTL_USBFS_CONNECT; - command.data = NULL; - - r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); - if (r < 0) { - if (errno == ENODATA) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - - usbi_err(HANDLE_CTX(handle), - "attach failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } else if (r == 0) { - return LIBUSB_ERROR_NOT_FOUND; - } - - return 0; -} - -static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, - int interface) -{ - struct usbfs_disconnect_claim dc; - int r, fd = _device_handle_priv(handle)->fd; - - dc.interface = interface; - strcpy(dc.driver, "usbfs"); - dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; - r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); - if (r != 0 && errno != ENOTTY) { - switch (errno) { - case EBUSY: - return LIBUSB_ERROR_BUSY; - case EINVAL: - return LIBUSB_ERROR_INVALID_PARAM; - case ENODEV: - return LIBUSB_ERROR_NO_DEVICE; - } - usbi_err(HANDLE_CTX(handle), - "disconnect-and-claim failed errno %d", errno); - return LIBUSB_ERROR_OTHER; - } else if (r == 0) - return 0; - - /* Fallback code for kernels which don't support the - disconnect-and-claim ioctl */ - r = op_detach_kernel_driver(handle, interface); - if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND) - return r; - - return claim_interface(handle, interface); -} - -static int op_claim_interface(struct libusb_device_handle *handle, int iface) -{ - if (handle->auto_detach_kernel_driver) - return detach_kernel_driver_and_claim(handle, iface); - else - return claim_interface(handle, iface); -} - -static int op_release_interface(struct libusb_device_handle *handle, int iface) -{ - int r; - - r = release_interface(handle, iface); - if (r) - return r; - - if (handle->auto_detach_kernel_driver) - op_attach_kernel_driver(handle, iface); - - return 0; -} - -static void op_destroy_device(struct libusb_device *dev) -{ - struct linux_device_priv *priv = _device_priv(dev); - if (priv->descriptors) - free(priv->descriptors); - if (priv->sysfs_dir) - free(priv->sysfs_dir); -} - -/* URBs are discarded in reverse order of submission to avoid races. */ -static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = - usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - int i, ret = 0; - struct usbfs_urb *urb; - - for (i = last_plus_one - 1; i >= first; i--) { - if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type) - urb = tpriv->iso_urbs[i]; - else - urb = &tpriv->urbs[i]; - - if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb)) - continue; - - if (EINVAL == errno) { - usbi_dbg("URB not found --> assuming ready to be reaped"); - if (i == (last_plus_one - 1)) - ret = LIBUSB_ERROR_NOT_FOUND; - } else if (ENODEV == errno) { - usbi_dbg("Device not found for URB --> assuming ready to be reaped"); - ret = LIBUSB_ERROR_NO_DEVICE; - } else { - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - ret = LIBUSB_ERROR_OTHER; - } - } - return ret; -} - -static void free_iso_urbs(struct linux_transfer_priv *tpriv) -{ - int i; - for (i = 0; i < tpriv->num_urbs; i++) { - struct usbfs_urb *urb = tpriv->iso_urbs[i]; - if (!urb) - break; - free(urb); - } - - free(tpriv->iso_urbs); - tpriv->iso_urbs = NULL; -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb *urbs; - int is_out = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_OUT; - int bulk_buffer_len, use_bulk_continuation; - int r; - int i; - - if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) && - !(dpriv->caps & USBFS_CAP_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; - - /* - * Older versions of usbfs place a 16kb limit on bulk URBs. We work - * around this by splitting large transfers into 16k blocks, and then - * submit all urbs at once. it would be simpler to submit one urb at - * a time, but there is a big performance gain doing it this way. - * - * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM), - * using arbritary large transfers can still be a bad idea though, as - * the kernel needs to allocate physical contiguous memory for this, - * which may fail for large buffers. - * - * The kernel solves this problem by splitting the transfer into - * blocks itself when the host-controller is scatter-gather capable - * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are. - * - * Last, there is the issue of short-transfers when splitting, for - * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION - * is needed, but this is not always available. - */ - if (dpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) { - /* Good! Just submit everything in one go */ - bulk_buffer_len = transfer->length ? transfer->length : 1; - use_bulk_continuation = 0; - } else if (dpriv->caps & USBFS_CAP_BULK_CONTINUATION) { - /* Split the transfers and use bulk-continuation to - avoid issues with short-transfers */ - bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; - use_bulk_continuation = 1; - } else if (dpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) { - /* Don't split, assume the kernel can alloc the buffer - (otherwise the submit will fail with -ENOMEM) */ - bulk_buffer_len = transfer->length ? transfer->length : 1; - use_bulk_continuation = 0; - } else { - /* Bad, splitting without bulk-continuation, short transfers - which end before the last urb will not work reliable! */ - /* Note we don't warn here as this is "normal" on kernels < - 2.6.32 and not a problem for most applications */ - bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; - use_bulk_continuation = 0; - } - - int num_urbs = transfer->length / bulk_buffer_len; - int last_urb_partial = 0; - - if (transfer->length == 0) { - num_urbs = 1; - } else if ((transfer->length % bulk_buffer_len) > 0) { - last_urb_partial = 1; - num_urbs++; - } - usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, - transfer->length); - urbs = calloc(num_urbs, sizeof(struct usbfs_urb)); - if (!urbs) - return LIBUSB_ERROR_NO_MEM; - tpriv->urbs = urbs; - tpriv->num_urbs = num_urbs; - tpriv->num_retired = 0; - tpriv->reap_action = NORMAL; - tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED; - - for (i = 0; i < num_urbs; i++) { - struct usbfs_urb *urb = &urbs[i]; - urb->usercontext = itransfer; - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - urb->type = USBFS_URB_TYPE_BULK; - urb->stream_id = 0; - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - urb->type = USBFS_URB_TYPE_BULK; - urb->stream_id = itransfer->stream_id; - break; - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - urb->type = USBFS_URB_TYPE_INTERRUPT; - break; - } - urb->endpoint = transfer->endpoint; - urb->buffer = transfer->buffer + (i * bulk_buffer_len); - /* don't set the short not ok flag for the last URB */ - if (use_bulk_continuation && !is_out && (i < num_urbs - 1)) - urb->flags = USBFS_URB_SHORT_NOT_OK; - if (i == num_urbs - 1 && last_urb_partial) - urb->buffer_length = transfer->length % bulk_buffer_len; - else if (transfer->length == 0) - urb->buffer_length = 0; - else - urb->buffer_length = bulk_buffer_len; - - if (i > 0 && use_bulk_continuation) - urb->flags |= USBFS_URB_BULK_CONTINUATION; - - /* we have already checked that the flag is supported */ - if (is_out && i == num_urbs - 1 && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) - urb->flags |= USBFS_URB_ZERO_PACKET; - - r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); - if (r < 0) { - if (errno == ENODEV) { - r = LIBUSB_ERROR_NO_DEVICE; - } else { - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - r = LIBUSB_ERROR_IO; - } - - /* if the first URB submission fails, we can simply free up and - * return failure immediately. */ - if (i == 0) { - usbi_dbg("first URB failed, easy peasy"); - free(urbs); - tpriv->urbs = NULL; - return r; - } - - /* if it's not the first URB that failed, the situation is a bit - * tricky. we may need to discard all previous URBs. there are - * complications: - * - discarding is asynchronous - discarded urbs will be reaped - * later. the user must not have freed the transfer when the - * discarded URBs are reaped, otherwise libusb will be using - * freed memory. - * - the earlier URBs may have completed successfully and we do - * not want to throw away any data. - * - this URB failing may be no error; EREMOTEIO means that - * this transfer simply didn't need all the URBs we submitted - * so, we report that the transfer was submitted successfully and - * in case of error we discard all previous URBs. later when - * the final reap completes we can report error to the user, - * or success if an earlier URB was completed successfully. - */ - tpriv->reap_action = EREMOTEIO == errno ? COMPLETED_EARLY : SUBMIT_FAILED; - - /* The URBs we haven't submitted yet we count as already - * retired. */ - tpriv->num_retired += num_urbs - i; - - /* If we completed short then don't try to discard. */ - if (COMPLETED_EARLY == tpriv->reap_action) - return 0; - - discard_urbs(itransfer, 0, i); - - usbi_dbg("reporting successful submission but waiting for %d " - "discards before reporting error", i); - return 0; - } - } - - return 0; -} - -static int submit_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb **urbs; - int num_packets = transfer->num_iso_packets; - int num_packets_remaining; - int i, j; - int num_urbs; - unsigned int packet_len; - unsigned int total_len = 0; - unsigned char *urb_buffer = transfer->buffer; - - if (num_packets < 1) - return LIBUSB_ERROR_INVALID_PARAM; - - /* usbfs places arbitrary limits on iso URBs. this limit has changed - * at least three times, but we attempt to detect this limit during - * init and check it here. if the kernel rejects the request due to - * its size, we return an error indicating such to the user. - */ - for (i = 0; i < num_packets; i++) { - packet_len = transfer->iso_packet_desc[i].length; - - if (packet_len > max_iso_packet_len) { - usbi_warn(TRANSFER_CTX(transfer), - "iso packet length of %u bytes exceeds maximum of %u bytes", - packet_len, max_iso_packet_len); - return LIBUSB_ERROR_INVALID_PARAM; - } - - total_len += packet_len; - } - - if (transfer->length < (int)total_len) - return LIBUSB_ERROR_INVALID_PARAM; - - /* usbfs limits the number of iso packets per URB */ - num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB; - - usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, - transfer->length); - - urbs = calloc(num_urbs, sizeof(*urbs)); - if (!urbs) - return LIBUSB_ERROR_NO_MEM; - - tpriv->iso_urbs = urbs; - tpriv->num_urbs = num_urbs; - tpriv->num_retired = 0; - tpriv->reap_action = NORMAL; - tpriv->iso_packet_offset = 0; - - /* allocate + initialize each URB with the correct number of packets */ - num_packets_remaining = num_packets; - for (i = 0, j = 0; i < num_urbs; i++) { - int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB); - struct usbfs_urb *urb; - size_t alloc_size; - int k; - - alloc_size = sizeof(*urb) - + (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc)); - urb = calloc(1, alloc_size); - if (!urb) { - free_iso_urbs(tpriv); - return LIBUSB_ERROR_NO_MEM; - } - urbs[i] = urb; - - /* populate packet lengths */ - for (k = 0; k < num_packets_in_urb; j++, k++) { - packet_len = transfer->iso_packet_desc[j].length; - urb->buffer_length += packet_len; - urb->iso_frame_desc[k].length = packet_len; - } - - urb->usercontext = itransfer; - urb->type = USBFS_URB_TYPE_ISO; - /* FIXME: interface for non-ASAP data? */ - urb->flags = USBFS_URB_ISO_ASAP; - urb->endpoint = transfer->endpoint; - urb->number_of_packets = num_packets_in_urb; - urb->buffer = urb_buffer; - - urb_buffer += urb->buffer_length; - num_packets_remaining -= num_packets_in_urb; - } - - /* submit URBs */ - for (i = 0; i < num_urbs; i++) { - int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]); - if (r < 0) { - if (errno == ENODEV) { - r = LIBUSB_ERROR_NO_DEVICE; - } else if (errno == EINVAL) { - usbi_warn(TRANSFER_CTX(transfer), - "submiturb failed, transfer too large"); - r = LIBUSB_ERROR_INVALID_PARAM; - } else if (errno == EMSGSIZE) { - usbi_warn(TRANSFER_CTX(transfer), - "submiturb failed, iso packet length too large"); - r = LIBUSB_ERROR_INVALID_PARAM; - } else { - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - r = LIBUSB_ERROR_IO; - } - - /* if the first URB submission fails, we can simply free up and - * return failure immediately. */ - if (i == 0) { - usbi_dbg("first URB failed, easy peasy"); - free_iso_urbs(tpriv); - return r; - } - - /* if it's not the first URB that failed, the situation is a bit - * tricky. we must discard all previous URBs. there are - * complications: - * - discarding is asynchronous - discarded urbs will be reaped - * later. the user must not have freed the transfer when the - * discarded URBs are reaped, otherwise libusb will be using - * freed memory. - * - the earlier URBs may have completed successfully and we do - * not want to throw away any data. - * so, in this case we discard all the previous URBs BUT we report - * that the transfer was submitted successfully. then later when - * the final discard completes we can report error to the user. - */ - tpriv->reap_action = SUBMIT_FAILED; - - /* The URBs we haven't submitted yet we count as already - * retired. */ - tpriv->num_retired = num_urbs - i; - discard_urbs(itransfer, 0, i); - - usbi_dbg("reporting successful submission but waiting for %d " - "discards before reporting error", i); - return 0; - } - } - - return 0; -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb *urb; - int r; - - if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - urb = calloc(1, sizeof(struct usbfs_urb)); - if (!urb) - return LIBUSB_ERROR_NO_MEM; - tpriv->urbs = urb; - tpriv->num_urbs = 1; - tpriv->reap_action = NORMAL; - - urb->usercontext = itransfer; - urb->type = USBFS_URB_TYPE_CONTROL; - urb->endpoint = transfer->endpoint; - urb->buffer = transfer->buffer; - urb->buffer_length = transfer->length; - - r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); - if (r < 0) { - free(urb); - tpriv->urbs = NULL; - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - return LIBUSB_ERROR_IO; - } - return 0; -} - -static int op_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - default: - usbi_err(TRANSFER_CTX(transfer), - "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int op_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int r; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - r = discard_urbs(itransfer, 0, tpriv->num_urbs); - if (r != 0) - return r; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - if (tpriv->reap_action == ERROR) - break; - /* else, fall through */ - default: - tpriv->reap_action = CANCELLED; - } - - return 0; -} - -static void op_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (tpriv->urbs) { - free(tpriv->urbs); - tpriv->urbs = NULL; - } - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (tpriv->iso_urbs) { - free_iso_urbs(tpriv); - tpriv->iso_urbs = NULL; - } - break; - default: - usbi_err(TRANSFER_CTX(transfer), - "unknown endpoint type %d", transfer->type); - } -} - -static int handle_bulk_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int urb_idx = urb - tpriv->urbs; - - usbi_mutex_lock(&itransfer->lock); - usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, - urb_idx + 1, tpriv->num_urbs); - - tpriv->num_retired++; - - if (tpriv->reap_action != NORMAL) { - /* cancelled, submit_fail, or completed early */ - usbi_dbg("abnormal reap: urb status %d", urb->status); - - /* even though we're in the process of cancelling, it's possible that - * we may receive some data in these URBs that we don't want to lose. - * examples: - * 1. while the kernel is cancelling all the packets that make up an - * URB, a few of them might complete. so we get back a successful - * cancellation *and* some data. - * 2. we receive a short URB which marks the early completion condition, - * so we start cancelling the remaining URBs. however, we're too - * slow and another URB completes (or at least completes partially). - * (this can't happen since we always use BULK_CONTINUATION.) - * - * When this happens, our objectives are not to lose any "surplus" data, - * and also to stick it at the end of the previously-received data - * (closing any holes), so that libusb reports the total amount of - * transferred data and presents it in a contiguous chunk. - */ - if (urb->actual_length > 0) { - unsigned char *target = transfer->buffer + itransfer->transferred; - usbi_dbg("received %d bytes of surplus data", urb->actual_length); - if (urb->buffer != target) { - usbi_dbg("moving surplus data from offset %d to offset %d", - (unsigned char *) urb->buffer - transfer->buffer, - target - transfer->buffer); - memmove(target, urb->buffer, urb->actual_length); - } - itransfer->transferred += urb->actual_length; - } - - if (tpriv->num_retired == tpriv->num_urbs) { - usbi_dbg("abnormal reap: last URB handled, reporting"); - if (tpriv->reap_action != COMPLETED_EARLY && - tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_ERROR; - goto completed; - } - goto out_unlock; - } - - itransfer->transferred += urb->actual_length; - - /* Many of these errors can occur on *any* urb of a multi-urb - * transfer. When they do, we tear down the rest of the transfer. - */ - switch (urb->status) { - case 0: - break; - case -EREMOTEIO: /* short transfer */ - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE; - goto cancel_remaining; - case -EPIPE: - usbi_dbg("detected endpoint stall"); - if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_STALL; - goto cancel_remaining; - case -EOVERFLOW: - /* overflow can only ever occur in the last urb */ - usbi_dbg("overflow, actual_length=%d", urb->actual_length); - if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_OVERFLOW; - goto completed; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - usbi_dbg("low level error %d", urb->status); - tpriv->reap_action = ERROR; - goto cancel_remaining; - default: - usbi_warn(ITRANSFER_CTX(itransfer), - "unrecognised urb status %d", urb->status); - tpriv->reap_action = ERROR; - goto cancel_remaining; - } - - /* if we're the last urb or we got less data than requested then we're - * done */ - if (urb_idx == tpriv->num_urbs - 1) { - usbi_dbg("last URB in transfer --> complete!"); - goto completed; - } else if (urb->actual_length < urb->buffer_length) { - usbi_dbg("short transfer %d/%d --> complete!", - urb->actual_length, urb->buffer_length); - if (tpriv->reap_action == NORMAL) - tpriv->reap_action = COMPLETED_EARLY; - } else - goto out_unlock; - -cancel_remaining: - if (ERROR == tpriv->reap_action && LIBUSB_TRANSFER_COMPLETED == tpriv->reap_status) - tpriv->reap_status = LIBUSB_TRANSFER_ERROR; - - if (tpriv->num_retired == tpriv->num_urbs) /* nothing to cancel */ - goto completed; - - /* cancel remaining urbs and wait for their completion before - * reporting results */ - discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs); - -out_unlock: - usbi_mutex_unlock(&itransfer->lock); - return 0; - -completed: - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return CANCELLED == tpriv->reap_action ? - usbi_handle_transfer_cancellation(itransfer) : - usbi_handle_transfer_completion(itransfer, tpriv->reap_status); -} - -static int handle_iso_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int num_urbs = tpriv->num_urbs; - int urb_idx = 0; - int i; - enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; - - usbi_mutex_lock(&itransfer->lock); - for (i = 0; i < num_urbs; i++) { - if (urb == tpriv->iso_urbs[i]) { - urb_idx = i + 1; - break; - } - } - if (urb_idx == 0) { - usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); - usbi_mutex_unlock(&itransfer->lock); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("handling completion status %d of iso urb %d/%d", urb->status, - urb_idx, num_urbs); - - /* copy isochronous results back in */ - - for (i = 0; i < urb->number_of_packets; i++) { - struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i]; - struct libusb_iso_packet_descriptor *lib_desc = - &transfer->iso_packet_desc[tpriv->iso_packet_offset++]; - lib_desc->status = LIBUSB_TRANSFER_COMPLETED; - switch (urb_desc->status) { - case 0: - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE; - break; - case -EPIPE: - usbi_dbg("detected endpoint stall"); - lib_desc->status = LIBUSB_TRANSFER_STALL; - break; - case -EOVERFLOW: - usbi_dbg("overflow error"); - lib_desc->status = LIBUSB_TRANSFER_OVERFLOW; - break; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - case -EXDEV: - usbi_dbg("low-level USB error %d", urb_desc->status); - lib_desc->status = LIBUSB_TRANSFER_ERROR; - break; - default: - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised urb status %d", urb_desc->status); - lib_desc->status = LIBUSB_TRANSFER_ERROR; - break; - } - lib_desc->actual_length = urb_desc->actual_length; - } - - tpriv->num_retired++; - - if (tpriv->reap_action != NORMAL) { /* cancelled or submit_fail */ - usbi_dbg("CANCEL: urb status %d", urb->status); - - if (tpriv->num_retired == num_urbs) { - usbi_dbg("CANCEL: last URB handled, reporting"); - free_iso_urbs(tpriv); - if (tpriv->reap_action == CANCELLED) { - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_cancellation(itransfer); - } else { - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, - LIBUSB_TRANSFER_ERROR); - } - } - goto out; - } - - switch (urb->status) { - case 0: - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ESHUTDOWN: - usbi_dbg("device removed"); - status = LIBUSB_TRANSFER_NO_DEVICE; - break; - default: - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised urb status %d", urb->status); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - /* if we're the last urb then we're done */ - if (urb_idx == num_urbs) { - usbi_dbg("last URB in transfer --> complete!"); - free_iso_urbs(tpriv); - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); - } - -out: - usbi_mutex_unlock(&itransfer->lock); - return 0; -} - -static int handle_control_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int status; - - usbi_mutex_lock(&itransfer->lock); - usbi_dbg("handling completion status %d", urb->status); - - itransfer->transferred += urb->actual_length; - - if (tpriv->reap_action == CANCELLED) { - if (urb->status != 0 && urb->status != -ENOENT) - usbi_warn(ITRANSFER_CTX(itransfer), - "cancel: unrecognised urb status %d", urb->status); - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_cancellation(itransfer); - } - - switch (urb->status) { - case 0: - status = LIBUSB_TRANSFER_COMPLETED; - break; - case -ENOENT: /* cancelled */ - status = LIBUSB_TRANSFER_CANCELLED; - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - status = LIBUSB_TRANSFER_NO_DEVICE; - break; - case -EPIPE: - usbi_dbg("unsupported control request"); - status = LIBUSB_TRANSFER_STALL; - break; - case -EOVERFLOW: - usbi_dbg("control overflow error"); - status = LIBUSB_TRANSFER_OVERFLOW; - break; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - usbi_dbg("low-level bus error occurred"); - status = LIBUSB_TRANSFER_ERROR; - break; - default: - usbi_warn(ITRANSFER_CTX(itransfer), - "unrecognised urb status %d", urb->status); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); -} - -static int reap_for_handle(struct libusb_device_handle *handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - int r; - struct usbfs_urb *urb; - struct usbi_transfer *itransfer; - struct libusb_transfer *transfer; - - r = ioctl(hpriv->fd, IOCTL_USBFS_REAPURBNDELAY, &urb); - if (r == -1 && errno == EAGAIN) - return 1; - if (r < 0) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d", - r, errno); - return LIBUSB_ERROR_IO; - } - - itransfer = urb->usercontext; - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status, - urb->actual_length); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return handle_iso_completion(itransfer, urb); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return handle_bulk_completion(itransfer, urb); - case LIBUSB_TRANSFER_TYPE_CONTROL: - return handle_control_completion(itransfer, urb); - default: - usbi_err(HANDLE_CTX(handle), "unrecognised endpoint type %x", - transfer->type); - return LIBUSB_ERROR_OTHER; - } -} - -static int op_handle_events(struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - int r; - unsigned int i = 0; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - struct pollfd *pollfd = &fds[i]; - struct libusb_device_handle *handle; - struct linux_device_handle_priv *hpriv = NULL; - - if (!pollfd->revents) - continue; - - num_ready--; - list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { - hpriv = _device_handle_priv(handle); - if (hpriv->fd == pollfd->fd) - break; - } - - if (!hpriv || hpriv->fd != pollfd->fd) { - usbi_err(ctx, "cannot find handle for fd %d", - pollfd->fd); - continue; - } - - if (pollfd->revents & POLLERR) { - /* remove the fd from the pollfd set so that it doesn't continuously - * trigger an event, and flag that it has been removed so op_close() - * doesn't try to remove it a second time */ - usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd); - hpriv->fd_removed = 1; - - /* device will still be marked as attached if hotplug monitor thread - * hasn't processed remove event yet */ - usbi_mutex_static_lock(&linux_hotplug_lock); - if (handle->dev->attached) - linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address); - usbi_mutex_static_unlock(&linux_hotplug_lock); - - if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) { - do { - r = reap_for_handle(handle); - } while (r == 0); - } - - usbi_handle_disconnect(handle); - continue; - } - - do { - r = reap_for_handle(handle); - } while (r == 0); - if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE) - continue; - else if (r < 0) - goto out; - } - - r = 0; -out: - usbi_mutex_unlock(&ctx->open_devs_lock); - return r; -} - -static int op_clock_gettime(int clk_id, struct timespec *tp) -{ - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - return clock_gettime(monotonic_clkid, tp); - case USBI_CLOCK_REALTIME: - return clock_gettime(CLOCK_REALTIME, tp); - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -#ifdef USBI_TIMERFD_AVAILABLE -static clockid_t op_get_timerfd_clockid(void) -{ - return monotonic_clkid; - -} -#endif - -const struct usbi_os_backend usbi_backend = { - .name = "Linux usbfs", - .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, - .init = op_init, - .exit = op_exit, - .get_device_list = NULL, - .hotplug_poll = op_hotplug_poll, - .get_device_descriptor = op_get_device_descriptor, - .get_active_config_descriptor = op_get_active_config_descriptor, - .get_config_descriptor = op_get_config_descriptor, - .get_config_descriptor_by_value = op_get_config_descriptor_by_value, - - .open = op_open, - .close = op_close, - .get_configuration = op_get_configuration, - .set_configuration = op_set_configuration, - .claim_interface = op_claim_interface, - .release_interface = op_release_interface, - - .set_interface_altsetting = op_set_interface, - .clear_halt = op_clear_halt, - .reset_device = op_reset_device, - - .alloc_streams = op_alloc_streams, - .free_streams = op_free_streams, - - .dev_mem_alloc = op_dev_mem_alloc, - .dev_mem_free = op_dev_mem_free, - - .kernel_driver_active = op_kernel_driver_active, - .detach_kernel_driver = op_detach_kernel_driver, - .attach_kernel_driver = op_attach_kernel_driver, - - .destroy_device = op_destroy_device, - - .submit_transfer = op_submit_transfer, - .cancel_transfer = op_cancel_transfer, - .clear_transfer_priv = op_clear_transfer_priv, - - .handle_events = op_handle_events, - - .clock_gettime = op_clock_gettime, - -#ifdef USBI_TIMERFD_AVAILABLE - .get_timerfd_clockid = op_get_timerfd_clockid, -#endif - - .device_priv_size = sizeof(struct linux_device_priv), - .device_handle_priv_size = sizeof(struct linux_device_handle_priv), - .transfer_priv_size = sizeof(struct linux_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h deleted file mode 100644 index 24496325f6..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * usbfs header structures - * Copyright © 2007 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_USBFS_H -#define LIBUSB_USBFS_H - -#include - -#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices" - -struct usbfs_ctrltransfer { - /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */ - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - - uint32_t timeout; /* in milliseconds */ - - /* pointer to data */ - void *data; -}; - -struct usbfs_bulktransfer { - /* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */ - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - - /* pointer to data */ - void *data; -}; - -struct usbfs_setinterface { - /* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */ - unsigned int interface; - unsigned int altsetting; -}; - -#define USBFS_MAXDRIVERNAME 255 - -struct usbfs_getdriver { - unsigned int interface; - char driver[USBFS_MAXDRIVERNAME + 1]; -}; - -#define USBFS_URB_SHORT_NOT_OK 0x01 -#define USBFS_URB_ISO_ASAP 0x02 -#define USBFS_URB_BULK_CONTINUATION 0x04 -#define USBFS_URB_QUEUE_BULK 0x10 -#define USBFS_URB_ZERO_PACKET 0x40 - -enum usbfs_urb_type { - USBFS_URB_TYPE_ISO = 0, - USBFS_URB_TYPE_INTERRUPT = 1, - USBFS_URB_TYPE_CONTROL = 2, - USBFS_URB_TYPE_BULK = 3, -}; - -struct usbfs_iso_packet_desc { - unsigned int length; - unsigned int actual_length; - unsigned int status; -}; - -#define MAX_BULK_BUFFER_LENGTH 16384 -#define MAX_CTRL_BUFFER_LENGTH 4096 - -#define MAX_ISO_PACKETS_PER_URB 128 - -struct usbfs_urb { - unsigned char type; - unsigned char endpoint; - int status; - unsigned int flags; - void *buffer; - int buffer_length; - int actual_length; - int start_frame; - union { - int number_of_packets; /* Only used for isoc urbs */ - unsigned int stream_id; /* Only used with bulk streams */ - }; - int error_count; - unsigned int signr; - void *usercontext; - struct usbfs_iso_packet_desc iso_frame_desc[0]; -}; - -struct usbfs_connectinfo { - unsigned int devnum; - unsigned char slow; -}; - -struct usbfs_ioctl { - int ifno; /* interface 0..N ; negative numbers reserved */ - int ioctl_code; /* MUST encode size + direction of data so the - * macros in give correct values */ - void *data; /* param buffer (in, or out) */ -}; - -struct usbfs_hub_portinfo { - unsigned char numports; - unsigned char port[127]; /* port to device num mapping */ -}; - -#define USBFS_CAP_ZERO_PACKET 0x01 -#define USBFS_CAP_BULK_CONTINUATION 0x02 -#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04 -#define USBFS_CAP_BULK_SCATTER_GATHER 0x08 -#define USBFS_CAP_REAP_AFTER_DISCONNECT 0x10 - -#define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01 -#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02 - -struct usbfs_disconnect_claim { - unsigned int interface; - unsigned int flags; - char driver[USBFS_MAXDRIVERNAME + 1]; -}; - -struct usbfs_streams { - unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */ - unsigned int num_eps; - unsigned char eps[0]; -}; - -#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer) -#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer) -#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int) -#define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface) -#define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int) -#define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver) -#define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb) -#define IOCTL_USBFS_DISCARDURB _IO('U', 11) -#define IOCTL_USBFS_REAPURB _IOW('U', 12, void *) -#define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *) -#define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int) -#define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int) -#define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo) -#define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl) -#define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo) -#define IOCTL_USBFS_RESET _IO('U', 20) -#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int) -#define IOCTL_USBFS_DISCONNECT _IO('U', 22) -#define IOCTL_USBFS_CONNECT _IO('U', 23) -#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int) -#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int) -#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32) -#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim) -#define IOCTL_USBFS_ALLOC_STREAMS _IOR('U', 28, struct usbfs_streams) -#define IOCTL_USBFS_FREE_STREAMS _IOR('U', 29, struct usbfs_streams) - -extern usbi_mutex_static_t linux_hotplug_lock; - -#if defined(HAVE_LIBUDEV) -int linux_udev_start_event_monitor(void); -int linux_udev_stop_event_monitor(void); -int linux_udev_scan_devices(struct libusb_context *ctx); -void linux_udev_hotplug_poll(void); -#else -int linux_netlink_start_event_monitor(void); -int linux_netlink_stop_event_monitor(void); -void linux_netlink_hotplug_poll(void); -#endif - -void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name); -void linux_device_disconnected(uint8_t busnum, uint8_t devaddr); - -int linux_get_device_address (struct libusb_context *ctx, int detached, - uint8_t *busnum, uint8_t *devaddr, const char *dev_node, - const char *sys_name); -int linux_enumerate_device(struct libusb_context *ctx, - uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); - -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c deleted file mode 100644 index d9c059a776..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright © 2011 Martin Pieuchot - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "libusbi.h" - -struct device_priv { - char devnode[16]; - int fd; - - unsigned char *cdesc; /* active config descriptor */ - usb_device_descriptor_t ddesc; /* usb device descriptor */ -}; - -struct handle_priv { - int endpoints[USB_MAX_ENDPOINTS]; -}; - -/* - * Backend functions - */ -static int netbsd_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int netbsd_open(struct libusb_device_handle *); -static void netbsd_close(struct libusb_device_handle *); - -static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *, - int *); -static int netbsd_get_active_config_descriptor(struct libusb_device *, - unsigned char *, size_t, int *); -static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t, - unsigned char *, size_t, int *); - -static int netbsd_get_configuration(struct libusb_device_handle *, int *); -static int netbsd_set_configuration(struct libusb_device_handle *, int); - -static int netbsd_claim_interface(struct libusb_device_handle *, int); -static int netbsd_release_interface(struct libusb_device_handle *, int); - -static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int, - int); -static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char); -static int netbsd_reset_device(struct libusb_device_handle *); -static void netbsd_destroy_device(struct libusb_device *); - -static int netbsd_submit_transfer(struct usbi_transfer *); -static int netbsd_cancel_transfer(struct usbi_transfer *); -static void netbsd_clear_transfer_priv(struct usbi_transfer *); -static int netbsd_handle_transfer_completion(struct usbi_transfer *); -static int netbsd_clock_gettime(int, struct timespec *); - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int _cache_active_config_descriptor(struct libusb_device *, int); -static int _sync_control_transfer(struct usbi_transfer *); -static int _sync_gen_transfer(struct usbi_transfer *); -static int _access_endpoint(struct libusb_transfer *); - -const struct usbi_os_backend usbi_backend = { - "Synchronous NetBSD backend", - 0, - NULL, /* init() */ - NULL, /* exit() */ - NULL, /* set_option() */ - netbsd_get_device_list, - NULL, /* hotplug_poll */ - netbsd_open, - netbsd_close, - - netbsd_get_device_descriptor, - netbsd_get_active_config_descriptor, - netbsd_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - netbsd_get_configuration, - netbsd_set_configuration, - - netbsd_claim_interface, - netbsd_release_interface, - - netbsd_set_interface_altsetting, - netbsd_clear_halt, - netbsd_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - NULL, /* kernel_driver_active() */ - NULL, /* detach_kernel_driver() */ - NULL, /* attach_kernel_driver() */ - - netbsd_destroy_device, - - netbsd_submit_transfer, - netbsd_cancel_transfer, - netbsd_clear_transfer_priv, - - NULL, /* handle_events() */ - netbsd_handle_transfer_completion, - - netbsd_clock_gettime, - 0, /* context_priv_size */ - sizeof(struct device_priv), - sizeof(struct handle_priv), - 0, /* transfer_priv_size */ -}; - -int -netbsd_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - struct libusb_device *dev; - struct device_priv *dpriv; - struct usb_device_info di; - unsigned long session_id; - char devnode[16]; - int fd, err, i; - - usbi_dbg(""); - - /* Only ugen(4) is supported */ - for (i = 0; i < USB_MAX_DEVICES; i++) { - /* Control endpoint is always .00 */ - snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i); - - if ((fd = open(devnode, O_RDONLY)) < 0) { - if (errno != ENOENT && errno != ENXIO) - usbi_err(ctx, "could not open %s", devnode); - continue; - } - - if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0) - continue; - - session_id = (di.udi_bus << 8 | di.udi_addr); - dev = usbi_get_device_by_session_id(ctx, session_id); - - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) - return (LIBUSB_ERROR_NO_MEM); - - dev->bus_number = di.udi_bus; - dev->device_address = di.udi_addr; - dev->speed = di.udi_speed; - - dpriv = (struct device_priv *)dev->os_priv; - strlcpy(dpriv->devnode, devnode, sizeof(devnode)); - dpriv->fd = -1; - - if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) { - err = errno; - goto error; - } - - dpriv->cdesc = NULL; - if (_cache_active_config_descriptor(dev, fd)) { - err = errno; - goto error; - } - - if ((err = usbi_sanitize_device(dev))) - goto error; - } - close(fd); - - if (discovered_devs_append(*discdevs, dev) == NULL) - return (LIBUSB_ERROR_NO_MEM); - - libusb_unref_device(dev); - } - - return (LIBUSB_SUCCESS); - -error: - close(fd); - libusb_unref_device(dev); - return _errno_to_libusb(err); -} - -int -netbsd_open(struct libusb_device_handle *handle) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - dpriv->fd = open(dpriv->devnode, O_RDWR); - if (dpriv->fd < 0) { - dpriv->fd = open(dpriv->devnode, O_RDONLY); - if (dpriv->fd < 0) - return _errno_to_libusb(errno); - } - - usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); - - return (LIBUSB_SUCCESS); -} - -void -netbsd_close(struct libusb_device_handle *handle) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg("close: fd %d", dpriv->fd); - - close(dpriv->fd); - dpriv->fd = -1; -} - -int -netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, - int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -netbsd_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - usb_config_descriptor_t *ucd; - - ucd = (usb_config_descriptor_t *) dpriv->cdesc; - len = MIN(len, UGETW(ucd->wTotalLength)); - - usbi_dbg("len %d", len); - - memcpy(buf, dpriv->cdesc, len); - - *host_endian = 0; - - return len; -} - -int -netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_full_desc ufd; - int fd, err; - - usbi_dbg("index %d, len %d", idx, len); - - /* A config descriptor may be requested before opening the device */ - if (dpriv->fd >= 0) { - fd = dpriv->fd; - } else { - fd = open(dpriv->devnode, O_RDONLY); - if (fd < 0) - return _errno_to_libusb(errno); - } - - ufd.ufd_config_index = idx; - ufd.ufd_size = len; - ufd.ufd_data = buf; - - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { - err = errno; - if (dpriv->fd < 0) - close(fd); - return _errno_to_libusb(err); - } - - if (dpriv->fd < 0) - close(fd); - - *host_endian = 0; - - return len; -} - -int -netbsd_get_configuration(struct libusb_device_handle *handle, int *config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg(""); - - if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("configuration %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg("configuration %d", config); - - if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) - return _errno_to_libusb(errno); - - return _cache_active_config_descriptor(handle->dev, dpriv->fd); -} - -int -netbsd_claim_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - hpriv->endpoints[i] = -1; - - return (LIBUSB_SUCCESS); -} - -int -netbsd_release_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - if (hpriv->endpoints[i] >= 0) - close(hpriv->endpoints[i]); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_alt_interface intf; - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - memset(&intf, 0, sizeof(intf)); - - intf.uai_interface_index = iface; - intf.uai_alt_no = altsetting; - - if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_ctl_request req; - - usbi_dbg(""); - - req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; - req.ucr_request.bRequest = UR_CLEAR_FEATURE; - USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); - USETW(req.ucr_request.wIndex, endpoint); - USETW(req.ucr_request.wLength, 0); - - if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -netbsd_destroy_device(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - free(dpriv->cdesc); -} - -int -netbsd_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct handle_priv *hpriv; - int err = 0; - - usbi_dbg(""); - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - err = _sync_control_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (IS_XFEROUT(transfer)) { - /* Isochronous write is not supported */ - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (err) - return (err); - - usbi_signal_transfer_completion(itransfer); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_cancel_transfer(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -netbsd_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -netbsd_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -netbsd_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - } - - usbi_dbg("error: %s", strerror(err)); - - return (LIBUSB_ERROR_OTHER); -} - -int -_cache_active_config_descriptor(struct libusb_device *dev, int fd) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_config_desc ucd; - struct usb_full_desc ufd; - unsigned char* buf; - int len; - - usbi_dbg("fd %d", fd); - - ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX; - - if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("active bLength %d", ucd.ucd_desc.bLength); - - len = UGETW(ucd.ucd_desc.wTotalLength); - buf = malloc(len); - if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); - - ufd.ufd_config_index = ucd.ucd_config_index; - ufd.ufd_size = len; - ufd.ufd_data = buf; - - usbi_dbg("index %d, len %d", ufd.ufd_config_index, len); - - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { - free(buf); - return _errno_to_libusb(errno); - } - - if (dpriv->cdesc) - free(dpriv->cdesc); - dpriv->cdesc = buf; - - return (0); -} - -int -_sync_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_control_setup *setup; - struct device_priv *dpriv; - struct usb_ctl_request req; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - setup = (struct libusb_control_setup *)transfer->buffer; - - usbi_dbg("type %d request %d value %d index %d length %d timeout %d", - setup->bmRequestType, setup->bRequest, - libusb_le16_to_cpu(setup->wValue), - libusb_le16_to_cpu(setup->wIndex), - libusb_le16_to_cpu(setup->wLength), transfer->timeout); - - req.ucr_request.bmRequestType = setup->bmRequestType; - req.ucr_request.bRequest = setup->bRequest; - /* Don't use USETW, libusb already deals with the endianness */ - (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; - (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; - (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; - req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - req.ucr_flags = USBD_SHORT_XFER_OK; - - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = req.ucr_actlen; - - usbi_dbg("transferred %d", itransfer->transferred); - - return (0); -} - -int -_access_endpoint(struct libusb_transfer *transfer) -{ - struct handle_priv *hpriv; - struct device_priv *dpriv; - char *s, devnode[16]; - int fd, endpt; - mode_t mode; - - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - endpt = UE_GET_ADDR(transfer->endpoint); - mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; - - usbi_dbg("endpoint %d mode %d", endpt, mode); - - if (hpriv->endpoints[endpt] < 0) { - /* Pick the right node given the control one */ - strlcpy(devnode, dpriv->devnode, sizeof(devnode)); - s = strchr(devnode, '.'); - snprintf(s, 4, ".%02d", endpt); - - /* We may need to read/write to the same endpoint later. */ - if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) - if ((fd = open(devnode, mode)) < 0) - return (-1); - - hpriv->endpoints[endpt] = fd; - } - - return (hpriv->endpoints[endpt]); -} - -int -_sync_gen_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - int fd, nr = 1; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - /* - * Bulk, Interrupt or Isochronous transfer depends on the - * endpoint and thus the node to open. - */ - if ((fd = _access_endpoint(transfer)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if (IS_XFERIN(transfer)) { - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) - return _errno_to_libusb(errno); - - nr = read(fd, transfer->buffer, transfer->length); - } else { - nr = write(fd, transfer->buffer, transfer->length); - } - - if (nr < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = nr; - - return (0); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c deleted file mode 100644 index f174e496c4..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * Copyright © 2011-2013 Martin Pieuchot - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "libusbi.h" - -struct device_priv { - char *devname; /* name of the ugen(4) node */ - int fd; /* device file descriptor */ - - unsigned char *cdesc; /* active config descriptor */ - usb_device_descriptor_t ddesc; /* usb device descriptor */ -}; - -struct handle_priv { - int endpoints[USB_MAX_ENDPOINTS]; -}; - -/* - * Backend functions - */ -static int obsd_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int obsd_open(struct libusb_device_handle *); -static void obsd_close(struct libusb_device_handle *); - -static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *, - int *); -static int obsd_get_active_config_descriptor(struct libusb_device *, - unsigned char *, size_t, int *); -static int obsd_get_config_descriptor(struct libusb_device *, uint8_t, - unsigned char *, size_t, int *); - -static int obsd_get_configuration(struct libusb_device_handle *, int *); -static int obsd_set_configuration(struct libusb_device_handle *, int); - -static int obsd_claim_interface(struct libusb_device_handle *, int); -static int obsd_release_interface(struct libusb_device_handle *, int); - -static int obsd_set_interface_altsetting(struct libusb_device_handle *, int, - int); -static int obsd_clear_halt(struct libusb_device_handle *, unsigned char); -static int obsd_reset_device(struct libusb_device_handle *); -static void obsd_destroy_device(struct libusb_device *); - -static int obsd_submit_transfer(struct usbi_transfer *); -static int obsd_cancel_transfer(struct usbi_transfer *); -static void obsd_clear_transfer_priv(struct usbi_transfer *); -static int obsd_handle_transfer_completion(struct usbi_transfer *); -static int obsd_clock_gettime(int, struct timespec *); - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int _cache_active_config_descriptor(struct libusb_device *); -static int _sync_control_transfer(struct usbi_transfer *); -static int _sync_gen_transfer(struct usbi_transfer *); -static int _access_endpoint(struct libusb_transfer *); - -static int _bus_open(int); - - -const struct usbi_os_backend usbi_backend = { - "Synchronous OpenBSD backend", - 0, - NULL, /* init() */ - NULL, /* exit() */ - NULL, /* set_option() */ - obsd_get_device_list, - NULL, /* hotplug_poll */ - obsd_open, - obsd_close, - - obsd_get_device_descriptor, - obsd_get_active_config_descriptor, - obsd_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - obsd_get_configuration, - obsd_set_configuration, - - obsd_claim_interface, - obsd_release_interface, - - obsd_set_interface_altsetting, - obsd_clear_halt, - obsd_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - NULL, /* kernel_driver_active() */ - NULL, /* detach_kernel_driver() */ - NULL, /* attach_kernel_driver() */ - - obsd_destroy_device, - - obsd_submit_transfer, - obsd_cancel_transfer, - obsd_clear_transfer_priv, - - NULL, /* handle_events() */ - obsd_handle_transfer_completion, - - obsd_clock_gettime, - 0, /* context_priv_size */ - sizeof(struct device_priv), - sizeof(struct handle_priv), - 0, /* transfer_priv_size */ -}; - -#define DEVPATH "/dev/" -#define USBDEV DEVPATH "usb" - -int -obsd_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - struct discovered_devs *ddd; - struct libusb_device *dev; - struct device_priv *dpriv; - struct usb_device_info di; - struct usb_device_ddesc dd; - unsigned long session_id; - char devices[USB_MAX_DEVICES]; - char busnode[16]; - char *udevname; - int fd, addr, i, j; - - usbi_dbg(""); - - for (i = 0; i < 8; i++) { - snprintf(busnode, sizeof(busnode), USBDEV "%d", i); - - if ((fd = open(busnode, O_RDWR)) < 0) { - if (errno != ENOENT && errno != ENXIO) - usbi_err(ctx, "could not open %s", busnode); - continue; - } - - bzero(devices, sizeof(devices)); - for (addr = 1; addr < USB_MAX_DEVICES; addr++) { - if (devices[addr]) - continue; - - di.udi_addr = addr; - if (ioctl(fd, USB_DEVICEINFO, &di) < 0) - continue; - - /* - * XXX If ugen(4) is attached to the USB device - * it will be used. - */ - udevname = NULL; - for (j = 0; j < USB_MAX_DEVNAMES; j++) - if (!strncmp("ugen", di.udi_devnames[j], 4)) { - udevname = strdup(di.udi_devnames[j]); - break; - } - - session_id = (di.udi_bus << 8 | di.udi_addr); - dev = usbi_get_device_by_session_id(ctx, session_id); - - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - close(fd); - return (LIBUSB_ERROR_NO_MEM); - } - - dev->bus_number = di.udi_bus; - dev->device_address = di.udi_addr; - dev->speed = di.udi_speed; - - dpriv = (struct device_priv *)dev->os_priv; - dpriv->fd = -1; - dpriv->cdesc = NULL; - dpriv->devname = udevname; - - dd.udd_bus = di.udi_bus; - dd.udd_addr = di.udi_addr; - if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) { - libusb_unref_device(dev); - continue; - } - dpriv->ddesc = dd.udd_desc; - - if (_cache_active_config_descriptor(dev)) { - libusb_unref_device(dev); - continue; - } - - if (usbi_sanitize_device(dev)) { - libusb_unref_device(dev); - continue; - } - } - - ddd = discovered_devs_append(*discdevs, dev); - if (ddd == NULL) { - close(fd); - return (LIBUSB_ERROR_NO_MEM); - } - libusb_unref_device(dev); - - *discdevs = ddd; - devices[addr] = 1; - } - - close(fd); - } - - return (LIBUSB_SUCCESS); -} - -int -obsd_open(struct libusb_device_handle *handle) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - char devnode[16]; - - if (dpriv->devname) { - /* - * Only open ugen(4) attached devices read-write, all - * read-only operations are done through the bus node. - */ - snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", - dpriv->devname); - dpriv->fd = open(devnode, O_RDWR); - if (dpriv->fd < 0) - return _errno_to_libusb(errno); - - usbi_dbg("open %s: fd %d", devnode, dpriv->fd); - } - - return (LIBUSB_SUCCESS); -} - -void -obsd_close(struct libusb_device_handle *handle) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - if (dpriv->devname) { - usbi_dbg("close: fd %d", dpriv->fd); - - close(dpriv->fd); - dpriv->fd = -1; - } -} - -int -obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, - int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -obsd_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; - - len = MIN(len, UGETW(ucd->wTotalLength)); - - usbi_dbg("len %d", len); - - memcpy(buf, dpriv->cdesc, len); - - *host_endian = 0; - - return (len); -} - -int -obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - unsigned char *buf, size_t len, int *host_endian) -{ - struct usb_device_fdesc udf; - int fd, err; - - if ((fd = _bus_open(dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - udf.udf_bus = dev->bus_number; - udf.udf_addr = dev->device_address; - udf.udf_config_index = idx; - udf.udf_size = len; - udf.udf_data = buf; - - usbi_dbg("index %d, len %d", udf.udf_config_index, len); - - if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - - *host_endian = 0; - - return (len); -} - -int -obsd_get_configuration(struct libusb_device_handle *handle, int *config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; - - *config = ucd->bConfigurationValue; - - usbi_dbg("bConfigurationValue %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -obsd_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - usbi_dbg("bConfigurationValue %d", config); - - if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) - return _errno_to_libusb(errno); - - return _cache_active_config_descriptor(handle->dev); -} - -int -obsd_claim_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - hpriv->endpoints[i] = -1; - - return (LIBUSB_SUCCESS); -} - -int -obsd_release_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - if (hpriv->endpoints[i] >= 0) - close(hpriv->endpoints[i]); - - return (LIBUSB_SUCCESS); -} - -int -obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_alt_interface intf; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - memset(&intf, 0, sizeof(intf)); - - intf.uai_interface_index = iface; - intf.uai_alt_no = altsetting; - - if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) -{ - struct usb_ctl_request req; - int fd, err; - - if ((fd = _bus_open(handle->dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg(""); - - req.ucr_addr = handle->dev->device_address; - req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; - req.ucr_request.bRequest = UR_CLEAR_FEATURE; - USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); - USETW(req.ucr_request.wIndex, endpoint); - USETW(req.ucr_request.wLength, 0); - - if (ioctl(fd, USB_REQUEST, &req) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - - return (LIBUSB_SUCCESS); -} - -int -obsd_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -obsd_destroy_device(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - free(dpriv->cdesc); - free(dpriv->devname); -} - -int -obsd_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct handle_priv *hpriv; - int err = 0; - - usbi_dbg(""); - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - err = _sync_control_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (IS_XFEROUT(transfer)) { - /* Isochronous write is not supported */ - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (err) - return (err); - - usbi_signal_transfer_completion(itransfer); - - return (LIBUSB_SUCCESS); -} - -int -obsd_cancel_transfer(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -obsd_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -obsd_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -obsd_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - usbi_dbg("error: %s (%d)", strerror(err), err); - - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); - } - - return (LIBUSB_ERROR_OTHER); -} - -int -_cache_active_config_descriptor(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_device_cdesc udc; - struct usb_device_fdesc udf; - unsigned char* buf; - int fd, len, err; - - if ((fd = _bus_open(dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("fd %d, addr %d", fd, dev->device_address); - - udc.udc_bus = dev->bus_number; - udc.udc_addr = dev->device_address; - udc.udc_config_index = USB_CURRENT_CONFIG_INDEX; - if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(errno); - } - - usbi_dbg("active bLength %d", udc.udc_desc.bLength); - - len = UGETW(udc.udc_desc.wTotalLength); - buf = malloc(len); - if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); - - udf.udf_bus = dev->bus_number; - udf.udf_addr = dev->device_address; - udf.udf_config_index = udc.udc_config_index; - udf.udf_size = len; - udf.udf_data = buf; - - usbi_dbg("index %d, len %d", udf.udf_config_index, len); - - if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { - err = errno; - close(fd); - free(buf); - return _errno_to_libusb(err); - } - close(fd); - - if (dpriv->cdesc) - free(dpriv->cdesc); - dpriv->cdesc = buf; - - return (LIBUSB_SUCCESS); -} - -int -_sync_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_control_setup *setup; - struct device_priv *dpriv; - struct usb_ctl_request req; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - setup = (struct libusb_control_setup *)transfer->buffer; - - usbi_dbg("type %x request %x value %x index %d length %d timeout %d", - setup->bmRequestType, setup->bRequest, - libusb_le16_to_cpu(setup->wValue), - libusb_le16_to_cpu(setup->wIndex), - libusb_le16_to_cpu(setup->wLength), transfer->timeout); - - req.ucr_addr = transfer->dev_handle->dev->device_address; - req.ucr_request.bmRequestType = setup->bmRequestType; - req.ucr_request.bRequest = setup->bRequest; - /* Don't use USETW, libusb already deals with the endianness */ - (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; - (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; - (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; - req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - req.ucr_flags = USBD_SHORT_XFER_OK; - - if (dpriv->devname == NULL) { - /* - * XXX If the device is not attached to ugen(4) it is - * XXX still possible to submit a control transfer but - * XXX with the default timeout only. - */ - int fd, err; - - if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_REQUEST, &req)) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - } else { - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) - return _errno_to_libusb(errno); - } - - itransfer->transferred = req.ucr_actlen; - - usbi_dbg("transferred %d", itransfer->transferred); - - return (0); -} - -int -_access_endpoint(struct libusb_transfer *transfer) -{ - struct handle_priv *hpriv; - struct device_priv *dpriv; - char devnode[16]; - int fd, endpt; - mode_t mode; - - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - endpt = UE_GET_ADDR(transfer->endpoint); - mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; - - usbi_dbg("endpoint %d mode %d", endpt, mode); - - if (hpriv->endpoints[endpt] < 0) { - /* Pick the right endpoint node */ - snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d", - dpriv->devname, endpt); - - /* We may need to read/write to the same endpoint later. */ - if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) - if ((fd = open(devnode, mode)) < 0) - return (-1); - - hpriv->endpoints[endpt] = fd; - } - - return (hpriv->endpoints[endpt]); -} - -int -_sync_gen_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct device_priv *dpriv; - int fd, nr = 1; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - /* - * Bulk, Interrupt or Isochronous transfer depends on the - * endpoint and thus the node to open. - */ - if ((fd = _access_endpoint(transfer)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if (IS_XFERIN(transfer)) { - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) - return _errno_to_libusb(errno); - - nr = read(fd, transfer->buffer, transfer->length); - } else { - nr = write(fd, transfer->buffer, transfer->length); - } - - if (nr < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = nr; - - return (0); -} - -int -_bus_open(int number) -{ - char busnode[16]; - - snprintf(busnode, sizeof(busnode), USBDEV "%d", number); - - return open(busnode, O_RDWR); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c deleted file mode 100644 index 337714aa6b..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * poll_posix: poll compatibility wrapper for POSIX systems - * Copyright © 2013 RealVNC Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -int usbi_pipe(int pipefd[2]) -{ -#if defined(HAVE_PIPE2) - int ret = pipe2(pipefd, O_CLOEXEC); -#else - int ret = pipe(pipefd); -#endif - - if (ret != 0) { - usbi_err(NULL, "failed to create pipe (%d)", errno); - return ret; - } - -#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC) - ret = fcntl(pipefd[0], F_GETFD); - if (ret == -1) { - usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); - goto err_close_pipe; - } - ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC); - if (ret == -1) { - usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); - goto err_close_pipe; - } - - ret = fcntl(pipefd[1], F_GETFD); - if (ret == -1) { - usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); - goto err_close_pipe; - } - ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC); - if (ret == -1) { - usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); - goto err_close_pipe; - } -#endif - - ret = fcntl(pipefd[1], F_GETFL); - if (ret == -1) { - usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno); - goto err_close_pipe; - } - ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); - if (ret == -1) { - usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno); - goto err_close_pipe; - } - - return 0; - -err_close_pipe: - close(pipefd[0]); - close(pipefd[1]); - return ret; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h deleted file mode 100644 index 5b4b2c905e..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef LIBUSB_POLL_POSIX_H -#define LIBUSB_POLL_POSIX_H - -#define usbi_write write -#define usbi_read read -#define usbi_close close -#define usbi_poll poll - -int usbi_pipe(int pipefd[2]); - -#endif /* LIBUSB_POLL_POSIX_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c deleted file mode 100644 index 4d283333d1..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * poll_windows: poll compatibility wrapper for Windows - * Copyright © 2017 Chris Dickens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* - * poll() and pipe() Windows compatibility layer for libusb 1.0 - * - * The way this layer works is by using OVERLAPPED with async I/O transfers, as - * OVERLAPPED have an associated event which is flagged for I/O completion. - * - * For USB pollable async I/O, you would typically: - * - obtain a Windows HANDLE to a file or device that has been opened in - * OVERLAPPED mode - * - call usbi_create_fd with this handle to obtain a custom fd. - * - leave the core functions call the poll routine and flag POLLIN/POLLOUT - * - * The pipe pollable synchronous I/O works using the overlapped event associated - * with a fake pipe. The read/write functions are only meant to be used in that - * context. - */ -#include - -#include -#include -#include - -#include "libusbi.h" -#include "windows_common.h" - -// public fd data -const struct winfd INVALID_WINFD = { -1, NULL }; - -// private data -struct file_descriptor { - enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type; - OVERLAPPED overlapped; -}; - -static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER; -static struct file_descriptor *fd_table[MAX_FDS]; - -static struct file_descriptor *create_fd(enum fd_type type) -{ - struct file_descriptor *fd = calloc(1, sizeof(*fd)); - if (fd == NULL) - return NULL; - fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (fd->overlapped.hEvent == NULL) { - free(fd); - return NULL; - } - fd->type = type; - return fd; -} - -static void free_fd(struct file_descriptor *fd) -{ - CloseHandle(fd->overlapped.hEvent); - free(fd); -} - -/* - * Create both an fd and an OVERLAPPED, so that it can be used with our - * polling function - * The handle MUST support overlapped transfers (usually requires CreateFile - * with FILE_FLAG_OVERLAPPED) - * Return a pollable file descriptor struct, or INVALID_WINFD on error - * - * Note that the fd returned by this function is a per-transfer fd, rather - * than a per-session fd and cannot be used for anything else but our - * custom functions. - * if you plan to do R/W on the same handle, you MUST create 2 fds: one for - * read and one for write. Using a single R/W fd is unsupported and will - * produce unexpected results - */ -struct winfd usbi_create_fd(void) -{ - struct file_descriptor *fd; - struct winfd wfd; - - fd = create_fd(FD_TYPE_TRANSFER); - if (fd == NULL) - return INVALID_WINFD; - - usbi_mutex_static_lock(&fd_table_lock); - for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) { - if (fd_table[wfd.fd] != NULL) - continue; - fd_table[wfd.fd] = fd; - break; - } - usbi_mutex_static_unlock(&fd_table_lock); - - if (wfd.fd == MAX_FDS) { - free_fd(fd); - return INVALID_WINFD; - } - - wfd.overlapped = &fd->overlapped; - - return wfd; -} - -static int check_pollfds(struct pollfd *fds, unsigned int nfds, - HANDLE *wait_handles, DWORD *nb_wait_handles) -{ - struct file_descriptor *fd; - unsigned int n; - int nready = 0; - - usbi_mutex_static_lock(&fd_table_lock); - - for (n = 0; n < nfds; ++n) { - fds[n].revents = 0; - - // Keep it simple - only allow either POLLIN *or* POLLOUT - assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT)); - if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) { - fds[n].revents = POLLNVAL; - nready++; - continue; - } - - if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS)) - fd = fd_table[fds[n].fd]; - else - fd = NULL; - - assert(fd != NULL); - if (fd == NULL) { - fds[n].revents = POLLNVAL; - nready++; - continue; - } - - if (HasOverlappedIoCompleted(&fd->overlapped) - && (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) { - fds[n].revents = fds[n].events; - nready++; - } else if (wait_handles != NULL) { - if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) { - usbi_warn(NULL, "too many HANDLEs to wait on"); - continue; - } - wait_handles[*nb_wait_handles] = fd->overlapped.hEvent; - (*nb_wait_handles)++; - } - } - - usbi_mutex_static_unlock(&fd_table_lock); - - return nready; -} -/* - * POSIX poll equivalent, using Windows OVERLAPPED - * Currently, this function only accepts one of POLLIN or POLLOUT per fd - * (but you can create multiple fds from the same handle for read and write) - */ -int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) -{ - HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; - DWORD nb_wait_handles = 0; - DWORD ret; - int nready; - - nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles); - - // If nothing was triggered, wait on all fds that require it - if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) { - ret = WaitForMultipleObjects(nb_wait_handles, wait_handles, - FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout); - if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) { - nready = check_pollfds(fds, nfds, NULL, NULL); - } else if (ret != WAIT_TIMEOUT) { - if (ret == WAIT_FAILED) - usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError()); - nready = -1; - } - } - - return nready; -} - -/* - * close a fake file descriptor - */ -int usbi_close(int _fd) -{ - struct file_descriptor *fd; - - if (_fd < 0 || _fd >= MAX_FDS) - goto err_badfd; - - usbi_mutex_static_lock(&fd_table_lock); - fd = fd_table[_fd]; - fd_table[_fd] = NULL; - usbi_mutex_static_unlock(&fd_table_lock); - - if (fd == NULL) - goto err_badfd; - - if (fd->type == FD_TYPE_PIPE) { - // InternalHigh is our reference count - fd->overlapped.InternalHigh--; - if (fd->overlapped.InternalHigh == 0) - free_fd(fd); - } else { - free_fd(fd); - } - - return 0; - -err_badfd: - errno = EBADF; - return -1; -} - -/* -* Create a fake pipe. -* As libusb only uses pipes for signaling, all we need from a pipe is an -* event. To that extent, we create a single wfd and overlapped as a means -* to access that event. -*/ -int usbi_pipe(int filedes[2]) -{ - struct file_descriptor *fd; - int r_fd = -1, w_fd = -1; - int i; - - fd = create_fd(FD_TYPE_PIPE); - if (fd == NULL) { - errno = ENOMEM; - return -1; - } - - // Use InternalHigh as a reference count - fd->overlapped.Internal = STATUS_PENDING; - fd->overlapped.InternalHigh = 2; - - usbi_mutex_static_lock(&fd_table_lock); - do { - for (i = 0; i < MAX_FDS; i++) { - if (fd_table[i] != NULL) - continue; - if (r_fd == -1) { - r_fd = i; - } else if (w_fd == -1) { - w_fd = i; - break; - } - } - - if (i == MAX_FDS) - break; - - fd_table[r_fd] = fd; - fd_table[w_fd] = fd; - - } while (0); - usbi_mutex_static_unlock(&fd_table_lock); - - if (i == MAX_FDS) { - free_fd(fd); - errno = EMFILE; - return -1; - } - - filedes[0] = r_fd; - filedes[1] = w_fd; - - return 0; -} - -/* - * synchronous write for fake "pipe" signaling - */ -ssize_t usbi_write(int fd, const void *buf, size_t count) -{ - int error = EBADF; - - UNUSED(buf); - - if (fd < 0 || fd >= MAX_FDS) - goto err_out; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - error = EINVAL; - goto err_out; - } - - usbi_mutex_static_lock(&fd_table_lock); - if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { - assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING); - assert(fd_table[fd]->overlapped.InternalHigh == 2); - fd_table[fd]->overlapped.Internal = STATUS_WAIT_0; - SetEvent(fd_table[fd]->overlapped.hEvent); - error = 0; - } - usbi_mutex_static_unlock(&fd_table_lock); - - if (error) - goto err_out; - - return sizeof(unsigned char); - -err_out: - errno = error; - return -1; -} - -/* - * synchronous read for fake "pipe" signaling - */ -ssize_t usbi_read(int fd, void *buf, size_t count) -{ - int error = EBADF; - - UNUSED(buf); - - if (fd < 0 || fd >= MAX_FDS) - goto err_out; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - error = EINVAL; - goto err_out; - } - - usbi_mutex_static_lock(&fd_table_lock); - if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { - assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0); - assert(fd_table[fd]->overlapped.InternalHigh == 2); - fd_table[fd]->overlapped.Internal = STATUS_PENDING; - ResetEvent(fd_table[fd]->overlapped.hEvent); - error = 0; - } - usbi_mutex_static_unlock(&fd_table_lock); - - if (error) - goto err_out; - - return sizeof(unsigned char); - -err_out: - errno = error; - return -1; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h deleted file mode 100644 index bd22c7f623..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Windows compat: POSIX compatibility wrapper - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2010 Pete Batard - * Copyright © 2016-2018 Chris Dickens - * With contributions from Michael Plante, Orin Eman et al. - * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -#pragma once - -#if defined(_MSC_VER) -// disable /W4 MSVC warnings that are benign -#pragma warning(disable:4127) // conditional expression is constant -#endif - -// Handle synchronous completion through the overlapped structure -#if !defined(STATUS_REPARSE) // reuse the REPARSE status code -#define STATUS_REPARSE ((LONG)0x00000104L) -#endif -#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE -#if defined(_WIN32_WCE) -// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it -#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING) -#endif -#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) - -#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) - -#define MAX_FDS 256 - -#define POLLIN 0x0001 /* There is data to read */ -#define POLLPRI 0x0002 /* There is urgent data to read */ -#define POLLOUT 0x0004 /* Writing now will not block */ -#define POLLERR 0x0008 /* Error condition */ -#define POLLHUP 0x0010 /* Hung up */ -#define POLLNVAL 0x0020 /* Invalid request: fd not open */ - -struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -}; - -struct winfd { - int fd; // what's exposed to libusb core - OVERLAPPED *overlapped; // what will report our I/O status -}; - -extern const struct winfd INVALID_WINFD; - -struct winfd usbi_create_fd(void); - -int usbi_pipe(int pipefd[2]); -int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); -ssize_t usbi_write(int fd, const void *buf, size_t count); -ssize_t usbi_read(int fd, void *buf, size_t count); -int usbi_close(int fd); - -/* - * Timeval operations - */ -#if defined(DDKBUILD) -#include // defines timeval functions on DDK -#endif - -#if !defined(TIMESPEC_TO_TIMEVAL) -#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ - (tv)->tv_sec = (long)(ts)->tv_sec; \ - (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \ -} -#endif -#if !defined(timersub) -#define timersub(a, b, result) \ -do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ -} while (0) -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c deleted file mode 100644 index 7150a3e9d9..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c +++ /dev/null @@ -1,1675 +0,0 @@ -/* - * - * Copyright (c) 2016, Oracle and/or its affiliates. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "sunos_usb.h" - -#define UPDATEDRV_PATH "/usr/sbin/update_drv" -#define UPDATEDRV "update_drv" - -typedef list_t string_list_t; -typedef struct string_node { - char *string; - list_node_t link; -} string_node_t; - -/* - * Backend functions - */ -static int sunos_init(struct libusb_context *); -static void sunos_exit(struct libusb_context *); -static int sunos_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int sunos_open(struct libusb_device_handle *); -static void sunos_close(struct libusb_device_handle *); -static int sunos_get_device_descriptor(struct libusb_device *, - uint8_t*, int *); -static int sunos_get_active_config_descriptor(struct libusb_device *, - uint8_t*, size_t, int *); -static int sunos_get_config_descriptor(struct libusb_device *, uint8_t, - uint8_t*, size_t, int *); -static int sunos_get_configuration(struct libusb_device_handle *, int *); -static int sunos_set_configuration(struct libusb_device_handle *, int); -static int sunos_claim_interface(struct libusb_device_handle *, int); -static int sunos_release_interface(struct libusb_device_handle *, int); -static int sunos_set_interface_altsetting(struct libusb_device_handle *, - int, int); -static int sunos_clear_halt(struct libusb_device_handle *, uint8_t); -static int sunos_reset_device(struct libusb_device_handle *); -static void sunos_destroy_device(struct libusb_device *); -static int sunos_submit_transfer(struct usbi_transfer *); -static int sunos_cancel_transfer(struct usbi_transfer *); -static void sunos_clear_transfer_priv(struct usbi_transfer *); -static int sunos_handle_transfer_completion(struct usbi_transfer *); -static int sunos_clock_gettime(int, struct timespec *); -static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface); -static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number); -static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number); -static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv); -static int sunos_usb_ioctl(struct libusb_device *dev, int cmd); - -static struct devctl_iocdata iocdata; -static int sunos_get_link(di_devlink_t devlink, void *arg) -{ - walk_link_t *larg = (walk_link_t *)arg; - const char *p; - const char *q; - - if (larg->path) { - char *content = (char *)di_devlink_content(devlink); - char *start = strstr(content, "/devices/"); - start += strlen("/devices"); - usbi_dbg("%s", start); - - /* line content must have minor node */ - if (start == NULL || - strncmp(start, larg->path, larg->len) != 0 || - start[larg->len] != ':') - return (DI_WALK_CONTINUE); - } - - p = di_devlink_path(devlink); - q = strrchr(p, '/'); - usbi_dbg("%s", q); - - *(larg->linkpp) = strndup(p, strlen(p) - strlen(q)); - - return (DI_WALK_TERMINATE); -} - - -static int sunos_physpath_to_devlink( - const char *node_path, const char *match, char **link_path) -{ - walk_link_t larg; - di_devlink_handle_t hdl; - - *link_path = NULL; - larg.linkpp = link_path; - if ((hdl = di_devlink_init(NULL, 0)) == NULL) { - usbi_dbg("di_devlink_init failure"); - return (-1); - } - - larg.len = strlen(node_path); - larg.path = (char *)node_path; - - (void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK, - (void *)&larg, sunos_get_link); - - (void) di_devlink_fini(&hdl); - - if (*link_path == NULL) { - usbi_dbg("there is no devlink for this path"); - return (-1); - } - - return 0; -} - -static int -sunos_usb_ioctl(struct libusb_device *dev, int cmd) -{ - int fd; - nvlist_t *nvlist; - char *end; - char *phypath; - char *hubpath; - char path_arg[PATH_MAX]; - sunos_dev_priv_t *dpriv; - devctl_ap_state_t devctl_ap_state; - - dpriv = (sunos_dev_priv_t *)dev->os_priv; - phypath = dpriv->phypath; - - end = strrchr(phypath, '/'); - if (end == NULL) - return (-1); - hubpath = strndup(phypath, end - phypath); - if (hubpath == NULL) - return (-1); - - end = strrchr(hubpath, '@'); - if (end == NULL) { - free(hubpath); - return (-1); - } - end++; - usbi_dbg("unitaddr: %s", end); - - nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); - nvlist_add_int32(nvlist, "port", dev->port_number); - //find the hub path - snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath); - usbi_dbg("ioctl hub path: %s", path_arg); - - fd = open(path_arg, O_RDONLY); - if (fd < 0) { - usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno)); - nvlist_free(nvlist); - free(hubpath); - return (-1); - } - - memset(&iocdata, 0, sizeof(iocdata)); - memset(&devctl_ap_state, 0, sizeof(devctl_ap_state)); - - nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0); - - iocdata.cmd = DEVCTL_AP_GETSTATE; - iocdata.flags = 0; - iocdata.c_nodename = "hub"; - iocdata.c_unitaddr = end; - iocdata.cpyout_buf = &devctl_ap_state; - usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz); - - errno = 0; - if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) { - usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", - fd, DEVCTL_AP_GETSTATE, errno, strerror(errno)); - } else { - usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate); - usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate); - } - - errno = 0; - iocdata.cmd = cmd; - if (ioctl(fd, (int)cmd, &iocdata) != 0) { - usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", - fd, cmd, errno, strerror(errno)); - sleep(2); - } - - close(fd); - free(iocdata.nvl_user); - nvlist_free(nvlist); - free(hubpath); - - return (-errno); -} - -static int -sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface) -{ - sunos_dev_priv_t *dpriv; - dpriv = (sunos_dev_priv_t *)dev->dev->os_priv; - - usbi_dbg("%s", dpriv->ugenpath); - - return (dpriv->ugenpath == NULL); -} - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int sunos_usb_get_status(int fd); - -static int sunos_init(struct libusb_context *ctx) -{ - return (LIBUSB_SUCCESS); -} - -static void sunos_exit(struct libusb_context *ctx) -{ - usbi_dbg(""); -} - -static string_list_t * -sunos_new_string_list(void) -{ - string_list_t *list; - - list = calloc(1, sizeof(*list)); - if (list != NULL) - list_create(list, sizeof(string_node_t), - offsetof(string_node_t, link)); - - return (list); -} - -static int -sunos_append_to_string_list(string_list_t *list, const char *arg) -{ - string_node_t *np; - - np = calloc(1, sizeof(*np)); - if (!np) - return (-1); - - np->string = strdup(arg); - if (!np->string) { - free(np); - return (-1); - } - - list_insert_tail(list, np); - - return (0); -} - -static void -sunos_free_string_list(string_list_t *list) -{ - string_node_t *np; - - while ((np = list_remove_head(list)) != NULL) { - free(np->string); - free(np); - } - - free(list); -} - -static char ** -sunos_build_argv_list(string_list_t *list) -{ - char **argv_list; - string_node_t *np; - int n; - - n = 1; /* Start at 1 for NULL terminator */ - for (np = list_head(list); np != NULL; np = list_next(list, np)) - n++; - - argv_list = calloc(n, sizeof(char *)); - if (argv_list == NULL) - return NULL; - - n = 0; - for (np = list_head(list); np != NULL; np = list_next(list, np)) - argv_list[n++] = np->string; - - return (argv_list); -} - - -static int -sunos_exec_command(struct libusb_context *ctx, const char *path, - string_list_t *list) -{ - pid_t pid; - int status; - int waitstat; - int exit_status; - char **argv_list; - - argv_list = sunos_build_argv_list(list); - if (argv_list == NULL) - return (-1); - - pid = fork(); - if (pid == 0) { - /* child */ - execv(path, argv_list); - _exit(127); - } else if (pid > 0) { - /* parent */ - do { - waitstat = waitpid(pid, &status, 0); - } while ((waitstat == -1 && errno == EINTR) || - (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status))); - - if (waitstat == 0) { - if (WIFEXITED(status)) - exit_status = WEXITSTATUS(status); - else - exit_status = WTERMSIG(status); - } else { - usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno)); - exit_status = -1; - } - } else { - /* fork failed */ - usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno)); - exit_status = -1; - } - - free(argv_list); - - return (exit_status); -} - -static int -sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle, - int interface_number) -{ - struct libusb_context *ctx = HANDLE_CTX(dev_handle); - string_list_t *list; - char path_arg[PATH_MAX]; - sunos_dev_priv_t *dpriv; - int r; - - dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; - snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); - usbi_dbg("%s", path_arg); - - list = sunos_new_string_list(); - if (list == NULL) - return (LIBUSB_ERROR_NO_MEM); - - /* attach ugen driver */ - r = 0; - r |= sunos_append_to_string_list(list, UPDATEDRV); - r |= sunos_append_to_string_list(list, "-a"); /* add rule */ - r |= sunos_append_to_string_list(list, "-i"); /* specific device */ - r |= sunos_append_to_string_list(list, path_arg); /* physical path */ - r |= sunos_append_to_string_list(list, "ugen"); - if (r) { - sunos_free_string_list(list); - return (LIBUSB_ERROR_NO_MEM); - } - - r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); - sunos_free_string_list(list); - if (r < 0) - return (LIBUSB_ERROR_OTHER); - - /* reconfigure the driver node */ - r = 0; - r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); - r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); - if (r) - usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); - - snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor, - dpriv->dev_descr.idProduct); - sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath); - - if (access(dpriv->ugenpath, F_OK) == -1) { - usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver"); - return (LIBUSB_ERROR_IO); - } - - return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv); -} - -static int -sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle, - int interface_number) -{ - struct libusb_context *ctx = HANDLE_CTX(dev_handle); - string_list_t *list; - char path_arg[PATH_MAX]; - sunos_dev_priv_t *dpriv; - int r; - - /* we open the dev in detach driver, so we need close it first. */ - sunos_close(dev_handle); - - dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; - snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); - usbi_dbg("%s", path_arg); - - list = sunos_new_string_list(); - if (list == NULL) - return (LIBUSB_ERROR_NO_MEM); - - /* detach ugen driver */ - r = 0; - r |= sunos_append_to_string_list(list, UPDATEDRV); - r |= sunos_append_to_string_list(list, "-d"); /* add rule */ - r |= sunos_append_to_string_list(list, "-i"); /* specific device */ - r |= sunos_append_to_string_list(list, path_arg); /* physical path */ - r |= sunos_append_to_string_list(list, "ugen"); - if (r) { - sunos_free_string_list(list); - return (LIBUSB_ERROR_NO_MEM); - } - - r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); - sunos_free_string_list(list); - if (r < 0) - return (LIBUSB_ERROR_OTHER); - - /* reconfigure the driver node */ - r = 0; - r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); - r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); - r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); - if (r) - usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); - - return 0; -} - -static int -sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) -{ - int proplen; - int n, *addr, *port_prop; - char *phypath; - uint8_t *rdata; - struct libusb_device_descriptor *descr; - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - char match_str[PATH_MAX]; - - /* Device descriptors */ - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-dev-descriptor", &rdata); - if (proplen <= 0) { - - return (LIBUSB_ERROR_IO); - } - - descr = (struct libusb_device_descriptor *)rdata; - bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); - dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB); - dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor); - dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct); - dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice); - - /* Raw configuration descriptors */ - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-raw-cfg-descriptors", &rdata); - if (proplen <= 0) { - usbi_dbg("can't find raw config descriptors"); - - return (LIBUSB_ERROR_IO); - } - dpriv->raw_cfgdescr = calloc(1, proplen); - if (dpriv->raw_cfgdescr == NULL) { - return (LIBUSB_ERROR_NO_MEM); - } else { - bcopy(rdata, dpriv->raw_cfgdescr, proplen); - dpriv->cfgvalue = ((struct libusb_config_descriptor *) - rdata)->bConfigurationValue; - } - - n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop); - - if ((n != 1) || (*port_prop <= 0)) { - return (LIBUSB_ERROR_IO); - } - dev->port_number = *port_prop; - - /* device physical path */ - phypath = di_devfs_path(node); - if (phypath) { - dpriv->phypath = strdup(phypath); - snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct); - usbi_dbg("match is %s", match_str); - sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath); - di_devfs_path_free(phypath); - - } else { - free(dpriv->raw_cfgdescr); - - return (LIBUSB_ERROR_IO); - } - - /* address */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr); - if (n != 1 || *addr == 0) { - usbi_dbg("can't get address"); - } else { - dev->device_address = *addr; - } - - /* speed */ - if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { - dev->speed = LIBUSB_SPEED_LOW; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { - dev->speed = LIBUSB_SPEED_HIGH; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { - dev->speed = LIBUSB_SPEED_FULL; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { - dev->speed = LIBUSB_SPEED_SUPER; - } - - usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, " - "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct, - dpriv->phypath, dev->bus_number, dev->port_number, dev->speed); - - return (LIBUSB_SUCCESS); -} - -static int -sunos_add_devices(di_devlink_t link, void *arg) -{ - struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; - struct node_args *nargs; - di_node_t myself, dn; - uint64_t session_id = 0; - uint64_t sid = 0; - uint64_t bdf = 0; - struct libusb_device *dev; - sunos_dev_priv_t *devpriv; - int n; - int i = 0; - int *addr_prop; - uint8_t bus_number = 0; - uint32_t * regbuf = NULL; - uint32_t reg; - - nargs = (struct node_args *)largs->nargs; - myself = largs->myself; - - /* - * Construct session ID. - * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf - * 8 bits 8bits 8 bits 16bits - */ - if (myself == DI_NODE_NIL) - return (DI_WALK_CONTINUE); - - dn = myself; - /* find the root hub */ - while (di_prop_exists(DDI_DEV_T_ANY, dn, "root-hub") != 1) { - usbi_dbg("find_root_hub:%s", di_devfs_path(dn)); - n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, - "assigned-address", &addr_prop); - session_id |= ((addr_prop[0] & 0xff) << i++ * 8); - dn = di_parent_node(dn); - } - - /* dn is the root hub node */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf); - reg = regbuf[0]; - bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - /* bdf must larger than i*8 bits */ - session_id |= (bdf << i * 8); - bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - - usbi_dbg("device bus address=%s:%x, name:%s", - di_bus_addr(myself), bus_number, di_node_name(dn)); - usbi_dbg("session id org:%lx", session_id); - - /* dn is the usb device */ - for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) { - usbi_dbg("device path:%s", di_devfs_path(dn)); - /* skip hub devices, because its driver can not been unload */ - if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1) - continue; - /* usb_addr */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, - "assigned-address", &addr_prop); - if ((n != 1) || (addr_prop[0] == 0)) { - usbi_dbg("cannot get valid usb_addr"); - continue; - } - - sid = (session_id << 8) | (addr_prop[0] & 0xff) ; - usbi_dbg("session id %lx", sid); - - dev = usbi_get_device_by_session_id(nargs->ctx, sid); - if (dev == NULL) { - dev = usbi_alloc_device(nargs->ctx, sid); - if (dev == NULL) { - usbi_dbg("can't alloc device"); - continue; - } - devpriv = (sunos_dev_priv_t *)dev->os_priv; - dev->bus_number = bus_number; - - if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - usbi_dbg("get infomation fail"); - continue; - } - if (usbi_sanitize_device(dev) < 0) { - libusb_unref_device(dev); - usbi_dbg("sanatize failed: "); - return (DI_WALK_TERMINATE); - } - } else { - devpriv = (sunos_dev_priv_t *)dev->os_priv; - usbi_dbg("Dev %s exists", devpriv->ugenpath); - } - - if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { - usbi_dbg("cannot append device"); - } - - /* - * we alloc and hence ref this dev. We don't need to ref it - * hereafter. Front end or app should take care of their ref. - */ - libusb_unref_device(dev); - - usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", - devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid, - (*nargs->discdevs)->len, bdf); - } - - return (DI_WALK_CONTINUE); -} - -static int -sunos_walk_minor_node_link(di_node_t node, void *args) -{ - di_minor_t minor = DI_MINOR_NIL; - char *minor_path; - struct devlink_cbarg arg; - struct node_args *nargs = (struct node_args *)args; - di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; - - /* walk each minor to find usb devices */ - while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - minor_path = di_devfs_minor_path(minor); - arg.nargs = args; - arg.myself = node; - arg.minor = minor; - (void) di_devlink_walk(devlink_hdl, - "^usb/hub[0-9]+", minor_path, - DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); - di_devfs_path_free(minor_path); - } - - /* switch to a different node */ - nargs->last_ugenpath = NULL; - - return (DI_WALK_CONTINUE); -} - -int -sunos_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - di_node_t root_node; - struct node_args args; - di_devlink_handle_t devlink_hdl; - - args.ctx = ctx; - args.discdevs = discdevs; - args.last_ugenpath = NULL; - if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { - usbi_dbg("di_int() failed: %s", strerror(errno)); - return (LIBUSB_ERROR_IO); - } - - if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { - di_fini(root_node); - usbi_dbg("di_devlink_init() failed: %s", strerror(errno)); - - return (LIBUSB_ERROR_IO); - } - args.dlink_hdl = devlink_hdl; - - /* walk each node to find USB devices */ - if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args, - sunos_walk_minor_node_link) == -1) { - usbi_dbg("di_walk_node() failed: %s", strerror(errno)); - di_fini(root_node); - - return (LIBUSB_ERROR_IO); - } - - di_fini(root_node); - di_devlink_fini(&devlink_hdl); - - usbi_dbg("%d devices", (*discdevs)->len); - - return ((*discdevs)->len); -} - -static int -sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv) -{ - char filename[PATH_MAX + 1]; - - if (hpriv->eps[0].datafd > 0) { - - return (LIBUSB_SUCCESS); - } - snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath); - - usbi_dbg("opening %s", filename); - hpriv->eps[0].datafd = open(filename, O_RDWR); - if (hpriv->eps[0].datafd < 0) { - return(_errno_to_libusb(errno)); - } - - snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath); - hpriv->eps[0].statfd = open(filename, O_RDONLY); - if (hpriv->eps[0].statfd < 0) { - close(hpriv->eps[0].datafd); - hpriv->eps[0].datafd = -1; - - return(_errno_to_libusb(errno)); - } - - return (LIBUSB_SUCCESS); -} - -static void -sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev) -{ - int i; - - /* not close ep0 */ - for (i = 1; i < USB_MAXENDPOINTS; i++) { - if (hdev->eps[i].datafd != -1) { - (void) close(hdev->eps[i].datafd); - hdev->eps[i].datafd = -1; - } - if (hdev->eps[i].statfd != -1) { - (void) close(hdev->eps[i].statfd); - hdev->eps[i].statfd = -1; - } - } -} - -static void -sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv) -{ - if (hdev->eps[0].datafd >= 0) { - close(hdev->eps[0].datafd); - close(hdev->eps[0].statfd); - hdev->eps[0].datafd = -1; - hdev->eps[0].statfd = -1; - } -} - -static uchar_t -sunos_usb_ep_index(uint8_t ep_addr) -{ - return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) + - ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0)); -} - -static int -sunos_find_interface(struct libusb_device_handle *hdev, - uint8_t endpoint, uint8_t *interface) -{ - struct libusb_config_descriptor *config; - int r; - int iface_idx; - - r = libusb_get_active_config_descriptor(hdev->dev, &config); - if (r < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { - const struct libusb_interface *iface = - &config->interface[iface_idx]; - int altsetting_idx; - - for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; - altsetting_idx++) { - const struct libusb_interface_descriptor *altsetting = - &iface->altsetting[altsetting_idx]; - int ep_idx; - - for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; - ep_idx++) { - const struct libusb_endpoint_descriptor *ep = - &altsetting->endpoint[ep_idx]; - if (ep->bEndpointAddress == endpoint) { - *interface = iface_idx; - libusb_free_config_descriptor(config); - - return (LIBUSB_SUCCESS); - } - } - } - } - libusb_free_config_descriptor(config); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -static int -sunos_check_device_and_status_open(struct libusb_device_handle *hdl, - uint8_t ep_addr, int ep_type) -{ - char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1]; - char cfg_num[16], alt_num[16]; - int fd, fdstat, mode; - uint8_t ifc = 0; - uint8_t ep_index; - sunos_dev_handle_priv_t *hpriv; - - usbi_dbg("open ep 0x%02x", ep_addr); - hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; - ep_index = sunos_usb_ep_index(ep_addr); - /* ep already opened */ - if ((hpriv->eps[ep_index].datafd > 0) && - (hpriv->eps[ep_index].statfd > 0)) { - usbi_dbg("ep 0x%02x already opened, return success", - ep_addr); - - return (0); - } - - if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) { - usbi_dbg("can't find interface for endpoint 0x%02x", - ep_addr); - - return (EACCES); - } - - /* create filename */ - if (hpriv->config_index > 0) { - (void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d", - hpriv->config_index + 1); - } else { - bzero(cfg_num, sizeof (cfg_num)); - } - - if (hpriv->altsetting[ifc] > 0) { - (void) snprintf(alt_num, sizeof (alt_num), ".%d", - hpriv->altsetting[ifc]); - } else { - bzero(alt_num, sizeof (alt_num)); - } - - (void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d", - hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num, - (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : - "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK)); - (void) snprintf(statfilename, PATH_MAX, "%sstat", filename); - - /* - * for interrupt IN endpoints, we need to enable one xfer - * mode before opening the endpoint - */ - if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) && - (ep_addr & LIBUSB_ENDPOINT_IN)) { - char control = USB_EP_INTR_ONE_XFER; - int count; - - /* open the status device node for the ep first RDWR */ - if ((fdstat = open(statfilename, O_RDWR)) == -1) { - usbi_dbg("can't open %s RDWR: %d", - statfilename, errno); - } else { - count = write(fdstat, &control, sizeof (control)); - if (count != 1) { - /* this should have worked */ - usbi_dbg("can't write to %s: %d", - statfilename, errno); - (void) close(fdstat); - - return (errno); - } - /* close status node and open xfer node first */ - close (fdstat); - } - } - - /* open the xfer node first in case alt needs to be changed */ - if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - mode = O_RDWR; - } else if (ep_addr & LIBUSB_ENDPOINT_IN) { - mode = O_RDONLY; - } else { - mode = O_WRONLY; - } - - /* - * IMPORTANT: must open data xfer node first and then open stat node - * Otherwise, it will fail on multi-config or multi-altsetting devices - * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and - * ugen_epxs_check_alt_switch() in ugen driver source code. - */ - if ((fd = open(filename, mode)) == -1) { - usbi_dbg("can't open %s: %d(%s)", filename, errno, - strerror(errno)); - - return (errno); - } - /* open the status node */ - if ((fdstat = open(statfilename, O_RDONLY)) == -1) { - usbi_dbg("can't open %s: %d", statfilename, errno); - - (void) close(fd); - - return (errno); - } - - hpriv->eps[ep_index].datafd = fd; - hpriv->eps[ep_index].statfd = fdstat; - usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat); - - return (0); -} - -int -sunos_open(struct libusb_device_handle *handle) -{ - sunos_dev_handle_priv_t *hpriv; - sunos_dev_priv_t *dpriv; - int i; - int ret; - - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - hpriv->dpriv = dpriv; - - /* set all file descriptors to "closed" */ - for (i = 0; i < USB_MAXENDPOINTS; i++) { - hpriv->eps[i].datafd = -1; - hpriv->eps[i].statfd = -1; - } - - if (sunos_kernel_driver_active(handle, 0)) { - /* pretend we can open the device */ - return (LIBUSB_SUCCESS); - } - - if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { - usbi_dbg("fail: %d", ret); - return (ret); - } - - return (LIBUSB_SUCCESS); -} - -void -sunos_close(struct libusb_device_handle *handle) -{ - sunos_dev_handle_priv_t *hpriv; - sunos_dev_priv_t *dpriv; - - usbi_dbg(""); - if (!handle) { - return; - } - - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - if (!hpriv) { - return; - } - dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - if (!dpriv) { - return; - } - - sunos_usb_close_all_eps(hpriv); - sunos_usb_close_ep0(hpriv, dpriv); -} - -int -sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf, - int *host_endian) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -sunos_get_active_config_descriptor(struct libusb_device *dev, - uint8_t *buf, size_t len, int *host_endian) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - struct libusb_config_descriptor *cfg; - int proplen; - di_node_t node; - uint8_t *rdata; - - /* - * Keep raw configuration descriptors updated, in case config - * has ever been changed through setCfg. - */ - if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) { - usbi_dbg("di_int() failed: %s", strerror(errno)); - return (LIBUSB_ERROR_IO); - } - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-raw-cfg-descriptors", &rdata); - if (proplen <= 0) { - usbi_dbg("can't find raw config descriptors"); - - return (LIBUSB_ERROR_IO); - } - dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen); - if (dpriv->raw_cfgdescr == NULL) { - return (LIBUSB_ERROR_NO_MEM); - } else { - bcopy(rdata, dpriv->raw_cfgdescr, proplen); - dpriv->cfgvalue = ((struct libusb_config_descriptor *) - rdata)->bConfigurationValue; - } - di_fini(node); - - cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr; - len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength)); - memcpy(buf, dpriv->raw_cfgdescr, len); - *host_endian = 0; - usbi_dbg("path:%s len %d", dpriv->phypath, len); - - return (len); -} - -int -sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - uint8_t *buf, size_t len, int *host_endian) -{ - /* XXX */ - return(sunos_get_active_config_descriptor(dev, buf, len, host_endian)); -} - -int -sunos_get_configuration(struct libusb_device_handle *handle, int *config) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - - *config = dpriv->cfgvalue; - - usbi_dbg("bConfigurationValue %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -sunos_set_configuration(struct libusb_device_handle *handle, int config) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - sunos_dev_handle_priv_t *hpriv; - - usbi_dbg("bConfigurationValue %d", config); - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - - if (dpriv->ugenpath == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - if (config < 1 || config > dpriv->dev_descr.bNumConfigurations) - return (LIBUSB_ERROR_INVALID_PARAM); - - dpriv->cfgvalue = config; - hpriv->config_index = config - 1; - - return (LIBUSB_SUCCESS); -} - -int -sunos_claim_interface(struct libusb_device_handle *handle, int iface) -{ - usbi_dbg("iface %d", iface); - if (iface < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - return (LIBUSB_SUCCESS); -} - -int -sunos_release_interface(struct libusb_device_handle *handle, int iface) -{ - sunos_dev_handle_priv_t *hpriv = - (sunos_dev_handle_priv_t *)handle->os_priv; - - usbi_dbg("iface %d", iface); - if (iface < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - /* XXX: can we release it? */ - hpriv->altsetting[iface] = 0; - - return (LIBUSB_SUCCESS); -} - -int -sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - sunos_dev_handle_priv_t *hpriv = - (sunos_dev_handle_priv_t *)handle->os_priv; - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - if (iface < 0 || altsetting < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - if (dpriv->ugenpath == NULL) - return (LIBUSB_ERROR_NOT_FOUND); - - /* XXX: can we switch altsetting? */ - hpriv->altsetting[iface] = altsetting; - - return (LIBUSB_SUCCESS); -} - -static void -usb_dump_data(unsigned char *data, size_t size) -{ - int i; - - if (getenv("LIBUSB_DEBUG") == NULL) { - return; - } - - (void) fprintf(stderr, "data dump:"); - for (i = 0; i < size; i++) { - if (i % 16 == 0) { - (void) fprintf(stderr, "\n%08x ", i); - } - (void) fprintf(stderr, "%02x ", (uchar_t)data[i]); - } - (void) fprintf(stderr, "\n"); -} - -static void -sunos_async_callback(union sigval arg) -{ - struct sunos_transfer_priv *tpriv = - (struct sunos_transfer_priv *)arg.sival_ptr; - struct libusb_transfer *xfer = tpriv->transfer; - struct aiocb *aiocb = &tpriv->aiocb; - int ret; - sunos_dev_handle_priv_t *hpriv; - uint8_t ep; - - hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(xfer->endpoint); - - ret = aio_error(aiocb); - if (ret != 0) { - xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); - } else { - xfer->actual_length = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = - aio_return(aiocb); - } - - usb_dump_data(xfer->buffer, xfer->actual_length); - - usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, - xfer->actual_length); - - /* async notification */ - usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); -} - -static int -sunos_do_async_io(struct libusb_transfer *transfer) -{ - int ret = -1; - struct aiocb *aiocb; - sunos_dev_handle_priv_t *hpriv; - uint8_t ep; - struct sunos_transfer_priv *tpriv; - - usbi_dbg(""); - - tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); - hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(transfer->endpoint); - - tpriv->transfer = transfer; - aiocb = &tpriv->aiocb; - bzero(aiocb, sizeof (*aiocb)); - aiocb->aio_fildes = hpriv->eps[ep].datafd; - aiocb->aio_buf = transfer->buffer; - aiocb->aio_nbytes = transfer->length; - aiocb->aio_lio_opcode = - ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) == - LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE; - aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD; - aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv; - aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback; - - if (aiocb->aio_lio_opcode == LIO_READ) { - ret = aio_read(aiocb); - } else { - ret = aio_write(aiocb); - } - - return (ret); -} - -/* return the number of bytes read/written */ -static int -usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status) -{ - int error; - int ret = -1; - - usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s", - fd, stat_fd, size, flag? "WRITE":"READ"); - - switch (flag) { - case READ: - errno = 0; - ret = read(fd, data, size); - usb_dump_data(data, size); - break; - case WRITE: - usb_dump_data(data, size); - errno = 0; - ret = write(fd, data, size); - break; - } - - usbi_dbg("usb_do_io(): amount=%d", ret); - - if (ret < 0) { - int save_errno = errno; - - usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(), - flag?"WRITE":"READ", errno, strerror(errno), ret); - - /* sunos_usb_get_status will do a read and overwrite errno */ - error = sunos_usb_get_status(stat_fd); - usbi_dbg("io status=%d errno=%d(%s)", error, - save_errno, strerror(save_errno)); - - if (status) { - *status = save_errno; - } - - return (save_errno); - - } else if (status) { - *status = 0; - } - - return (ret); -} - -static int -solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) -{ - int ret = -1, setup_ret; - int status; - sunos_dev_handle_priv_t *hpriv; - struct libusb_device_handle *hdl = transfer->dev_handle; - uint16_t wLength; - uint8_t *data = transfer->buffer; - - hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; - wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - if (hpriv->eps[0].datafd == -1) { - usbi_dbg("ep0 not opened"); - - return (LIBUSB_ERROR_NOT_FOUND); - } - - if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { - usbi_dbg("IN request"); - ret = usb_do_io(hpriv->eps[0].datafd, - hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE, - WRITE, (int *)&status); - } else { - usbi_dbg("OUT request"); - ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, - transfer->buffer, transfer->length, WRITE, - (int *)&transfer->status); - } - - setup_ret = ret; - if (ret < LIBUSB_CONTROL_SETUP_SIZE) { - usbi_dbg("error sending control msg: %d", ret); - - return (LIBUSB_ERROR_IO); - } - - ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - /* Read the remaining bytes for IN request */ - if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == - LIBUSB_ENDPOINT_IN)) { - usbi_dbg("DATA: %d", transfer->length - setup_ret); - ret = usb_do_io(hpriv->eps[0].datafd, - hpriv->eps[0].statfd, - (char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, - wLength, READ, (int *)&transfer->status); - } - - if (ret >= 0) { - transfer->actual_length = ret; - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret; - } - usbi_dbg("Done: ctrl data bytes %d", ret); - - /* sync transfer handling */ - ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), - transfer->status); - - return (ret); -} - -int -sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint) -{ - int ret; - - usbi_dbg("endpoint=0x%02x", endpoint); - - ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | - LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD, - LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000); - - usbi_dbg("ret=%d", ret); - - return (ret); -} - -int -sunos_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -sunos_destroy_device(struct libusb_device *dev) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - usbi_dbg("destroy everyting"); - free(dpriv->raw_cfgdescr); - free(dpriv->ugenpath); - free(dpriv->phypath); -} - -int -sunos_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_device_handle *hdl; - int err = 0; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hdl = transfer->dev_handle; - - err = sunos_check_device_and_status_open(hdl, - transfer->endpoint, transfer->type); - if (err < 0) { - - return (_errno_to_libusb(err)); - } - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - /* sync transfer */ - usbi_dbg("CTRL transfer: %d", transfer->length); - err = solaris_submit_ctrl_on_default(transfer); - break; - - case LIBUSB_TRANSFER_TYPE_BULK: - /* fallthru */ - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK) - usbi_dbg("BULK transfer: %d", transfer->length); - else - usbi_dbg("INTR transfer: %d", transfer->length); - err = sunos_do_async_io(transfer); - break; - - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - /* Isochronous/Stream is not supported */ - - /* fallthru */ - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) - usbi_dbg("ISOC transfer: %d", transfer->length); - else - usbi_dbg("BULK STREAM transfer: %d", transfer->length); - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - return (err); -} - -int -sunos_cancel_transfer(struct usbi_transfer *itransfer) -{ - sunos_xfer_priv_t *tpriv; - sunos_dev_handle_priv_t *hpriv; - struct libusb_transfer *transfer; - struct aiocb *aiocb; - uint8_t ep; - int ret; - - tpriv = usbi_transfer_get_os_priv(itransfer); - aiocb = &tpriv->aiocb; - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(transfer->endpoint); - - ret = aio_cancel(hpriv->eps[ep].datafd, aiocb); - - usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes, - hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)? - strerror(0):strerror(errno)); - - if (ret != AIO_CANCELED) { - ret = _errno_to_libusb(errno); - } else { - /* - * we don't need to call usbi_handle_transfer_cancellation(), - * because we'll handle everything in sunos_async_callback. - */ - ret = LIBUSB_SUCCESS; - } - - return (ret); -} - -void -sunos_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -sunos_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -sunos_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - usbi_dbg("error: %s (%d)", strerror(err), err); - - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); - } - - return (LIBUSB_ERROR_OTHER); -} - -/* - * sunos_usb_get_status: - * gets status of endpoint - * - * Returns: ugen's last cmd status - */ -static int -sunos_usb_get_status(int fd) -{ - int status, ret; - - usbi_dbg("sunos_usb_get_status(): fd=%d", fd); - - ret = read(fd, &status, sizeof (status)); - if (ret == sizeof (status)) { - switch (status) { - case USB_LC_STAT_NOERROR: - usbi_dbg("No Error"); - break; - case USB_LC_STAT_CRC: - usbi_dbg("CRC Timeout Detected\n"); - break; - case USB_LC_STAT_BITSTUFFING: - usbi_dbg("Bit Stuffing Violation\n"); - break; - case USB_LC_STAT_DATA_TOGGLE_MM: - usbi_dbg("Data Toggle Mismatch\n"); - break; - case USB_LC_STAT_STALL: - usbi_dbg("End Point Stalled\n"); - break; - case USB_LC_STAT_DEV_NOT_RESP: - usbi_dbg("Device is Not Responding\n"); - break; - case USB_LC_STAT_PID_CHECKFAILURE: - usbi_dbg("PID Check Failure\n"); - break; - case USB_LC_STAT_UNEXP_PID: - usbi_dbg("Unexpected PID\n"); - break; - case USB_LC_STAT_DATA_OVERRUN: - usbi_dbg("Data Exceeded Size\n"); - break; - case USB_LC_STAT_DATA_UNDERRUN: - usbi_dbg("Less data received\n"); - break; - case USB_LC_STAT_BUFFER_OVERRUN: - usbi_dbg("Buffer Size Exceeded\n"); - break; - case USB_LC_STAT_BUFFER_UNDERRUN: - usbi_dbg("Buffer Underrun\n"); - break; - case USB_LC_STAT_TIMEOUT: - usbi_dbg("Command Timed Out\n"); - break; - case USB_LC_STAT_NOT_ACCESSED: - usbi_dbg("Not Accessed by h/w\n"); - break; - case USB_LC_STAT_UNSPECIFIED_ERR: - usbi_dbg("Unspecified Error\n"); - break; - case USB_LC_STAT_NO_BANDWIDTH: - usbi_dbg("No Bandwidth\n"); - break; - case USB_LC_STAT_HW_ERR: - usbi_dbg("Host Controller h/w Error\n"); - break; - case USB_LC_STAT_SUSPENDED: - usbi_dbg("Device was Suspended\n"); - break; - case USB_LC_STAT_DISCONNECTED: - usbi_dbg("Device was Disconnected\n"); - break; - case USB_LC_STAT_INTR_BUF_FULL: - usbi_dbg("Interrupt buffer was full\n"); - break; - case USB_LC_STAT_INVALID_REQ: - usbi_dbg("Request was Invalid\n"); - break; - case USB_LC_STAT_INTERRUPTED: - usbi_dbg("Request was Interrupted\n"); - break; - case USB_LC_STAT_NO_RESOURCES: - usbi_dbg("No resources available for " - "request\n"); - break; - case USB_LC_STAT_INTR_POLLING_FAILED: - usbi_dbg("Failed to Restart Poll"); - break; - default: - usbi_dbg("Error Not Determined %d\n", - status); - break; - } - } else { - usbi_dbg("read stat error: %s",strerror(errno)); - status = -1; - } - - return (status); -} - -const struct usbi_os_backend usbi_backend = { - .name = "Solaris", - .caps = 0, - .init = sunos_init, - .exit = sunos_exit, - .get_device_list = sunos_get_device_list, - .get_device_descriptor = sunos_get_device_descriptor, - .get_active_config_descriptor = sunos_get_active_config_descriptor, - .get_config_descriptor = sunos_get_config_descriptor, - .hotplug_poll = NULL, - .open = sunos_open, - .close = sunos_close, - .get_configuration = sunos_get_configuration, - .set_configuration = sunos_set_configuration, - - .claim_interface = sunos_claim_interface, - .release_interface = sunos_release_interface, - .set_interface_altsetting = sunos_set_interface_altsetting, - .clear_halt = sunos_clear_halt, - .reset_device = sunos_reset_device, /* TODO */ - .alloc_streams = NULL, - .free_streams = NULL, - .kernel_driver_active = sunos_kernel_driver_active, - .detach_kernel_driver = sunos_detach_kernel_driver, - .attach_kernel_driver = sunos_attach_kernel_driver, - .destroy_device = sunos_destroy_device, - .submit_transfer = sunos_submit_transfer, - .cancel_transfer = sunos_cancel_transfer, - .handle_events = NULL, - .clear_transfer_priv = sunos_clear_transfer_priv, - .handle_transfer_completion = sunos_handle_transfer_completion, - .clock_gettime = sunos_clock_gettime, - .device_priv_size = sizeof(sunos_dev_priv_t), - .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), - .transfer_priv_size = sizeof(sunos_xfer_priv_t), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h deleted file mode 100644 index 52bb3d33a0..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright (c) 2016, Oracle and/or its affiliates. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_SUNOS_H -#define LIBUSB_SUNOS_H - -#include -#include -#include "libusbi.h" - -#define READ 0 -#define WRITE 1 - -typedef struct sunos_device_priv { - uint8_t cfgvalue; /* active config value */ - uint8_t *raw_cfgdescr; /* active config descriptor */ - struct libusb_device_descriptor dev_descr; /* usb device descriptor */ - char *ugenpath; /* name of the ugen(4) node */ - char *phypath; /* physical path */ -} sunos_dev_priv_t; - -typedef struct endpoint { - int datafd; /* data file */ - int statfd; /* state file */ -} sunos_ep_priv_t; - -typedef struct sunos_device_handle_priv { - uint8_t altsetting[USB_MAXINTERFACES]; /* a interface's alt */ - uint8_t config_index; - sunos_ep_priv_t eps[USB_MAXENDPOINTS]; - sunos_dev_priv_t *dpriv; /* device private */ -} sunos_dev_handle_priv_t; - -typedef struct sunos_transfer_priv { - struct aiocb aiocb; - struct libusb_transfer *transfer; -} sunos_xfer_priv_t; - -struct node_args { - struct libusb_context *ctx; - struct discovered_devs **discdevs; - const char *last_ugenpath; - di_devlink_handle_t dlink_hdl; -}; - -struct devlink_cbarg { - struct node_args *nargs; /* di node walk arguments */ - di_node_t myself; /* the di node */ - di_minor_t minor; -}; - -typedef struct walk_link { - char *path; - int len; - char **linkpp; -} walk_link_t; - -/* AIO callback args */ -struct aio_callback_args{ - struct libusb_transfer *transfer; - struct aiocb aiocb; -}; - -#endif /* LIBUSB_SUNOS_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c deleted file mode 100644 index 16a7578b81..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * libusb synchronization using POSIX Threads - * - * Copyright © 2011 Vitali Lovich - * Copyright © 2011 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#if defined(__linux__) || defined(__OpenBSD__) -# if defined(__OpenBSD__) -# define _BSD_SOURCE -# endif -# include -# include -#elif defined(__APPLE__) -# include -#elif defined(__CYGWIN__) -# include -#endif - -#include "threads_posix.h" -#include "libusbi.h" - -int usbi_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mutex, const struct timeval *tv) -{ - struct timespec timeout; - int r; - - r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout); - if (r < 0) - return r; - - timeout.tv_sec += tv->tv_sec; - timeout.tv_nsec += tv->tv_usec * 1000; - while (timeout.tv_nsec >= 1000000000L) { - timeout.tv_nsec -= 1000000000L; - timeout.tv_sec++; - } - - return pthread_cond_timedwait(cond, mutex, &timeout); -} - -int usbi_get_tid(void) -{ - int ret; -#if defined(__ANDROID__) - ret = gettid(); -#elif defined(__linux__) - ret = syscall(SYS_gettid); -#elif defined(__OpenBSD__) - /* The following only works with OpenBSD > 5.1 as it requires - real thread support. For 5.1 and earlier, -1 is returned. */ - ret = syscall(SYS_getthrid); -#elif defined(__APPLE__) - ret = (int)pthread_mach_thread_np(pthread_self()); -#elif defined(__CYGWIN__) - ret = GetCurrentThreadId(); -#else - ret = -1; -#endif -/* TODO: NetBSD thread ID support */ - return ret; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h deleted file mode 100644 index 9f1ef94bc7..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * libusb synchronization using POSIX Threads - * - * Copyright © 2010 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_THREADS_POSIX_H -#define LIBUSB_THREADS_POSIX_H - -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -typedef pthread_mutex_t usbi_mutex_static_t; -static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) -{ - (void)pthread_mutex_lock(mutex); -} -static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) -{ - (void)pthread_mutex_unlock(mutex); -} - -typedef pthread_mutex_t usbi_mutex_t; -static inline int usbi_mutex_init(usbi_mutex_t *mutex) -{ - return pthread_mutex_init(mutex, NULL); -} -static inline void usbi_mutex_lock(usbi_mutex_t *mutex) -{ - (void)pthread_mutex_lock(mutex); -} -static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) -{ - (void)pthread_mutex_unlock(mutex); -} -static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) -{ - return pthread_mutex_trylock(mutex); -} -static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) -{ - (void)pthread_mutex_destroy(mutex); -} - -typedef pthread_cond_t usbi_cond_t; -static inline void usbi_cond_init(pthread_cond_t *cond) -{ - (void)pthread_cond_init(cond, NULL); -} -static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) -{ - return pthread_cond_wait(cond, mutex); -} -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv); -static inline void usbi_cond_broadcast(usbi_cond_t *cond) -{ - (void)pthread_cond_broadcast(cond); -} -static inline void usbi_cond_destroy(usbi_cond_t *cond) -{ - (void)pthread_cond_destroy(cond); -} - -typedef pthread_key_t usbi_tls_key_t; -static inline void usbi_tls_key_create(usbi_tls_key_t *key) -{ - (void)pthread_key_create(key, NULL); -} -static inline void *usbi_tls_key_get(usbi_tls_key_t key) -{ - return pthread_getspecific(key); -} -static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) -{ - (void)pthread_setspecific(key, ptr); -} -static inline void usbi_tls_key_delete(usbi_tls_key_t key) -{ - (void)pthread_key_delete(key); -} - -int usbi_get_tid(void); - -#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c deleted file mode 100644 index 409c490553..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * libusb synchronization on Microsoft Windows - * - * Copyright © 2010 Michael Plante - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include - -#include "libusbi.h" - -struct usbi_cond_perthread { - struct list_head list; - HANDLE event; -}; - -void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) -{ - while (InterlockedExchange(mutex, 1L) == 1L) - SleepEx(0, TRUE); -} - -void usbi_cond_init(usbi_cond_t *cond) -{ - list_init(&cond->waiters); - list_init(&cond->not_waiting); -} - -static int usbi_cond_intwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, DWORD timeout_ms) -{ - struct usbi_cond_perthread *pos; - DWORD r; - - // Same assumption as usbi_cond_broadcast() holds - if (list_empty(&cond->not_waiting)) { - pos = malloc(sizeof(*pos)); - if (pos == NULL) - return ENOMEM; // This errno is not POSIX-allowed. - pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if (pos->event == NULL) { - free(pos); - return ENOMEM; - } - } else { - pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list); - list_del(&pos->list); // remove from not_waiting list. - // Ensure the event is clear before waiting - WaitForSingleObject(pos->event, 0); - } - - list_add(&pos->list, &cond->waiters); - - LeaveCriticalSection(mutex); - r = WaitForSingleObject(pos->event, timeout_ms); - EnterCriticalSection(mutex); - - list_del(&pos->list); - list_add(&pos->list, &cond->not_waiting); - - if (r == WAIT_OBJECT_0) - return 0; - else if (r == WAIT_TIMEOUT) - return ETIMEDOUT; - else - return EINVAL; -} - -// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) -{ - return usbi_cond_intwait(cond, mutex, INFINITE); -} - -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv) -{ - DWORD millis; - - millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); - /* round up to next millisecond */ - if (tv->tv_usec % 1000) - millis++; - return usbi_cond_intwait(cond, mutex, millis); -} - -void usbi_cond_broadcast(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - struct usbi_cond_perthread *pos; - - list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) - SetEvent(pos->event); - // The wait function will remove its respective item from the list. -} - -void usbi_cond_destroy(usbi_cond_t *cond) -{ - // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next; - - if (!list_empty(&cond->waiters)) - return; // (!see above!) - list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) { - CloseHandle(pos->event); - list_del(&pos->list); - free(pos); - } -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h deleted file mode 100644 index 409de2d0e2..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * libusb synchronization on Microsoft Windows - * - * Copyright © 2010 Michael Plante - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_THREADS_WINDOWS_H -#define LIBUSB_THREADS_WINDOWS_H - -#define USBI_MUTEX_INITIALIZER 0L -#ifdef _WIN32_WCE -typedef LONG usbi_mutex_static_t; -#else -typedef volatile LONG usbi_mutex_static_t; -#endif -void usbi_mutex_static_lock(usbi_mutex_static_t *mutex); -static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) -{ - InterlockedExchange(mutex, 0L); -} - -typedef CRITICAL_SECTION usbi_mutex_t; -static inline int usbi_mutex_init(usbi_mutex_t *mutex) -{ - InitializeCriticalSection(mutex); - return 0; -} -static inline void usbi_mutex_lock(usbi_mutex_t *mutex) -{ - EnterCriticalSection(mutex); -} -static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) -{ - LeaveCriticalSection(mutex); -} -static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) -{ - return !TryEnterCriticalSection(mutex); -} -static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) -{ - DeleteCriticalSection(mutex); -} - -// We *were* getting timespec from pthread.h: -#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) -#define HAVE_STRUCT_TIMESPEC 1 -#define _TIMESPEC_DEFINED 1 -struct timespec { - long tv_sec; - long tv_nsec; -}; -#endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */ - -// We *were* getting ETIMEDOUT from pthread.h: -#ifndef ETIMEDOUT -#define ETIMEDOUT 10060 /* This is the value in winsock.h. */ -#endif - -typedef struct usbi_cond { - // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread terminates. - struct list_head waiters; - struct list_head not_waiting; -} usbi_cond_t; - -void usbi_cond_init(usbi_cond_t *cond); -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv); -void usbi_cond_broadcast(usbi_cond_t *cond); -void usbi_cond_destroy(usbi_cond_t *cond); - -typedef DWORD usbi_tls_key_t; -static inline void usbi_tls_key_create(usbi_tls_key_t *key) -{ - *key = TlsAlloc(); -} -static inline void *usbi_tls_key_get(usbi_tls_key_t key) -{ - return TlsGetValue(key); -} -static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) -{ - (void)TlsSetValue(key, ptr); -} -static inline void usbi_tls_key_delete(usbi_tls_key_t key) -{ - (void)TlsFree(key); -} - -static inline int usbi_get_tid(void) -{ - return (int)GetCurrentThreadId(); -} - -#endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c deleted file mode 100644 index a0f35e93e5..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Windows CE backend for libusb 1.0 - * Copyright © 2011-2013 RealVNC Ltd. - * Large portions taken from Windows backend, which is - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include "libusbi.h" -#include "wince_usb.h" - -// Global variables -int errno = 0; -static uint64_t hires_frequency, hires_ticks_to_ps; -static HANDLE driver_handle = INVALID_HANDLE_VALUE; -static int concurrent_usage = -1; - -/* - * Converts a windows error to human readable string - * uses retval as errorcode, or, if 0, use GetLastError() - */ -#if defined(ENABLE_LOGGING) -static const char *windows_error_str(DWORD error_code) -{ - static TCHAR wErr_string[ERR_BUFFER_SIZE]; - static char err_string[ERR_BUFFER_SIZE]; - - DWORD size; - int len; - - if (error_code == 0) - error_code = GetLastError(); - - len = sprintf(err_string, "[%u] ", (unsigned int)error_code); - - size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - wErr_string, ERR_BUFFER_SIZE, NULL); - if (size == 0) { - DWORD format_error = GetLastError(); - if (format_error) - snprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", - (unsigned int)error_code, (unsigned int)format_error); - else - snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); - } else { - // Remove CR/LF terminators, if present - size_t pos = size - 2; - if (wErr_string[pos] == 0x0D) - wErr_string[pos] = 0; - - if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL)) - strcpy(err_string, "Unable to convert error string"); - } - - return err_string; -} -#endif - -static struct wince_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct wince_device_priv *)dev->os_priv; -} - -// ceusbkwrapper to libusb error code mapping -static int translate_driver_error(DWORD error) -{ - switch (error) { - case ERROR_INVALID_PARAMETER: - return LIBUSB_ERROR_INVALID_PARAM; - case ERROR_CALL_NOT_IMPLEMENTED: - case ERROR_NOT_SUPPORTED: - return LIBUSB_ERROR_NOT_SUPPORTED; - case ERROR_NOT_ENOUGH_MEMORY: - return LIBUSB_ERROR_NO_MEM; - case ERROR_INVALID_HANDLE: - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_BUSY: - return LIBUSB_ERROR_BUSY; - - // Error codes that are either unexpected, or have - // no suitable LIBUSB_ERROR equivalent. - case ERROR_CANCELLED: - case ERROR_INTERNAL_ERROR: - default: - return LIBUSB_ERROR_OTHER; - } -} - -static BOOL init_dllimports(void) -{ - DLL_GET_HANDLE(ceusbkwrapper); - DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); - - return TRUE; -} - -static void exit_dllimports(void) -{ - DLL_FREE_HANDLE(ceusbkwrapper); -} - -static int init_device( - struct libusb_device *dev, UKW_DEVICE drv_dev, - unsigned char bus_addr, unsigned char dev_addr) -{ - struct wince_device_priv *priv = _device_priv(dev); - int r = LIBUSB_SUCCESS; - - dev->bus_number = bus_addr; - dev->device_address = dev_addr; - priv->dev = drv_dev; - - if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) - r = translate_driver_error(GetLastError()); - - return r; -} - -// Internal API functions -static int wince_init(struct libusb_context *ctx) -{ - int r = LIBUSB_ERROR_OTHER; - HANDLE semaphore; - LARGE_INTEGER li_frequency; - TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphore(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; - } - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if ( ++concurrent_usage == 0 ) { // First init? - // Load DLL imports - if (!init_dllimports()) { - usbi_err(ctx, "could not resolve DLL functions"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // try to open a handle to the driver - driver_handle = UkwOpenDriver(); - if (driver_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not connect to driver"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // find out if we have access to a monotonic (hires) timer - if (QueryPerformanceFrequency(&li_frequency)) { - hires_frequency = li_frequency.QuadPart; - // The hires frequency can go as high as 4 GHz, so we'll use a conversion - // to picoseconds to compute the tv_nsecs part in clock_gettime - hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; - usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); - } else { - usbi_dbg("no hires timer available on this platform"); - hires_frequency = 0; - hires_ticks_to_ps = UINT64_C(0); - } - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here. - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - exit_dllimports(); - - if (driver_handle != INVALID_HANDLE_VALUE) { - UkwCloseDriver(driver_handle); - driver_handle = INVALID_HANDLE_VALUE; - } - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -static void wince_exit(struct libusb_context *ctx) -{ - HANDLE semaphore; - TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - UNUSED(ctx); - - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphore(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - exit_dllimports(); - - if (driver_handle != INVALID_HANDLE_VALUE) { - UkwCloseDriver(driver_handle); - driver_handle = INVALID_HANDLE_VALUE; - } - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int wince_get_device_list( - struct libusb_context *ctx, - struct discovered_devs **discdevs) -{ - UKW_DEVICE devices[MAX_DEVICE_COUNT]; - struct discovered_devs *new_devices = *discdevs; - DWORD count = 0, i; - struct libusb_device *dev = NULL; - unsigned char bus_addr, dev_addr; - unsigned long session_id; - BOOL success; - DWORD release_list_offset = 0; - int r = LIBUSB_SUCCESS; - - success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count); - if (!success) { - int libusbErr = translate_driver_error(GetLastError()); - usbi_err(ctx, "could not get devices: %s", windows_error_str(0)); - return libusbErr; - } - - for (i = 0; i < count; ++i) { - release_list_offset = i; - success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id); - if (!success) { - r = translate_driver_error(GetLastError()); - usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0)); - goto err_out; - } - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - usbi_dbg("using existing device for %u/%u (session %lu)", - bus_addr, dev_addr, session_id); - // Release just this element in the device list (as we already hold a - // reference to it). - UkwReleaseDeviceList(driver_handle, &devices[i], 1); - release_list_offset++; - } else { - usbi_dbg("allocating new device for %u/%u (session %lu)", - bus_addr, dev_addr, session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) { - r = LIBUSB_ERROR_NO_MEM; - goto err_out; - } - - r = init_device(dev, devices[i], bus_addr, dev_addr); - if (r < 0) - goto err_out; - - r = usbi_sanitize_device(dev); - if (r < 0) - goto err_out; - } - - new_devices = discovered_devs_append(new_devices, dev); - if (!new_devices) { - r = LIBUSB_ERROR_NO_MEM; - goto err_out; - } - - libusb_unref_device(dev); - } - - *discdevs = new_devices; - return r; -err_out: - *discdevs = new_devices; - libusb_unref_device(dev); - // Release the remainder of the unprocessed device list. - // The devices added to new_devices already will still be passed up to libusb, - // which can dispose of them at its leisure. - UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset); - return r; -} - -static int wince_open(struct libusb_device_handle *handle) -{ - // Nothing to do to open devices as a handle to it has - // been retrieved by wince_get_device_list - return LIBUSB_SUCCESS; -} - -static void wince_close(struct libusb_device_handle *handle) -{ - // Nothing to do as wince_open does nothing. -} - -static int wince_get_device_descriptor( - struct libusb_device *device, - unsigned char *buffer, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - - *host_endian = 1; - memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH); - return LIBUSB_SUCCESS; -} - -static int wince_get_active_config_descriptor( - struct libusb_device *device, - unsigned char *buffer, size_t len, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - DWORD actualSize = len; - - *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) - return translate_driver_error(GetLastError()); - - return actualSize; -} - -static int wince_get_config_descriptor( - struct libusb_device *device, - uint8_t config_index, - unsigned char *buffer, size_t len, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - DWORD actualSize = len; - - *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) - return translate_driver_error(GetLastError()); - - return actualSize; -} - -static int wince_get_configuration( - struct libusb_device_handle *handle, - int *config) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - UCHAR cv = 0; - - if (!UkwGetConfig(priv->dev, &cv)) - return translate_driver_error(GetLastError()); - - (*config) = cv; - return LIBUSB_SUCCESS; -} - -static int wince_set_configuration( - struct libusb_device_handle *handle, - int config) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - // Setting configuration 0 places the device in Address state. - // This should correspond to the "unconfigured state" required by - // libusb when the specified configuration is -1. - UCHAR cv = (config < 0) ? 0 : config; - if (!UkwSetConfig(priv->dev, cv)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_claim_interface( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwClaimInterface(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_release_interface( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) - return translate_driver_error(GetLastError()); - - if (!UkwReleaseInterface(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_set_interface_altsetting( - struct libusb_device_handle *handle, - int interface_number, int altsetting) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_clear_halt( - struct libusb_device_handle *handle, - unsigned char endpoint) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwClearHaltHost(priv->dev, endpoint)) - return translate_driver_error(GetLastError()); - - if (!UkwClearHaltDevice(priv->dev, endpoint)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_reset_device( - struct libusb_device_handle *handle) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwResetDevice(priv->dev)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_kernel_driver_active( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - BOOL result = FALSE; - - if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) - return translate_driver_error(GetLastError()); - - return result ? 1 : 0; -} - -static int wince_detach_kernel_driver( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwDetachKernelDriver(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_attach_kernel_driver( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwAttachKernelDriver(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static void wince_destroy_device(struct libusb_device *dev) -{ - struct wince_device_priv *priv = _device_priv(dev); - - UkwReleaseDeviceList(driver_handle, &priv->dev, 1); -} - -static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_close(transfer_priv->pollable_fd.fd); - transfer_priv->pollable_fd = INVALID_WINFD; -} - -static int wince_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - BOOL direction_in, ret; - struct winfd wfd; - DWORD flags; - PUKW_CONTROL_HEADER setup = NULL; - const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; - int r; - - if (control_transfer) { - setup = (PUKW_CONTROL_HEADER) transfer->buffer; - direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; - } else { - direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - } - flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; - flags |= UKW_TF_SHORT_TRANSFER_OK; - - wfd = usbi_create_fd(); - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT); - if (r) { - usbi_close(wfd.fd); - return r; - } - - transfer_priv->pollable_fd = wfd; - - if (control_transfer) { - // Split out control setup header and data buffer - DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); - PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)]; - - ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped); - } else { - ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, - transfer->length, &transfer->actual_length, wfd.overlapped); - } - - if (!ret) { - int libusbErr = translate_driver_error(GetLastError()); - usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", - control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); - usbi_remove_pollfd(ctx, wfd.fd); - usbi_close(wfd.fd); - transfer_priv->pollable_fd = INVALID_WINFD; - return libusbErr; - } - - - return LIBUSB_SUCCESS; -} - -static int wince_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return wince_submit_control_or_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static void wince_transfer_callback( - struct usbi_transfer *itransfer, - uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int status; - - usbi_dbg("handling I/O completion with errcode %u", io_result); - - if (io_result == ERROR_NOT_SUPPORTED && - transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) { - /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper - * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the - * endpoint isn't actually stalled. - * - * One example of this is that some devices will occasionally fail to reply to an IN - * token. The WinCE USB layer carries on with the transaction until it is completed - * (or cancelled) but then completes it with USB_ERROR_STALL. - * - * This code therefore needs to confirm that there really is a stall error, by both - * checking the pipe status and requesting the endpoint status from the device. - */ - BOOL halted = FALSE; - usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall"); - if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) { - /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS - * control request to the device. This is done synchronously, which is a bit - * naughty, but this is a special corner case. - */ - WORD wStatus = 0; - DWORD written = 0; - UKW_CONTROL_HEADER ctrlHeader; - ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD | - LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT; - ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS; - ctrlHeader.wValue = 0; - ctrlHeader.wIndex = transfer->endpoint; - ctrlHeader.wLength = sizeof(wStatus); - if (UkwIssueControlTransfer(priv->dev, - UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT, - &ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) { - if (written == sizeof(wStatus) && - (wStatus & STATUS_HALT_FLAG) == 0) { - if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) { - usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success"); - io_result = ERROR_SUCCESS; - } else { - usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error"); - io_result = ERROR_IO_DEVICE; - } - } - } - } - } - - switch(io_result) { - case ERROR_SUCCESS: - itransfer->transferred += io_size; - status = LIBUSB_TRANSFER_COMPLETED; - break; - case ERROR_CANCELLED: - usbi_dbg("detected transfer cancel"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - case ERROR_NOT_SUPPORTED: - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - wince_clear_transfer_priv(itransfer); - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -static void wince_handle_callback( - struct usbi_transfer *itransfer, - uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - wince_transfer_callback (itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -static int wince_handle_events( - struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - struct wince_transfer_priv* transfer_priv = NULL; - POLL_NFDS_TYPE i = 0; - BOOL found = FALSE; - struct usbi_transfer *itransfer; - DWORD io_size, io_result; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { - transfer_priv = usbi_transfer_get_os_priv(itransfer); - if (transfer_priv->pollable_fd.fd == fds[i].fd) { - found = TRUE; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { - io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; - io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; - usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - wince_handle_callback(itransfer, io_result, io_size); - } else if (found) { - usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); - r = LIBUSB_ERROR_OTHER; - break; - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -/* - * Monotonic and real time functions - */ -static int wince_clock_gettime(int clk_id, struct timespec *tp) -{ - LARGE_INTEGER hires_counter; - ULARGE_INTEGER rtime; - FILETIME filetime; - SYSTEMTIME st; - - switch(clk_id) { - case USBI_CLOCK_MONOTONIC: - if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) { - tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); - tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); - return LIBUSB_SUCCESS; - } - // Fall through and return real-time if monotonic read failed or was not detected @ init - case USBI_CLOCK_REALTIME: - // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 - // Note however that our resolution is bounded by the Windows system time - // functions and is at best of the order of 1 ms (or, usually, worse) - GetSystemTime(&st); - SystemTimeToFileTime(&st, &filetime); - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= EPOCH_TIME; - tp->tv_sec = (long)(rtime.QuadPart / 10000000); - tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -const struct usbi_os_backend usbi_backend = { - "Windows CE", - 0, - wince_init, - wince_exit, - NULL, /* set_option() */ - - wince_get_device_list, - NULL, /* hotplug_poll */ - wince_open, - wince_close, - - wince_get_device_descriptor, - wince_get_active_config_descriptor, - wince_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - wince_get_configuration, - wince_set_configuration, - wince_claim_interface, - wince_release_interface, - - wince_set_interface_altsetting, - wince_clear_halt, - wince_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - wince_kernel_driver_active, - wince_detach_kernel_driver, - wince_attach_kernel_driver, - - wince_destroy_device, - - wince_submit_transfer, - wince_cancel_transfer, - wince_clear_transfer_priv, - - wince_handle_events, - NULL, /* handle_transfer_completion() */ - - wince_clock_gettime, - 0, - sizeof(struct wince_device_priv), - 0, - sizeof(struct wince_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h deleted file mode 100644 index edcb9fcc40..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Windows CE backend for libusb 1.0 - * Copyright © 2011-2013 RealVNC Ltd. - * Portions taken from Windows backend, which is - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#pragma once - -#include "windows_common.h" - -#include -#include "poll_windows.h" - -#define MAX_DEVICE_COUNT 256 - -// This is a modified dump of the types in the ceusbkwrapper.h library header -// with functions transformed into extern pointers. -// -// This backend dynamically loads ceusbkwrapper.dll and doesn't include -// ceusbkwrapper.h directly to simplify the build process. The kernel -// side wrapper driver is built using the platform image build tools, -// which makes it difficult to reference directly from the libusb build -// system. -struct UKW_DEVICE_PRIV; -typedef struct UKW_DEVICE_PRIV *UKW_DEVICE; -typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE; - -typedef struct { - UINT8 bLength; - UINT8 bDescriptorType; - UINT16 bcdUSB; - UINT8 bDeviceClass; - UINT8 bDeviceSubClass; - UINT8 bDeviceProtocol; - UINT8 bMaxPacketSize0; - UINT16 idVendor; - UINT16 idProduct; - UINT16 bcdDevice; - UINT8 iManufacturer; - UINT8 iProduct; - UINT8 iSerialNumber; - UINT8 bNumConfigurations; -} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR; - -typedef struct { - UINT8 bmRequestType; - UINT8 bRequest; - UINT16 wValue; - UINT16 wIndex; - UINT16 wLength; -} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER; - -// Collection of flags which can be used when issuing transfer requests -/* Indicates that the transfer direction is 'in' */ -#define UKW_TF_IN_TRANSFER 0x00000001 -/* Indicates that the transfer direction is 'out' */ -#define UKW_TF_OUT_TRANSFER 0x00000000 -/* Specifies that the transfer should complete as soon as possible, - * even if no OVERLAPPED structure has been provided. */ -#define UKW_TF_NO_WAIT 0x00000100 -/* Indicates that transfers shorter than the buffer are ok */ -#define UKW_TF_SHORT_TRANSFER_OK 0x00000200 -#define UKW_TF_SEND_TO_DEVICE 0x00010000 -#define UKW_TF_SEND_TO_INTERFACE 0x00020000 -#define UKW_TF_SEND_TO_ENDPOINT 0x00040000 -/* Don't block when waiting for memory allocations */ -#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000 - -/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor, - * to specify the currently active configuration for the device. */ -#define UKW_ACTIVE_CONFIGURATION -1 - -DLL_DECLARE_HANDLE(ceusbkwrapper); -DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ()); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD)); -DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD)); -DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL)); - -// Used to determine if an endpoint status really is halted on a failed transfer. -#define STATUS_HALT_FLAG 0x1 - -struct wince_device_priv { - UKW_DEVICE dev; - UKW_DEVICE_DESCRIPTOR desc; -}; - -struct wince_transfer_priv { - struct winfd pollable_fd; - uint8_t interface_number; -}; - diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h deleted file mode 100644 index b1725c2e32..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Windows backend common header for libusb 1.0 - * - * This file brings together header code common between - * the desktop Windows and Windows CE backends. - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -// Windows API default is uppercase - ugh! -#if !defined(bool) -#define bool BOOL -#endif -#if !defined(true) -#define true TRUE -#endif -#if !defined(false) -#define false FALSE -#endif - -#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime - -#if defined(__CYGWIN__ ) -#define _stricmp strcasecmp -#define _strdup strdup -// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread -#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) -#endif - -#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0) - -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif - -#define ERR_BUFFER_SIZE 256 - -/* - * API macros - leveraged from libusb-win32 1.x - */ -#ifndef _WIN32_WCE -#define DLL_STRINGIFY(s) #s -#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name)) -#else -#define DLL_STRINGIFY(s) L#s -#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name)) -#endif - -/* - * Macros for handling DLL themselves - */ -#define DLL_HANDLE_NAME(name) __dll_##name##_handle - -#define DLL_DECLARE_HANDLE(name) \ - static HMODULE DLL_HANDLE_NAME(name) = NULL - -#define DLL_GET_HANDLE(name) \ - do { \ - DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \ - if (!DLL_HANDLE_NAME(name)) \ - return FALSE; \ - } while (0) - -#define DLL_FREE_HANDLE(name) \ - do { \ - if (DLL_HANDLE_NAME(name)) { \ - FreeLibrary(DLL_HANDLE_NAME(name)); \ - DLL_HANDLE_NAME(name) = NULL; \ - } \ - } while (0) - - -/* - * Macros for handling functions within a DLL - */ -#define DLL_FUNC_NAME(name) __dll_##name##_func_t - -#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ - typedef ret (api * DLL_FUNC_NAME(name))args; \ - static DLL_FUNC_NAME(name) prefixname = NULL - -#define DLL_DECLARE_FUNC(api, ret, name, args) \ - DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) -#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args) \ - DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args) - -#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ - do { \ - HMODULE h = DLL_HANDLE_NAME(dll); \ - prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ - DLL_STRINGIFY(name)); \ - if (prefixname) \ - break; \ - prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ - if (prefixname) \ - break; \ - prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ - if (prefixname) \ - break; \ - if (ret_on_failure) \ - return FALSE; \ - } while (0) - -#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ - DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) -#define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure) \ - DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure) diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c deleted file mode 100644 index 92dbde5a84..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software - * Hash table functions adapted from glibc, by Ulrich Drepper et al. - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include - -#include "libusbi.h" -#include "windows_common.h" -#include "windows_nt_common.h" - -// Public -BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); -enum windows_version windows_version = WINDOWS_UNDEFINED; - - // Global variables for init/exit -static unsigned int init_count = 0; -static bool usbdk_available = false; - -// Global variables for clock_gettime mechanism -static uint64_t hires_ticks_to_ps; -static uint64_t hires_frequency; - -#define TIMER_REQUEST_RETRY_MS 100 -#define WM_TIMER_REQUEST (WM_USER + 1) -#define WM_TIMER_EXIT (WM_USER + 2) - -// used for monotonic clock_gettime() -struct timer_request { - struct timespec *tp; - HANDLE event; -}; - -// Timer thread -static HANDLE timer_thread = NULL; -static DWORD timer_thread_id = 0; - -/* Kernel32 dependencies */ -DLL_DECLARE_HANDLE(Kernel32); -/* This call is only available from XP SP2 */ -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); - -/* User32 dependencies */ -DLL_DECLARE_HANDLE(User32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); - -static unsigned __stdcall windows_clock_gettime_threaded(void *param); - -/* -* Converts a windows error to human readable string -* uses retval as errorcode, or, if 0, use GetLastError() -*/ -#if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD error_code) -{ - static char err_string[ERR_BUFFER_SIZE]; - - DWORD size; - int len; - - if (error_code == 0) - error_code = GetLastError(); - - len = sprintf(err_string, "[%u] ", (unsigned int)error_code); - - // Translate codes returned by SetupAPI. The ones we are dealing with are either - // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. - // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx - switch (error_code & 0xE0000000) { - case 0: - error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified - break; - case 0xE0000000: - error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); - break; - default: - break; - } - - size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - &err_string[len], ERR_BUFFER_SIZE - len, NULL); - if (size == 0) { - DWORD format_error = GetLastError(); - if (format_error) - snprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", - (unsigned int)error_code, (unsigned int)format_error); - else - snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); - } else { - // Remove CRLF from end of message, if present - size_t pos = len + size - 2; - if (err_string[pos] == '\r') - err_string[pos] = '\0'; - } - - return err_string; -} -#endif - -static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx) -{ - return (struct windows_context_priv *)ctx->os_priv; -} - -/* Hash table functions - modified From glibc 2.3.2: - [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 - [Knuth] The Art of Computer Programming, part 3 (6.4) */ - -#define HTAB_SIZE 1021UL // *MUST* be a prime number!! - -typedef struct htab_entry { - unsigned long used; - char *str; -} htab_entry; - -static htab_entry *htab_table = NULL; -static usbi_mutex_t htab_mutex; -static unsigned long htab_filled; - -/* Before using the hash table we must allocate memory for it. - We allocate one element more as the found prime number says. - This is done for more effective indexing as explained in the - comment for the hash function. */ -static bool htab_create(struct libusb_context *ctx) -{ - if (htab_table != NULL) { - usbi_err(ctx, "hash table already allocated"); - return true; - } - - // Create a mutex - usbi_mutex_init(&htab_mutex); - - usbi_dbg("using %lu entries hash table", HTAB_SIZE); - htab_filled = 0; - - // allocate memory and zero out. - htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry)); - if (htab_table == NULL) { - usbi_err(ctx, "could not allocate space for hash table"); - return false; - } - - return true; -} - -/* After using the hash table it has to be destroyed. */ -static void htab_destroy(void) -{ - unsigned long i; - - if (htab_table == NULL) - return; - - for (i = 0; i < HTAB_SIZE; i++) - free(htab_table[i].str); - - safe_free(htab_table); - - usbi_mutex_destroy(&htab_mutex); -} - -/* This is the search function. It uses double hashing with open addressing. - We use a trick to speed up the lookup. The table is created with one - more element available. This enables us to use the index zero special. - This index will never be used because we store the first hash index in - the field used where zero means not used. Every other value means used. - The used field can be used as a first fast comparison for equality of - the stored and the parameter value. This helps to prevent unnecessary - expensive calls of strcmp. */ -unsigned long htab_hash(const char *str) -{ - unsigned long hval, hval2; - unsigned long idx; - unsigned long r = 5381; - int c; - const char *sz = str; - - if (str == NULL) - return 0; - - // Compute main hash value (algorithm suggested by Nokia) - while ((c = *sz++) != 0) - r = ((r << 5) + r) + c; - if (r == 0) - ++r; - - // compute table hash: simply take the modulus - hval = r % HTAB_SIZE; - if (hval == 0) - ++hval; - - // Try the first index - idx = hval; - - // Mutually exclusive access (R/W lock would be better) - usbi_mutex_lock(&htab_mutex); - - if (htab_table[idx].used) { - if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) - goto out_unlock; // existing hash - - usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str); - - // Second hash function, as suggested in [Knuth] - hval2 = 1 + hval % (HTAB_SIZE - 2); - - do { - // Because size is prime this guarantees to step through all available indexes - if (idx <= hval2) - idx = HTAB_SIZE + idx - hval2; - else - idx -= hval2; - - // If we visited all entries leave the loop unsuccessfully - if (idx == hval) - break; - - // If entry is found use it. - if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) - goto out_unlock; - } while (htab_table[idx].used); - } - - // Not found => New entry - - // If the table is full return an error - if (htab_filled >= HTAB_SIZE) { - usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE); - idx = 0; - goto out_unlock; - } - - htab_table[idx].str = _strdup(str); - if (htab_table[idx].str == NULL) { - usbi_err(NULL, "could not duplicate string for hash table"); - idx = 0; - goto out_unlock; - } - - htab_table[idx].used = hval; - ++htab_filled; - -out_unlock: - usbi_mutex_unlock(&htab_mutex); - - return idx; -} - -/* -* Make a transfer complete synchronously -*/ -void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size) -{ - overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - overlapped->InternalHigh = size; - SetEvent(overlapped->hEvent); -} - -static BOOL windows_init_dlls(void) -{ - DLL_GET_HANDLE(Kernel32); - DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); - pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED)) - GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx"); - usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : ""); - - DLL_GET_HANDLE(User32); - DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); - DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); - DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); - - return TRUE; -} - -static void windows_exit_dlls(void) -{ - DLL_FREE_HANDLE(Kernel32); - DLL_FREE_HANDLE(User32); -} - -static bool windows_init_clock(struct libusb_context *ctx) -{ - DWORD_PTR affinity, dummy; - HANDLE event; - LARGE_INTEGER li_frequency; - int i; - - if (QueryPerformanceFrequency(&li_frequency)) { - // The hires frequency can go as high as 4 GHz, so we'll use a conversion - // to picoseconds to compute the tv_nsecs part in clock_gettime - hires_frequency = li_frequency.QuadPart; - hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; - usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); - - // Because QueryPerformanceCounter might report different values when - // running on different cores, we create a separate thread for the timer - // calls, which we glue to the first available core always to prevent timing discrepancies. - if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) { - usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0)); - return false; - } - - // The process affinity mask is a bitmask where each set bit represents a core on - // which this process is allowed to run, so we find the first set bit - for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++); - affinity = (DWORD_PTR)(1 << i); - - usbi_dbg("timer thread will run on core #%d", i); - - event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (event == NULL) { - usbi_err(ctx, "could not create event: %s", windows_error_str(0)); - return false; - } - - timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event, - 0, (unsigned int *)&timer_thread_id); - if (timer_thread == NULL) { - usbi_err(ctx, "unable to create timer thread - aborting"); - CloseHandle(event); - return false; - } - - if (!SetThreadAffinityMask(timer_thread, affinity)) - usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise"); - - // Wait for timer thread to init before continuing. - if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failed to wait for timer thread to become ready - aborting"); - CloseHandle(event); - return false; - } - - CloseHandle(event); - } else { - usbi_dbg("no hires timer available on this platform"); - hires_frequency = 0; - hires_ticks_to_ps = UINT64_C(0); - } - - return true; -} - -static void windows_destroy_clock(void) -{ - if (timer_thread) { - // actually the signal to quit the thread. - if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) - || (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) { - usbi_dbg("could not wait for timer thread to quit"); - TerminateThread(timer_thread, 1); - // shouldn't happen, but we're destroying - // all objects it might have held anyway. - } - CloseHandle(timer_thread); - timer_thread = NULL; - timer_thread_id = 0; - } -} - -/* Windows version detection */ -static BOOL is_x64(void) -{ - BOOL ret = FALSE; - - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - if (pIsWow64Process != NULL) - pIsWow64Process(GetCurrentProcess(), &ret); - } else { - ret = TRUE; - } - - return ret; -} - -static void get_windows_version(void) -{ - OSVERSIONINFOEXA vi, vi2; - const char *arch, *w = NULL; - unsigned major, minor, version; - ULONGLONG major_equal, minor_equal; - BOOL ws; - - windows_version = WINDOWS_UNDEFINED; - - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) - return; - } - - if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) - return; - - if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) { - // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version - // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx - - major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - for (major = vi.dwMajorVersion; major <= 9; major++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMajorVersion = major; - if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) - continue; - - if (vi.dwMajorVersion < major) { - vi.dwMajorVersion = major; - vi.dwMinorVersion = 0; - } - - minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); - for (minor = vi.dwMinorVersion; minor <= 9; minor++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMinorVersion = minor; - if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) - continue; - - vi.dwMinorVersion = minor; - break; - } - - break; - } - } - - if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf)) - return; - - ws = (vi.wProductType <= VER_NT_WORKSTATION); - version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; - switch (version) { - case 0x50: windows_version = WINDOWS_2000; w = "2000"; break; - case 0x51: windows_version = WINDOWS_XP; w = "XP"; break; - case 0x52: windows_version = WINDOWS_2003; w = "2003"; break; - case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break; - case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break; - case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break; - case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break; - case 0x64: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break; - default: - if (version < 0x50) { - return; - } else { - windows_version = WINDOWS_11_OR_LATER; - w = "11 or later"; - } - } - - arch = is_x64() ? "64-bit" : "32-bit"; - - if (vi.wServicePackMinor) - usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch); - else if (vi.wServicePackMajor) - usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch); - else - usbi_dbg("Windows %s %s", w, arch); -} - -/* -* Monotonic and real time functions -*/ -static unsigned __stdcall windows_clock_gettime_threaded(void *param) -{ - struct timer_request *request; - LARGE_INTEGER hires_counter; - MSG msg; - - // The following call will create this thread's message queue - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx - pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); - - // Signal windows_init_clock() that we're ready to service requests - if (!SetEvent((HANDLE)param)) - usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0)); - param = NULL; - - // Main loop - wait for requests - while (1) { - if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) { - usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0)); - return 1; - } - - switch (msg.message) { - case WM_TIMER_REQUEST: - // Requests to this thread are for hires always - // Microsoft says that this function always succeeds on XP and later - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx - request = (struct timer_request *)msg.lParam; - QueryPerformanceCounter(&hires_counter); - request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); - request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); - if (!SetEvent(request->event)) - usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0)); - break; - case WM_TIMER_EXIT: - usbi_dbg("timer thread quitting"); - return 0; - } - } -} - -static void windows_transfer_callback(const struct windows_backend *backend, - struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) -{ - int status, istatus; - - usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size); - - switch (io_result) { - case NO_ERROR: - status = backend->copy_transfer_data(itransfer, (uint32_t)io_size); - break; - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size); - if (istatus != LIBUSB_TRANSFER_COMPLETED) - usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - case ERROR_FILE_NOT_FOUND: - usbi_dbg("detected device removed"); - status = LIBUSB_TRANSFER_NO_DEVICE; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - backend->clear_transfer_priv(itransfer); // Cancel polling - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -static void windows_handle_callback(const struct windows_backend *backend, - struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_transfer_callback(backend, itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -static int windows_init(struct libusb_context *ctx) -{ - struct windows_context_priv *priv = _context_priv(ctx); - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - int r = LIBUSB_ERROR_OTHER; - bool winusb_backend_init = false; - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; - } - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if (++init_count == 1) { // First init? - // Load DLL imports - if (!windows_init_dlls()) { - usbi_err(ctx, "could not resolve DLL functions"); - goto init_exit; - } - - get_windows_version(); - - if (windows_version == WINDOWS_UNDEFINED) { - usbi_err(ctx, "failed to detect Windows version"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - if (!windows_init_clock(ctx)) - goto init_exit; - - if (!htab_create(ctx)) - goto init_exit; - - r = winusb_backend.init(ctx); - if (r != LIBUSB_SUCCESS) - goto init_exit; - winusb_backend_init = true; - - r = usbdk_backend.init(ctx); - if (r == LIBUSB_SUCCESS) { - usbi_dbg("UsbDk backend is available"); - usbdk_available = true; - } else { - usbi_info(ctx, "UsbDk backend is not available"); - // Do not report this as an error - r = LIBUSB_SUCCESS; - } - } - - // By default, new contexts will use the WinUSB backend - priv->backend = &winusb_backend; - - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here - if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed? - if (winusb_backend_init) - winusb_backend.exit(ctx); - htab_destroy(); - windows_destroy_clock(); - windows_exit_dlls(); - --init_count; - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -static void windows_exit(struct libusb_context *ctx) -{ - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - UNUSED(ctx); - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--init_count == 0) { // Last exit - if (usbdk_available) { - usbdk_backend.exit(ctx); - usbdk_available = false; - } - winusb_backend.exit(ctx); - htab_destroy(); - windows_destroy_clock(); - windows_exit_dlls(); - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) -{ - struct windows_context_priv *priv = _context_priv(ctx); - - UNUSED(ap); - - switch (option) { - case LIBUSB_OPTION_USE_USBDK: - if (usbdk_available) { - usbi_dbg("switching context %p to use UsbDk backend", ctx); - priv->backend = &usbdk_backend; - } else { - usbi_err(ctx, "UsbDk backend not available"); - return LIBUSB_ERROR_NOT_FOUND; - } - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_NOT_SUPPORTED; - } - -} - -static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs) -{ - struct windows_context_priv *priv = _context_priv(ctx); - return priv->backend->get_device_list(ctx, discdevs); -} - -static int windows_open(struct libusb_device_handle *dev_handle) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->open(dev_handle); -} - -static void windows_close(struct libusb_device_handle *dev_handle) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - priv->backend->close(dev_handle); -} - -static int windows_get_device_descriptor(struct libusb_device *dev, - unsigned char *buffer, int *host_endian) -{ - struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); - *host_endian = 0; - return priv->backend->get_device_descriptor(dev, buffer); -} - -static int windows_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); - *host_endian = 0; - return priv->backend->get_active_config_descriptor(dev, buffer, len); -} - -static int windows_get_config_descriptor(struct libusb_device *dev, - uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); - *host_endian = 0; - return priv->backend->get_config_descriptor(dev, config_index, buffer, len); -} - -static int windows_get_config_descriptor_by_value(struct libusb_device *dev, - uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian) -{ - struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); - *host_endian = 0; - return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer); -} - -static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->get_configuration(dev_handle, config); -} - -static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->set_configuration(dev_handle, config); -} - -static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->claim_interface(dev_handle, interface_number); -} - -static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->release_interface(dev_handle, interface_number); -} - -static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, - int interface_number, int altsetting) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting); -} - -static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->clear_halt(dev_handle, endpoint); -} - -static int windows_reset_device(struct libusb_device_handle *dev_handle) -{ - struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); - return priv->backend->reset_device(dev_handle); -} - -static void windows_destroy_device(struct libusb_device *dev) -{ - struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); - priv->backend->destroy_device(dev); -} - -static int windows_submit_transfer(struct usbi_transfer *itransfer) -{ - struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); - return priv->backend->submit_transfer(itransfer); -} - -static int windows_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); - return priv->backend->cancel_transfer(itransfer); -} - -static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); - priv->backend->clear_transfer_priv(itransfer); -} - -static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - struct windows_context_priv *priv = _context_priv(ctx); - struct usbi_transfer *itransfer; - DWORD io_size, io_result; - POLL_NFDS_TYPE i; - bool found; - int transfer_fd; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - found = false; - transfer_fd = -1; - usbi_mutex_lock(&ctx->flying_transfers_lock); - list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { - transfer_fd = priv->backend->get_transfer_fd(itransfer); - if (transfer_fd == fds[i].fd) { - found = true; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found) { - priv->backend->get_overlapped_result(itransfer, &io_result, &io_size); - - usbi_remove_pollfd(ctx, transfer_fd); - - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - windows_handle_callback(priv->backend, itransfer, io_result, io_size); - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -static int windows_clock_gettime(int clk_id, struct timespec *tp) -{ - struct timer_request request; -#if !defined(_MSC_VER) || (_MSC_VER < 1900) - FILETIME filetime; - ULARGE_INTEGER rtime; -#endif - DWORD r; - - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - if (timer_thread) { - request.tp = tp; - request.event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (request.event == NULL) - return LIBUSB_ERROR_NO_MEM; - - if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) { - usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0)); - CloseHandle(request.event); - return LIBUSB_ERROR_OTHER; - } - - do { - r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS); - if (r == WAIT_TIMEOUT) - usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); - else if (r == WAIT_FAILED) - usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0)); - } while (r == WAIT_TIMEOUT); - CloseHandle(request.event); - - if (r == WAIT_OBJECT_0) - return LIBUSB_SUCCESS; - else - return LIBUSB_ERROR_OTHER; - } - // Fall through and return real-time if monotonic was not detected @ timer init - case USBI_CLOCK_REALTIME: -#if defined(_MSC_VER) && (_MSC_VER >= 1900) - timespec_get(tp, TIME_UTC); -#else - // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 - // Note however that our resolution is bounded by the Windows system time - // functions and is at best of the order of 1 ms (or, usually, worse) - GetSystemTimeAsFileTime(&filetime); - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= EPOCH_TIME; - tp->tv_sec = (long)(rtime.QuadPart / 10000000); - tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); -#endif - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -// NB: MSVC6 does not support named initializers. -const struct usbi_os_backend usbi_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - windows_init, - windows_exit, - windows_set_option, - windows_get_device_list, - NULL, /* hotplug_poll */ - windows_open, - windows_close, - windows_get_device_descriptor, - windows_get_active_config_descriptor, - windows_get_config_descriptor, - windows_get_config_descriptor_by_value, - windows_get_configuration, - windows_set_configuration, - windows_claim_interface, - windows_release_interface, - windows_set_interface_altsetting, - windows_clear_halt, - windows_reset_device, - NULL, /* alloc_streams */ - NULL, /* free_streams */ - NULL, /* dev_mem_alloc */ - NULL, /* dev_mem_free */ - NULL, /* kernel_driver_active */ - NULL, /* detach_kernel_driver */ - NULL, /* attach_kernel_driver */ - windows_destroy_device, - windows_submit_transfer, - windows_cancel_transfer, - windows_clear_transfer_priv, - windows_handle_events, - NULL, /* handle_transfer_completion */ - windows_clock_gettime, - sizeof(struct windows_context_priv), - sizeof(union windows_device_priv), - sizeof(union windows_device_handle_priv), - sizeof(union windows_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h deleted file mode 100644 index e155b5d3e3..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Windows backend common header for libusb 1.0 - * - * This file brings together header code common between - * the desktop Windows backends. - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "windows_nt_shared_types.h" - - /* Windows versions */ -enum windows_version { - WINDOWS_UNDEFINED, - WINDOWS_2000, - WINDOWS_XP, - WINDOWS_2003, // Also XP x64 - WINDOWS_VISTA, - WINDOWS_7, - WINDOWS_8, - WINDOWS_8_1, - WINDOWS_10, - WINDOWS_11_OR_LATER -}; - -extern enum windows_version windows_version; - -/* This call is only available from Vista */ -extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); - -struct windows_backend { - int (*init)(struct libusb_context *ctx); - void (*exit)(struct libusb_context *ctx); - int (*get_device_list)(struct libusb_context *ctx, - struct discovered_devs **discdevs); - int (*open)(struct libusb_device_handle *dev_handle); - void (*close)(struct libusb_device_handle *dev_handle); - int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer); - int (*get_active_config_descriptor)(struct libusb_device *device, - unsigned char *buffer, size_t len); - int (*get_config_descriptor)(struct libusb_device *device, - uint8_t config_index, unsigned char *buffer, size_t len); - int (*get_config_descriptor_by_value)(struct libusb_device *device, - uint8_t bConfigurationValue, unsigned char **buffer); - int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); - int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); - int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); - int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); - int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, - int interface_number, int altsetting); - int (*clear_halt)(struct libusb_device_handle *dev_handle, - unsigned char endpoint); - int (*reset_device)(struct libusb_device_handle *dev_handle); - void (*destroy_device)(struct libusb_device *dev); - int (*submit_transfer)(struct usbi_transfer *itransfer); - int (*cancel_transfer)(struct usbi_transfer *itransfer); - void (*clear_transfer_priv)(struct usbi_transfer *itransfer); - int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size); - int (*get_transfer_fd)(struct usbi_transfer *itransfer); - void (*get_overlapped_result)(struct usbi_transfer *itransfer, - DWORD *io_result, DWORD *io_size); -}; - -struct windows_context_priv { - const struct windows_backend *backend; -}; - -union windows_device_priv { - struct usbdk_device_priv usbdk_priv; - struct winusb_device_priv winusb_priv; -}; - -union windows_device_handle_priv { - struct usbdk_device_handle_priv usbdk_priv; - struct winusb_device_handle_priv winusb_priv; -}; - -union windows_transfer_priv { - struct usbdk_transfer_priv usbdk_priv; - struct winusb_transfer_priv winusb_priv; -}; - -extern const struct windows_backend usbdk_backend; -extern const struct windows_backend winusb_backend; - -unsigned long htab_hash(const char *str); -void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size); - -#if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD error_code); -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h deleted file mode 100644 index 68bf261d5d..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -#include "windows_common.h" - -#include - -typedef struct USB_DEVICE_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - USHORT bcdUSB; - UCHAR bDeviceClass; - UCHAR bDeviceSubClass; - UCHAR bDeviceProtocol; - UCHAR bMaxPacketSize0; - USHORT idVendor; - USHORT idProduct; - USHORT bcdDevice; - UCHAR iManufacturer; - UCHAR iProduct; - UCHAR iSerialNumber; - UCHAR bNumConfigurations; -} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; - -typedef struct USB_CONFIGURATION_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wTotalLength; - UCHAR bNumInterfaces; - UCHAR bConfigurationValue; - UCHAR iConfiguration; - UCHAR bmAttributes; - UCHAR MaxPower; -} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; - -#include - -#define MAX_DEVICE_ID_LEN 200 - -typedef struct USB_DK_DEVICE_ID { - WCHAR DeviceID[MAX_DEVICE_ID_LEN]; - WCHAR InstanceID[MAX_DEVICE_ID_LEN]; -} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; - -typedef struct USB_DK_DEVICE_INFO { - USB_DK_DEVICE_ID ID; - ULONG64 FilterID; - ULONG64 Port; - ULONG64 Speed; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; -} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; - -typedef struct USB_DK_ISO_TRANSFER_RESULT { - ULONG64 ActualLength; - ULONG64 TransferResult; -} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; - -typedef struct USB_DK_GEN_TRANSFER_RESULT { - ULONG64 BytesTransferred; - ULONG64 UsbdStatus; // USBD_STATUS code -} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; - -typedef struct USB_DK_TRANSFER_RESULT { - USB_DK_GEN_TRANSFER_RESULT GenResult; - PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT -} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; - -typedef struct USB_DK_TRANSFER_REQUEST { - ULONG64 EndpointAddress; - PVOID64 Buffer; - ULONG64 BufferLength; - ULONG64 TransferType; - ULONG64 IsochronousPacketsArraySize; - PVOID64 IsochronousPacketsArray; - USB_DK_TRANSFER_RESULT Result; -} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; - -struct usbdk_device_priv { - USB_DK_DEVICE_INFO info; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; - HANDLE redirector_handle; - HANDLE system_handle; - uint8_t active_configuration; -}; - -struct winusb_device_priv { - bool initialized; - bool root_hub; - uint8_t active_config; - uint8_t depth; // distance to HCD - const struct windows_usb_api_backend *apib; - char *dev_id; - char *path; // device interface path - int sub_api; // for WinUSB-like APIs - struct { - char *path; // each interface needs a device interface path, - const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support), - int sub_api; - int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) - uint8_t *endpoint; - bool restricted_functionality; // indicates if the interface functionality is restricted - // by Windows (eg. HID keyboards or mice cannot do R/W) - } usb_interface[USB_MAXINTERFACES]; - struct hid_device_priv *hid; - USB_DEVICE_DESCRIPTOR dev_descriptor; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors -}; - -struct usbdk_device_handle_priv { - // Not currently used - char dummy; -}; - -struct winusb_device_handle_priv { - int active_interface; - struct { - HANDLE dev_handle; // WinUSB needs an extra handle for the file - HANDLE api_handle; // used by the API to communicate with the device - } interface_handle[USB_MAXINTERFACES]; - int autoclaim_count[USB_MAXINTERFACES]; // For auto-release -}; - -struct usbdk_transfer_priv { - USB_DK_TRANSFER_REQUEST request; - struct winfd pollable_fd; - HANDLE system_handle; - PULONG64 IsochronousPacketsArray; - PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; -}; - -struct winusb_transfer_priv { - struct winfd pollable_fd; - HANDLE handle; - uint8_t interface_number; - uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID - uint8_t *hid_dest; // transfer buffer destination, required for HID - size_t hid_expected_size; - void *iso_context; -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c deleted file mode 100644 index fbccbd5cff..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c +++ /dev/null @@ -1,830 +0,0 @@ -/* - * windows UsbDk backend for libusb 1.0 - * Copyright © 2014 Red Hat, Inc. - - * Authors: - * Dmitry Fleytman - * Pavel Gurvich - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include "libusbi.h" -#include "windows_common.h" -#include "windows_nt_common.h" -#include "windows_usbdk.h" - -#if !defined(STATUS_SUCCESS) -typedef LONG NTSTATUS; -#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) -#endif - -#if !defined(STATUS_CANCELLED) -#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) -#endif - -#if !defined(STATUS_REQUEST_CANCELED) -#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) -#endif - -#if !defined(USBD_SUCCESS) -typedef LONG USBD_STATUS; -#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) -#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) -#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) -#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) -#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) -#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) -#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) -#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) -#endif - -static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) -{ - return (struct usbdk_device_priv *)dev->os_priv; -} - -static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) -{ - return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer); -} - -static struct { - HMODULE module; - - USBDK_GET_DEVICES_LIST GetDevicesList; - USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; - USBDK_START_REDIRECT StartRedirect; - USBDK_STOP_REDIRECT StopRedirect; - USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; - USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; - USBDK_READ_PIPE ReadPipe; - USBDK_WRITE_PIPE WritePipe; - USBDK_ABORT_PIPE AbortPipe; - USBDK_RESET_PIPE ResetPipe; - USBDK_SET_ALTSETTING SetAltsetting; - USBDK_RESET_DEVICE ResetDevice; - USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; -} usbdk_helper; - -static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) -{ - FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); - - if (api_ptr == NULL) - usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0)); - - return api_ptr; -} - -static void unload_usbdk_helper_dll(void) -{ - if (usbdk_helper.module != NULL) { - FreeLibrary(usbdk_helper.module); - usbdk_helper.module = NULL; - } -} - -static int load_usbdk_helper_dll(struct libusb_context *ctx) -{ - usbdk_helper.module = LoadLibraryA("UsbDkHelper"); - if (usbdk_helper.module == NULL) { - usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0)); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); - if (usbdk_helper.GetDevicesList == NULL) - goto error_unload; - - usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); - if (usbdk_helper.ReleaseDevicesList == NULL) - goto error_unload; - - usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); - if (usbdk_helper.StartRedirect == NULL) - goto error_unload; - - usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); - if (usbdk_helper.StopRedirect == NULL) - goto error_unload; - - usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); - if (usbdk_helper.GetConfigurationDescriptor == NULL) - goto error_unload; - - usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); - if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) - goto error_unload; - - usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); - if (usbdk_helper.ReadPipe == NULL) - goto error_unload; - - usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); - if (usbdk_helper.WritePipe == NULL) - goto error_unload; - - usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); - if (usbdk_helper.AbortPipe == NULL) - goto error_unload; - - usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); - if (usbdk_helper.ResetPipe == NULL) - goto error_unload; - - usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); - if (usbdk_helper.SetAltsetting == NULL) - goto error_unload; - - usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); - if (usbdk_helper.ResetDevice == NULL) - goto error_unload; - - usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); - if (usbdk_helper.GetRedirectorSystemHandle == NULL) - goto error_unload; - - return LIBUSB_SUCCESS; - -error_unload: - FreeLibrary(usbdk_helper.module); - usbdk_helper.module = NULL; - return LIBUSB_ERROR_NOT_FOUND; -} - -static int usbdk_init(struct libusb_context *ctx) -{ - SC_HANDLE managerHandle; - SC_HANDLE serviceHandle; - - managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); - if (managerHandle == NULL) { - usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0)); - return LIBUSB_ERROR_OTHER; - } - - serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ); - CloseServiceHandle(managerHandle); - - if (serviceHandle == NULL) { - if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) - usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0)); - return LIBUSB_ERROR_NOT_FOUND; - } - - CloseServiceHandle(serviceHandle); - - return load_usbdk_helper_dll(ctx); -} - -static void usbdk_exit(struct libusb_context *ctx) -{ - UNUSED(ctx); - unload_usbdk_helper_dll(); -} - -static int usbdk_get_session_id_for_device(struct libusb_context *ctx, - PUSB_DK_DEVICE_ID id, unsigned long *session_id) -{ - char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1]; - - if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) { - usbi_warn(ctx, "cannot form device identity", id->DeviceID); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - *session_id = htab_hash(dev_identity); - - return LIBUSB_SUCCESS; -} - -static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count) -{ - uint8_t i; - - for (i = 0; i < count; i++) - usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); - - free(p->config_descriptors); - p->config_descriptors = NULL; -} - -static int usbdk_cache_config_descriptors(struct libusb_context *ctx, - struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info) -{ - uint8_t i; - USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; - Request.ID = info->ID; - - p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); - if (p->config_descriptors == NULL) { - usbi_err(ctx, "failed to allocate configuration descriptors holder"); - return LIBUSB_ERROR_NO_MEM; - } - - for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { - ULONG Length; - - Request.Index = i; - if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) { - usbi_err(ctx, "failed to retrieve configuration descriptors"); - usbdk_release_config_descriptors(p, i); - return LIBUSB_ERROR_OTHER; - } - } - - return LIBUSB_SUCCESS; -} - -static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info) -{ - struct usbdk_device_priv *p = _usbdk_device_priv(dev); - - p->info = *info; - p->active_configuration = 0; - - return usbdk_cache_config_descriptors(ctx, p, info); -} - -static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) -{ - dev->bus_number = (uint8_t)info->FilterID; - dev->port_number = (uint8_t)info->Port; - dev->parent_dev = NULL; - - // Addresses in libusb are 1-based - dev->device_address = (uint8_t)(info->Port + 1); - - dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; - memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); - - switch (info->Speed) { - case LowSpeed: - dev->speed = LIBUSB_SPEED_LOW; - break; - case FullSpeed: - dev->speed = LIBUSB_SPEED_FULL; - break; - case HighSpeed: - dev->speed = LIBUSB_SPEED_HIGH; - break; - case SuperSpeed: - dev->speed = LIBUSB_SPEED_SUPER; - break; - case NoSpeed: - default: - dev->speed = LIBUSB_SPEED_UNKNOWN; - break; - } -} - -static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) -{ - int r = LIBUSB_SUCCESS; - ULONG i; - struct discovered_devs *discdevs = NULL; - ULONG dev_number; - PUSB_DK_DEVICE_INFO devices; - - if (!usbdk_helper.GetDevicesList(&devices, &dev_number)) - return LIBUSB_ERROR_OTHER; - - for (i = 0; i < dev_number; i++) { - unsigned long session_id; - struct libusb_device *dev = NULL; - - if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) - continue; - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - usbi_err(ctx, "failed to allocate a new device structure"); - continue; - } - - usbdk_device_init(dev, &devices[i]); - if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - continue; - } - } - - discdevs = discovered_devs_append(*_discdevs, dev); - libusb_unref_device(dev); - if (!discdevs) { - usbi_err(ctx, "cannot append new device to list"); - r = LIBUSB_ERROR_NO_MEM; - goto func_exit; - } - - *_discdevs = discdevs; - } - -func_exit: - usbdk_helper.ReleaseDevicesList(devices); - return r; -} - -static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - - memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); - - return LIBUSB_SUCCESS; -} - -static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; - - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; - - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index]; - - size = min(config_header->wTotalLength, len); - memcpy(buffer, config_header, size); - return (int)size; -} - -static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, - unsigned char **buffer) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - uint8_t index; - - for (index = 0; index < dev->num_configurations; index++) { - config_header = priv->config_descriptors[index]; - if (config_header->bConfigurationValue == bConfigurationValue) { - *buffer = (unsigned char *)priv->config_descriptors[index]; - return (int)config_header->wTotalLength; - } - } - - return LIBUSB_ERROR_NOT_FOUND; -} - -static int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) -{ - return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, - buffer, len); -} - -static int usbdk_open(struct libusb_device_handle *dev_handle) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); - if (priv->redirector_handle == INVALID_HANDLE_VALUE) { - usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); - return LIBUSB_ERROR_OTHER; - } - - priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - return LIBUSB_SUCCESS; -} - -static void usbdk_close(struct libusb_device_handle *dev_handle) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.StopRedirect(priv->redirector_handle)) - usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed"); -} - -static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; - - return LIBUSB_SUCCESS; -} - -static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - UNUSED(dev_handle); - UNUSED(config); - return LIBUSB_SUCCESS; -} - -static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_SUCCESS; -} - -static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = HANDLE_CTX(dev_handle); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { - usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_SUCCESS; -} - -static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = HANDLE_CTX(dev_handle); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_reset_device(struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = HANDLE_CTX(dev_handle); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { - usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static void usbdk_destroy_device(struct libusb_device *dev) -{ - struct usbdk_device_priv* p = _usbdk_device_priv(dev); - - if (p->config_descriptors != NULL) - usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); -} - -static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - usbi_close(transfer_priv->pollable_fd.fd); - transfer_priv->pollable_fd = INVALID_WINFD; - transfer_priv->system_handle = NULL; - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - safe_free(transfer_priv->IsochronousPacketsArray); - safe_free(transfer_priv->IsochronousResultsArray); - } -} - -static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; - TransferResult transResult; - - transfer_priv->request.Buffer = (PVOID64)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.TransferType = ControlTransferType; - - if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) - transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); - else - transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); - - switch (transResult) { - case TransferSuccess: - windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); - break; - case TransferSuccessAsync: - break; - case TransferFailure: - usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; - TransferResult transferRes; - - transfer_priv->request.Buffer = (PVOID64)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - transfer_priv->request.TransferType = BulkTransferType; - break; - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - transfer_priv->request.TransferType = InterruptTransferType; - break; - default: - usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); - else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); - - switch (transferRes) { - case TransferSuccess: - windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); - break; - case TransferSuccessAsync: - break; - case TransferFailure: - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; - TransferResult transferRes; - int i; - - transfer_priv->request.Buffer = (PVOID64)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - transfer_priv->request.TransferType = IsochronousTransferType; - transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; - transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); - transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray; - if (!transfer_priv->IsochronousPacketsArray) { - usbi_err(ctx, "Allocation of IsochronousPacketsArray failed"); - return LIBUSB_ERROR_NO_MEM; - } - - transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); - transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray; - if (!transfer_priv->IsochronousResultsArray) { - usbi_err(ctx, "Allocation of isochronousResultsArray failed"); - return LIBUSB_ERROR_NO_MEM; - } - - for (i = 0; i < transfer->num_iso_packets; i++) - transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; - - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); - else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); - - switch (transferRes) { - case TransferSuccess: - windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); - break; - case TransferSuccessAsync: - break; - case TransferFailure: - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer, - short events, int (*transfer_fn)(struct usbi_transfer *)) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct winfd wfd; - int r; - - wfd = usbi_create_fd(); - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_add_pollfd(ctx, wfd.fd, events); - if (r) { - usbi_close(wfd.fd); - return r; - } - - // Use transfer_priv to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->system_handle = priv->system_handle; - - r = transfer_fn(itransfer); - if (r != LIBUSB_SUCCESS) { - usbi_remove_pollfd(ctx, wfd.fd); - usbdk_clear_transfer_priv(itransfer); - return r; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int (*transfer_fn)(struct usbi_transfer *); - short events; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; - transfer_fn = usbdk_do_control_transfer; - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk - events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; - transfer_fn = usbdk_do_bulk_transfer; - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; - transfer_fn = usbdk_do_iso_transfer; - break; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - return usbdk_do_submit_transfer(itransfer, events, transfer_fn); -} - -static int usbdk_abort_transfers(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct winfd *pollable_fd = &transfer_priv->pollable_fd; - - if (pCancelIoEx != NULL) { - // Use CancelIoEx if available to cancel just a single transfer - if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) { - usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } else { - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - // Control transfers cancelled by IoCancelXXX() API - // No special treatment needed - return LIBUSB_SUCCESS; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_abort_transfers(itransfer); - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) -{ - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; -} - -static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer) -{ - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - return transfer_priv->pollable_fd.fd; -} - -static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) -{ - if (USBD_SUCCESS(UsbdStatus)) - return NO_ERROR; - - switch (UsbdStatus) { - case USBD_STATUS_TIMEOUT: - return ERROR_SEM_TIMEOUT; - case USBD_STATUS_CANCELED: - return ERROR_OPERATION_ABORTED; - default: - return ERROR_GEN_FAILURE; - } -} - -static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size) -{ - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct winfd *pollable_fd = &transfer_priv->pollable_fd; - - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first - || GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - ULONG64 i; - for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { - struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; - - switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { - case STATUS_SUCCESS: - case STATUS_CANCELLED: - case STATUS_REQUEST_CANCELED: - lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS - break; - default: - lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; - break; - } - - lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength; - } - } - - *io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred; - *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus); - } else { - *io_result = GetLastError(); - } -} - -const struct windows_backend usbdk_backend = { - usbdk_init, - usbdk_exit, - usbdk_get_device_list, - usbdk_open, - usbdk_close, - usbdk_get_device_descriptor, - usbdk_get_active_config_descriptor, - usbdk_get_config_descriptor, - usbdk_get_config_descriptor_by_value, - usbdk_get_configuration, - usbdk_set_configuration, - usbdk_claim_interface, - usbdk_release_interface, - usbdk_set_interface_altsetting, - usbdk_clear_halt, - usbdk_reset_device, - usbdk_destroy_device, - usbdk_submit_transfer, - usbdk_cancel_transfer, - usbdk_clear_transfer_priv, - usbdk_copy_transfer_data, - usbdk_get_transfer_fd, - usbdk_get_overlapped_result, -}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h deleted file mode 100644 index 77660ae97f..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -* windows UsbDk backend for libusb 1.0 -* Copyright © 2014 Red Hat, Inc. - -* Authors: -* Dmitry Fleytman -* Pavel Gurvich -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#pragma once - -#include "windows_nt_common.h" - -typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST { - USB_DK_DEVICE_ID ID; - ULONG64 Index; -} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; - -typedef enum { - TransferFailure = 0, - TransferSuccess, - TransferSuccessAsync -} TransferResult; - -typedef enum { - NoSpeed = 0, - LowSpeed, - FullSpeed, - HighSpeed, - SuperSpeed -} USB_DK_DEVICE_SPEED; - -typedef enum { - ControlTransferType, - BulkTransferType, - InterruptTransferType, - IsochronousTransferType -} USB_DK_TRANSFER_TYPE; - -typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)( - PUSB_DK_DEVICE_INFO *DeviceInfo, - PULONG DeviceNumber -); -typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)( - PUSB_DK_DEVICE_INFO DeviceInfo -); -typedef HANDLE (__cdecl *USBDK_START_REDIRECT)( - PUSB_DK_DEVICE_ID DeviceId -); -typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)( - HANDLE DeviceHandle -); -typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)( - PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, - PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, - PULONG Length -); -typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)( - PUSB_CONFIGURATION_DESCRIPTOR Descriptor -); -typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)( - HANDLE DeviceHandle, - PUSB_DK_TRANSFER_REQUEST Request, - LPOVERLAPPED lpOverlapped -); -typedef TransferResult (__cdecl *USBDK_READ_PIPE)( - HANDLE DeviceHandle, - PUSB_DK_TRANSFER_REQUEST Request, - LPOVERLAPPED lpOverlapped -); -typedef BOOL (__cdecl *USBDK_ABORT_PIPE)( - HANDLE DeviceHandle, - ULONG64 PipeAddress -); -typedef BOOL (__cdecl *USBDK_RESET_PIPE)( - HANDLE DeviceHandle, - ULONG64 PipeAddress -); -typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)( - HANDLE DeviceHandle, - ULONG64 InterfaceIdx, - ULONG64 AltSettingIdx -); -typedef BOOL (__cdecl *USBDK_RESET_DEVICE)( - HANDLE DeviceHandle -); -typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)( - HANDLE DeviceHandle -); diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c deleted file mode 100644 index ce1b55cd61..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c +++ /dev/null @@ -1,3009 +0,0 @@ -/* - * windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * Copyright © 2016-2018 Chris Dickens - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software - * Hash table functions adapted from glibc, by Ulrich Drepper et al. - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "windows_common.h" -#include "windows_nt_common.h" -#include "windows_winusb.h" - -// Unfuckup the 'inferface' keyword -#undef interface - -#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE)) - -// The 2 macros below are used in conjunction with safe loops. -#define LOOP_CHECK(fcall) \ - { \ - r = fcall; \ - if (r != LIBUSB_SUCCESS) \ - continue; \ - } -#define LOOP_BREAK(err) \ - { \ - r = err; \ - continue; \ - } - -// WinUSB-like API prototypes -static int winusbx_init(struct libusb_context *ctx); -static void winusbx_exit(void); -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -// Composite API prototypes -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); - -static usbi_mutex_t autoclaim_lock; - -// API globals -static HMODULE WinUSBX_handle = NULL; -static struct winusb_interface WinUSBX[SUB_API_MAX]; -#define CHECK_WINUSBX_AVAILABLE(sub_api) \ - do { \ - if (sub_api == SUB_API_NOTSET) \ - sub_api = priv->sub_api; \ - if (!WinUSBX[sub_api].initialized) \ - return LIBUSB_ERROR_ACCESS; \ - } while (0) - -static bool api_hid_available = false; -#define CHECK_HID_AVAILABLE \ - do { \ - if (!api_hid_available) \ - return LIBUSB_ERROR_ACCESS; \ - } while (0) - -#if defined(ENABLE_LOGGING) -static const char *guid_to_string(const GUID *guid) -{ - static char guid_string[MAX_GUID_STRING_LENGTH]; - - if (guid == NULL) - return ""; - - sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - (unsigned int)guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); - - return guid_string; -} -#endif - -/* - * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. - * Return an allocated sanitized string or NULL on error. - */ -static char *sanitize_path(const char *path) -{ - const char root_prefix[] = {'\\', '\\', '.', '\\'}; - size_t j, size; - char *ret_path; - size_t add_root = 0; - - if (path == NULL) - return NULL; - - size = strlen(path) + 1; - - // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. - if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) - || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { - add_root = sizeof(root_prefix); - size += add_root; - } - - ret_path = malloc(size); - if (ret_path == NULL) - return NULL; - - strcpy(&ret_path[add_root], path); - - // Ensure consistency with root prefix - memcpy(ret_path, root_prefix, sizeof(root_prefix)); - - // Same goes for '\' and '#' after the root prefix. Ensure '#' is used - for (j = sizeof(root_prefix); j < size; j++) { - ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too - if (ret_path[j] == '\\') - ret_path[j] = '#'; - } - - return ret_path; -} - -/* - * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions - */ -static BOOL init_dlls(void) -{ - DLL_GET_HANDLE(Cfgmgr32); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); - - // Prefixed to avoid conflict with header files - DLL_GET_HANDLE(AdvAPI32); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); - - DLL_GET_HANDLE(OLE32); - DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE); - - DLL_GET_HANDLE(SetupAPI); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - - return TRUE; -} - -static void exit_dlls(void) -{ - DLL_FREE_HANDLE(Cfgmgr32); - DLL_FREE_HANDLE(AdvAPI32); - DLL_FREE_HANDLE(OLE32); - DLL_FREE_HANDLE(SetupAPI); -} - -/* - * enumerate interfaces for the whole USB class - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * enumerator: the generic USB class for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static bool get_devinfo_data(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index) -{ - if (_index == 0) { - *dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); - if (*dev_info == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s", - enumerator, windows_error_str(0)); - return false; - } - } - - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s", - enumerator, _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return false; - } - return true; -} - -/* - * enumerate interfaces for a specific GUID - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * guid: the GUID for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info, - PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details; - DWORD size; - - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - for (;;) { - if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { - usbi_err(ctx, "Could not obtain device info data for %s index %u: %s", - guid_to_string(guid), *_index, windows_error_str(0)); - return LIBUSB_ERROR_OTHER; - } - - // No more devices - return LIBUSB_SUCCESS; - } - - // Always advance the index for the next iteration - (*_index)++; - - if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data)) - break; - - if (GetLastError() != ERROR_NO_MORE_ITEMS) { - usbi_err(ctx, "Could not obtain interface data for %s devInst %X: %s", - guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); - return LIBUSB_ERROR_OTHER; - } - - // Device does not have an interface matching this GUID, skip - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for %s devInst %X: %s", - guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); - return LIBUSB_ERROR_OTHER; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong"); - return LIBUSB_ERROR_OTHER; - } - - dev_interface_details = malloc(size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for %s devInst %X", - guid_to_string(guid), dev_info_data->DevInst); - return LIBUSB_ERROR_NO_MEM; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, - dev_interface_details, size, NULL, NULL)) { - usbi_err(ctx, "could not access interface data (actual) for %s devInst %X: %s", - guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); - free(dev_interface_details); - return LIBUSB_ERROR_OTHER; - } - - *dev_interface_path = sanitize_path(dev_interface_details->DevicePath); - free(dev_interface_details); - - if (*dev_interface_path == NULL) { - usbi_err(ctx, "could not allocate interface path for %s devInst %X", - guid_to_string(guid), dev_info_data->DevInst); - return LIBUSB_ERROR_NO_MEM; - } - - return LIBUSB_SUCCESS; -} - -/* For libusb0 filter */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; - DWORD size; - - if (_index == 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; - } - - dev_interface_details = calloc(1, size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); - - // [trobinso] lookup the libusb0 symbolic index. - if (dev_interface_details) { - HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); - if (hkey_device_interface != INVALID_HANDLE_VALUE) { - DWORD libusb0_symboliclink_index = 0; - DWORD value_length = sizeof(DWORD); - DWORD value_type = 0; - LONG status; - - status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, - (LPBYTE)&libusb0_symboliclink_index, &value_length); - if (status == ERROR_SUCCESS) { - if (libusb0_symboliclink_index < 256) { - // libusb0.sys is connected to this device instance. - // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. - sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); - usbi_dbg("assigned libusb0 symbolic link %s", filter_path); - } else { - // libusb0.sys was connected to this device instance at one time; but not anymore. - } - } - pRegCloseKey(hkey_device_interface); - } - } - - return dev_interface_details; - -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; -} - -/* - * Returns the first known ancestor of a device - */ -static struct libusb_device *get_ancestor(struct libusb_context *ctx, - DEVINST devinst, PDEVINST _parent_devinst) -{ - struct libusb_device *dev = NULL; - DEVINST parent_devinst; - - while (dev == NULL) { - if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) - break; - devinst = parent_devinst; - dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst); - } - - if ((dev != NULL) && (_parent_devinst != NULL)) - *_parent_devinst = devinst; - - return dev; -} - -/* - * Determine which interface the given endpoint address belongs to - */ -static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep) -{ - const struct libusb_interface *intf; - const struct libusb_interface_descriptor *intf_desc; - int i, j, k; - - for (i = 0; i < conf_desc->bNumInterfaces; i++) { - intf = &conf_desc->interface[i]; - for (j = 0; j < intf->num_altsetting; j++) { - intf_desc = &intf->altsetting[j]; - for (k = 0; k < intf_desc->bNumEndpoints; k++) { - if (intf_desc->endpoint[k].bEndpointAddress == ep) { - usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i); - return intf_desc->bInterfaceNumber; - } - } - } - } - - usbi_dbg("endpoint %02X not found on any interface", ep); - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * Populate the endpoints addresses of the device_priv interface helper structs - */ -static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - int i, r; - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - const struct libusb_interface_descriptor *if_desc; - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); - if (r != LIBUSB_SUCCESS) { - usbi_warn(ctx, "could not read config descriptor: error %d", r); - return r; - } - - if_desc = &conf_desc->interface[iface].altsetting[altsetting]; - safe_free(priv->usb_interface[iface].endpoint); - - if (if_desc->bNumEndpoints == 0) { - usbi_dbg("no endpoints found for interface %d", iface); - libusb_free_config_descriptor(conf_desc); - return LIBUSB_SUCCESS; - } - - priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); - if (priv->usb_interface[iface].endpoint == NULL) { - libusb_free_config_descriptor(conf_desc); - return LIBUSB_ERROR_NO_MEM; - } - - priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; - for (i = 0; i < if_desc->bNumEndpoints; i++) { - priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; - usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); - } - libusb_free_config_descriptor(conf_desc); - - // Extra init may be required to configure endpoints - if (priv->apib->configure_endpoints) - r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); - - return r; -} - -// Lookup for a match in the list of API driver names -// return -1 if not found, driver match number otherwise -static int get_sub_api(char *driver, int api) -{ - int i; - const char sep_str[2] = {LIST_SEPARATOR, 0}; - char *tok, *tmp_str; - size_t len = strlen(driver); - - if (len == 0) - return SUB_API_NOTSET; - - tmp_str = _strdup(driver); - if (tmp_str == NULL) - return SUB_API_NOTSET; - - tok = strtok(tmp_str, sep_str); - while (tok != NULL) { - for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { - if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { - free(tmp_str); - return i; - } - } - tok = strtok(NULL, sep_str); - } - - free(tmp_str); - return SUB_API_NOTSET; -} - -/* - * auto-claiming and auto-release helper functions - */ -static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) -{ - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv( - transfer->dev_handle); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = *interface_number; - int r = LIBUSB_SUCCESS; - - switch (api_type) { - case USB_API_WINUSBX: - case USB_API_HID: - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_mutex_lock(&autoclaim_lock); - if (current_interface < 0) { // No serviceable interface was found - for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { - // Must claim an interface of the same API type - if ((priv->usb_interface[current_interface].apib->id == api_type) - && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { - usbi_dbg("auto-claimed interface %d for control request", current_interface); - if (handle_priv->autoclaim_count[current_interface] != 0) - usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); - handle_priv->autoclaim_count[current_interface]++; - break; - } - } - if (current_interface == USB_MAXINTERFACES) { - usbi_err(ctx, "could not auto-claim any interface"); - r = LIBUSB_ERROR_NOT_FOUND; - } - } else { - // If we have a valid interface that was autoclaimed, we must increment - // its autoclaim count so that we can prevent an early release. - if (handle_priv->autoclaim_count[current_interface] != 0) - handle_priv->autoclaim_count[current_interface]++; - } - usbi_mutex_unlock(&autoclaim_lock); - - *interface_number = current_interface; - return r; -} - -static void auto_release(struct usbi_transfer *itransfer) -{ - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - libusb_device_handle *dev_handle = transfer->dev_handle; - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - int r; - - usbi_mutex_lock(&autoclaim_lock); - if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) { - handle_priv->autoclaim_count[transfer_priv->interface_number]--; - if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { - r = libusb_release_interface(dev_handle, transfer_priv->interface_number); - if (r == LIBUSB_SUCCESS) - usbi_dbg("auto-released interface %d", transfer_priv->interface_number); - else - usbi_dbg("failed to auto-release interface %d (%s)", - transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); - } - } - usbi_mutex_unlock(&autoclaim_lock); -} - -/* - * init: libusb backend init function - */ -static int winusb_init(struct libusb_context *ctx) -{ - int i; - - // We need a lock for proper auto-release - usbi_mutex_init(&autoclaim_lock); - - // Load DLL imports - if (!init_dlls()) { - usbi_err(ctx, "could not resolve DLL functions"); - return LIBUSB_ERROR_OTHER; - } - - // Initialize the low level APIs (we don't care about errors at this stage) - for (i = 0; i < USB_API_MAX; i++) { - if (usb_api_backend[i].init && usb_api_backend[i].init(ctx)) - usbi_warn(ctx, "error initializing %s backend", - usb_api_backend[i].designation); - } - - return LIBUSB_SUCCESS; -} - -/* -* exit: libusb backend deinitialization function -*/ -static void winusb_exit(struct libusb_context *ctx) -{ - int i; - - for (i = 0; i < USB_API_MAX; i++) { - if (usb_api_backend[i].exit) - usb_api_backend[i].exit(); - } - - exit_dlls(); - usbi_mutex_destroy(&autoclaim_lock); -} - -/* - * fetch and cache all the config descriptors through I/O - */ -static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct winusb_device_priv *priv = _device_priv(dev); - DWORD size, ret_size; - uint8_t i; - - USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request - PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request - PUSB_CONFIGURATION_DESCRIPTOR cd_data; - - if (dev->num_configurations == 0) - return; - - priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); - if (priv->config_descriptor == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id); - return; - } - - for (i = 0; i <= dev->num_configurations; i++) { - safe_free(cd_buf_actual); - - if (i == dev->num_configurations) - break; - - size = sizeof(cd_buf_short); - memset(&cd_buf_short, 0, size); - - cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number; - cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; - cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; - cd_buf_short.req.SetupPacket.wIndex = 0; - cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR); - - // Dummy call to get the required data size. Initial failures are reported as info rather - // than error as they can occur for non-penalizing situations, such as with some hubs. - // coverity[tainted_data_argument] - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, - &cd_buf_short, size, &ret_size, NULL)) { - usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0)); - continue; - } - - if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { - usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id); - continue; - } - - size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength; - cd_buf_actual = malloc(size); - if (cd_buf_actual == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); - continue; - } - - // Actual call - cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number; - cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; - cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; - cd_buf_actual->SetupPacket.wIndex = 0; - cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength; - - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, - cd_buf_actual, size, &ret_size, NULL)) { - usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0)); - continue; - } - - cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); - - if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) { - usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id); - continue; - } - - if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) { - usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id); - continue; - } - - usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)", - i, cd_data->bConfigurationValue, cd_data->wTotalLength); - - // Cache the descriptor - priv->config_descriptor[i] = malloc(cd_data->wTotalLength); - if (priv->config_descriptor[i] != NULL) { - memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); - } else { - usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); - } - } -} - -/* - * Populate a libusb device structure - */ -static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, - uint8_t port_number, DEVINST devinst) -{ - struct libusb_context *ctx; - struct libusb_device *tmp_dev; - struct winusb_device_priv *priv, *parent_priv; - USB_NODE_CONNECTION_INFORMATION_EX conn_info; - USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; - HANDLE hub_handle; - DWORD size; - uint8_t bus_number, depth; - int r; - - priv = _device_priv(dev); - - // If the device is already initialized, we can stop here - if (priv->initialized) - return LIBUSB_SUCCESS; - - if (parent_dev != NULL) { // Not a HCD root hub - ctx = DEVICE_CTX(dev); - parent_priv = _device_priv(parent_dev); - if (parent_priv->apib->id != USB_API_HUB) { - usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - // Calculate depth and fetch bus number - bus_number = parent_dev->bus_number; - if (bus_number == 0) { - tmp_dev = get_ancestor(ctx, devinst, &devinst); - if (tmp_dev != parent_dev) { - usbi_err(ctx, "program assertion failed - first ancestor is not parent"); - return LIBUSB_ERROR_NOT_FOUND; - } - libusb_unref_device(tmp_dev); - - for (depth = 1; bus_number == 0; depth++) { - tmp_dev = get_ancestor(ctx, devinst, &devinst); - if (tmp_dev->bus_number != 0) { - bus_number = tmp_dev->bus_number; - depth += _device_priv(tmp_dev)->depth; - } - libusb_unref_device(tmp_dev); - } - } else { - depth = parent_priv->depth + 1; - } - - if (bus_number == 0) { - usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - dev->bus_number = bus_number; - dev->port_number = port_number; - dev->parent_dev = parent_dev; - priv->depth = depth; - - hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - 0, NULL); - if (hub_handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - - memset(&conn_info, 0, sizeof(conn_info)); - conn_info.ConnectionIndex = (ULONG)port_number; - // coverity[tainted_data_argument] - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), - &conn_info, sizeof(conn_info), &size, NULL)) { - usbi_warn(ctx, "could not get node connection information for device '%s': %s", - priv->dev_id, windows_error_str(0)); - CloseHandle(hub_handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); - CloseHandle(hub_handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); - dev->num_configurations = priv->dev_descriptor.bNumConfigurations; - priv->active_config = conn_info.CurrentConfigurationValue; - usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); - - // Cache as many config descriptors as we can - cache_config_descriptors(dev, hub_handle); - - // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 - if (windows_version >= WINDOWS_8) { - conn_info_v2.ConnectionIndex = (ULONG)port_number; - conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); - conn_info_v2.SupportedUsbProtocols.Usb300 = 1; - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, - &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) { - usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", - priv->dev_id, windows_error_str(0)); - } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { - conn_info.Speed = 3; - } - } - - CloseHandle(hub_handle); - - if (conn_info.DeviceAddress > UINT8_MAX) - usbi_err(ctx, "program assertion failed - device address overflow"); - - dev->device_address = (uint8_t)conn_info.DeviceAddress; - - switch (conn_info.Speed) { - case 0: dev->speed = LIBUSB_SPEED_LOW; break; - case 1: dev->speed = LIBUSB_SPEED_FULL; break; - case 2: dev->speed = LIBUSB_SPEED_HIGH; break; - case 3: dev->speed = LIBUSB_SPEED_SUPER; break; - default: - usbi_warn(ctx, "unknown device speed %u", conn_info.Speed); - break; - } - } - - r = usbi_sanitize_device(dev); - if (r) - return r; - - priv->initialized = true; - - usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", - dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id); - - return LIBUSB_SUCCESS; -} - -static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, - uint8_t bus_number, DEVINST devinst) -{ - struct libusb_device *dev; - struct winusb_device_priv *priv; - unsigned long session_id; - DEVINST child_devinst; - - if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) { - usbi_err(ctx, "could not get child devinst for '%s'", dev_id); - return LIBUSB_ERROR_OTHER; - } - - session_id = (unsigned long)child_devinst; - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (dev->bus_number == 0) { - // Only do this once - usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number); - priv = _device_priv(dev); - dev->bus_number = bus_number; - dev->num_configurations = 1; - priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE; - priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE; - priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB; - priv->dev_descriptor.bNumConfigurations = 1; - priv->active_config = 1; - priv->root_hub = true; - if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) { - usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id); - priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub - priv->dev_descriptor.idProduct = 1; - } - } - - libusb_unref_device(dev); - return LIBUSB_SUCCESS; -} - -// Returns the api type, or 0 if not found/unsupported -static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, - SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) -{ - // Precedence for filter drivers vs driver is in the order of this array - struct driver_lookup lookup[3] = { - {"\0\0", SPDRP_SERVICE, "driver"}, - {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"}, - {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"} - }; - DWORD size, reg_type; - unsigned k, l; - int i, j; - - // Check the service & filter names to know the API we should use - for (k = 0; k < 3; k++) { - if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, - ®_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) { - // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ - if (lookup[k].reg_prop == SPDRP_SERVICE) - // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed - lookup[k].list[strlen(lookup[k].list) + 1] = 0; - - // MULTI_SZ is a pain to work with. Turn it into something much more manageable - // NB: none of the driver names we check against contain LIST_SEPARATOR, - // (currently ';'), so even if an unsuported one does, it's not an issue - for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { - if (lookup[k].list[l] == 0) - lookup[k].list[l] = LIST_SEPARATOR; - } - usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); - } else { - if (GetLastError() != ERROR_INVALID_DATA) - usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); - lookup[k].list[0] = 0; - } - } - - for (i = 2; i < USB_API_MAX; i++) { - for (k = 0; k < 3; k++) { - j = get_sub_api(lookup[k].list, i); - if (j >= 0) { - usbi_dbg("matched %s name against %s", lookup[k].designation, - (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]); - *api = i; - *sub_api = j; - return; - } - } - } -} - -static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path, char *device_id, int api, int sub_api) -{ - struct winusb_device_priv *priv = _device_priv(dev); - int interface_number; - const char *mi_str; - - // Because MI_## are not necessarily in sequential order (some composite - // devices will have only MI_00 & MI_03 for instance), we retrieve the actual - // interface number from the path's MI value - mi_str = strstr(device_id, "MI_"); - if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) { - interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0'); - } else { - usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id); - interface_number = 0; - } - - if (interface_number >= USB_MAXINTERFACES) { - usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path); - return LIBUSB_ERROR_ACCESS; - } - - if (priv->usb_interface[interface_number].path != NULL) { - if (api == USB_API_HID) { - // HID devices can have multiple collections (COL##) for each MI_## interface - usbi_dbg("interface[%d] already set - ignoring HID collection: %s", - interface_number, device_id); - return LIBUSB_ERROR_ACCESS; - } - // In other cases, just use the latest data - safe_free(priv->usb_interface[interface_number].path); - } - - usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); - priv->usb_interface[interface_number].path = dev_interface_path; - priv->usb_interface[interface_number].apib = &usb_api_backend[api]; - priv->usb_interface[interface_number].sub_api = sub_api; - if ((api == USB_API_HID) && (priv->hid == NULL)) { - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - return LIBUSB_ERROR_NO_MEM; - } - - return LIBUSB_SUCCESS; -} - -static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path) -{ - int i; - struct winusb_device_priv *priv = _device_priv(dev); - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed: parent is not HID"); - return LIBUSB_ERROR_NO_DEVICE; - } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { - usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); - return LIBUSB_ERROR_NO_DEVICE; - } - - for (i = 0; i < priv->hid->nb_interfaces; i++) { - if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { - usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); - return LIBUSB_ERROR_ACCESS; - } - } - - priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; - priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; - usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path); - priv->hid->nb_interfaces++; - return LIBUSB_SUCCESS; -} - -/* - * get_device_list: libusb backend device enumeration function - */ -static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) -{ - struct discovered_devs *discdevs; - HDEVINFO *dev_info, dev_info_intf, dev_info_enum; - SP_DEVINFO_DATA dev_info_data; - DWORD _index = 0; - GUID hid_guid; - int r = LIBUSB_SUCCESS; - int api, sub_api; - unsigned int pass, i, j; - char enumerator[16]; - char dev_id[MAX_PATH_LENGTH]; - struct libusb_device *dev, *parent_dev; - struct winusb_device_priv *priv, *parent_priv; - char *dev_interface_path = NULL; - unsigned long session_id; - DWORD size, port_nr, reg_type, install_state; - HKEY key; - WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; - GUID *if_guid; - LONG s; -#define HUB_PASS 0 -#define DEV_PASS 1 -#define HCD_PASS 2 -#define GEN_PASS 3 -#define HID_PASS 4 -#define EXT_PASS 5 - // Keep a list of guids that will be enumerated -#define GUID_SIZE_STEP 8 - const GUID **guid_list, **new_guid_list; - unsigned int guid_size = GUID_SIZE_STEP; - unsigned int nb_guids; - // Keep a list of PnP enumerator strings that are found - char *usb_enumerator[8] = { "USB" }; - unsigned int nb_usb_enumerators = 1; - unsigned int usb_enum_index = 0; - // Keep a list of newly allocated devs to unref -#define UNREF_SIZE_STEP 16 - libusb_device **unref_list, **new_unref_list; - unsigned int unref_size = UNREF_SIZE_STEP; - unsigned int unref_cur = 0; - - // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) - // PASS 2 : (re)enumerate HUBS - // PASS 3 : (re)enumerate generic USB devices (including driverless) - // and list additional USB device interface GUIDs to explore - // PASS 4 : (re)enumerate master USB devices that have a device interface - // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and - // set the device interfaces. - - // Init the GUID table - guid_list = malloc(guid_size * sizeof(void *)); - if (guid_list == NULL) { - usbi_err(ctx, "failed to alloc guid list"); - return LIBUSB_ERROR_NO_MEM; - } - - guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; - guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; - guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; - guid_list[GEN_PASS] = NULL; - if (api_hid_available) { - HidD_GetHidGuid(&hid_guid); - guid_list[HID_PASS] = &hid_guid; - } else { - guid_list[HID_PASS] = NULL; - } - nb_guids = EXT_PASS; - - unref_list = malloc(unref_size * sizeof(void *)); - if (unref_list == NULL) { - usbi_err(ctx, "failed to alloc unref list"); - free((void *)guid_list); - return LIBUSB_ERROR_NO_MEM; - } - - dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (dev_info_intf == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0)); - free(unref_list); - free((void *)guid_list); - return LIBUSB_ERROR_OTHER; - } - - for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { -//#define ENUM_DEBUG -#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) - const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; - usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass])); -#endif - if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) - continue; - - dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum; - - for (i = 0; ; i++) { - // safe loop: free up any (unprotected) dynamic resource - // NB: this is always executed before breaking the loop - safe_free(dev_interface_path); - priv = parent_priv = NULL; - dev = parent_dev = NULL; - - // Safe loop: end of loop conditions - if (r != LIBUSB_SUCCESS) - break; - - if ((pass == HCD_PASS) && (i == UINT8_MAX)) { - usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX); - break; - } - - if (pass != GEN_PASS) { - // Except for GEN, all passes deal with device interfaces - r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path); - if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) { - _index = 0; - break; - } - } else { - // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are - // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". - // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" - // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" - for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) { - if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i)) - break; - i = 0; - } - if (usb_enum_index == nb_usb_enumerators) - break; - } - - // Read the Device ID path - if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) { - usbi_warn(ctx, "could not read the device instance ID for devInst %X, skipping", - dev_info_data.DevInst); - continue; - } - -#ifdef ENUM_DEBUG - usbi_dbg("PRO: %s", dev_id); -#endif - - // Set API to use or get additional data from generic pass - api = USB_API_UNSUPPORTED; - sub_api = SUB_API_NOTSET; - switch (pass) { - case HCD_PASS: - break; - case HUB_PASS: - api = USB_API_HUB; - // Fetch the PnP enumerator class for this hub - // This will allow us to enumerate all classes during the GEN pass - if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, - NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) { - usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_OTHER); - } - for (j = 0; j < nb_usb_enumerators; j++) { - if (strcmp(usb_enumerator[j], enumerator) == 0) - break; - } - if (j == nb_usb_enumerators) { - usbi_dbg("found new PnP enumerator string '%s'", enumerator); - if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) { - usb_enumerator[nb_usb_enumerators] = _strdup(enumerator); - if (usb_enumerator[nb_usb_enumerators] != NULL) { - nb_usb_enumerators++; - } else { - usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - } else { - usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible"); - } - } - break; - case GEN_PASS: - // We use the GEN pass to detect driverless devices... - if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER, - NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { - usbi_info(ctx, "The following device has no driver: '%s'", dev_id); - usbi_info(ctx, "libusb will not be able to access it"); - } - // ...and to add the additional device interface GUIDs - key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (key == INVALID_HANDLE_VALUE) - break; - // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order - size = sizeof(guid_string_w); - s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, - (LPBYTE)guid_string_w, &size); - if (s == ERROR_FILE_NOT_FOUND) - s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, ®_type, - (LPBYTE)guid_string_w, &size); - pRegCloseKey(key); - if ((s == ERROR_SUCCESS) && - (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) || - ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) { - if (nb_guids == guid_size) { - new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); - if (new_guid_list == NULL) { - usbi_err(ctx, "failed to realloc guid list"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - guid_list = new_guid_list; - guid_size += GUID_SIZE_STEP; - } - if_guid = malloc(sizeof(*if_guid)); - if (if_guid == NULL) { - usbi_err(ctx, "failed to alloc if_guid"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - if (pIIDFromString(guid_string_w, if_guid) != 0) { - usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id); - free(if_guid); - } else { - // Check if we've already seen this GUID - for (j = EXT_PASS; j < nb_guids; j++) { - if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0) - break; - } - if (j == nb_guids) { - usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); - guid_list[nb_guids++] = if_guid; - } else { - // Duplicate, ignore - free(if_guid); - } - } - } else if (s == ERROR_SUCCESS) { - usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id); - } - break; - case HID_PASS: - api = USB_API_HID; - break; - default: - // Get the API type (after checking that the driver installation is OK) - if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE, - NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) { - usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", - dev_id, windows_error_str(0)); - } else if (install_state != 0) { - usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", - dev_id, (unsigned int)install_state); - continue; - } - get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api); - break; - } - - // Find parent device (for the passes that need it) - if (pass >= GEN_PASS) { - parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL); - if (parent_dev == NULL) { - // Root hubs will not have a parent - dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst); - if (dev != NULL) { - priv = _device_priv(dev); - if (priv->root_hub) - goto track_unref; - libusb_unref_device(dev); - } - - usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id); - continue; - } - - parent_priv = _device_priv(parent_dev); - // virtual USB devices are also listed during GEN - don't process these yet - if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { - libusb_unref_device(parent_dev); - continue; - } - } - - // Create new or match existing device, using the devInst as session id - if ((pass <= GEN_PASS) && (pass != HCD_PASS)) { // For subsequent passes, we'll lookup the parent - // These are the passes that create "new" devices - session_id = (unsigned long)dev_info_data.DevInst; - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - alloc_device: - usbi_dbg("allocating new device for session [%lX]", session_id); - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - priv = winusb_device_priv_init(dev); - priv->dev_id = _strdup(dev_id); - if (priv->dev_id == NULL) { - libusb_unref_device(dev); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - } else { - usbi_dbg("found existing device for session [%lX]", session_id); - - priv = _device_priv(dev); - if (strcmp(priv->dev_id, dev_id) != 0) { - usbi_dbg("device instance ID for session [%lX] changed", session_id); - usbi_disconnect_device(dev); - libusb_unref_device(dev); - goto alloc_device; - } - } - - track_unref: - // Keep track of devices that need unref - if (unref_cur == unref_size) { - new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *)); - if (new_unref_list == NULL) { - usbi_err(ctx, "could not realloc list for unref - aborting"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - unref_list = new_unref_list; - unref_size += UNREF_SIZE_STEP; - } - unref_list[unref_cur++] = dev; - } - - // Setup device - switch (pass) { - case HUB_PASS: - case DEV_PASS: - // If the device has already been setup, don't do it again - if (priv->path != NULL) - break; - // Take care of API initialization - priv->path = dev_interface_path; - dev_interface_path = NULL; - priv->apib = &usb_api_backend[api]; - priv->sub_api = sub_api; - switch (api) { - case USB_API_COMPOSITE: - case USB_API_HUB: - break; - case USB_API_HID: - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - break; - default: - // For other devices, the first interface is the same as the device - priv->usb_interface[0].path = _strdup(priv->path); - if (priv->usb_interface[0].path == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - // The following is needed if we want API calls to work for both simple - // and composite devices. - for (j = 0; j < USB_MAXINTERFACES; j++) - priv->usb_interface[j].apib = &usb_api_backend[api]; - break; - } - break; - case HCD_PASS: - r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); - break; - case GEN_PASS: - // The SPDRP_ADDRESS for USB devices is the device port number on the hub - port_nr = 0; - if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS, - NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr))) - usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0)); - r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst); - if (r == LIBUSB_SUCCESS) { - // Append device to the list of discovered devices - discdevs = discovered_devs_append(*_discdevs, dev); - if (!discdevs) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - *_discdevs = discdevs; - } else if (r == LIBUSB_ERROR_NO_DEVICE) { - // This can occur if the device was disconnected but Windows hasn't - // refreshed its enumeration yet - in that case, we ignore the device - r = LIBUSB_SUCCESS; - } - break; - default: // HID_PASS and later - if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { - if (parent_priv->apib->id == USB_API_HID) { - usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); - r = set_hid_interface(ctx, parent_dev, dev_interface_path); - } else { - usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); - r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api); - } - switch (r) { - case LIBUSB_SUCCESS: - dev_interface_path = NULL; - break; - case LIBUSB_ERROR_ACCESS: - // interface has already been set => make sure dev_interface_path is freed then - r = LIBUSB_SUCCESS; - break; - default: - LOOP_BREAK(r); - break; - } - } - libusb_unref_device(parent_dev); - break; - } - } - } - - pSetupDiDestroyDeviceInfoList(dev_info_intf); - - // Free any additional GUIDs - for (pass = EXT_PASS; pass < nb_guids; pass++) - free((void *)guid_list[pass]); - free((void *)guid_list); - - // Free any PnP enumerator strings - for (i = 1; i < nb_usb_enumerators; i++) - free(usb_enumerator[i]); - - // Unref newly allocated devs - for (i = 0; i < unref_cur; i++) - libusb_unref_device(unref_list[i]); - free(unref_list); - - return r; -} - -static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) -{ - struct winusb_device_priv *priv = _device_priv(dev); - - memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); - return LIBUSB_SUCCESS; -} - -static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) -{ - struct winusb_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; - - // config index is zero based - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; - - if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - config_header = priv->config_descriptor[config_index]; - - size = MIN(config_header->wTotalLength, len); - memcpy(buffer, priv->config_descriptor[config_index], size); - return (int)size; -} - -static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, - unsigned char **buffer) -{ - struct winusb_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - uint8_t index; - - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NOT_FOUND; - - for (index = 0; index < dev->num_configurations; index++) { - config_header = priv->config_descriptor[index]; - if (config_header == NULL) - continue; - if (config_header->bConfigurationValue == bConfigurationValue) { - *buffer = (unsigned char *)priv->config_descriptor[index]; - return (int)config_header->wTotalLength; - } - } - - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * return the cached copy of the active config descriptor - */ -static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) -{ - struct winusb_device_priv *priv = _device_priv(dev); - unsigned char *config_desc; - int r; - - if (priv->active_config == 0) - return LIBUSB_ERROR_NOT_FOUND; - - r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc); - if (r < 0) - return r; - - len = MIN((size_t)r, len); - memcpy(buffer, config_desc, len); - return (int)len; -} - -static int winusb_open(struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, open); - - return priv->apib->open(SUB_API_NOTSET, dev_handle); -} - -static void winusb_close(struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - if (priv->apib->close) - priv->apib->close(SUB_API_NOTSET, dev_handle); -} - -static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - if (priv->active_config == 0) { - *config = 0; - return LIBUSB_ERROR_NOT_FOUND; - } - - *config = priv->active_config; - return LIBUSB_SUCCESS; -} - -/* - * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver - * does not currently expose a service that allows higher-level drivers to set - * the configuration." - */ -static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_SUCCESS; - - if (config >= USB_MAXCONFIG) - return LIBUSB_ERROR_INVALID_PARAM; - - r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | - LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, - LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, - 0, NULL, 0, 1000); - - if (r == LIBUSB_SUCCESS) - priv->active_config = (uint8_t)config; - - return r; -} - -static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int r; - - CHECK_SUPPORTED_API(priv->apib, claim_interface); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, 0); - - return r; -} - -static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int r; - - CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, altsetting); - - return r; -} - -static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, release_interface); - - return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); -} - -static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, clear_halt); - - return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); -} - -static int winusb_reset_device(struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, reset_device); - - return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); -} - -static void winusb_destroy_device(struct libusb_device *dev) -{ - winusb_device_priv_release(dev); -} - -static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_close(transfer_priv->pollable_fd.fd); - transfer_priv->pollable_fd = INVALID_WINFD; - transfer_priv->handle = NULL; - safe_free(transfer_priv->hid_buffer); - safe_free(transfer_priv->iso_context); - - // When auto claim is in use, attempt to release the auto-claimed interface - auto_release(itransfer); -} - -static int do_submit_transfer(struct usbi_transfer *itransfer, short events, - int (*transfer_fn)(int, struct usbi_transfer *)) -{ - struct libusb_context *ctx = ITRANSFER_CTX(itransfer); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winfd wfd; - int r; - - wfd = usbi_create_fd(); - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_add_pollfd(ctx, wfd.fd, events); - if (r) { - usbi_close(wfd.fd); - return r; - } - - // Use transfer_priv to store data needed for async polling - transfer_priv->pollable_fd = wfd; - - r = transfer_fn(SUB_API_NOTSET, itransfer); - - if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) { - usbi_remove_pollfd(ctx, wfd.fd); - usbi_close(wfd.fd); - transfer_priv->pollable_fd = INVALID_WINFD; - } - - return r; -} - -static int winusb_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int (*transfer_fn)(int, struct usbi_transfer *); - short events; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; - transfer_fn = priv->apib->submit_control_transfer; - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; - events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; - transfer_fn = priv->apib->submit_bulk_transfer; - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; - transfer_fn = priv->apib->submit_iso_transfer; - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (transfer_fn == NULL) { - usbi_warn(TRANSFER_CTX(transfer), - "unsupported transfer type %d (unrecognized device driver)", - transfer->type); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - return do_submit_transfer(itransfer, events, transfer_fn); -} - -static int windows_abort_control(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, abort_control); - - return priv->apib->abort_control(SUB_API_NOTSET, itransfer); -} - -static int windows_abort_transfers(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - CHECK_SUPPORTED_API(priv->apib, abort_transfers); - - return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); -} - -static int winusb_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return windows_abort_control(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return windows_abort_transfers(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); -} - -static int winusb_get_transfer_fd(struct usbi_transfer *itransfer) -{ - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - return transfer_priv->pollable_fd.fd; -} - -static void winusb_get_overlapped_result(struct usbi_transfer *itransfer, - DWORD *io_result, DWORD *io_size) -{ - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winfd *pollable_fd = &transfer_priv->pollable_fd; - - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { - *io_result = NO_ERROR; - *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; - } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) { - // Regular async overlapped - *io_result = NO_ERROR; - } else { - *io_result = GetLastError(); - } -} - -// NB: MSVC6 does not support named initializers. -const struct windows_backend winusb_backend = { - winusb_init, - winusb_exit, - winusb_get_device_list, - winusb_open, - winusb_close, - winusb_get_device_descriptor, - winusb_get_active_config_descriptor, - winusb_get_config_descriptor, - winusb_get_config_descriptor_by_value, - winusb_get_configuration, - winusb_set_configuration, - winusb_claim_interface, - winusb_release_interface, - winusb_set_interface_altsetting, - winusb_clear_halt, - winusb_reset_device, - winusb_destroy_device, - winusb_submit_transfer, - winusb_cancel_transfer, - winusb_clear_transfer_priv, - winusb_copy_transfer_data, - winusb_get_transfer_fd, - winusb_get_overlapped_result, -}; - -/* - * USB API backends - */ - -static const char * const composite_driver_names[] = {"USBCCGP"}; -static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"}; -static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; -const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { - { - USB_API_UNSUPPORTED, - "Unsupported API", - // No supported operations - }, - { - USB_API_HUB, - "HUB API", - // No supported operations - }, - { - USB_API_COMPOSITE, - "Composite API", - composite_driver_names, - ARRAYSIZE(composite_driver_names), - NULL, /* init */ - NULL, /* exit */ - composite_open, - composite_close, - NULL, /* configure_endpoints */ - composite_claim_interface, - composite_set_interface_altsetting, - composite_release_interface, - composite_clear_halt, - composite_reset_device, - composite_submit_bulk_transfer, - composite_submit_iso_transfer, - composite_submit_control_transfer, - composite_abort_control, - composite_abort_transfers, - composite_copy_transfer_data, - }, - { - USB_API_WINUSBX, - "WinUSB-like APIs", - winusbx_driver_names, - ARRAYSIZE(winusbx_driver_names), - winusbx_init, - winusbx_exit, - winusbx_open, - winusbx_close, - winusbx_configure_endpoints, - winusbx_claim_interface, - winusbx_set_interface_altsetting, - winusbx_release_interface, - winusbx_clear_halt, - winusbx_reset_device, - winusbx_submit_bulk_transfer, - winusbx_submit_iso_transfer, - winusbx_submit_control_transfer, - winusbx_abort_control, - winusbx_abort_transfers, - winusbx_copy_transfer_data, - }, - { - USB_API_HID, - "HID API", - // No supported operations - }, -}; - - -/* - * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions - */ -#define WinUSBX_Set(fn) \ - do { \ - if (native_winusb) \ - WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ - else \ - pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ - } while (0) - -static int winusbx_init(struct libusb_context *ctx) -{ - HMODULE h; - bool native_winusb; - int i; - KLIB_VERSION LibK_Version; - LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; - LibK_GetVersion_t pLibK_GetVersion; - - h = LoadLibraryA("libusbK"); - - if (h == NULL) { - usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); - h = LoadLibraryA("WinUSB"); - - if (h == NULL) { - usbi_warn(ctx, "WinUSB DLL is not available either, " - "you will not be able to access devices outside of enumeration"); - return LIBUSB_ERROR_NOT_FOUND; - } - } else { - usbi_dbg("using libusbK DLL for universal access"); - pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); - if (pLibK_GetVersion != NULL) { - pLibK_GetVersion(&LibK_Version); - usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, - LibK_Version.Micro, LibK_Version.Nano); - } - pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); - if (pLibK_GetProcAddress == NULL) { - usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); - FreeLibrary(h); - return LIBUSB_ERROR_NOT_FOUND; - } - } - - native_winusb = (pLibK_GetProcAddress == NULL); - for (i = 0; i < SUB_API_MAX; i++) { - WinUSBX_Set(AbortPipe); - WinUSBX_Set(ControlTransfer); - WinUSBX_Set(FlushPipe); - WinUSBX_Set(Free); - WinUSBX_Set(GetAssociatedInterface); - WinUSBX_Set(Initialize); - WinUSBX_Set(ReadPipe); - if (!native_winusb) - WinUSBX_Set(ResetDevice); - WinUSBX_Set(ResetPipe); - WinUSBX_Set(SetCurrentAlternateSetting); - WinUSBX_Set(SetPipePolicy); - WinUSBX_Set(WritePipe); - WinUSBX_Set(IsoReadPipe); - WinUSBX_Set(IsoWritePipe); - - if (WinUSBX[i].Initialize != NULL) { - WinUSBX[i].initialized = true; - // Assume driver supports CancelIoEx() if it is available - WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); - usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); - } else { - usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); - WinUSBX[i].initialized = false; - } - } - - WinUSBX_handle = h; - return LIBUSB_SUCCESS; -} - -static void winusbx_exit(void) -{ - if (WinUSBX_handle != NULL) { - FreeLibrary(WinUSBX_handle); - WinUSBX_handle = NULL; - - /* Reset the WinUSBX API structures */ - memset(&WinUSBX, 0, sizeof(WinUSBX)); - } -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HANDLE file_handle; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // WinUSB requires a separate handle for each interface - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { - file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - handle_priv->interface_handle[i].dev_handle = file_handle; - } - } - return LIBUSB_SUCCESS; -} - -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE handle; - int i; - - if (sub_api == SUB_API_NOTSET) - sub_api = priv->sub_api; - - if (!WinUSBX[sub_api].initialized) - return; - - if (priv->apib->id == USB_API_COMPOSITE) { - // If this is a composite device, just free and close all WinUSB-like - // interfaces directly (each is independent and not associated with another) - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[i].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } - } - } else { - // If this is a WinUSB device, free all interfaces above interface 0, - // then free and close interface 0 last - for (i = 1; i < USB_MAXINTERFACES; i++) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - } - handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[0].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } -} - -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; - UCHAR policy; - ULONG timeout = 0; - uint8_t endpoint_address; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // With handle and enpoints set (in parent), we can setup the default pipe properties - // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx - for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { - endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) - usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); - - if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) - continue; // Other policies don't apply to control endpoint or libusb0 - - policy = false; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); - - policy = true; - /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: - https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - HDEVINFO dev_info = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA dev_info_data; - char *dev_path_no_guid = NULL; - char filter_path[] = "\\\\.\\libusb0-0000"; - bool found_filter = false; - HANDLE file_handle, winusb_handle; - DWORD err; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // If the device is composite, but using the default Windows composite parent driver (usbccgp) - // or if it's the first WinUSB-like interface, we get a handle through Initialize(). - if ((is_using_usbccgp) || (iface == 0)) { - // composite device (independent interfaces) or interface 0 - file_handle = handle_priv->interface_handle[iface].dev_handle; - if (!HANDLE_VALID(file_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - err = GetLastError(); - switch (err) { - case ERROR_BAD_COMMAND: - // The device was disconnected - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - default: - // it may be that we're using the libusb0 filter driver. - // TODO: can we move this whole business into the K/0 DLL? - for (i = 0; ; i++) { - safe_free(dev_interface_details); - safe_free(dev_path_no_guid); - - dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); - if ((found_filter) || (dev_interface_details == NULL)) - break; - - // ignore GUID part - dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); - if (dev_path_no_guid == NULL) - continue; - - if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { - file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle != INVALID_HANDLE_VALUE) { - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - // Replace the existing file handle with the working one - CloseHandle(handle_priv->interface_handle[iface].dev_handle); - handle_priv->interface_handle[iface].dev_handle = file_handle; - found_filter = true; - } else { - usbi_err(ctx, "could not initialize filter driver for %s", filter_path); - CloseHandle(file_handle); - } - } else { - usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); - } - } - } - free(dev_interface_details); - if (!found_filter) { - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); - return LIBUSB_ERROR_ACCESS; - } - } - } - handle_priv->interface_handle[iface].api_handle = winusb_handle; - } else { - // For all other interfaces, use GetAssociatedInterface() - winusb_handle = handle_priv->interface_handle[0].api_handle; - // It is a requirement for multiple interface devices on Windows that, to you - // must first claim the first interface before you claim the others - if (!HANDLE_VALID(winusb_handle)) { - file_handle = handle_priv->interface_handle[0].dev_handle; - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[0].api_handle = winusb_handle; - usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface); - } else { - usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), - &handle_priv->interface_handle[iface].api_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - switch (GetLastError()) { - case ERROR_NO_MORE_ITEMS: // invalid iface - return LIBUSB_ERROR_NOT_FOUND; - case ERROR_BAD_COMMAND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ALREADY_EXISTS: // already claimed - return LIBUSB_ERROR_BUSY; - default: - usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - } - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - WinUSBX[sub_api].Free(winusb_handle); - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -/* - * Return the first valid interface (of the same API type), for control transfers - */ -static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) -{ - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int i; - - if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { - usbi_dbg("unsupported API ID"); - return -1; - } - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) - && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) - && (priv->usb_interface[i].apib->id == api_id)) - return i; - } - - return -1; -} - -/* - * Lookup interface by endpoint address. -1 if not found - */ -static int interface_by_endpoint(struct winusb_device_priv *priv, - struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address) -{ - int i, j; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) - continue; - if (priv->usb_interface[i].endpoint == NULL) - continue; - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - if (priv->usb_interface[i].endpoint[j] == endpoint_address) - return i; - } - } - - return -1; -} - -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer; - ULONG size; - HANDLE winusb_handle; - OVERLAPPED *overlapped; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - // Windows places upper limits on the control transfer size - // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx - if (size > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); - if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("will use interface %d", current_interface); - - transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - overlapped = transfer_priv->pollable_fd.overlapped; - - // Sending of set configuration control requests from WinUSB creates issues - if ((LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD) - && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) { - if (setup->Value != priv->active_config) { - usbi_warn(ctx, "cannot set configuration other than the default one"); - return LIBUSB_ERROR_INVALID_PARAM; - } - windows_force_sync_completion(overlapped, 0); - } else { - if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - } else { - windows_force_sync_completion(overlapped, size); - } - } - - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - if (altsetting > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) { - usbi_err(ctx, "interface must be claimed first"); - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) { - usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - OVERLAPPED *overlapped; - bool ret; - int current_interface; - int i; - UINT offset; - PKISO_CONTEXT iso_context; - size_t iso_ctx_size; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - if ((sub_api != SUB_API_LIBUSBK) && (sub_api != SUB_API_LIBUSB0)) { - // iso only supported on libusbk-based backends - PRINT_UNSUPPORTED_API(submit_iso_transfer); - return LIBUSB_ERROR_NOT_SUPPORTED; - }; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - overlapped = transfer_priv->pollable_fd.overlapped; - - iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET)); - transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size); - if (transfer_priv->iso_context == NULL) - return LIBUSB_ERROR_NO_MEM; - - // start ASAP - iso_context->StartFrame = 0; - iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets; - - // convert the transfer packet lengths to iso_packet offsets - offset = 0; - for (i = 0; i < transfer->num_iso_packets; i++) { - iso_context->IsoPackets[i].offset = offset; - offset += transfer->iso_packet_desc[i].length; - } - - if (IS_XFERIN(transfer)) { - usbi_dbg("reading %d iso packets", transfer->num_iso_packets); - ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); - } else { - usbi_dbg("writing %d iso packets", transfer->num_iso_packets); - ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - } else { - windows_force_sync_completion(overlapped, (ULONG)transfer->length); - } - - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - OVERLAPPED *overlapped; - bool ret; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - overlapped = transfer_priv->pollable_fd.overlapped; - - if (IS_XFERIN(transfer)) { - usbi_dbg("reading %d bytes", transfer->length); - ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); - } else { - usbi_dbg("writing %d bytes", transfer->length); - ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - } else { - windows_force_sync_completion(overlapped, (ULONG)transfer->length); - } - - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed - * through testing as well): - * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel - * the control transfer using CancelIo" - */ -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - // Cancelling of the I/O is done in the parent - return LIBUSB_SUCCESS; -} - -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = transfer_priv->interface_number; - if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { - usbi_err(ctx, "program assertion failed: invalid interface_number"); - return LIBUSB_ERROR_NOT_FOUND; - } - usbi_dbg("will use interface %d", current_interface); - - if (WinUSBX[sub_api].CancelIoEx_supported) { - // Try to use CancelIoEx if available to cancel just a single transfer - handle = handle_priv->interface_handle[current_interface].dev_handle; - if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) - return LIBUSB_SUCCESS; - else if (GetLastError() == ERROR_NOT_FOUND) - return LIBUSB_ERROR_NOT_FOUND; - - // Not every driver implements the necessary functionality for CancelIoEx - usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]); - WinUSBX[sub_api].CancelIoEx_supported = false; - } - - handle = handle_priv->interface_handle[current_interface].api_handle; - if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper - * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx): - * "WinUSB does not support host-initiated reset port and cycle port operations" and - * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the - * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is - * cycle the pipes (and even then, the control pipe can not be reset using WinUSB) - */ -// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?) -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - int i, j; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // Reset any available pipe (except control) - for (i = 0; i < USB_MAXINTERFACES; i++) { - winusb_handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(winusb_handle)) { - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - // FlushPipe seems to fail on OUT pipes - if (IS_EPIN(priv->usb_interface[i].endpoint[j]) - && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) - usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } - } - } - - // libusbK & libusb0 have the ability to issue an actual device reset - if (WinUSBX[sub_api].ResetDevice != NULL) { - winusb_handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(winusb_handle)) - WinUSBX[sub_api].ResetDevice(winusb_handle); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - PKISO_CONTEXT iso_context; - int i; - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - CHECK_WINUSBX_AVAILABLE(sub_api); - - // for isochronous, need to copy the individual iso packet actual_lengths and statuses - if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) { - // iso only supported on libusbk-based backends for now - iso_context = transfer_priv->iso_context; - for (i = 0; i < transfer->num_iso_packets; i++) { - transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length; - // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status - //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status; - } - } else { - // This should only occur if backend is not set correctly or other backend isoc is partially implemented - PRINT_UNSUPPORTED_API(copy_transfer_data); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - } - - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; -} - -/* - * Composite API functions - */ -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_ERROR_NOT_FOUND; - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) { - available[priv->usb_interface[i].sub_api] = true; - } - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle); - if (r != LIBUSB_SUCCESS) { - return r; - } - } - } -/* - if (available[SUB_API_MAX]) // HID driver - r = hid_open(SUB_API_NOTSET, dev_handle); -*/ - return r; -} - -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) - available[priv->usb_interface[i].sub_api] = true; - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) - usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); - } -/* - if (available[SUB_API_MAX]) // HID driver - hid_close(SUB_API_NOTSET, dev_handle); -*/ -} - -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface); - - return priv->usb_interface[iface].apib-> - claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting); - - return priv->usb_interface[iface].apib-> - set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); -} - -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface); - - return priv->usb_interface[iface].apib-> - release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - int iface, pass, r; - - // Interface shouldn't matter for control, but it does in practice, with Windows' - // restrictions with regards to accessing HID keyboards and mice. Try to target - // a specific interface first, if possible. - switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) { - case LIBUSB_RECIPIENT_INTERFACE: - iface = setup->Index & 0xFF; - break; - case LIBUSB_RECIPIENT_ENDPOINT: - r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); - if (r == LIBUSB_SUCCESS) { - iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF)); - libusb_free_config_descriptor(conf_desc); - break; - } - // Fall through if not able to determine interface - default: - iface = -1; - break; - } - - // Try and target a specific interface if the control setup indicates such - if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { - usbi_dbg("attempting control transfer targeted to interface %d", iface); - if ((priv->usb_interface[iface].path != NULL) - && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - if (r == LIBUSB_SUCCESS) - return r; - } - } - - // Either not targeted to a specific interface or no luck in doing so. - // Try a 2 pass approach with all interfaces. - for (pass = 0; pass < 2; pass++) { - for (iface = 0; iface < USB_MAXINTERFACES; iface++) { - if ((priv->usb_interface[iface].path != NULL) - && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { - if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { - usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); - continue; - } - usbi_dbg("using interface %d", iface); - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - // If not supported on this API, it may be supported on another, so don't give up yet!! - if (r == LIBUSB_ERROR_NOT_SUPPORTED) - continue; - return r; - } - } - } - usbi_err(ctx, "no libusb supported interfaces to complete request"); - return LIBUSB_ERROR_NOT_FOUND; -} - -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer); - - return priv->usb_interface[current_interface].apib-> - submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer); - - return priv->usb_interface[current_interface].apib-> - submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt); - - return priv->usb_interface[current_interface].apib-> - clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); -} - -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = transfer_priv->interface_number; - - if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { - usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control); - - return priv->usb_interface[current_interface].apib-> - abort_control(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = transfer_priv->interface_number; - - if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { - usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); - return LIBUSB_ERROR_NOT_FOUND; - } - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers); - - return priv->usb_interface[current_interface].apib-> - abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - int r; - uint8_t i; - bool available[SUB_API_MAX]; - - for (i = 0; i < SUB_API_MAX; i++) - available[i] = false; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) - && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) - available[priv->usb_interface[i].sub_api] = true; - } - - for (i = 0; i < SUB_API_MAX; i++) { - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle); - if (r != LIBUSB_SUCCESS) - return r; - } - } - - return LIBUSB_SUCCESS; -} - -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = transfer_priv->interface_number; - - CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data); - - return priv->usb_interface[current_interface].apib-> - copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h deleted file mode 100644 index c1ad4eb9b2..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "windows_common.h" -#include "windows_nt_common.h" - -#if defined(_MSC_VER) -// disable /W4 MSVC warnings that are benign -#pragma warning(disable:4100) // unreferenced formal parameter -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4201) // nameless struct/union -#pragma warning(disable:4214) // bit field types other than int -#pragma warning(disable:4996) // deprecated API calls -#pragma warning(disable:28159) // more deprecated API calls -#endif - -// Missing from MSVC6 setupapi.h -#ifndef SPDRP_ADDRESS -#define SPDRP_ADDRESS 28 -#endif -#ifndef SPDRP_INSTALL_STATE -#define SPDRP_INSTALL_STATE 34 -#endif - -#define MAX_CTRL_BUFFER_LENGTH 4096 -#define MAX_USB_STRING_LENGTH 128 -#define MAX_HID_REPORT_SIZE 1024 -#define MAX_HID_DESCRIPTOR_SIZE 256 -#define MAX_GUID_STRING_LENGTH 40 -#define MAX_PATH_LENGTH 128 -#define MAX_KEY_LENGTH 256 -#define LIST_SEPARATOR ';' - -// Handle code for HID interface that have been claimed ("dibs") -#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5) -// Additional return code for HID operations that completed synchronously -#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) - -// http://msdn.microsoft.com/en-us/library/ff545978.aspx -// http://msdn.microsoft.com/en-us/library/ff545972.aspx -// http://msdn.microsoft.com/en-us/library/ff545982.aspx -#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER -const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}}; -#endif -#ifndef GUID_DEVINTERFACE_USB_DEVICE -const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}; -#endif -#ifndef GUID_DEVINTERFACE_USB_HUB -const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}}; -#endif -#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER -const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}}; -#endif - - -/* - * Multiple USB API backend support - */ -#define USB_API_UNSUPPORTED 0 -#define USB_API_HUB 1 -#define USB_API_COMPOSITE 2 -#define USB_API_WINUSBX 3 -#define USB_API_HID 4 -#define USB_API_MAX 5 - -// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL) -// Must have the same values as the KUSB_DRVID enum from libusbk.h -#define SUB_API_NOTSET -1 -#define SUB_API_LIBUSBK 0 -#define SUB_API_LIBUSB0 1 -#define SUB_API_WINUSB 2 -#define SUB_API_MAX 3 - -struct windows_usb_api_backend { - const uint8_t id; - const char * const designation; - const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp" - const uint8_t nb_driver_names; - int (*init)(struct libusb_context *ctx); - void (*exit)(void); - int (*open)(int sub_api, struct libusb_device_handle *dev_handle); - void (*close)(int sub_api, struct libusb_device_handle *dev_handle); - int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); - int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); - int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle); - int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*abort_control)(int sub_api, struct usbi_transfer *itransfer); - int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer); - int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -}; - -extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; - -#define PRINT_UNSUPPORTED_API(fname) \ - usbi_dbg("unsupported API call for '%s' " \ - "(unrecognized device driver)", #fname) - -#define CHECK_SUPPORTED_API(apip, fname) \ - do { \ - if ((apip)->fname == NULL) { \ - PRINT_UNSUPPORTED_API(fname); \ - return LIBUSB_ERROR_NOT_SUPPORTED; \ - } \ - } while (0) - -/* - * private structures definition - * with inline pseudo constructors/destructors - */ - -// TODO (v2+): move hid desc to libusb.h? -struct libusb_hid_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bClassDescriptorType; - uint16_t wClassDescriptorLength; -}; - -#define LIBUSB_DT_HID_SIZE 9 -#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \ - + LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE) -#define HID_MAX_REPORT_SIZE 1024 -#define HID_IN_EP 0x81 -#define HID_OUT_EP 0x02 -#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F) -#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5)) -#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) -#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) - -#ifndef CTL_CODE -#define CTL_CODE(DeviceType, Function, Method, Access) \ - (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) -#endif - -// The following are used for HID reports IOCTLs -#define HID_IN_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) -#define HID_OUT_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - -#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) -#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) -#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100) -#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101) - -enum libusb_hid_request_type { - HID_REQ_GET_REPORT = 0x01, - HID_REQ_GET_IDLE = 0x02, - HID_REQ_GET_PROTOCOL = 0x03, - HID_REQ_SET_REPORT = 0x09, - HID_REQ_SET_IDLE = 0x0A, - HID_REQ_SET_PROTOCOL = 0x0B -}; - -enum libusb_hid_report_type { - HID_REPORT_TYPE_INPUT = 0x01, - HID_REPORT_TYPE_OUTPUT = 0x02, - HID_REPORT_TYPE_FEATURE = 0x03 -}; - -struct hid_device_priv { - uint16_t vid; - uint16_t pid; - uint8_t config; - uint8_t nb_interfaces; - bool uses_report_ids[3]; // input, ouptput, feature - uint16_t input_report_size; - uint16_t output_report_size; - uint16_t feature_report_size; - uint16_t usage; - uint16_t usagePage; - WCHAR string[3][MAX_USB_STRING_LENGTH]; - uint8_t string_index[3]; // man, prod, ser -}; - -static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct winusb_device_priv *)dev->os_priv; -} - -static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev) -{ - struct winusb_device_priv *p = _device_priv(dev); - int i; - - p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; - p->sub_api = SUB_API_NOTSET; - for (i = 0; i < USB_MAXINTERFACES; i++) { - p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; - p->usb_interface[i].sub_api = SUB_API_NOTSET; - } - - return p; -} - -static inline void winusb_device_priv_release(struct libusb_device *dev) -{ - struct winusb_device_priv *p = _device_priv(dev); - int i; - - free(p->dev_id); - free(p->path); - if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { - for (i = 0; i < dev->num_configurations; i++) - free(p->config_descriptor[i]); - } - free(p->config_descriptor); - free(p->hid); - for (i = 0; i < USB_MAXINTERFACES; i++) { - free(p->usb_interface[i].path); - free(p->usb_interface[i].endpoint); - } -} - -static inline struct winusb_device_handle_priv *_device_handle_priv( - struct libusb_device_handle *handle) -{ - return (struct winusb_device_handle_priv *)handle->os_priv; -} - -// used to match a device driver (including filter drivers) against a supported API -struct driver_lookup { - char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names - const DWORD reg_prop; // SPDRP registry key to use to retrieve list - const char* designation; // internal designation (for debug output) -}; - -/* - * Windows DDK API definitions. Most of it copied from MinGW's includes - */ -typedef DWORD DEVNODE, DEVINST; -typedef DEVNODE *PDEVNODE, *PDEVINST; -typedef DWORD RETURN_TYPE; -typedef RETURN_TYPE CONFIGRET; - -#define CR_SUCCESS 0x00000000 - -/* Cfgmgr32 dependencies */ -DLL_DECLARE_HANDLE(Cfgmgr32); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); - -/* AdvAPI32 dependencies */ -DLL_DECLARE_HANDLE(AdvAPI32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); - -/* OLE32 dependency */ -DLL_DECLARE_HANDLE(OLE32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID)); - -/* SetupAPI dependencies */ -DLL_DECLARE_HANDLE(SetupAPI); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, - LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA, - PCSTR, DWORD, PDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, - PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, - PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); - - -#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION -#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 -#endif -#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX -#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 -#endif -#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 -#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 -#endif - -#ifndef FILE_DEVICE_USB -#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN -#endif - -#define USB_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ - USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ - USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ - USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) - -typedef enum USB_CONNECTION_STATUS { - NoDeviceConnected, - DeviceConnected, - DeviceFailedEnumeration, - DeviceGeneralFailure, - DeviceCausedOvercurrent, - DeviceNotEnoughPower, - DeviceNotEnoughBandwidth, - DeviceHubNestedTooDeeply, - DeviceInLegacyHub -} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS; - -typedef enum USB_HUB_NODE { - UsbHub, - UsbMIParent -} USB_HUB_NODE; - -// Most of the structures below need to be packed -#include - -typedef struct _USB_DESCRIPTOR_REQUEST { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; -// UCHAR Data[0]; -} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; - -typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT { - USB_DESCRIPTOR_REQUEST req; - USB_CONFIGURATION_DESCRIPTOR desc; -} USB_CONFIGURATION_DESCRIPTOR_SHORT; - -typedef struct USB_INTERFACE_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bInterfaceNumber; - UCHAR bAlternateSetting; - UCHAR bNumEndpoints; - UCHAR bInterfaceClass; - UCHAR bInterfaceSubClass; - UCHAR bInterfaceProtocol; - UCHAR iInterface; -} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; - -typedef struct _USB_NODE_CONNECTION_INFORMATION_EX { - ULONG ConnectionIndex; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; - UCHAR CurrentConfigurationValue; - UCHAR Speed; - BOOLEAN DeviceIsHub; - USHORT DeviceAddress; - ULONG NumberOfOpenPipes; - USB_CONNECTION_STATUS ConnectionStatus; -// USB_PIPE_INFO PipeList[0]; -} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX; - -typedef union _USB_PROTOCOLS { - ULONG ul; - struct { - ULONG Usb110:1; - ULONG Usb200:1; - ULONG Usb300:1; - ULONG ReservedMBZ:29; - }; -} USB_PROTOCOLS, *PUSB_PROTOCOLS; - -typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS { - ULONG ul; - struct { - ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1; - ULONG DeviceIsSuperSpeedCapableOrHigher:1; - ULONG ReservedMBZ:30; - }; -} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS; - -typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 { - ULONG ConnectionIndex; - ULONG Length; - USB_PROTOCOLS SupportedUsbProtocols; - USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; -} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; - -#include - -/* winusb.dll interface */ - -#define SHORT_PACKET_TERMINATE 0x01 -#define AUTO_CLEAR_STALL 0x02 -#define PIPE_TRANSFER_TIMEOUT 0x03 -#define IGNORE_SHORT_PACKETS 0x04 -#define ALLOW_PARTIAL_READS 0x05 -#define AUTO_FLUSH 0x06 -#define RAW_IO 0x07 -#define MAXIMUM_TRANSFER_SIZE 0x08 - -typedef enum _USBD_PIPE_TYPE { - UsbdPipeTypeControl, - UsbdPipeTypeIsochronous, - UsbdPipeTypeBulk, - UsbdPipeTypeInterrupt -} USBD_PIPE_TYPE; - -#include - -typedef struct _WINUSB_SETUP_PACKET { - UCHAR RequestType; - UCHAR Request; - USHORT Value; - USHORT Index; - USHORT Length; -} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; - -#include - -typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; - -typedef BOOL (WINAPI *WinUsb_AbortPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - WINUSB_SETUP_PACKET SetupPacket, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); -typedef BOOL (WINAPI *WinUsb_FlushPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_Free_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AssociatedInterfaceIndex, - PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_Initialize_t)( - HANDLE DeviceHandle, - PWINUSB_INTERFACE_HANDLE InterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); -typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateSetting -); -typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - ULONG PolicyType, - ULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_WritePipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); - -/* /!\ These must match the ones from the official libusbk.h */ -typedef enum _KUSB_FNID { - KUSB_FNID_Init, - KUSB_FNID_Free, - KUSB_FNID_ClaimInterface, - KUSB_FNID_ReleaseInterface, - KUSB_FNID_SetAltInterface, - KUSB_FNID_GetAltInterface, - KUSB_FNID_GetDescriptor, - KUSB_FNID_ControlTransfer, - KUSB_FNID_SetPowerPolicy, - KUSB_FNID_GetPowerPolicy, - KUSB_FNID_SetConfiguration, - KUSB_FNID_GetConfiguration, - KUSB_FNID_ResetDevice, - KUSB_FNID_Initialize, - KUSB_FNID_SelectInterface, - KUSB_FNID_GetAssociatedInterface, - KUSB_FNID_Clone, - KUSB_FNID_QueryInterfaceSettings, - KUSB_FNID_QueryDeviceInformation, - KUSB_FNID_SetCurrentAlternateSetting, - KUSB_FNID_GetCurrentAlternateSetting, - KUSB_FNID_QueryPipe, - KUSB_FNID_SetPipePolicy, - KUSB_FNID_GetPipePolicy, - KUSB_FNID_ReadPipe, - KUSB_FNID_WritePipe, - KUSB_FNID_ResetPipe, - KUSB_FNID_AbortPipe, - KUSB_FNID_FlushPipe, - KUSB_FNID_IsoReadPipe, - KUSB_FNID_IsoWritePipe, - KUSB_FNID_GetCurrentFrameNumber, - KUSB_FNID_GetOverlappedResult, - KUSB_FNID_GetProperty, - KUSB_FNID_COUNT, -} KUSB_FNID; - -typedef struct _KLIB_VERSION { - INT Major; - INT Minor; - INT Micro; - INT Nano; -} KLIB_VERSION, *PKLIB_VERSION; - -typedef BOOL (WINAPI *LibK_GetProcAddress_t)( - PVOID *ProcAddress, - ULONG DriverID, - ULONG FunctionID -); - -typedef VOID (WINAPI *LibK_GetVersion_t)( - PKLIB_VERSION Version -); - -//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths -typedef struct _KISO_PACKET { - UINT offset; - USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity - USHORT status; -} KISO_PACKET, *PKISO_PACKET; - -typedef enum _KISO_FLAG { - KISO_FLAG_NONE = 0, - KISO_FLAG_SET_START_FRAME = 0x00000001, -} KISO_FLAG; - -//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version -typedef struct _KISO_CONTEXT { - KISO_FLAG Flags; - UINT StartFrame; - SHORT ErrorCount; - SHORT NumberOfPackets; - UINT UrbHdrStatus; - KISO_PACKET IsoPackets[0]; -} KISO_CONTEXT, *PKISO_CONTEXT; - -typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - LPOVERLAPPED Overlapped, - PKISO_CONTEXT IsoContext -); - -typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - LPOVERLAPPED Overlapped, - PKISO_CONTEXT IsoContext -); - -struct winusb_interface { - bool initialized; - bool CancelIoEx_supported; - WinUsb_AbortPipe_t AbortPipe; - WinUsb_ControlTransfer_t ControlTransfer; - WinUsb_FlushPipe_t FlushPipe; - WinUsb_Free_t Free; - WinUsb_GetAssociatedInterface_t GetAssociatedInterface; - WinUsb_Initialize_t Initialize; - WinUsb_ReadPipe_t ReadPipe; - WinUsb_ResetDevice_t ResetDevice; - WinUsb_ResetPipe_t ResetPipe; - WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; - WinUsb_SetPipePolicy_t SetPipePolicy; - WinUsb_WritePipe_t WritePipe; - WinUsb_IsoReadPipe_t IsoReadPipe; - WinUsb_IsoWritePipe_t IsoWritePipe; -}; - -/* hid.dll interface */ - -#define HIDP_STATUS_SUCCESS 0x110000 -typedef void * PHIDP_PREPARSED_DATA; - -#include -#include - -typedef USHORT USAGE; - -typedef enum _HIDP_REPORT_TYPE { - HidP_Input, - HidP_Output, - HidP_Feature -} HIDP_REPORT_TYPE; - -typedef struct _HIDP_VALUE_CAPS { - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - USHORT BitField; - USHORT LinkCollection; - USAGE LinkUsage; - USAGE LinkUsagePage; - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - BOOLEAN HasNull; - UCHAR Reserved; - USHORT BitSize; - USHORT ReportCount; - USHORT Reserved2[5]; - ULONG UnitsExp; - ULONG Units; - LONG LogicalMin, LogicalMax; - LONG PhysicalMin, PhysicalMax; - union { - struct { - USAGE UsageMin, UsageMax; - USHORT StringMin, StringMax; - USHORT DesignatorMin, DesignatorMax; - USHORT DataIndexMin, DataIndexMax; - } Range; - struct { - USAGE Usage, Reserved1; - USHORT StringIndex, Reserved2; - USHORT DesignatorIndex, Reserved3; - USHORT DataIndex, Reserved4; - } NotRange; - } u; -} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; - -DLL_DECLARE_HANDLE(hid); -DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c b/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c deleted file mode 100644 index d2be0e2a00..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * libusb strerror code - * Copyright © 2013 Hans de Goede - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#if defined(HAVE_STRINGS_H) -#include -#endif - -#include "libusbi.h" - -#if defined(_MSC_VER) -#define strncasecmp _strnicmp -#endif - -static size_t usbi_locale = 0; - -/** \ingroup libusb_misc - * How to add a new \ref libusb_strerror() translation: - *
    - *
  1. Download the latest \c strerror.c from:
    - * https://raw.github.com/libusb/libusb/master/libusb/sterror.c
  2. - *
  3. Open the file in an UTF-8 capable editor
  4. - *
  5. Add the 2 letter ISO 639-1 - * code for your locale at the end of \c usbi_locale_supported[]
    - * Eg. for Chinese, you would add "zh" so that: - * \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode - * becomes: - * \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode
  6. - *
  7. Copy the { / * English (en) * / ... } section and add it at the end of \c usbi_localized_errors
    - * Eg. for Chinese, the last section of \c usbi_localized_errors could look like: - * \code - * }, { / * Chinese (zh) * / - * "Success", - * ... - * "Other error", - * } - * };\endcode
  8. - *
  9. Translate each of the English messages from the section you copied into your language
  10. - *
  11. Save the file (in UTF-8 format) and send it to \c libusb-devel\@lists.sourceforge.net
  12. - *
- */ - -static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" }; -static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = { - { /* English (en) */ - "Success", - "Input/Output Error", - "Invalid parameter", - "Access denied (insufficient permissions)", - "No such device (it may have been disconnected)", - "Entity not found", - "Resource busy", - "Operation timed out", - "Overflow", - "Pipe error", - "System call interrupted (perhaps due to signal)", - "Insufficient memory", - "Operation not supported or unimplemented on this platform", - "Other error", - }, { /* Dutch (nl) */ - "Gelukt", - "Invoer-/uitvoerfout", - "Ongeldig argument", - "Toegang geweigerd (onvoldoende toegangsrechten)", - "Apparaat bestaat niet (verbinding met apparaat verbroken?)", - "Niet gevonden", - "Apparaat of hulpbron is bezig", - "Bewerking verlopen", - "Waarde is te groot", - "Gebroken pijp", - "Onderbroken systeemaanroep", - "Onvoldoende geheugen beschikbaar", - "Bewerking wordt niet ondersteund", - "Andere fout", - }, { /* French (fr) */ - "Succès", - "Erreur d'entrée/sortie", - "Paramètre invalide", - "Accès refusé (permissions insuffisantes)", - "Périphérique introuvable (peut-être déconnecté)", - "Elément introuvable", - "Resource déjà occupée", - "Operation expirée", - "Débordement", - "Erreur de pipe", - "Appel système abandonné (peut-être à cause d’un signal)", - "Mémoire insuffisante", - "Opération non supportée or non implémentée sur cette plateforme", - "Autre erreur", - }, { /* Russian (ru) */ - "Успех", - "Ошибка ввода/вывода", - "Неверный параметр", - "Доступ запрещён (не хватает прав)", - "Устройство отсутствует (возможно, оно было отсоединено)", - "Элемент не найден", - "Ресурс занят", - "Истекло время ожидания операции", - "Переполнение", - "Ошибка канала", - "Системный вызов прерван (возможно, сигналом)", - "Память исчерпана", - "Операция не поддерживается данной платформой", - "Неизвестная ошибка" - } -}; - -/** \ingroup libusb_misc - * Set the language, and only the language, not the encoding! used for - * translatable libusb messages. - * - * This takes a locale string in the default setlocale format: lang[-region] - * or lang[_country_region][.codeset]. Only the lang part of the string is - * used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de". - * The optional region, country_region or codeset parts are ignored. This - * means that functions which return translatable strings will NOT honor the - * specified encoding. - * All strings returned are encoded as UTF-8 strings. - * - * If libusb_setlocale() is not called, all messages will be in English. - * - * The following functions return translatable strings: libusb_strerror(). - * Note that the libusb log messages controlled through libusb_set_debug() - * are not translated, they are always in English. - * - * For POSIX UTF-8 environments if you want libusb to follow the standard - * locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)), - * after your app has done its locale setup. - * - * \param locale locale-string in the form of lang[_country_region][.codeset] - * or lang[-region], where lang is a 2 letter ISO 639-1 code - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements - * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported - * \returns a LIBUSB_ERROR code on other errors - */ - -int API_EXPORTED libusb_setlocale(const char *locale) -{ - size_t i; - - if ( (locale == NULL) || (strlen(locale) < 2) - || ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) ) - return LIBUSB_ERROR_INVALID_PARAM; - - for (i=0; i= ARRAYSIZE(usbi_locale_supported)) { - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_locale = i; - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_misc - * Returns a constant string with a short description of the given error code, - * this description is intended for displaying to the end user and will be in - * the language set by libusb_setlocale(). - * - * The returned string is encoded in UTF-8. - * - * The messages always start with a capital letter and end without any dot. - * The caller must not free() the returned string. - * - * \param errcode the error code whose description is desired - * \returns a short description of the error code in UTF-8 encoding - */ -DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode) -{ - int errcode_index = -errcode; - - if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) { - /* "Other Error", which should always be our last message, is returned */ - errcode_index = LIBUSB_ERROR_COUNT - 1; - } - - return usbi_localized_errors[usbi_locale][errcode_index]; -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/sync.c b/vendor/github.com/karalabe/usb/libusb/libusb/sync.c deleted file mode 100644 index a609f65f44..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/sync.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Synchronous I/O functions for libusb - * Copyright © 2007-2008 Daniel Drake - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -/** - * @defgroup libusb_syncio Synchronous device I/O - * - * This page documents libusb's synchronous (blocking) API for USB device I/O. - * This interface is easy to use but has some limitations. More advanced users - * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead. - */ - -static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; - usbi_dbg("actual_length=%d", transfer->actual_length); - /* caller interprets result and frees transfer */ -} - -static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) -{ - int r, *completed = transfer->user_data; - struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); - - while (!*completed) { - r = libusb_handle_events_completed(ctx, completed); - if (r < 0) { - if (r == LIBUSB_ERROR_INTERRUPTED) - continue; - usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", - libusb_error_name(r)); - libusb_cancel_transfer(transfer); - continue; - } - } -} - -/** \ingroup libusb_syncio - * Perform a USB control transfer. - * - * The direction of the transfer is inferred from the bmRequestType field of - * the setup packet. - * - * The wValue, wIndex and wLength fields values should be given in host-endian - * byte order. - * - * \param dev_handle a handle for the device to communicate with - * \param bmRequestType the request type field for the setup packet - * \param bRequest the request field for the setup packet - * \param wValue the value field for the setup packet - * \param wIndex the index field for the setup packet - * \param data a suitably-sized data buffer for either input or output - * (depending on direction bits within bmRequestType) - * \param wLength the length field for the setup packet. The data buffer should - * be at least this size. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * \returns on success, the number of bytes actually transferred - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the - * device - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than - * the operating system and/or hardware can support - * \returns another LIBUSB_ERROR code on other failures - */ -int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout) -{ - struct libusb_transfer *transfer; - unsigned char *buffer; - int completed = 0; - int r; - - if (usbi_handling_events(HANDLE_CTX(dev_handle))) - return LIBUSB_ERROR_BUSY; - - transfer = libusb_alloc_transfer(0); - if (!transfer) - return LIBUSB_ERROR_NO_MEM; - - buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); - if (!buffer) { - libusb_free_transfer(transfer); - return LIBUSB_ERROR_NO_MEM; - } - - libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, - wLength); - if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) - memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); - - libusb_fill_control_transfer(transfer, dev_handle, buffer, - sync_transfer_cb, &completed, timeout); - transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - sync_transfer_wait_for_completion(transfer); - - if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) - memcpy(data, libusb_control_transfer_get_data(transfer), - transfer->actual_length); - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = transfer->actual_length; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = LIBUSB_ERROR_TIMEOUT; - break; - case LIBUSB_TRANSFER_STALL: - r = LIBUSB_ERROR_PIPE; - break; - case LIBUSB_TRANSFER_NO_DEVICE: - r = LIBUSB_ERROR_NO_DEVICE; - break; - case LIBUSB_TRANSFER_OVERFLOW: - r = LIBUSB_ERROR_OVERFLOW; - break; - case LIBUSB_TRANSFER_ERROR: - case LIBUSB_TRANSFER_CANCELLED: - r = LIBUSB_ERROR_IO; - break; - default: - usbi_warn(HANDLE_CTX(dev_handle), - "unrecognised status code %d", transfer->status); - r = LIBUSB_ERROR_OTHER; - } - - libusb_free_transfer(transfer); - return r; -} - -static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - int *transferred, unsigned int timeout, unsigned char type) -{ - struct libusb_transfer *transfer; - int completed = 0; - int r; - - if (usbi_handling_events(HANDLE_CTX(dev_handle))) - return LIBUSB_ERROR_BUSY; - - transfer = libusb_alloc_transfer(0); - if (!transfer) - return LIBUSB_ERROR_NO_MEM; - - libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, - sync_transfer_cb, &completed, timeout); - transfer->type = type; - - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - sync_transfer_wait_for_completion(transfer); - - if (transferred) - *transferred = transfer->actual_length; - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = 0; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = LIBUSB_ERROR_TIMEOUT; - break; - case LIBUSB_TRANSFER_STALL: - r = LIBUSB_ERROR_PIPE; - break; - case LIBUSB_TRANSFER_OVERFLOW: - r = LIBUSB_ERROR_OVERFLOW; - break; - case LIBUSB_TRANSFER_NO_DEVICE: - r = LIBUSB_ERROR_NO_DEVICE; - break; - case LIBUSB_TRANSFER_ERROR: - case LIBUSB_TRANSFER_CANCELLED: - r = LIBUSB_ERROR_IO; - break; - default: - usbi_warn(HANDLE_CTX(dev_handle), - "unrecognised status code %d", transfer->status); - r = LIBUSB_ERROR_OTHER; - } - - libusb_free_transfer(transfer); - return r; -} - -/** \ingroup libusb_syncio - * Perform a USB bulk transfer. The direction of the transfer is inferred from - * the direction bits of the endpoint address. - * - * For bulk reads, the length field indicates the maximum length of - * data you are expecting to receive. If less data arrives than expected, - * this function will return that data, so be sure to check the - * transferred output parameter. - * - * You should also check the transferred parameter for bulk writes. - * Not all of the data may have been written. - * - * Also check transferred when dealing with a timeout error code. - * libusb may have to split your transfer into a number of chunks to satisfy - * underlying O/S requirements, meaning that the timeout may expire after - * the first few chunks have completed. libusb is careful not to lose any data - * that may have been transferred; do not assume that timeout conditions - * indicate a complete lack of I/O. - * - * \param dev_handle a handle for the device to communicate with - * \param endpoint the address of a valid endpoint to communicate with - * \param data a suitably-sized data buffer for either input or output - * (depending on endpoint) - * \param length for bulk writes, the number of bytes from data to be sent. for - * bulk reads, the maximum number of bytes to receive into the data buffer. - * \param transferred output location for the number of bytes actually - * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), - * it is legal to pass a NULL pointer if you do not wish to receive this - * information. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * - * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates - * transferred) - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns another LIBUSB_ERROR code on other failures - */ -int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, int *transferred, - unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); -} - -/** \ingroup libusb_syncio - * Perform a USB interrupt transfer. The direction of the transfer is inferred - * from the direction bits of the endpoint address. - * - * For interrupt reads, the length field indicates the maximum length - * of data you are expecting to receive. If less data arrives than expected, - * this function will return that data, so be sure to check the - * transferred output parameter. - * - * You should also check the transferred parameter for interrupt - * writes. Not all of the data may have been written. - * - * Also check transferred when dealing with a timeout error code. - * libusb may have to split your transfer into a number of chunks to satisfy - * underlying O/S requirements, meaning that the timeout may expire after - * the first few chunks have completed. libusb is careful not to lose any data - * that may have been transferred; do not assume that timeout conditions - * indicate a complete lack of I/O. - * - * The default endpoint bInterval value is used as the polling interval. - * - * \param dev_handle a handle for the device to communicate with - * \param endpoint the address of a valid endpoint to communicate with - * \param data a suitably-sized data buffer for either input or output - * (depending on endpoint) - * \param length for bulk writes, the number of bytes from data to be sent. for - * bulk reads, the maximum number of bytes to receive into the data buffer. - * \param transferred output location for the number of bytes actually - * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), - * it is legal to pass a NULL pointer if you do not wish to receive this - * information. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * - * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns another LIBUSB_ERROR code on other error - */ -int API_EXPORTED libusb_interrupt_transfer( - struct libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *data, int length, int *transferred, unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); -} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/version.h b/vendor/github.com/karalabe/usb/libusb/libusb/version.h deleted file mode 100644 index c6dfe37093..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/version.h +++ /dev/null @@ -1,18 +0,0 @@ -/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */ -#include "version_nano.h" -#ifndef LIBUSB_MAJOR -#define LIBUSB_MAJOR 1 -#endif -#ifndef LIBUSB_MINOR -#define LIBUSB_MINOR 0 -#endif -#ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 22 -#endif -#ifndef LIBUSB_NANO -#define LIBUSB_NANO 0 -#endif -/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ -#ifndef LIBUSB_RC -#define LIBUSB_RC "" -#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h b/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h deleted file mode 100644 index 90a782a6bf..0000000000 --- a/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h +++ /dev/null @@ -1 +0,0 @@ -#define LIBUSB_NANO 11312 diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go deleted file mode 100644 index 5d052781bc..0000000000 --- a/vendor/golang.org/x/net/html/atom/gen.go +++ /dev/null @@ -1,712 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -//go:generate go run gen.go -//go:generate go run gen.go -test - -package main - -import ( - "bytes" - "flag" - "fmt" - "go/format" - "io/ioutil" - "math/rand" - "os" - "sort" - "strings" -) - -// identifier converts s to a Go exported identifier. -// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". -func identifier(s string) string { - b := make([]byte, 0, len(s)) - cap := true - for _, c := range s { - if c == '-' { - cap = true - continue - } - if cap && 'a' <= c && c <= 'z' { - c -= 'a' - 'A' - } - cap = false - b = append(b, byte(c)) - } - return string(b) -} - -var test = flag.Bool("test", false, "generate table_test.go") - -func genFile(name string, buf *bytes.Buffer) { - b, err := format.Source(buf.Bytes()) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - if err := ioutil.WriteFile(name, b, 0644); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func main() { - flag.Parse() - - var all []string - all = append(all, elements...) - all = append(all, attributes...) - all = append(all, eventHandlers...) - all = append(all, extra...) - sort.Strings(all) - - // uniq - lists have dups - w := 0 - for _, s := range all { - if w == 0 || all[w-1] != s { - all[w] = s - w++ - } - } - all = all[:w] - - if *test { - var buf bytes.Buffer - fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") - fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") - fmt.Fprintln(&buf, "package atom\n") - fmt.Fprintln(&buf, "var testAtomList = []string{") - for _, s := range all { - fmt.Fprintf(&buf, "\t%q,\n", s) - } - fmt.Fprintln(&buf, "}") - - genFile("table_test.go", &buf) - return - } - - // Find hash that minimizes table size. - var best *table - for i := 0; i < 1000000; i++ { - if best != nil && 1<<(best.k-1) < len(all) { - break - } - h := rand.Uint32() - for k := uint(0); k <= 16; k++ { - if best != nil && k >= best.k { - break - } - var t table - if t.init(h, k, all) { - best = &t - break - } - } - } - if best == nil { - fmt.Fprintf(os.Stderr, "failed to construct string table\n") - os.Exit(1) - } - - // Lay out strings, using overlaps when possible. - layout := append([]string{}, all...) - - // Remove strings that are substrings of other strings - for changed := true; changed; { - changed = false - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i != j && t != "" && strings.Contains(s, t) { - changed = true - layout[j] = "" - } - } - } - } - - // Join strings where one suffix matches another prefix. - for { - // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], - // maximizing overlap length k. - besti := -1 - bestj := -1 - bestk := 0 - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i == j { - continue - } - for k := bestk + 1; k <= len(s) && k <= len(t); k++ { - if s[len(s)-k:] == t[:k] { - besti = i - bestj = j - bestk = k - } - } - } - } - if bestk > 0 { - layout[besti] += layout[bestj][bestk:] - layout[bestj] = "" - continue - } - break - } - - text := strings.Join(layout, "") - - atom := map[string]uint32{} - for _, s := range all { - off := strings.Index(text, s) - if off < 0 { - panic("lost string " + s) - } - atom[s] = uint32(off<<8 | len(s)) - } - - var buf bytes.Buffer - // Generate the Go code. - fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") - fmt.Fprintln(&buf, "//go:generate go run gen.go\n") - fmt.Fprintln(&buf, "package atom\n\nconst (") - - // compute max len - maxLen := 0 - for _, s := range all { - if maxLen < len(s) { - maxLen = len(s) - } - fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) - } - fmt.Fprintln(&buf, ")\n") - - fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) - fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) - - fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) - for i, s := range best.tab { - if s == "" { - continue - } - fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) - } - fmt.Fprintf(&buf, "}\n") - datasize := (1 << best.k) * 4 - - fmt.Fprintln(&buf, "const atomText =") - textsize := len(text) - for len(text) > 60 { - fmt.Fprintf(&buf, "\t%q +\n", text[:60]) - text = text[60:] - } - fmt.Fprintf(&buf, "\t%q\n\n", text) - - genFile("table.go", &buf) - - fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) -} - -type byLen []string - -func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } -func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byLen) Len() int { return len(x) } - -// fnv computes the FNV hash with an arbitrary starting value h. -func fnv(h uint32, s string) uint32 { - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - return h -} - -// A table represents an attempt at constructing the lookup table. -// The lookup table uses cuckoo hashing, meaning that each string -// can be found in one of two positions. -type table struct { - h0 uint32 - k uint - mask uint32 - tab []string -} - -// hash returns the two hashes for s. -func (t *table) hash(s string) (h1, h2 uint32) { - h := fnv(t.h0, s) - h1 = h & t.mask - h2 = (h >> 16) & t.mask - return -} - -// init initializes the table with the given parameters. -// h0 is the initial hash value, -// k is the number of bits of hash value to use, and -// x is the list of strings to store in the table. -// init returns false if the table cannot be constructed. -func (t *table) init(h0 uint32, k uint, x []string) bool { - t.h0 = h0 - t.k = k - t.tab = make([]string, 1< len(t.tab) { - return false - } - s := t.tab[i] - h1, h2 := t.hash(s) - j := h1 + h2 - i - if t.tab[j] != "" && !t.push(j, depth+1) { - return false - } - t.tab[j] = s - return true -} - -// The lists of element names and attribute keys were taken from -// https://html.spec.whatwg.org/multipage/indices.html#index -// as of the "HTML Living Standard - Last Updated 16 April 2018" version. - -// "command", "keygen" and "menuitem" have been removed from the spec, -// but are kept here for backwards compatibility. -var elements = []string{ - "a", - "abbr", - "address", - "area", - "article", - "aside", - "audio", - "b", - "base", - "bdi", - "bdo", - "blockquote", - "body", - "br", - "button", - "canvas", - "caption", - "cite", - "code", - "col", - "colgroup", - "command", - "data", - "datalist", - "dd", - "del", - "details", - "dfn", - "dialog", - "div", - "dl", - "dt", - "em", - "embed", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "hgroup", - "hr", - "html", - "i", - "iframe", - "img", - "input", - "ins", - "kbd", - "keygen", - "label", - "legend", - "li", - "link", - "main", - "map", - "mark", - "menu", - "menuitem", - "meta", - "meter", - "nav", - "noscript", - "object", - "ol", - "optgroup", - "option", - "output", - "p", - "param", - "picture", - "pre", - "progress", - "q", - "rp", - "rt", - "ruby", - "s", - "samp", - "script", - "section", - "select", - "slot", - "small", - "source", - "span", - "strong", - "style", - "sub", - "summary", - "sup", - "table", - "tbody", - "td", - "template", - "textarea", - "tfoot", - "th", - "thead", - "time", - "title", - "tr", - "track", - "u", - "ul", - "var", - "video", - "wbr", -} - -// https://html.spec.whatwg.org/multipage/indices.html#attributes-3 -// -// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", -// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, -// but are kept here for backwards compatibility. -var attributes = []string{ - "abbr", - "accept", - "accept-charset", - "accesskey", - "action", - "allowfullscreen", - "allowpaymentrequest", - "allowusermedia", - "alt", - "as", - "async", - "autocomplete", - "autofocus", - "autoplay", - "challenge", - "charset", - "checked", - "cite", - "class", - "color", - "cols", - "colspan", - "command", - "content", - "contenteditable", - "contextmenu", - "controls", - "coords", - "crossorigin", - "data", - "datetime", - "default", - "defer", - "dir", - "dirname", - "disabled", - "download", - "draggable", - "dropzone", - "enctype", - "for", - "form", - "formaction", - "formenctype", - "formmethod", - "formnovalidate", - "formtarget", - "headers", - "height", - "hidden", - "high", - "href", - "hreflang", - "http-equiv", - "icon", - "id", - "inputmode", - "integrity", - "is", - "ismap", - "itemid", - "itemprop", - "itemref", - "itemscope", - "itemtype", - "keytype", - "kind", - "label", - "lang", - "list", - "loop", - "low", - "manifest", - "max", - "maxlength", - "media", - "mediagroup", - "method", - "min", - "minlength", - "multiple", - "muted", - "name", - "nomodule", - "nonce", - "novalidate", - "open", - "optimum", - "pattern", - "ping", - "placeholder", - "playsinline", - "poster", - "preload", - "radiogroup", - "readonly", - "referrerpolicy", - "rel", - "required", - "reversed", - "rows", - "rowspan", - "sandbox", - "spellcheck", - "scope", - "scoped", - "seamless", - "selected", - "shape", - "size", - "sizes", - "sortable", - "sorted", - "slot", - "span", - "spellcheck", - "src", - "srcdoc", - "srclang", - "srcset", - "start", - "step", - "style", - "tabindex", - "target", - "title", - "translate", - "type", - "typemustmatch", - "updateviacache", - "usemap", - "value", - "width", - "workertype", - "wrap", -} - -// "onautocomplete", "onautocompleteerror", "onmousewheel", -// "onshow" and "onsort" have been removed from the spec, -// but are kept here for backwards compatibility. -var eventHandlers = []string{ - "onabort", - "onautocomplete", - "onautocompleteerror", - "onauxclick", - "onafterprint", - "onbeforeprint", - "onbeforeunload", - "onblur", - "oncancel", - "oncanplay", - "oncanplaythrough", - "onchange", - "onclick", - "onclose", - "oncontextmenu", - "oncopy", - "oncuechange", - "oncut", - "ondblclick", - "ondrag", - "ondragend", - "ondragenter", - "ondragexit", - "ondragleave", - "ondragover", - "ondragstart", - "ondrop", - "ondurationchange", - "onemptied", - "onended", - "onerror", - "onfocus", - "onhashchange", - "oninput", - "oninvalid", - "onkeydown", - "onkeypress", - "onkeyup", - "onlanguagechange", - "onload", - "onloadeddata", - "onloadedmetadata", - "onloadend", - "onloadstart", - "onmessage", - "onmessageerror", - "onmousedown", - "onmouseenter", - "onmouseleave", - "onmousemove", - "onmouseout", - "onmouseover", - "onmouseup", - "onmousewheel", - "onwheel", - "onoffline", - "ononline", - "onpagehide", - "onpageshow", - "onpaste", - "onpause", - "onplay", - "onplaying", - "onpopstate", - "onprogress", - "onratechange", - "onreset", - "onresize", - "onrejectionhandled", - "onscroll", - "onsecuritypolicyviolation", - "onseeked", - "onseeking", - "onselect", - "onshow", - "onsort", - "onstalled", - "onstorage", - "onsubmit", - "onsuspend", - "ontimeupdate", - "ontoggle", - "onunhandledrejection", - "onunload", - "onvolumechange", - "onwaiting", -} - -// extra are ad-hoc values not covered by any of the lists above. -var extra = []string{ - "acronym", - "align", - "annotation", - "annotation-xml", - "applet", - "basefont", - "bgsound", - "big", - "blink", - "center", - "color", - "desc", - "face", - "font", - "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. - "foreignobject", - "frame", - "frameset", - "image", - "isindex", - "listing", - "malignmark", - "marquee", - "math", - "mglyph", - "mi", - "mn", - "mo", - "ms", - "mtext", - "nobr", - "noembed", - "noframes", - "plaintext", - "prompt", - "public", - "rb", - "rtc", - "spacer", - "strike", - "svg", - "system", - "tt", - "xmp", -} diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go index e3c01d7c90..ae0d1b05cd 100644 --- a/vendor/golang.org/x/net/html/token.go +++ b/vendor/golang.org/x/net/html/token.go @@ -347,6 +347,7 @@ loop: break loop } if c != '/' { + z.raw.end-- continue loop } if z.readRawEndTag() || z.err != nil { @@ -1067,6 +1068,11 @@ loop: // Raw returns the unmodified text of the current token. Calling Next, Token, // Text, TagName or TagAttr may change the contents of the returned slice. +// +// The token stream's raw bytes partition the byte stream (up until an +// ErrorToken). There are no overlaps or gaps between two consecutive token's +// raw bytes. One implication is that the byte offset of the current token is +// the sum of the lengths of all previous tokens' raw bytes. func (z *Tokenizer) Raw() []byte { return z.buf[z.raw.start:z.raw.end] } diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go index 1565cf2702..97f17831fc 100644 --- a/vendor/golang.org/x/net/http2/hpack/encode.go +++ b/vendor/golang.org/x/net/http2/hpack/encode.go @@ -150,7 +150,7 @@ func appendIndexed(dst []byte, i uint64) []byte { // extended buffer. // // If f.Sensitive is true, "Never Indexed" representation is used. If -// f.Sensitive is false and indexing is true, "Inremental Indexing" +// f.Sensitive is false and indexing is true, "Incremental Indexing" // representation is used. func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go index a6140099cb..2a5399ec4a 100644 --- a/vendor/golang.org/x/net/http2/pipe.go +++ b/vendor/golang.org/x/net/http2/pipe.go @@ -17,6 +17,7 @@ type pipe struct { mu sync.Mutex c sync.Cond // c.L lazily initialized to &p.mu b pipeBuffer // nil when done reading + unread int // bytes unread when done err error // read error once empty. non-nil means closed. breakErr error // immediate read error (caller doesn't see rest of b) donec chan struct{} // closed on error @@ -33,7 +34,7 @@ func (p *pipe) Len() int { p.mu.Lock() defer p.mu.Unlock() if p.b == nil { - return 0 + return p.unread } return p.b.Len() } @@ -80,6 +81,7 @@ func (p *pipe) Write(d []byte) (n int, err error) { return 0, errClosedPipeWrite } if p.breakErr != nil { + p.unread += len(d) return len(d), nil // discard when there is no reader } return p.b.Write(d) @@ -117,6 +119,9 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) { } p.readFn = fn if dst == &p.breakErr { + if p.b != nil { + p.unread += p.b.Len() + } p.b = nil } *dst = err diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 57334dc79b..d2ba820c70 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -52,10 +52,11 @@ import ( ) const ( - prefaceTimeout = 10 * time.Second - firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway - handlerChunkWriteSize = 4 << 10 - defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + prefaceTimeout = 10 * time.Second + firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway + handlerChunkWriteSize = 4 << 10 + defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + maxQueuedControlFrames = 10000 ) var ( @@ -163,6 +164,15 @@ func (s *Server) maxConcurrentStreams() uint32 { return defaultMaxStreams } +// maxQueuedControlFrames is the maximum number of control frames like +// SETTINGS, PING and RST_STREAM that will be queued for writing before +// the connection is closed to prevent memory exhaustion attacks. +func (s *Server) maxQueuedControlFrames() int { + // TODO: if anybody asks, add a Server field, and remember to define the + // behavior of negative values. + return maxQueuedControlFrames +} + type serverInternalState struct { mu sync.Mutex activeConns map[*serverConn]struct{} @@ -312,7 +322,7 @@ type ServeConnOpts struct { } func (o *ServeConnOpts) context() context.Context { - if o.Context != nil { + if o != nil && o.Context != nil { return o.Context } return context.Background() @@ -506,6 +516,7 @@ type serverConn struct { sawFirstSettings bool // got the initial SETTINGS frame after the preface needToSendSettingsAck bool unackedSettings int // how many SETTINGS have we sent without ACKs? + queuedControlFrames int // control frames in the writeSched queue clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client @@ -894,6 +905,14 @@ func (sc *serverConn) serve() { } } + // If the peer is causing us to generate a lot of control frames, + // but not reading them from us, assume they are trying to make us + // run out of memory. + if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() { + sc.vlogf("http2: too many control frames in send queue, closing connection") + return + } + // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY // with no error code (graceful shutdown), don't start the timer until // all open streams have been completed. @@ -1093,6 +1112,14 @@ func (sc *serverConn) writeFrame(wr FrameWriteRequest) { } if !ignoreWrite { + if wr.isControl() { + sc.queuedControlFrames++ + // For extra safety, detect wraparounds, which should not happen, + // and pull the plug. + if sc.queuedControlFrames < 0 { + sc.conn.Close() + } + } sc.writeSched.Push(wr) } sc.scheduleFrameWrite() @@ -1210,10 +1237,8 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) { // If a frame is already being written, nothing happens. This will be called again // when the frame is done being written. // -// If a frame isn't being written we need to send one, the best frame -// to send is selected, preferring first things that aren't -// stream-specific (e.g. ACKing settings), and then finding the -// highest priority stream. +// If a frame isn't being written and we need to send one, the best frame +// to send is selected by writeSched. // // If a frame isn't being written and there's nothing else to send, we // flush the write buffer. @@ -1241,6 +1266,9 @@ func (sc *serverConn) scheduleFrameWrite() { } if !sc.inGoAway || sc.goAwayCode == ErrCodeNo { if wr, ok := sc.writeSched.Pop(); ok { + if wr.isControl() { + sc.queuedControlFrames-- + } sc.startFrameWrite(wr) continue } @@ -1533,6 +1561,8 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error { if err := f.ForeachSetting(sc.processSetting); err != nil { return err } + // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be + // acknowledged individually, even if multiple are received before the ACK. sc.needToSendSettingsAck = true sc.scheduleFrameWrite() return nil @@ -2385,7 +2415,11 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { clen = strconv.Itoa(len(p)) } _, hasContentType := rws.snapHeader["Content-Type"] - if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 { + // If the Content-Encoding is non-blank, we shouldn't + // sniff the body. See Issue golang.org/issue/31753. + ce := rws.snapHeader.Get("Content-Encoding") + hasCE := len(ce) > 0 + if !hasCE && !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 { ctype = http.DetectContentType(p) } var date string @@ -2494,7 +2528,7 @@ const TrailerPrefix = "Trailer:" // trailers. That worked for a while, until we found the first major // user of Trailers in the wild: gRPC (using them only over http2), // and gRPC libraries permit setting trailers mid-stream without -// predeclarnig them. So: change of plans. We still permit the old +// predeclaring them. So: change of plans. We still permit the old // way, but we also permit this hack: if a Header() key begins with // "Trailer:", the suffix of that key is a Trailer. Because ':' is an // invalid token byte anyway, there is no ambiguity. (And it's already @@ -2794,7 +2828,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) { // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that // is in either the "open" or "half-closed (remote)" state. if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { - // responseWriter.Push checks that the stream is peer-initiaed. + // responseWriter.Push checks that the stream is peer-initiated. msg.done <- errStreamClosed return } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index aeac7d8a51..42ad181448 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -603,7 +603,7 @@ func (t *Transport) expectContinueTimeout() time.Duration { } func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { - return t.newClientConn(c, false) + return t.newClientConn(c, t.disableKeepAlives()) } func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { @@ -1216,6 +1216,8 @@ var ( // abort request body write, but send stream reset of cancel. errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") + + errReqBodyTooLong = errors.New("http2: request body larger than specified content length") ) func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { @@ -1238,10 +1240,32 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) ( req := cs.req hasTrailers := req.Trailer != nil + remainLen := actualContentLength(req) + hasContentLen := remainLen != -1 var sawEOF bool for !sawEOF { - n, err := body.Read(buf) + n, err := body.Read(buf[:len(buf)-1]) + if hasContentLen { + remainLen -= int64(n) + if remainLen == 0 && err == nil { + // The request body's Content-Length was predeclared and + // we just finished reading it all, but the underlying io.Reader + // returned the final chunk with a nil error (which is one of + // the two valid things a Reader can do at EOF). Because we'd prefer + // to send the END_STREAM bit early, double-check that we're actually + // at EOF. Subsequent reads should return (0, EOF) at this point. + // If either value is different, we return an error in one of two ways below. + var n1 int + n1, err = body.Read(buf[n:]) + remainLen -= int64(n1) + } + if remainLen < 0 { + err = errReqBodyTooLong + cc.writeStreamReset(cs.ID, ErrCodeCancel, err) + return err + } + } if err == io.EOF { sawEOF = true err = nil @@ -1454,7 +1478,29 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail if vv[0] == "" { continue } - + } else if strings.EqualFold(k, "cookie") { + // Per 8.1.2.5 To allow for better compression efficiency, the + // Cookie header field MAY be split into separate header fields, + // each with one or more cookie-pairs. + for _, v := range vv { + for { + p := strings.IndexByte(v, ';') + if p < 0 { + break + } + f("cookie", v[:p]) + p++ + // strip space after semicolon if any. + for p+1 <= len(v) && v[p] == ' ' { + p++ + } + v = v[p:] + } + if len(v) > 0 { + f("cookie", v) + } + } + continue } for _, v := range vv { diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go index 4fe3073073..f24d2b1e7d 100644 --- a/vendor/golang.org/x/net/http2/writesched.go +++ b/vendor/golang.org/x/net/http2/writesched.go @@ -32,7 +32,7 @@ type WriteScheduler interface { // Pop dequeues the next frame to write. Returns false if no frames can // be written. Frames with a given wr.StreamID() are Pop'd in the same - // order they are Push'd. + // order they are Push'd. No frames should be discarded except by CloseStream. Pop() (wr FrameWriteRequest, ok bool) } @@ -76,6 +76,12 @@ func (wr FrameWriteRequest) StreamID() uint32 { return wr.stream.id } +// isControl reports whether wr is a control frame for MaxQueuedControlFrames +// purposes. That includes non-stream frames and RST_STREAM frames. +func (wr FrameWriteRequest) isControl() bool { + return wr.stream == nil +} + // DataSize returns the number of flow control bytes that must be consumed // to write this entire frame. This is 0 for non-DATA frames. func (wr FrameWriteRequest) DataSize() int { diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go index 848fed6ec7..2618b2c11d 100644 --- a/vendor/golang.org/x/net/http2/writesched_priority.go +++ b/vendor/golang.org/x/net/http2/writesched_priority.go @@ -149,7 +149,7 @@ func (n *priorityNode) addBytes(b int64) { } // walkReadyInOrder iterates over the tree in priority order, calling f for each node -// with a non-empty write queue. When f returns true, this funcion returns true and the +// with a non-empty write queue. When f returns true, this function returns true and the // walk halts. tmp is used as scratch space for sorting. // // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true diff --git a/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go index 36d7919f16..9a7b9e581c 100644 --- a/vendor/golang.org/x/net/http2/writesched_random.go +++ b/vendor/golang.org/x/net/http2/writesched_random.go @@ -19,7 +19,8 @@ type randomWriteScheduler struct { zero writeQueue // sq contains the stream-specific queues, keyed by stream ID. - // When a stream is idle or closed, it's deleted from the map. + // When a stream is idle, closed, or emptied, it's deleted + // from the map. sq map[uint32]*writeQueue // pool of empty queues for reuse. @@ -63,8 +64,12 @@ func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) { return ws.zero.shift(), true } // Iterate over all non-idle streams until finding one that can be consumed. - for _, q := range ws.sq { + for streamID, q := range ws.sq { if wr, ok := q.consume(math.MaxInt32); ok { + if q.empty() { + delete(ws.sq, streamID) + ws.queuePool.put(q) + } return wr, true } } diff --git a/vendor/golang.org/x/net/idna/tables11.0.0.go b/vendor/golang.org/x/net/idna/tables11.0.0.go index c515d7ad2a..8ce0811fdf 100644 --- a/vendor/golang.org/x/net/idna/tables11.0.0.go +++ b/vendor/golang.org/x/net/idna/tables11.0.0.go @@ -1,6 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. -// +build go1.13 +// +build go1.13,!go1.14 package idna diff --git a/vendor/golang.org/x/net/idna/tables12.00.go b/vendor/golang.org/x/net/idna/tables12.00.go new file mode 100644 index 0000000000..f4b8ea3638 --- /dev/null +++ b/vendor/golang.org/x/net/idna/tables12.00.go @@ -0,0 +1,4733 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +// +build go1.14 + +package idna + +// UnicodeVersion is the Unicode version from which the tables in this package are derived. +const UnicodeVersion = "12.0.0" + +var mappings string = "" + // Size: 8178 bytes + "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" + + "\x053⁄4\x03i̇\x03l·\x03ʼn\x01s\x03dž\x03ⱥ\x03ⱦ\x01h\x01j\x01r\x01w\x01y" + + "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" + + "\x04եւ\x04اٴ\x04وٴ\x04ۇٴ\x04يٴ\x06क़\x06ख़\x06ग़\x06ज़\x06ड़\x06ढ़\x06फ़" + + "\x06य़\x06ড়\x06ঢ়\x06য়\x06ਲ਼\x06ਸ਼\x06ਖ਼\x06ਗ਼\x06ਜ਼\x06ਫ਼\x06ଡ଼\x06ଢ଼" + + "\x06ํา\x06ໍາ\x06ຫນ\x06ຫມ\x06གྷ\x06ཌྷ\x06དྷ\x06བྷ\x06ཛྷ\x06ཀྵ\x06ཱི\x06ཱུ" + + "\x06ྲྀ\x09ྲཱྀ\x06ླྀ\x09ླཱྀ\x06ཱྀ\x06ྒྷ\x06ྜྷ\x06ྡྷ\x06ྦྷ\x06ྫྷ\x06ྐྵ\x02" + + "в\x02д\x02о\x02с\x02т\x02ъ\x02ѣ\x02æ\x01b\x01d\x01e\x02ǝ\x01g\x01i\x01k" + + "\x01m\x01n\x02ȣ\x01p\x01t\x01u\x02ɐ\x02ɑ\x02ə\x02ɛ\x02ɜ\x02ŋ\x02ɔ\x02ɯ" + + "\x01v\x02β\x02γ\x02δ\x02φ\x02χ\x02ρ\x02н\x02ɒ\x01c\x02ɕ\x02ð\x01f\x02ɟ" + + "\x02ɡ\x02ɥ\x02ɨ\x02ɩ\x02ɪ\x02ʝ\x02ɭ\x02ʟ\x02ɱ\x02ɰ\x02ɲ\x02ɳ\x02ɴ\x02ɵ" + + "\x02ɸ\x02ʂ\x02ʃ\x02ƫ\x02ʉ\x02ʊ\x02ʋ\x02ʌ\x01z\x02ʐ\x02ʑ\x02ʒ\x02θ\x02ss" + + "\x02ά\x02έ\x02ή\x02ί\x02ό\x02ύ\x02ώ\x05ἀι\x05ἁι\x05ἂι\x05ἃι\x05ἄι\x05ἅι" + + "\x05ἆι\x05ἇι\x05ἠι\x05ἡι\x05ἢι\x05ἣι\x05ἤι\x05ἥι\x05ἦι\x05ἧι\x05ὠι\x05ὡι" + + "\x05ὢι\x05ὣι\x05ὤι\x05ὥι\x05ὦι\x05ὧι\x05ὰι\x04αι\x04άι\x05ᾶι\x02ι\x05 ̈͂" + + "\x05ὴι\x04ηι\x04ήι\x05ῆι\x05 ̓̀\x05 ̓́\x05 ̓͂\x02ΐ\x05 ̔̀\x05 ̔́\x05 ̔͂" + + "\x02ΰ\x05 ̈̀\x01`\x05ὼι\x04ωι\x04ώι\x05ῶι\x06′′\x09′′′\x06‵‵\x09‵‵‵\x02!" + + "!\x02??\x02?!\x02!?\x0c′′′′\x010\x014\x015\x016\x017\x018\x019\x01+\x01=" + + "\x01(\x01)\x02rs\x02ħ\x02no\x01q\x02sm\x02tm\x02ω\x02å\x02א\x02ב\x02ג" + + "\x02ד\x02π\x051⁄7\x051⁄9\x061⁄10\x051⁄3\x052⁄3\x051⁄5\x052⁄5\x053⁄5\x054" + + "⁄5\x051⁄6\x055⁄6\x051⁄8\x053⁄8\x055⁄8\x057⁄8\x041⁄\x02ii\x02iv\x02vi" + + "\x04viii\x02ix\x02xi\x050⁄3\x06∫∫\x09∫∫∫\x06∮∮\x09∮∮∮\x0210\x0211\x0212" + + "\x0213\x0214\x0215\x0216\x0217\x0218\x0219\x0220\x04(10)\x04(11)\x04(12)" + + "\x04(13)\x04(14)\x04(15)\x04(16)\x04(17)\x04(18)\x04(19)\x04(20)\x0c∫∫∫∫" + + "\x02==\x05⫝̸\x02ɫ\x02ɽ\x02ȿ\x02ɀ\x01.\x04 ゙\x04 ゚\x06より\x06コト\x05(ᄀ)\x05" + + "(ᄂ)\x05(ᄃ)\x05(ᄅ)\x05(ᄆ)\x05(ᄇ)\x05(ᄉ)\x05(ᄋ)\x05(ᄌ)\x05(ᄎ)\x05(ᄏ)\x05(ᄐ" + + ")\x05(ᄑ)\x05(ᄒ)\x05(가)\x05(나)\x05(다)\x05(라)\x05(마)\x05(바)\x05(사)\x05(아)" + + "\x05(자)\x05(차)\x05(카)\x05(타)\x05(파)\x05(하)\x05(주)\x08(오전)\x08(오후)\x05(一)" + + "\x05(二)\x05(三)\x05(四)\x05(五)\x05(六)\x05(七)\x05(八)\x05(九)\x05(十)\x05(月)" + + "\x05(火)\x05(水)\x05(木)\x05(金)\x05(土)\x05(日)\x05(株)\x05(有)\x05(社)\x05(名)" + + "\x05(特)\x05(財)\x05(祝)\x05(労)\x05(代)\x05(呼)\x05(学)\x05(監)\x05(企)\x05(資)" + + "\x05(協)\x05(祭)\x05(休)\x05(自)\x05(至)\x0221\x0222\x0223\x0224\x0225\x0226" + + "\x0227\x0228\x0229\x0230\x0231\x0232\x0233\x0234\x0235\x06참고\x06주의\x0236" + + "\x0237\x0238\x0239\x0240\x0241\x0242\x0243\x0244\x0245\x0246\x0247\x0248" + + "\x0249\x0250\x041月\x042月\x043月\x044月\x045月\x046月\x047月\x048月\x049月\x0510" + + "月\x0511月\x0512月\x02hg\x02ev\x0cアパート\x0cアルファ\x0cアンペア\x09アール\x0cイニング\x09" + + "インチ\x09ウォン\x0fエスクード\x0cエーカー\x09オンス\x09オーム\x09カイリ\x0cカラット\x0cカロリー\x09ガロ" + + "ン\x09ガンマ\x06ギガ\x09ギニー\x0cキュリー\x0cギルダー\x06キロ\x0fキログラム\x12キロメートル\x0fキロワッ" + + "ト\x09グラム\x0fグラムトン\x0fクルゼイロ\x0cクローネ\x09ケース\x09コルナ\x09コーポ\x0cサイクル\x0fサンチ" + + "ーム\x0cシリング\x09センチ\x09セント\x09ダース\x06デシ\x06ドル\x06トン\x06ナノ\x09ノット\x09ハイツ" + + "\x0fパーセント\x09パーツ\x0cバーレル\x0fピアストル\x09ピクル\x06ピコ\x06ビル\x0fファラッド\x0cフィート" + + "\x0fブッシェル\x09フラン\x0fヘクタール\x06ペソ\x09ペニヒ\x09ヘルツ\x09ペンス\x09ページ\x09ベータ\x0cポイ" + + "ント\x09ボルト\x06ホン\x09ポンド\x09ホール\x09ホーン\x0cマイクロ\x09マイル\x09マッハ\x09マルク\x0fマ" + + "ンション\x0cミクロン\x06ミリ\x0fミリバール\x06メガ\x0cメガトン\x0cメートル\x09ヤード\x09ヤール\x09ユアン" + + "\x0cリットル\x06リラ\x09ルピー\x0cルーブル\x06レム\x0fレントゲン\x09ワット\x040点\x041点\x042点" + + "\x043点\x044点\x045点\x046点\x047点\x048点\x049点\x0510点\x0511点\x0512点\x0513点" + + "\x0514点\x0515点\x0516点\x0517点\x0518点\x0519点\x0520点\x0521点\x0522点\x0523点" + + "\x0524点\x02da\x02au\x02ov\x02pc\x02dm\x02iu\x06平成\x06昭和\x06大正\x06明治\x0c株" + + "式会社\x02pa\x02na\x02ma\x02ka\x02kb\x02mb\x02gb\x04kcal\x02pf\x02nf\x02m" + + "g\x02kg\x02hz\x02ml\x02dl\x02kl\x02fm\x02nm\x02mm\x02cm\x02km\x02m2\x02m" + + "3\x05m∕s\x06m∕s2\x07rad∕s\x08rad∕s2\x02ps\x02ns\x02ms\x02pv\x02nv\x02mv" + + "\x02kv\x02pw\x02nw\x02mw\x02kw\x02bq\x02cc\x02cd\x06c∕kg\x02db\x02gy\x02" + + "ha\x02hp\x02in\x02kk\x02kt\x02lm\x02ln\x02lx\x02ph\x02pr\x02sr\x02sv\x02" + + "wb\x05v∕m\x05a∕m\x041日\x042日\x043日\x044日\x045日\x046日\x047日\x048日\x049日" + + "\x0510日\x0511日\x0512日\x0513日\x0514日\x0515日\x0516日\x0517日\x0518日\x0519日" + + "\x0520日\x0521日\x0522日\x0523日\x0524日\x0525日\x0526日\x0527日\x0528日\x0529日" + + "\x0530日\x0531日\x02ь\x02ɦ\x02ɬ\x02ʞ\x02ʇ\x02œ\x04𤋮\x04𢡊\x04𢡄\x04𣏕\x04𥉉" + + "\x04𥳐\x04𧻓\x02ff\x02fi\x02fl\x02st\x04մն\x04մե\x04մի\x04վն\x04մխ\x04יִ" + + "\x04ײַ\x02ע\x02ה\x02כ\x02ל\x02ם\x02ר\x02ת\x04שׁ\x04שׂ\x06שּׁ\x06שּׂ\x04א" + + "ַ\x04אָ\x04אּ\x04בּ\x04גּ\x04דּ\x04הּ\x04וּ\x04זּ\x04טּ\x04יּ\x04ךּ\x04" + + "כּ\x04לּ\x04מּ\x04נּ\x04סּ\x04ףּ\x04פּ\x04צּ\x04קּ\x04רּ\x04שּ\x04תּ" + + "\x04וֹ\x04בֿ\x04כֿ\x04פֿ\x04אל\x02ٱ\x02ٻ\x02پ\x02ڀ\x02ٺ\x02ٿ\x02ٹ\x02ڤ" + + "\x02ڦ\x02ڄ\x02ڃ\x02چ\x02ڇ\x02ڍ\x02ڌ\x02ڎ\x02ڈ\x02ژ\x02ڑ\x02ک\x02گ\x02ڳ" + + "\x02ڱ\x02ں\x02ڻ\x02ۀ\x02ہ\x02ھ\x02ے\x02ۓ\x02ڭ\x02ۇ\x02ۆ\x02ۈ\x02ۋ\x02ۅ" + + "\x02ۉ\x02ې\x02ى\x04ئا\x04ئە\x04ئو\x04ئۇ\x04ئۆ\x04ئۈ\x04ئې\x04ئى\x02ی\x04" + + "ئج\x04ئح\x04ئم\x04ئي\x04بج\x04بح\x04بخ\x04بم\x04بى\x04بي\x04تج\x04تح" + + "\x04تخ\x04تم\x04تى\x04تي\x04ثج\x04ثم\x04ثى\x04ثي\x04جح\x04جم\x04حج\x04حم" + + "\x04خج\x04خح\x04خم\x04سج\x04سح\x04سخ\x04سم\x04صح\x04صم\x04ضج\x04ضح\x04ضخ" + + "\x04ضم\x04طح\x04طم\x04ظم\x04عج\x04عم\x04غج\x04غم\x04فج\x04فح\x04فخ\x04فم" + + "\x04فى\x04في\x04قح\x04قم\x04قى\x04قي\x04كا\x04كج\x04كح\x04كخ\x04كل\x04كم" + + "\x04كى\x04كي\x04لج\x04لح\x04لخ\x04لم\x04لى\x04لي\x04مج\x04مح\x04مخ\x04مم" + + "\x04مى\x04مي\x04نج\x04نح\x04نخ\x04نم\x04نى\x04ني\x04هج\x04هم\x04هى\x04هي" + + "\x04يج\x04يح\x04يخ\x04يم\x04يى\x04يي\x04ذٰ\x04رٰ\x04ىٰ\x05 ٌّ\x05 ٍّ\x05" + + " َّ\x05 ُّ\x05 ِّ\x05 ّٰ\x04ئر\x04ئز\x04ئن\x04بر\x04بز\x04بن\x04تر\x04تز" + + "\x04تن\x04ثر\x04ثز\x04ثن\x04ما\x04نر\x04نز\x04نن\x04ير\x04يز\x04ين\x04ئخ" + + "\x04ئه\x04به\x04ته\x04صخ\x04له\x04نه\x04هٰ\x04يه\x04ثه\x04سه\x04شم\x04شه" + + "\x06ـَّ\x06ـُّ\x06ـِّ\x04طى\x04طي\x04عى\x04عي\x04غى\x04غي\x04سى\x04سي" + + "\x04شى\x04شي\x04حى\x04حي\x04جى\x04جي\x04خى\x04خي\x04صى\x04صي\x04ضى\x04ضي" + + "\x04شج\x04شح\x04شخ\x04شر\x04سر\x04صر\x04ضر\x04اً\x06تجم\x06تحج\x06تحم" + + "\x06تخم\x06تمج\x06تمح\x06تمخ\x06جمح\x06حمي\x06حمى\x06سحج\x06سجح\x06سجى" + + "\x06سمح\x06سمج\x06سمم\x06صحح\x06صمم\x06شحم\x06شجي\x06شمخ\x06شمم\x06ضحى" + + "\x06ضخم\x06طمح\x06طمم\x06طمي\x06عجم\x06عمم\x06عمى\x06غمم\x06غمي\x06غمى" + + "\x06فخم\x06قمح\x06قمم\x06لحم\x06لحي\x06لحى\x06لجج\x06لخم\x06لمح\x06محج" + + "\x06محم\x06محي\x06مجح\x06مجم\x06مخج\x06مخم\x06مجخ\x06همج\x06همم\x06نحم" + + "\x06نحى\x06نجم\x06نجى\x06نمي\x06نمى\x06يمم\x06بخي\x06تجي\x06تجى\x06تخي" + + "\x06تخى\x06تمي\x06تمى\x06جمي\x06جحى\x06جمى\x06سخى\x06صحي\x06شحي\x06ضحي" + + "\x06لجي\x06لمي\x06يحي\x06يجي\x06يمي\x06ممي\x06قمي\x06نحي\x06عمي\x06كمي" + + "\x06نجح\x06مخي\x06لجم\x06كمم\x06جحي\x06حجي\x06مجي\x06فمي\x06بحي\x06سخي" + + "\x06نجي\x06صلے\x06قلے\x08الله\x08اكبر\x08محمد\x08صلعم\x08رسول\x08عليه" + + "\x08وسلم\x06صلى!صلى الله عليه وسلم\x0fجل جلاله\x08ریال\x01,\x01:\x01!" + + "\x01?\x01_\x01{\x01}\x01[\x01]\x01#\x01&\x01*\x01-\x01<\x01>\x01\\\x01$" + + "\x01%\x01@\x04ـً\x04ـَ\x04ـُ\x04ـِ\x04ـّ\x04ـْ\x02ء\x02آ\x02أ\x02ؤ\x02إ" + + "\x02ئ\x02ا\x02ب\x02ة\x02ت\x02ث\x02ج\x02ح\x02خ\x02د\x02ذ\x02ر\x02ز\x02س" + + "\x02ش\x02ص\x02ض\x02ط\x02ظ\x02ع\x02غ\x02ف\x02ق\x02ك\x02ل\x02م\x02ن\x02ه" + + "\x02و\x02ي\x04لآ\x04لأ\x04لإ\x04لا\x01\x22\x01'\x01/\x01^\x01|\x01~\x02¢" + + "\x02£\x02¬\x02¦\x02¥\x08𝅗𝅥\x08𝅘𝅥\x0c𝅘𝅥𝅮\x0c𝅘𝅥𝅯\x0c𝅘𝅥𝅰\x0c𝅘𝅥𝅱\x0c𝅘𝅥𝅲\x08𝆹" + + "𝅥\x08𝆺𝅥\x0c𝆹𝅥𝅮\x0c𝆺𝅥𝅮\x0c𝆹𝅥𝅯\x0c𝆺𝅥𝅯\x02ı\x02ȷ\x02α\x02ε\x02ζ\x02η\x02" + + "κ\x02λ\x02μ\x02ν\x02ξ\x02ο\x02σ\x02τ\x02υ\x02ψ\x03∇\x03∂\x02ϝ\x02ٮ\x02ڡ" + + "\x02ٯ\x020,\x021,\x022,\x023,\x024,\x025,\x026,\x027,\x028,\x029,\x03(a)" + + "\x03(b)\x03(c)\x03(d)\x03(e)\x03(f)\x03(g)\x03(h)\x03(i)\x03(j)\x03(k)" + + "\x03(l)\x03(m)\x03(n)\x03(o)\x03(p)\x03(q)\x03(r)\x03(s)\x03(t)\x03(u)" + + "\x03(v)\x03(w)\x03(x)\x03(y)\x03(z)\x07〔s〕\x02wz\x02hv\x02sd\x03ppv\x02w" + + "c\x02mc\x02md\x02mr\x02dj\x06ほか\x06ココ\x03サ\x03手\x03字\x03双\x03デ\x03二\x03多" + + "\x03解\x03天\x03交\x03映\x03無\x03料\x03前\x03後\x03再\x03新\x03初\x03終\x03生\x03販" + + "\x03声\x03吹\x03演\x03投\x03捕\x03一\x03三\x03遊\x03左\x03中\x03右\x03指\x03走\x03打" + + "\x03禁\x03空\x03合\x03満\x03有\x03月\x03申\x03割\x03営\x03配\x09〔本〕\x09〔三〕\x09〔二〕" + + "\x09〔安〕\x09〔点〕\x09〔打〕\x09〔盗〕\x09〔勝〕\x09〔敗〕\x03得\x03可\x03丽\x03丸\x03乁\x03你" + + "\x03侮\x03侻\x03倂\x03偺\x03備\x03僧\x03像\x03㒞\x03免\x03兔\x03兤\x03具\x03㒹\x03內" + + "\x03冗\x03冤\x03仌\x03冬\x03况\x03凵\x03刃\x03㓟\x03刻\x03剆\x03剷\x03㔕\x03勇\x03勉" + + "\x03勤\x03勺\x03包\x03匆\x03北\x03卉\x03卑\x03博\x03即\x03卽\x03卿\x03灰\x03及\x03叟" + + "\x03叫\x03叱\x03吆\x03咞\x03吸\x03呈\x03周\x03咢\x03哶\x03唐\x03啓\x03啣\x03善\x03喙" + + "\x03喫\x03喳\x03嗂\x03圖\x03嘆\x03圗\x03噑\x03噴\x03切\x03壮\x03城\x03埴\x03堍\x03型" + + "\x03堲\x03報\x03墬\x03売\x03壷\x03夆\x03夢\x03奢\x03姬\x03娛\x03娧\x03姘\x03婦\x03㛮" + + "\x03嬈\x03嬾\x03寃\x03寘\x03寧\x03寳\x03寿\x03将\x03尢\x03㞁\x03屠\x03屮\x03峀\x03岍" + + "\x03嵃\x03嵮\x03嵫\x03嵼\x03巡\x03巢\x03㠯\x03巽\x03帨\x03帽\x03幩\x03㡢\x03㡼\x03庰" + + "\x03庳\x03庶\x03廊\x03廾\x03舁\x03弢\x03㣇\x03形\x03彫\x03㣣\x03徚\x03忍\x03志\x03忹" + + "\x03悁\x03㤺\x03㤜\x03悔\x03惇\x03慈\x03慌\x03慎\x03慺\x03憎\x03憲\x03憤\x03憯\x03懞" + + "\x03懲\x03懶\x03成\x03戛\x03扝\x03抱\x03拔\x03捐\x03挽\x03拼\x03捨\x03掃\x03揤\x03搢" + + "\x03揅\x03掩\x03㨮\x03摩\x03摾\x03撝\x03摷\x03㩬\x03敏\x03敬\x03旣\x03書\x03晉\x03㬙" + + "\x03暑\x03㬈\x03㫤\x03冒\x03冕\x03最\x03暜\x03肭\x03䏙\x03朗\x03望\x03朡\x03杞\x03杓" + + "\x03㭉\x03柺\x03枅\x03桒\x03梅\x03梎\x03栟\x03椔\x03㮝\x03楂\x03榣\x03槪\x03檨\x03櫛" + + "\x03㰘\x03次\x03歔\x03㱎\x03歲\x03殟\x03殺\x03殻\x03汎\x03沿\x03泍\x03汧\x03洖\x03派" + + "\x03海\x03流\x03浩\x03浸\x03涅\x03洴\x03港\x03湮\x03㴳\x03滋\x03滇\x03淹\x03潮\x03濆" + + "\x03瀹\x03瀞\x03瀛\x03㶖\x03灊\x03災\x03灷\x03炭\x03煅\x03熜\x03爨\x03爵\x03牐\x03犀" + + "\x03犕\x03獺\x03王\x03㺬\x03玥\x03㺸\x03瑇\x03瑜\x03瑱\x03璅\x03瓊\x03㼛\x03甤\x03甾" + + "\x03異\x03瘐\x03㿼\x03䀈\x03直\x03眞\x03真\x03睊\x03䀹\x03瞋\x03䁆\x03䂖\x03硎\x03碌" + + "\x03磌\x03䃣\x03祖\x03福\x03秫\x03䄯\x03穀\x03穊\x03穏\x03䈂\x03篆\x03築\x03䈧\x03糒" + + "\x03䊠\x03糨\x03糣\x03紀\x03絣\x03䌁\x03緇\x03縂\x03繅\x03䌴\x03䍙\x03罺\x03羕\x03翺" + + "\x03者\x03聠\x03聰\x03䏕\x03育\x03脃\x03䐋\x03脾\x03媵\x03舄\x03辞\x03䑫\x03芑\x03芋" + + "\x03芝\x03劳\x03花\x03芳\x03芽\x03苦\x03若\x03茝\x03荣\x03莭\x03茣\x03莽\x03菧\x03著" + + "\x03荓\x03菊\x03菌\x03菜\x03䔫\x03蓱\x03蓳\x03蔖\x03蕤\x03䕝\x03䕡\x03䕫\x03虐\x03虜" + + "\x03虧\x03虩\x03蚩\x03蚈\x03蜎\x03蛢\x03蝹\x03蜨\x03蝫\x03螆\x03蟡\x03蠁\x03䗹\x03衠" + + "\x03衣\x03裗\x03裞\x03䘵\x03裺\x03㒻\x03䚾\x03䛇\x03誠\x03諭\x03變\x03豕\x03貫\x03賁" + + "\x03贛\x03起\x03跋\x03趼\x03跰\x03軔\x03輸\x03邔\x03郱\x03鄑\x03鄛\x03鈸\x03鋗\x03鋘" + + "\x03鉼\x03鏹\x03鐕\x03開\x03䦕\x03閷\x03䧦\x03雃\x03嶲\x03霣\x03䩮\x03䩶\x03韠\x03䪲" + + "\x03頋\x03頩\x03飢\x03䬳\x03餩\x03馧\x03駂\x03駾\x03䯎\x03鬒\x03鱀\x03鳽\x03䳎\x03䳭" + + "\x03鵧\x03䳸\x03麻\x03䵖\x03黹\x03黾\x03鼅\x03鼏\x03鼖\x03鼻" + +var xorData string = "" + // Size: 4862 bytes + "\x02\x0c\x09\x02\xb0\xec\x02\xad\xd8\x02\xad\xd9\x02\x06\x07\x02\x0f\x12" + + "\x02\x0f\x1f\x02\x0f\x1d\x02\x01\x13\x02\x0f\x16\x02\x0f\x0b\x02\x0f3" + + "\x02\x0f7\x02\x0f?\x02\x0f/\x02\x0f*\x02\x0c&\x02\x0c*\x02\x0c;\x02\x0c9" + + "\x02\x0c%\x02\xab\xed\x02\xab\xe2\x02\xab\xe3\x02\xa9\xe0\x02\xa9\xe1" + + "\x02\xa9\xe6\x02\xa3\xcb\x02\xa3\xc8\x02\xa3\xc9\x02\x01#\x02\x01\x08" + + "\x02\x0e>\x02\x0e'\x02\x0f\x03\x02\x03\x0d\x02\x03\x09\x02\x03\x17\x02" + + "\x03\x0e\x02\x02\x03\x02\x011\x02\x01\x00\x02\x01\x10\x02\x03<\x02\x07" + + "\x0d\x02\x02\x0c\x02\x0c0\x02\x01\x03\x02\x01\x01\x02\x01 \x02\x01\x22" + + "\x02\x01)\x02\x01\x0a\x02\x01\x0c\x02\x02\x06\x02\x02\x02\x02\x03\x10" + + "\x03\x037 \x03\x0b+\x03\x021\x00\x02\x01\x04\x02\x01\x02\x02\x019\x02" + + "\x03\x1c\x02\x02$\x03\x80p$\x02\x03:\x02\x03\x0a\x03\xc1r.\x03\xc1r,\x03" + + "\xc1r\x02\x02\x02:\x02\x02>\x02\x02,\x02\x02\x10\x02\x02\x00\x03\xc1s<" + + "\x03\xc1s*\x03\xc2L$\x03\xc2L;\x02\x09)\x02\x0a\x19\x03\x83\xab\xe3\x03" + + "\x83\xab\xf2\x03 4\xe0\x03\x81\xab\xea\x03\x81\xab\xf3\x03 4\xef\x03\x96" + + "\xe1\xcd\x03\x84\xe5\xc3\x02\x0d\x11\x03\x8b\xec\xcb\x03\x94\xec\xcf\x03" + + "\x9a\xec\xc2\x03\x8b\xec\xdb\x03\x94\xec\xdf\x03\x9a\xec\xd2\x03\x01\x0c" + + "!\x03\x01\x0c#\x03ʠ\x9d\x03ʣ\x9c\x03ʢ\x9f\x03ʥ\x9e\x03ʤ\x91\x03ʧ\x90\x03" + + "ʦ\x93\x03ʩ\x92\x03ʨ\x95\x03\xca\xf3\xb5\x03\xca\xf0\xb4\x03\xca\xf1\xb7" + + "\x03\xca\xf6\xb6\x03\xca\xf7\x89\x03\xca\xf4\x88\x03\xca\xf5\x8b\x03\xca" + + "\xfa\x8a\x03\xca\xfb\x8d\x03\xca\xf8\x8c\x03\xca\xf9\x8f\x03\xca\xfe\x8e" + + "\x03\xca\xff\x81\x03\xca\xfc\x80\x03\xca\xfd\x83\x03\xca\xe2\x82\x03\xca" + + "\xe3\x85\x03\xca\xe0\x84\x03\xca\xe1\x87\x03\xca\xe6\x86\x03\xca\xe7\x99" + + "\x03\xca\xe4\x98\x03\xca\xe5\x9b\x03\xca\xea\x9a\x03\xca\xeb\x9d\x03\xca" + + "\xe8\x9c\x03ؓ\x89\x03ߔ\x8b\x02\x010\x03\x03\x04\x1e\x03\x04\x15\x12\x03" + + "\x0b\x05,\x03\x06\x04\x00\x03\x06\x04)\x03\x06\x044\x03\x06\x04<\x03\x06" + + "\x05\x1d\x03\x06\x06\x00\x03\x06\x06\x0a\x03\x06\x06'\x03\x06\x062\x03" + + "\x0786\x03\x079/\x03\x079 \x03\x07:\x0e\x03\x07:\x1b\x03\x07:%\x03\x07;/" + + "\x03\x07;%\x03\x074\x11\x03\x076\x09\x03\x077*\x03\x070\x01\x03\x070\x0f" + + "\x03\x070.\x03\x071\x16\x03\x071\x04\x03\x0710\x03\x072\x18\x03\x072-" + + "\x03\x073\x14\x03\x073>\x03\x07'\x09\x03\x07 \x00\x03\x07\x1f\x0b\x03" + + "\x07\x18#\x03\x07\x18(\x03\x07\x186\x03\x07\x18\x03\x03\x07\x19\x16\x03" + + "\x07\x116\x03\x07\x12'\x03\x07\x13\x10\x03\x07\x0c&\x03\x07\x0c\x08\x03" + + "\x07\x0c\x13\x03\x07\x0d\x02\x03\x07\x0d\x1c\x03\x07\x0b5\x03\x07\x0b" + + "\x0a\x03\x07\x0b\x01\x03\x07\x0b\x0f\x03\x07\x05\x00\x03\x07\x05\x09\x03" + + "\x07\x05\x0b\x03\x07\x07\x01\x03\x07\x07\x08\x03\x07\x00<\x03\x07\x00+" + + "\x03\x07\x01)\x03\x07\x01\x1b\x03\x07\x01\x08\x03\x07\x03?\x03\x0445\x03" + + "\x044\x08\x03\x0454\x03\x04)/\x03\x04)5\x03\x04+\x05\x03\x04+\x14\x03" + + "\x04+ \x03\x04+<\x03\x04*&\x03\x04*\x22\x03\x04&8\x03\x04!\x01\x03\x04!" + + "\x22\x03\x04\x11+\x03\x04\x10.\x03\x04\x104\x03\x04\x13=\x03\x04\x12\x04" + + "\x03\x04\x12\x0a\x03\x04\x0d\x1d\x03\x04\x0d\x07\x03\x04\x0d \x03\x05<>" + + "\x03\x055<\x03\x055!\x03\x055#\x03\x055&\x03\x054\x1d\x03\x054\x02\x03" + + "\x054\x07\x03\x0571\x03\x053\x1a\x03\x053\x16\x03\x05.<\x03\x05.\x07\x03" + + "\x05):\x03\x05)<\x03\x05)\x0c\x03\x05)\x15\x03\x05+-\x03\x05+5\x03\x05$" + + "\x1e\x03\x05$\x14\x03\x05'\x04\x03\x05'\x14\x03\x05&\x02\x03\x05\x226" + + "\x03\x05\x22\x0c\x03\x05\x22\x1c\x03\x05\x19\x0a\x03\x05\x1b\x09\x03\x05" + + "\x1b\x0c\x03\x05\x14\x07\x03\x05\x16?\x03\x05\x16\x0c\x03\x05\x0c\x05" + + "\x03\x05\x0e\x0f\x03\x05\x01\x0e\x03\x05\x00(\x03\x05\x030\x03\x05\x03" + + "\x06\x03\x0a==\x03\x0a=1\x03\x0a=,\x03\x0a=\x0c\x03\x0a??\x03\x0a<\x08" + + "\x03\x0a9!\x03\x0a9)\x03\x0a97\x03\x0a99\x03\x0a6\x0a\x03\x0a6\x1c\x03" + + "\x0a6\x17\x03\x0a7'\x03\x0a78\x03\x0a73\x03\x0a'\x01\x03\x0a'&\x03\x0a" + + "\x1f\x0e\x03\x0a\x1f\x03\x03\x0a\x1f3\x03\x0a\x1b/\x03\x0a\x18\x19\x03" + + "\x0a\x19\x01\x03\x0a\x16\x14\x03\x0a\x0e\x22\x03\x0a\x0f\x10\x03\x0a\x0f" + + "\x02\x03\x0a\x0f \x03\x0a\x0c\x04\x03\x0a\x0b>\x03\x0a\x0b+\x03\x0a\x08/" + + "\x03\x0a\x046\x03\x0a\x05\x14\x03\x0a\x00\x04\x03\x0a\x00\x10\x03\x0a" + + "\x00\x14\x03\x0b<3\x03\x0b;*\x03\x0b9\x22\x03\x0b9)\x03\x0b97\x03\x0b+" + + "\x10\x03\x0b((\x03\x0b&5\x03\x0b$\x1c\x03\x0b$\x12\x03\x0b%\x04\x03\x0b#" + + "<\x03\x0b#0\x03\x0b#\x0d\x03\x0b#\x19\x03\x0b!:\x03\x0b!\x1f\x03\x0b!" + + "\x00\x03\x0b\x1e5\x03\x0b\x1c\x1d\x03\x0b\x1d-\x03\x0b\x1d(\x03\x0b\x18." + + "\x03\x0b\x18 \x03\x0b\x18\x16\x03\x0b\x14\x13\x03\x0b\x15$\x03\x0b\x15" + + "\x22\x03\x0b\x12\x1b\x03\x0b\x12\x10\x03\x0b\x132\x03\x0b\x13=\x03\x0b" + + "\x12\x18\x03\x0b\x0c&\x03\x0b\x061\x03\x0b\x06:\x03\x0b\x05#\x03\x0b\x05" + + "<\x03\x0b\x04\x0b\x03\x0b\x04\x04\x03\x0b\x04\x1b\x03\x0b\x042\x03\x0b" + + "\x041\x03\x0b\x03\x03\x03\x0b\x03\x1d\x03\x0b\x03/\x03\x0b\x03+\x03\x0b" + + "\x02\x1b\x03\x0b\x02\x00\x03\x0b\x01\x1e\x03\x0b\x01\x08\x03\x0b\x015" + + "\x03\x06\x0d9\x03\x06\x0d=\x03\x06\x0d?\x03\x02\x001\x03\x02\x003\x03" + + "\x02\x02\x19\x03\x02\x006\x03\x02\x02\x1b\x03\x02\x004\x03\x02\x00<\x03" + + "\x02\x02\x0a\x03\x02\x02\x0e\x03\x02\x01\x1a\x03\x02\x01\x07\x03\x02\x01" + + "\x05\x03\x02\x01\x0b\x03\x02\x01%\x03\x02\x01\x0c\x03\x02\x01\x04\x03" + + "\x02\x01\x1c\x03\x02\x00.\x03\x02\x002\x03\x02\x00>\x03\x02\x00\x12\x03" + + "\x02\x00\x16\x03\x02\x011\x03\x02\x013\x03\x02\x02 \x03\x02\x02%\x03\x02" + + "\x02$\x03\x02\x028\x03\x02\x02;\x03\x02\x024\x03\x02\x012\x03\x02\x022" + + "\x03\x02\x02/\x03\x02\x01,\x03\x02\x01\x13\x03\x02\x01\x16\x03\x02\x01" + + "\x11\x03\x02\x01\x1e\x03\x02\x01\x15\x03\x02\x01\x17\x03\x02\x01\x0f\x03" + + "\x02\x01\x08\x03\x02\x00?\x03\x02\x03\x07\x03\x02\x03\x0d\x03\x02\x03" + + "\x13\x03\x02\x03\x1d\x03\x02\x03\x1f\x03\x02\x00\x03\x03\x02\x00\x0d\x03" + + "\x02\x00\x01\x03\x02\x00\x1b\x03\x02\x00\x19\x03\x02\x00\x18\x03\x02\x00" + + "\x13\x03\x02\x00/\x03\x07>\x12\x03\x07<\x1f\x03\x07>\x1d\x03\x06\x1d\x0e" + + "\x03\x07>\x1c\x03\x07>:\x03\x07>\x13\x03\x04\x12+\x03\x07?\x03\x03\x07>" + + "\x02\x03\x06\x224\x03\x06\x1a.\x03\x07<%\x03\x06\x1c\x0b\x03\x0609\x03" + + "\x05\x1f\x01\x03\x04'\x08\x03\x93\xfd\xf5\x03\x02\x0d \x03\x02\x0d#\x03" + + "\x02\x0d!\x03\x02\x0d&\x03\x02\x0d\x22\x03\x02\x0d/\x03\x02\x0d,\x03\x02" + + "\x0d$\x03\x02\x0d'\x03\x02\x0d%\x03\x02\x0d;\x03\x02\x0d=\x03\x02\x0d?" + + "\x03\x099.\x03\x08\x0b7\x03\x08\x02\x14\x03\x08\x14\x0d\x03\x08.:\x03" + + "\x089'\x03\x0f\x0b\x18\x03\x0f\x1c1\x03\x0f\x17&\x03\x0f9\x1f\x03\x0f0" + + "\x0c\x03\x0e\x0a9\x03\x0e\x056\x03\x0e\x1c#\x03\x0f\x13\x0e\x03\x072\x00" + + "\x03\x070\x0d\x03\x072\x0b\x03\x06\x11\x18\x03\x070\x10\x03\x06\x0f(\x03" + + "\x072\x05\x03\x06\x0f,\x03\x073\x15\x03\x06\x07\x08\x03\x05\x16\x02\x03" + + "\x04\x0b \x03\x05:8\x03\x05\x16%\x03\x0a\x0d\x1f\x03\x06\x16\x10\x03\x05" + + "\x1d5\x03\x05*;\x03\x05\x16\x1b\x03\x04.-\x03\x06\x1a\x19\x03\x04\x03," + + "\x03\x0b87\x03\x04/\x0a\x03\x06\x00,\x03\x04-\x01\x03\x04\x1e-\x03\x06/(" + + "\x03\x0a\x0b5\x03\x06\x0e7\x03\x06\x07.\x03\x0597\x03\x0a*%\x03\x0760" + + "\x03\x06\x0c;\x03\x05'\x00\x03\x072.\x03\x072\x08\x03\x06=\x01\x03\x06" + + "\x05\x1b\x03\x06\x06\x12\x03\x06$=\x03\x06'\x0d\x03\x04\x11\x0f\x03\x076" + + ",\x03\x06\x07;\x03\x06.,\x03\x86\xf9\xea\x03\x8f\xff\xeb\x02\x092\x02" + + "\x095\x02\x094\x02\x09;\x02\x09>\x02\x098\x02\x09*\x02\x09/\x02\x09,\x02" + + "\x09%\x02\x09&\x02\x09#\x02\x09 \x02\x08!\x02\x08%\x02\x08$\x02\x08+\x02" + + "\x08.\x02\x08*\x02\x08&\x02\x088\x02\x08>\x02\x084\x02\x086\x02\x080\x02" + + "\x08\x10\x02\x08\x17\x02\x08\x12\x02\x08\x1d\x02\x08\x1f\x02\x08\x13\x02" + + "\x08\x15\x02\x08\x14\x02\x08\x0c\x03\x8b\xfd\xd0\x03\x81\xec\xc6\x03\x87" + + "\xe0\x8a\x03-2\xe3\x03\x80\xef\xe4\x03-2\xea\x03\x88\xe6\xeb\x03\x8e\xe6" + + "\xe8\x03\x84\xe6\xe9\x03\x97\xe6\xee\x03-2\xf9\x03-2\xf6\x03\x8e\xe3\xad" + + "\x03\x80\xe3\x92\x03\x88\xe3\x90\x03\x8e\xe3\x90\x03\x80\xe3\x97\x03\x88" + + "\xe3\x95\x03\x88\xfe\xcb\x03\x8e\xfe\xca\x03\x84\xfe\xcd\x03\x91\xef\xc9" + + "\x03-2\xc1\x03-2\xc0\x03-2\xcb\x03\x88@\x09\x03\x8e@\x08\x03\x8f\xe0\xf5" + + "\x03\x8e\xe6\xf9\x03\x8e\xe0\xfa\x03\x93\xff\xf4\x03\x84\xee\xd3\x03\x0b" + + "(\x04\x023 \x03\x0b)\x08\x021;\x02\x01*\x03\x0b#\x10\x03\x0b 0\x03\x0b!" + + "\x10\x03\x0b!0\x03\x07\x15\x08\x03\x09?5\x03\x07\x1f\x08\x03\x07\x17\x0b" + + "\x03\x09\x1f\x15\x03\x0b\x1c7\x03\x0a+#\x03\x06\x1a\x1b\x03\x06\x1a\x14" + + "\x03\x0a\x01\x18\x03\x06#\x1b\x03\x0a2\x0c\x03\x0a\x01\x04\x03\x09#;\x03" + + "\x08='\x03\x08\x1a\x0a\x03\x07\x03\x0a\x111\x03\x09\x1b\x09\x03\x073.\x03\x07" + + "\x01\x00\x03\x09/,\x03\x07#>\x03\x07\x048\x03\x0a\x1f\x22\x03\x098>\x03" + + "\x09\x11\x00\x03\x08/\x17\x03\x06'\x22\x03\x0b\x1a+\x03\x0a\x22\x19\x03" + + "\x0a/1\x03\x0974\x03\x09\x0f\x22\x03\x08,\x22\x03\x08?\x14\x03\x07$5\x03" + + "\x07<3\x03\x07=*\x03\x07\x13\x18\x03\x068\x0a\x03\x06\x09\x16\x03\x06" + + "\x13\x00\x03\x08\x067\x03\x08\x01\x03\x03\x08\x12\x1d\x03\x07+7\x03\x06(" + + ";\x03\x06\x1c?\x03\x07\x0e\x17\x03\x0a\x06\x1d\x03\x0a\x19\x07\x03\x08" + + "\x14$\x03\x07$;\x03\x08,$\x03\x08\x06\x0d\x03\x07\x16\x0a\x03\x06>>\x03" + + "\x0a\x06\x12\x03\x0a\x14)\x03\x09\x0d\x1f\x03\x09\x12\x17\x03\x09\x19" + + "\x01\x03\x08\x11 \x03\x08\x1d'\x03\x06<\x1a\x03\x0a.\x00\x03\x07'\x18" + + "\x03\x0a\x22\x08\x03\x08\x0d\x0a\x03\x08\x13)\x03\x07*)\x03\x06<,\x03" + + "\x07\x0b\x1a\x03\x09.\x14\x03\x09\x0d\x1e\x03\x07\x0e#\x03\x0b\x1d'\x03" + + "\x0a\x0a8\x03\x09%2\x03\x08+&\x03\x080\x12\x03\x0a)4\x03\x08\x06\x1f\x03" + + "\x0b\x1b\x1a\x03\x0a\x1b\x0f\x03\x0b\x1d*\x03\x09\x16$\x03\x090\x11\x03" + + "\x08\x11\x08\x03\x0a*(\x03\x0a\x042\x03\x089,\x03\x074'\x03\x07\x0f\x05" + + "\x03\x09\x0b\x0a\x03\x07\x1b\x01\x03\x09\x17:\x03\x09.\x0d\x03\x07.\x11" + + "\x03\x09+\x15\x03\x080\x13\x03\x0b\x1f\x19\x03\x0a \x11\x03\x0a\x220\x03" + + "\x09\x07;\x03\x08\x16\x1c\x03\x07,\x13\x03\x07\x0e/\x03\x06\x221\x03\x0a" + + ".\x0a\x03\x0a7\x02\x03\x0a\x032\x03\x0a\x1d.\x03\x091\x06\x03\x09\x19:" + + "\x03\x08\x02/\x03\x060+\x03\x06\x0f-\x03\x06\x1c\x1f\x03\x06\x1d\x07\x03" + + "\x0a,\x11\x03\x09=\x0d\x03\x09\x0b;\x03\x07\x1b/\x03\x0a\x1f:\x03\x09 " + + "\x1f\x03\x09.\x10\x03\x094\x0b\x03\x09\x1a1\x03\x08#\x1a\x03\x084\x1d" + + "\x03\x08\x01\x1f\x03\x08\x11\x22\x03\x07'8\x03\x07\x1a>\x03\x0757\x03" + + "\x06&9\x03\x06+\x11\x03\x0a.\x0b\x03\x0a,>\x03\x0a4#\x03\x08%\x17\x03" + + "\x07\x05\x22\x03\x07\x0c\x0b\x03\x0a\x1d+\x03\x0a\x19\x16\x03\x09+\x1f" + + "\x03\x09\x08\x0b\x03\x08\x16\x18\x03\x08+\x12\x03\x0b\x1d\x0c\x03\x0a=" + + "\x10\x03\x0a\x09\x0d\x03\x0a\x10\x11\x03\x09&0\x03\x08(\x1f\x03\x087\x07" + + "\x03\x08\x185\x03\x07'6\x03\x06.\x05\x03\x06=\x04\x03\x06;;\x03\x06\x06," + + "\x03\x0b\x18>\x03\x08\x00\x18\x03\x06 \x03\x03\x06<\x00\x03\x09%\x18\x03" + + "\x0b\x1c<\x03\x0a%!\x03\x0a\x09\x12\x03\x0a\x16\x02\x03\x090'\x03\x09" + + "\x0e=\x03\x08 \x0e\x03\x08>\x03\x03\x074>\x03\x06&?\x03\x06\x19\x09\x03" + + "\x06?(\x03\x0a-\x0e\x03\x09:3\x03\x098:\x03\x09\x12\x0b\x03\x09\x1d\x17" + + "\x03\x087\x05\x03\x082\x14\x03\x08\x06%\x03\x08\x13\x1f\x03\x06\x06\x0e" + + "\x03\x0a\x22<\x03\x09/<\x03\x06>+\x03\x0a'?\x03\x0a\x13\x0c\x03\x09\x10<" + + "\x03\x07\x1b=\x03\x0a\x19\x13\x03\x09\x22\x1d\x03\x09\x07\x0d\x03\x08)" + + "\x1c\x03\x06=\x1a\x03\x0a/4\x03\x0a7\x11\x03\x0a\x16:\x03\x09?3\x03\x09:" + + "/\x03\x09\x05\x0a\x03\x09\x14\x06\x03\x087\x22\x03\x080\x07\x03\x08\x1a" + + "\x1f\x03\x07\x04(\x03\x07\x04\x09\x03\x06 %\x03\x06<\x08\x03\x0a+\x14" + + "\x03\x09\x1d\x16\x03\x0a70\x03\x08 >\x03\x0857\x03\x070\x0a\x03\x06=\x12" + + "\x03\x06\x16%\x03\x06\x1d,\x03\x099#\x03\x09\x10>\x03\x07 \x1e\x03\x08" + + "\x0c<\x03\x08\x0b\x18\x03\x08\x15+\x03\x08,:\x03\x08%\x22\x03\x07\x0a$" + + "\x03\x0b\x1c=\x03\x07+\x08\x03\x0a/\x05\x03\x0a \x07\x03\x0a\x12'\x03" + + "\x09#\x11\x03\x08\x1b\x15\x03\x0a\x06\x01\x03\x09\x1c\x1b\x03\x0922\x03" + + "\x07\x14<\x03\x07\x09\x04\x03\x061\x04\x03\x07\x0e\x01\x03\x0a\x13\x18" + + "\x03\x0a-\x0c\x03\x0a?\x0d\x03\x0a\x09\x0a\x03\x091&\x03\x0a/\x0b\x03" + + "\x08$<\x03\x083\x1d\x03\x08\x0c$\x03\x08\x0d\x07\x03\x08\x0d?\x03\x08" + + "\x0e\x14\x03\x065\x0a\x03\x08\x1a#\x03\x08\x16#\x03\x0702\x03\x07\x03" + + "\x1a\x03\x06(\x1d\x03\x06+\x1b\x03\x06\x0b\x05\x03\x06\x0b\x17\x03\x06" + + "\x0c\x04\x03\x06\x1e\x19\x03\x06+0\x03\x062\x18\x03\x0b\x16\x1e\x03\x0a+" + + "\x16\x03\x0a-?\x03\x0a#:\x03\x0a#\x10\x03\x0a%$\x03\x0a>+\x03\x0a01\x03" + + "\x0a1\x10\x03\x0a\x099\x03\x0a\x0a\x12\x03\x0a\x19\x1f\x03\x0a\x19\x12" + + "\x03\x09*)\x03\x09-\x16\x03\x09.1\x03\x09.2\x03\x09<\x0e\x03\x09> \x03" + + "\x093\x12\x03\x09\x0b\x01\x03\x09\x1c2\x03\x09\x11\x1c\x03\x09\x15%\x03" + + "\x08,&\x03\x08!\x22\x03\x089(\x03\x08\x0b\x1a\x03\x08\x0d2\x03\x08\x0c" + + "\x04\x03\x08\x0c\x06\x03\x08\x0c\x1f\x03\x08\x0c\x0c\x03\x08\x0f\x1f\x03" + + "\x08\x0f\x1d\x03\x08\x00\x14\x03\x08\x03\x14\x03\x08\x06\x16\x03\x08\x1e" + + "#\x03\x08\x11\x11\x03\x08\x10\x18\x03\x08\x14(\x03\x07)\x1e\x03\x07.1" + + "\x03\x07 $\x03\x07 '\x03\x078\x08\x03\x07\x0d0\x03\x07\x0f7\x03\x07\x05#" + + "\x03\x07\x05\x1a\x03\x07\x1a7\x03\x07\x1d-\x03\x07\x17\x10\x03\x06)\x1f" + + "\x03\x062\x0b\x03\x066\x16\x03\x06\x09\x11\x03\x09(\x1e\x03\x07!5\x03" + + "\x0b\x11\x16\x03\x0a/\x04\x03\x0a,\x1a\x03\x0b\x173\x03\x0a,1\x03\x0a/5" + + "\x03\x0a\x221\x03\x0a\x22\x0d\x03\x0a?%\x03\x0a<,\x03\x0a?#\x03\x0a>\x19" + + "\x03\x0a\x08&\x03\x0a\x0b\x0e\x03\x0a\x0c:\x03\x0a\x0c+\x03\x0a\x03\x22" + + "\x03\x0a\x06)\x03\x0a\x11\x10\x03\x0a\x11\x1a\x03\x0a\x17-\x03\x0a\x14(" + + "\x03\x09)\x1e\x03\x09/\x09\x03\x09.\x00\x03\x09,\x07\x03\x09/*\x03\x09-9" + + "\x03\x09\x228\x03\x09%\x09\x03\x09:\x12\x03\x09;\x1d\x03\x09?\x06\x03" + + "\x093%\x03\x096\x05\x03\x096\x08\x03\x097\x02\x03\x09\x07,\x03\x09\x04," + + "\x03\x09\x1f\x16\x03\x09\x11\x03\x03\x09\x11\x12\x03\x09\x168\x03\x08*" + + "\x05\x03\x08/2\x03\x084:\x03\x08\x22+\x03\x08 0\x03\x08&\x0a\x03\x08;" + + "\x10\x03\x08>$\x03\x08>\x18\x03\x0829\x03\x082:\x03\x081,\x03\x081<\x03" + + "\x081\x1c\x03\x087#\x03\x087*\x03\x08\x09'\x03\x08\x00\x1d\x03\x08\x05-" + + "\x03\x08\x1f4\x03\x08\x1d\x04\x03\x08\x16\x0f\x03\x07*7\x03\x07'!\x03" + + "\x07%\x1b\x03\x077\x0c\x03\x07\x0c1\x03\x07\x0c.\x03\x07\x00\x06\x03\x07" + + "\x01\x02\x03\x07\x010\x03\x07\x06=\x03\x07\x01\x03\x03\x07\x01\x13\x03" + + "\x07\x06\x06\x03\x07\x05\x0a\x03\x07\x1f\x09\x03\x07\x17:\x03\x06*1\x03" + + "\x06-\x1d\x03\x06\x223\x03\x062:\x03\x060$\x03\x066\x1e\x03\x064\x12\x03" + + "\x0645\x03\x06\x0b\x00\x03\x06\x0b7\x03\x06\x07\x1f\x03\x06\x15\x12\x03" + + "\x0c\x05\x0f\x03\x0b+\x0b\x03\x0b+-\x03\x06\x16\x1b\x03\x06\x15\x17\x03" + + "\x89\xca\xea\x03\x89\xca\xe8\x03\x0c8\x10\x03\x0c8\x01\x03\x0c8\x0f\x03" + + "\x0d8%\x03\x0d8!\x03\x0c8-\x03\x0c8/\x03\x0c8+\x03\x0c87\x03\x0c85\x03" + + "\x0c9\x09\x03\x0c9\x0d\x03\x0c9\x0f\x03\x0c9\x0b\x03\xcfu\x0c\x03\xcfu" + + "\x0f\x03\xcfu\x0e\x03\xcfu\x09\x03\x0c9\x10\x03\x0d9\x0c\x03\xcf`;\x03" + + "\xcf`>\x03\xcf`9\x03\xcf`8\x03\xcf`7\x03\xcf`*\x03\xcf`-\x03\xcf`,\x03" + + "\x0d\x1b\x1a\x03\x0d\x1b&\x03\x0c=.\x03\x0c=%\x03\x0c>\x1e\x03\x0c>\x14" + + "\x03\x0c?\x06\x03\x0c?\x0b\x03\x0c?\x0c\x03\x0c?\x0d\x03\x0c?\x02\x03" + + "\x0c>\x0f\x03\x0c>\x08\x03\x0c>\x09\x03\x0c>,\x03\x0c>\x0c\x03\x0c?\x13" + + "\x03\x0c?\x16\x03\x0c?\x15\x03\x0c?\x1c\x03\x0c?\x1f\x03\x0c?\x1d\x03" + + "\x0c?\x1a\x03\x0c?\x17\x03\x0c?\x08\x03\x0c?\x09\x03\x0c?\x0e\x03\x0c?" + + "\x04\x03\x0c?\x05\x03\x0c" + + "\x03\x0c=2\x03\x0c=6\x03\x0c<\x07\x03\x0c<\x05\x03\x0e:!\x03\x0e:#\x03" + + "\x0e8\x09\x03\x0e:&\x03\x0e8\x0b\x03\x0e:$\x03\x0e:,\x03\x0e8\x1a\x03" + + "\x0e8\x1e\x03\x0e:*\x03\x0e:7\x03\x0e:5\x03\x0e:;\x03\x0e:\x15\x03\x0e:<" + + "\x03\x0e:4\x03\x0e:'\x03\x0e:-\x03\x0e:%\x03\x0e:?\x03\x0e:=\x03\x0e:)" + + "\x03\x0e:/\x03\xcfs'\x03\x0d=\x0f\x03\x0d+*\x03\x0d99\x03\x0d9;\x03\x0d9" + + "?\x03\x0d)\x0d\x03\x0d(%\x02\x01\x18\x02\x01(\x02\x01\x1e\x03\x0f$!\x03" + + "\x0f87\x03\x0f4\x0e\x03\x0f5\x1d\x03\x06'\x03\x03\x0f\x08\x18\x03\x0f" + + "\x0d\x1b\x03\x0e2=\x03\x0e;\x08\x03\x0e:\x0b\x03\x0e\x06$\x03\x0e\x0d)" + + "\x03\x0e\x16\x1f\x03\x0e\x16\x1b\x03\x0d$\x0a\x03\x05,\x1d\x03\x0d. \x03" + + "\x0d.#\x03\x0c(/\x03\x09%\x02\x03\x0d90\x03\x0d\x0e4\x03\x0d\x0d\x0f\x03" + + "\x0c#\x00\x03\x0c,\x1e\x03\x0c2\x0e\x03\x0c\x01\x17\x03\x0c\x09:\x03\x0e" + + "\x173\x03\x0c\x08\x03\x03\x0c\x11\x07\x03\x0c\x10\x18\x03\x0c\x1f\x1c" + + "\x03\x0c\x19\x0e\x03\x0c\x1a\x1f\x03\x0f0>\x03\x0b->\x03\x0b<+\x03\x0b8" + + "\x13\x03\x0b\x043\x03\x0b\x14\x03\x03\x0b\x16%\x03\x0d\x22&\x03\x0b\x1a" + + "\x1a\x03\x0b\x1a\x04\x03\x0a%9\x03\x0a&2\x03\x0a&0\x03\x0a!\x1a\x03\x0a!" + + "7\x03\x0a5\x10\x03\x0a=4\x03\x0a?\x0e\x03\x0a>\x10\x03\x0a\x00 \x03\x0a" + + "\x0f:\x03\x0a\x0f9\x03\x0a\x0b\x0a\x03\x0a\x17%\x03\x0a\x1b-\x03\x09-" + + "\x1a\x03\x09,4\x03\x09.,\x03\x09)\x09\x03\x096!\x03\x091\x1f\x03\x093" + + "\x16\x03\x0c+\x1f\x03\x098 \x03\x098=\x03\x0c(\x1a\x03\x0c(\x16\x03\x09" + + "\x0a+\x03\x09\x16\x12\x03\x09\x13\x0e\x03\x09\x153\x03\x08)!\x03\x09\x1a" + + "\x01\x03\x09\x18\x01\x03\x08%#\x03\x08>\x22\x03\x08\x05%\x03\x08\x02*" + + "\x03\x08\x15;\x03\x08\x1b7\x03\x0f\x07\x1d\x03\x0f\x04\x03\x03\x070\x0c" + + "\x03\x07;\x0b\x03\x07\x08\x17\x03\x07\x12\x06\x03\x06/-\x03\x0671\x03" + + "\x065+\x03\x06>7\x03\x06\x049\x03\x05+\x1e\x03\x05,\x17\x03\x05 \x1d\x03" + + "\x05\x22\x05\x03\x050\x1d" + +// lookup returns the trie value for the first UTF-8 encoding in s and +// the width in bytes of this encoding. The size will be 0 if s does not +// hold enough bytes to complete the encoding. len(s) must be greater than 0. +func (t *idnaTrie) lookup(s []byte) (v uint16, sz int) { + c0 := s[0] + switch { + case c0 < 0x80: // is ASCII + return idnaValues[c0], 1 + case c0 < 0xC2: + return 0, 1 // Illegal UTF-8: not a starter, not ASCII. + case c0 < 0xE0: // 2-byte UTF-8 + if len(s) < 2 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c1), 2 + case c0 < 0xF0: // 3-byte UTF-8 + if len(s) < 3 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + o := uint32(i)<<6 + uint32(c1) + i = idnaIndex[o] + c2 := s[2] + if c2 < 0x80 || 0xC0 <= c2 { + return 0, 2 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c2), 3 + case c0 < 0xF8: // 4-byte UTF-8 + if len(s) < 4 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + o := uint32(i)<<6 + uint32(c1) + i = idnaIndex[o] + c2 := s[2] + if c2 < 0x80 || 0xC0 <= c2 { + return 0, 2 // Illegal UTF-8: not a continuation byte. + } + o = uint32(i)<<6 + uint32(c2) + i = idnaIndex[o] + c3 := s[3] + if c3 < 0x80 || 0xC0 <= c3 { + return 0, 3 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c3), 4 + } + // Illegal rune + return 0, 1 +} + +// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. +// s must start with a full and valid UTF-8 encoded rune. +func (t *idnaTrie) lookupUnsafe(s []byte) uint16 { + c0 := s[0] + if c0 < 0x80 { // is ASCII + return idnaValues[c0] + } + i := idnaIndex[c0] + if c0 < 0xE0 { // 2-byte UTF-8 + return t.lookupValue(uint32(i), s[1]) + } + i = idnaIndex[uint32(i)<<6+uint32(s[1])] + if c0 < 0xF0 { // 3-byte UTF-8 + return t.lookupValue(uint32(i), s[2]) + } + i = idnaIndex[uint32(i)<<6+uint32(s[2])] + if c0 < 0xF8 { // 4-byte UTF-8 + return t.lookupValue(uint32(i), s[3]) + } + return 0 +} + +// lookupString returns the trie value for the first UTF-8 encoding in s and +// the width in bytes of this encoding. The size will be 0 if s does not +// hold enough bytes to complete the encoding. len(s) must be greater than 0. +func (t *idnaTrie) lookupString(s string) (v uint16, sz int) { + c0 := s[0] + switch { + case c0 < 0x80: // is ASCII + return idnaValues[c0], 1 + case c0 < 0xC2: + return 0, 1 // Illegal UTF-8: not a starter, not ASCII. + case c0 < 0xE0: // 2-byte UTF-8 + if len(s) < 2 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c1), 2 + case c0 < 0xF0: // 3-byte UTF-8 + if len(s) < 3 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + o := uint32(i)<<6 + uint32(c1) + i = idnaIndex[o] + c2 := s[2] + if c2 < 0x80 || 0xC0 <= c2 { + return 0, 2 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c2), 3 + case c0 < 0xF8: // 4-byte UTF-8 + if len(s) < 4 { + return 0, 0 + } + i := idnaIndex[c0] + c1 := s[1] + if c1 < 0x80 || 0xC0 <= c1 { + return 0, 1 // Illegal UTF-8: not a continuation byte. + } + o := uint32(i)<<6 + uint32(c1) + i = idnaIndex[o] + c2 := s[2] + if c2 < 0x80 || 0xC0 <= c2 { + return 0, 2 // Illegal UTF-8: not a continuation byte. + } + o = uint32(i)<<6 + uint32(c2) + i = idnaIndex[o] + c3 := s[3] + if c3 < 0x80 || 0xC0 <= c3 { + return 0, 3 // Illegal UTF-8: not a continuation byte. + } + return t.lookupValue(uint32(i), c3), 4 + } + // Illegal rune + return 0, 1 +} + +// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. +// s must start with a full and valid UTF-8 encoded rune. +func (t *idnaTrie) lookupStringUnsafe(s string) uint16 { + c0 := s[0] + if c0 < 0x80 { // is ASCII + return idnaValues[c0] + } + i := idnaIndex[c0] + if c0 < 0xE0 { // 2-byte UTF-8 + return t.lookupValue(uint32(i), s[1]) + } + i = idnaIndex[uint32(i)<<6+uint32(s[1])] + if c0 < 0xF0 { // 3-byte UTF-8 + return t.lookupValue(uint32(i), s[2]) + } + i = idnaIndex[uint32(i)<<6+uint32(s[2])] + if c0 < 0xF8 { // 4-byte UTF-8 + return t.lookupValue(uint32(i), s[3]) + } + return 0 +} + +// idnaTrie. Total size: 29708 bytes (29.01 KiB). Checksum: c3ecc76d8fffa6e6. +type idnaTrie struct{} + +func newIdnaTrie(i int) *idnaTrie { + return &idnaTrie{} +} + +// lookupValue determines the type of block n and looks up the value for b. +func (t *idnaTrie) lookupValue(n uint32, b byte) uint16 { + switch { + case n < 125: + return uint16(idnaValues[n<<6+uint32(b)]) + default: + n -= 125 + return uint16(idnaSparse.lookup(n, b)) + } +} + +// idnaValues: 127 blocks, 8128 entries, 16256 bytes +// The third block is the zero block. +var idnaValues = [8128]uint16{ + // Block 0x0, offset 0x0 + 0x00: 0x0080, 0x01: 0x0080, 0x02: 0x0080, 0x03: 0x0080, 0x04: 0x0080, 0x05: 0x0080, + 0x06: 0x0080, 0x07: 0x0080, 0x08: 0x0080, 0x09: 0x0080, 0x0a: 0x0080, 0x0b: 0x0080, + 0x0c: 0x0080, 0x0d: 0x0080, 0x0e: 0x0080, 0x0f: 0x0080, 0x10: 0x0080, 0x11: 0x0080, + 0x12: 0x0080, 0x13: 0x0080, 0x14: 0x0080, 0x15: 0x0080, 0x16: 0x0080, 0x17: 0x0080, + 0x18: 0x0080, 0x19: 0x0080, 0x1a: 0x0080, 0x1b: 0x0080, 0x1c: 0x0080, 0x1d: 0x0080, + 0x1e: 0x0080, 0x1f: 0x0080, 0x20: 0x0080, 0x21: 0x0080, 0x22: 0x0080, 0x23: 0x0080, + 0x24: 0x0080, 0x25: 0x0080, 0x26: 0x0080, 0x27: 0x0080, 0x28: 0x0080, 0x29: 0x0080, + 0x2a: 0x0080, 0x2b: 0x0080, 0x2c: 0x0080, 0x2d: 0x0008, 0x2e: 0x0008, 0x2f: 0x0080, + 0x30: 0x0008, 0x31: 0x0008, 0x32: 0x0008, 0x33: 0x0008, 0x34: 0x0008, 0x35: 0x0008, + 0x36: 0x0008, 0x37: 0x0008, 0x38: 0x0008, 0x39: 0x0008, 0x3a: 0x0080, 0x3b: 0x0080, + 0x3c: 0x0080, 0x3d: 0x0080, 0x3e: 0x0080, 0x3f: 0x0080, + // Block 0x1, offset 0x40 + 0x40: 0x0080, 0x41: 0xe105, 0x42: 0xe105, 0x43: 0xe105, 0x44: 0xe105, 0x45: 0xe105, + 0x46: 0xe105, 0x47: 0xe105, 0x48: 0xe105, 0x49: 0xe105, 0x4a: 0xe105, 0x4b: 0xe105, + 0x4c: 0xe105, 0x4d: 0xe105, 0x4e: 0xe105, 0x4f: 0xe105, 0x50: 0xe105, 0x51: 0xe105, + 0x52: 0xe105, 0x53: 0xe105, 0x54: 0xe105, 0x55: 0xe105, 0x56: 0xe105, 0x57: 0xe105, + 0x58: 0xe105, 0x59: 0xe105, 0x5a: 0xe105, 0x5b: 0x0080, 0x5c: 0x0080, 0x5d: 0x0080, + 0x5e: 0x0080, 0x5f: 0x0080, 0x60: 0x0080, 0x61: 0x0008, 0x62: 0x0008, 0x63: 0x0008, + 0x64: 0x0008, 0x65: 0x0008, 0x66: 0x0008, 0x67: 0x0008, 0x68: 0x0008, 0x69: 0x0008, + 0x6a: 0x0008, 0x6b: 0x0008, 0x6c: 0x0008, 0x6d: 0x0008, 0x6e: 0x0008, 0x6f: 0x0008, + 0x70: 0x0008, 0x71: 0x0008, 0x72: 0x0008, 0x73: 0x0008, 0x74: 0x0008, 0x75: 0x0008, + 0x76: 0x0008, 0x77: 0x0008, 0x78: 0x0008, 0x79: 0x0008, 0x7a: 0x0008, 0x7b: 0x0080, + 0x7c: 0x0080, 0x7d: 0x0080, 0x7e: 0x0080, 0x7f: 0x0080, + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0xc0: 0x0040, 0xc1: 0x0040, 0xc2: 0x0040, 0xc3: 0x0040, 0xc4: 0x0040, 0xc5: 0x0040, + 0xc6: 0x0040, 0xc7: 0x0040, 0xc8: 0x0040, 0xc9: 0x0040, 0xca: 0x0040, 0xcb: 0x0040, + 0xcc: 0x0040, 0xcd: 0x0040, 0xce: 0x0040, 0xcf: 0x0040, 0xd0: 0x0040, 0xd1: 0x0040, + 0xd2: 0x0040, 0xd3: 0x0040, 0xd4: 0x0040, 0xd5: 0x0040, 0xd6: 0x0040, 0xd7: 0x0040, + 0xd8: 0x0040, 0xd9: 0x0040, 0xda: 0x0040, 0xdb: 0x0040, 0xdc: 0x0040, 0xdd: 0x0040, + 0xde: 0x0040, 0xdf: 0x0040, 0xe0: 0x000a, 0xe1: 0x0018, 0xe2: 0x0018, 0xe3: 0x0018, + 0xe4: 0x0018, 0xe5: 0x0018, 0xe6: 0x0018, 0xe7: 0x0018, 0xe8: 0x001a, 0xe9: 0x0018, + 0xea: 0x0039, 0xeb: 0x0018, 0xec: 0x0018, 0xed: 0x03c0, 0xee: 0x0018, 0xef: 0x004a, + 0xf0: 0x0018, 0xf1: 0x0018, 0xf2: 0x0069, 0xf3: 0x0079, 0xf4: 0x008a, 0xf5: 0x0005, + 0xf6: 0x0018, 0xf7: 0x0008, 0xf8: 0x00aa, 0xf9: 0x00c9, 0xfa: 0x00d9, 0xfb: 0x0018, + 0xfc: 0x00e9, 0xfd: 0x0119, 0xfe: 0x0149, 0xff: 0x0018, + // Block 0x4, offset 0x100 + 0x100: 0xe00d, 0x101: 0x0008, 0x102: 0xe00d, 0x103: 0x0008, 0x104: 0xe00d, 0x105: 0x0008, + 0x106: 0xe00d, 0x107: 0x0008, 0x108: 0xe00d, 0x109: 0x0008, 0x10a: 0xe00d, 0x10b: 0x0008, + 0x10c: 0xe00d, 0x10d: 0x0008, 0x10e: 0xe00d, 0x10f: 0x0008, 0x110: 0xe00d, 0x111: 0x0008, + 0x112: 0xe00d, 0x113: 0x0008, 0x114: 0xe00d, 0x115: 0x0008, 0x116: 0xe00d, 0x117: 0x0008, + 0x118: 0xe00d, 0x119: 0x0008, 0x11a: 0xe00d, 0x11b: 0x0008, 0x11c: 0xe00d, 0x11d: 0x0008, + 0x11e: 0xe00d, 0x11f: 0x0008, 0x120: 0xe00d, 0x121: 0x0008, 0x122: 0xe00d, 0x123: 0x0008, + 0x124: 0xe00d, 0x125: 0x0008, 0x126: 0xe00d, 0x127: 0x0008, 0x128: 0xe00d, 0x129: 0x0008, + 0x12a: 0xe00d, 0x12b: 0x0008, 0x12c: 0xe00d, 0x12d: 0x0008, 0x12e: 0xe00d, 0x12f: 0x0008, + 0x130: 0x0179, 0x131: 0x0008, 0x132: 0x0035, 0x133: 0x004d, 0x134: 0xe00d, 0x135: 0x0008, + 0x136: 0xe00d, 0x137: 0x0008, 0x138: 0x0008, 0x139: 0xe01d, 0x13a: 0x0008, 0x13b: 0xe03d, + 0x13c: 0x0008, 0x13d: 0xe01d, 0x13e: 0x0008, 0x13f: 0x0199, + // Block 0x5, offset 0x140 + 0x140: 0x0199, 0x141: 0xe01d, 0x142: 0x0008, 0x143: 0xe03d, 0x144: 0x0008, 0x145: 0xe01d, + 0x146: 0x0008, 0x147: 0xe07d, 0x148: 0x0008, 0x149: 0x01b9, 0x14a: 0xe00d, 0x14b: 0x0008, + 0x14c: 0xe00d, 0x14d: 0x0008, 0x14e: 0xe00d, 0x14f: 0x0008, 0x150: 0xe00d, 0x151: 0x0008, + 0x152: 0xe00d, 0x153: 0x0008, 0x154: 0xe00d, 0x155: 0x0008, 0x156: 0xe00d, 0x157: 0x0008, + 0x158: 0xe00d, 0x159: 0x0008, 0x15a: 0xe00d, 0x15b: 0x0008, 0x15c: 0xe00d, 0x15d: 0x0008, + 0x15e: 0xe00d, 0x15f: 0x0008, 0x160: 0xe00d, 0x161: 0x0008, 0x162: 0xe00d, 0x163: 0x0008, + 0x164: 0xe00d, 0x165: 0x0008, 0x166: 0xe00d, 0x167: 0x0008, 0x168: 0xe00d, 0x169: 0x0008, + 0x16a: 0xe00d, 0x16b: 0x0008, 0x16c: 0xe00d, 0x16d: 0x0008, 0x16e: 0xe00d, 0x16f: 0x0008, + 0x170: 0xe00d, 0x171: 0x0008, 0x172: 0xe00d, 0x173: 0x0008, 0x174: 0xe00d, 0x175: 0x0008, + 0x176: 0xe00d, 0x177: 0x0008, 0x178: 0x0065, 0x179: 0xe01d, 0x17a: 0x0008, 0x17b: 0xe03d, + 0x17c: 0x0008, 0x17d: 0xe01d, 0x17e: 0x0008, 0x17f: 0x01d9, + // Block 0x6, offset 0x180 + 0x180: 0x0008, 0x181: 0x007d, 0x182: 0xe00d, 0x183: 0x0008, 0x184: 0xe00d, 0x185: 0x0008, + 0x186: 0x007d, 0x187: 0xe07d, 0x188: 0x0008, 0x189: 0x0095, 0x18a: 0x00ad, 0x18b: 0xe03d, + 0x18c: 0x0008, 0x18d: 0x0008, 0x18e: 0x00c5, 0x18f: 0x00dd, 0x190: 0x00f5, 0x191: 0xe01d, + 0x192: 0x0008, 0x193: 0x010d, 0x194: 0x0125, 0x195: 0x0008, 0x196: 0x013d, 0x197: 0x013d, + 0x198: 0xe00d, 0x199: 0x0008, 0x19a: 0x0008, 0x19b: 0x0008, 0x19c: 0x010d, 0x19d: 0x0155, + 0x19e: 0x0008, 0x19f: 0x016d, 0x1a0: 0xe00d, 0x1a1: 0x0008, 0x1a2: 0xe00d, 0x1a3: 0x0008, + 0x1a4: 0xe00d, 0x1a5: 0x0008, 0x1a6: 0x0185, 0x1a7: 0xe07d, 0x1a8: 0x0008, 0x1a9: 0x019d, + 0x1aa: 0x0008, 0x1ab: 0x0008, 0x1ac: 0xe00d, 0x1ad: 0x0008, 0x1ae: 0x0185, 0x1af: 0xe0fd, + 0x1b0: 0x0008, 0x1b1: 0x01b5, 0x1b2: 0x01cd, 0x1b3: 0xe03d, 0x1b4: 0x0008, 0x1b5: 0xe01d, + 0x1b6: 0x0008, 0x1b7: 0x01e5, 0x1b8: 0xe00d, 0x1b9: 0x0008, 0x1ba: 0x0008, 0x1bb: 0x0008, + 0x1bc: 0xe00d, 0x1bd: 0x0008, 0x1be: 0x0008, 0x1bf: 0x0008, + // Block 0x7, offset 0x1c0 + 0x1c0: 0x0008, 0x1c1: 0x0008, 0x1c2: 0x0008, 0x1c3: 0x0008, 0x1c4: 0x01e9, 0x1c5: 0x01e9, + 0x1c6: 0x01e9, 0x1c7: 0x01fd, 0x1c8: 0x0215, 0x1c9: 0x022d, 0x1ca: 0x0245, 0x1cb: 0x025d, + 0x1cc: 0x0275, 0x1cd: 0xe01d, 0x1ce: 0x0008, 0x1cf: 0xe0fd, 0x1d0: 0x0008, 0x1d1: 0xe01d, + 0x1d2: 0x0008, 0x1d3: 0xe03d, 0x1d4: 0x0008, 0x1d5: 0xe01d, 0x1d6: 0x0008, 0x1d7: 0xe07d, + 0x1d8: 0x0008, 0x1d9: 0xe01d, 0x1da: 0x0008, 0x1db: 0xe03d, 0x1dc: 0x0008, 0x1dd: 0x0008, + 0x1de: 0xe00d, 0x1df: 0x0008, 0x1e0: 0xe00d, 0x1e1: 0x0008, 0x1e2: 0xe00d, 0x1e3: 0x0008, + 0x1e4: 0xe00d, 0x1e5: 0x0008, 0x1e6: 0xe00d, 0x1e7: 0x0008, 0x1e8: 0xe00d, 0x1e9: 0x0008, + 0x1ea: 0xe00d, 0x1eb: 0x0008, 0x1ec: 0xe00d, 0x1ed: 0x0008, 0x1ee: 0xe00d, 0x1ef: 0x0008, + 0x1f0: 0x0008, 0x1f1: 0x028d, 0x1f2: 0x02a5, 0x1f3: 0x02bd, 0x1f4: 0xe00d, 0x1f5: 0x0008, + 0x1f6: 0x02d5, 0x1f7: 0x02ed, 0x1f8: 0xe00d, 0x1f9: 0x0008, 0x1fa: 0xe00d, 0x1fb: 0x0008, + 0x1fc: 0xe00d, 0x1fd: 0x0008, 0x1fe: 0xe00d, 0x1ff: 0x0008, + // Block 0x8, offset 0x200 + 0x200: 0xe00d, 0x201: 0x0008, 0x202: 0xe00d, 0x203: 0x0008, 0x204: 0xe00d, 0x205: 0x0008, + 0x206: 0xe00d, 0x207: 0x0008, 0x208: 0xe00d, 0x209: 0x0008, 0x20a: 0xe00d, 0x20b: 0x0008, + 0x20c: 0xe00d, 0x20d: 0x0008, 0x20e: 0xe00d, 0x20f: 0x0008, 0x210: 0xe00d, 0x211: 0x0008, + 0x212: 0xe00d, 0x213: 0x0008, 0x214: 0xe00d, 0x215: 0x0008, 0x216: 0xe00d, 0x217: 0x0008, + 0x218: 0xe00d, 0x219: 0x0008, 0x21a: 0xe00d, 0x21b: 0x0008, 0x21c: 0xe00d, 0x21d: 0x0008, + 0x21e: 0xe00d, 0x21f: 0x0008, 0x220: 0x0305, 0x221: 0x0008, 0x222: 0xe00d, 0x223: 0x0008, + 0x224: 0xe00d, 0x225: 0x0008, 0x226: 0xe00d, 0x227: 0x0008, 0x228: 0xe00d, 0x229: 0x0008, + 0x22a: 0xe00d, 0x22b: 0x0008, 0x22c: 0xe00d, 0x22d: 0x0008, 0x22e: 0xe00d, 0x22f: 0x0008, + 0x230: 0xe00d, 0x231: 0x0008, 0x232: 0xe00d, 0x233: 0x0008, 0x234: 0x0008, 0x235: 0x0008, + 0x236: 0x0008, 0x237: 0x0008, 0x238: 0x0008, 0x239: 0x0008, 0x23a: 0x0209, 0x23b: 0xe03d, + 0x23c: 0x0008, 0x23d: 0x031d, 0x23e: 0x0229, 0x23f: 0x0008, + // Block 0x9, offset 0x240 + 0x240: 0x0008, 0x241: 0x0008, 0x242: 0x0018, 0x243: 0x0018, 0x244: 0x0018, 0x245: 0x0018, + 0x246: 0x0008, 0x247: 0x0008, 0x248: 0x0008, 0x249: 0x0008, 0x24a: 0x0008, 0x24b: 0x0008, + 0x24c: 0x0008, 0x24d: 0x0008, 0x24e: 0x0008, 0x24f: 0x0008, 0x250: 0x0008, 0x251: 0x0008, + 0x252: 0x0018, 0x253: 0x0018, 0x254: 0x0018, 0x255: 0x0018, 0x256: 0x0018, 0x257: 0x0018, + 0x258: 0x029a, 0x259: 0x02ba, 0x25a: 0x02da, 0x25b: 0x02fa, 0x25c: 0x031a, 0x25d: 0x033a, + 0x25e: 0x0018, 0x25f: 0x0018, 0x260: 0x03ad, 0x261: 0x0359, 0x262: 0x01d9, 0x263: 0x0369, + 0x264: 0x03c5, 0x265: 0x0018, 0x266: 0x0018, 0x267: 0x0018, 0x268: 0x0018, 0x269: 0x0018, + 0x26a: 0x0018, 0x26b: 0x0018, 0x26c: 0x0008, 0x26d: 0x0018, 0x26e: 0x0008, 0x26f: 0x0018, + 0x270: 0x0018, 0x271: 0x0018, 0x272: 0x0018, 0x273: 0x0018, 0x274: 0x0018, 0x275: 0x0018, + 0x276: 0x0018, 0x277: 0x0018, 0x278: 0x0018, 0x279: 0x0018, 0x27a: 0x0018, 0x27b: 0x0018, + 0x27c: 0x0018, 0x27d: 0x0018, 0x27e: 0x0018, 0x27f: 0x0018, + // Block 0xa, offset 0x280 + 0x280: 0x03dd, 0x281: 0x03dd, 0x282: 0x3308, 0x283: 0x03f5, 0x284: 0x0379, 0x285: 0x040d, + 0x286: 0x3308, 0x287: 0x3308, 0x288: 0x3308, 0x289: 0x3308, 0x28a: 0x3308, 0x28b: 0x3308, + 0x28c: 0x3308, 0x28d: 0x3308, 0x28e: 0x3308, 0x28f: 0x33c0, 0x290: 0x3308, 0x291: 0x3308, + 0x292: 0x3308, 0x293: 0x3308, 0x294: 0x3308, 0x295: 0x3308, 0x296: 0x3308, 0x297: 0x3308, + 0x298: 0x3308, 0x299: 0x3308, 0x29a: 0x3308, 0x29b: 0x3308, 0x29c: 0x3308, 0x29d: 0x3308, + 0x29e: 0x3308, 0x29f: 0x3308, 0x2a0: 0x3308, 0x2a1: 0x3308, 0x2a2: 0x3308, 0x2a3: 0x3308, + 0x2a4: 0x3308, 0x2a5: 0x3308, 0x2a6: 0x3308, 0x2a7: 0x3308, 0x2a8: 0x3308, 0x2a9: 0x3308, + 0x2aa: 0x3308, 0x2ab: 0x3308, 0x2ac: 0x3308, 0x2ad: 0x3308, 0x2ae: 0x3308, 0x2af: 0x3308, + 0x2b0: 0xe00d, 0x2b1: 0x0008, 0x2b2: 0xe00d, 0x2b3: 0x0008, 0x2b4: 0x0425, 0x2b5: 0x0008, + 0x2b6: 0xe00d, 0x2b7: 0x0008, 0x2b8: 0x0040, 0x2b9: 0x0040, 0x2ba: 0x03a2, 0x2bb: 0x0008, + 0x2bc: 0x0008, 0x2bd: 0x0008, 0x2be: 0x03c2, 0x2bf: 0x043d, + // Block 0xb, offset 0x2c0 + 0x2c0: 0x0040, 0x2c1: 0x0040, 0x2c2: 0x0040, 0x2c3: 0x0040, 0x2c4: 0x008a, 0x2c5: 0x03d2, + 0x2c6: 0xe155, 0x2c7: 0x0455, 0x2c8: 0xe12d, 0x2c9: 0xe13d, 0x2ca: 0xe12d, 0x2cb: 0x0040, + 0x2cc: 0x03dd, 0x2cd: 0x0040, 0x2ce: 0x046d, 0x2cf: 0x0485, 0x2d0: 0x0008, 0x2d1: 0xe105, + 0x2d2: 0xe105, 0x2d3: 0xe105, 0x2d4: 0xe105, 0x2d5: 0xe105, 0x2d6: 0xe105, 0x2d7: 0xe105, + 0x2d8: 0xe105, 0x2d9: 0xe105, 0x2da: 0xe105, 0x2db: 0xe105, 0x2dc: 0xe105, 0x2dd: 0xe105, + 0x2de: 0xe105, 0x2df: 0xe105, 0x2e0: 0x049d, 0x2e1: 0x049d, 0x2e2: 0x0040, 0x2e3: 0x049d, + 0x2e4: 0x049d, 0x2e5: 0x049d, 0x2e6: 0x049d, 0x2e7: 0x049d, 0x2e8: 0x049d, 0x2e9: 0x049d, + 0x2ea: 0x049d, 0x2eb: 0x049d, 0x2ec: 0x0008, 0x2ed: 0x0008, 0x2ee: 0x0008, 0x2ef: 0x0008, + 0x2f0: 0x0008, 0x2f1: 0x0008, 0x2f2: 0x0008, 0x2f3: 0x0008, 0x2f4: 0x0008, 0x2f5: 0x0008, + 0x2f6: 0x0008, 0x2f7: 0x0008, 0x2f8: 0x0008, 0x2f9: 0x0008, 0x2fa: 0x0008, 0x2fb: 0x0008, + 0x2fc: 0x0008, 0x2fd: 0x0008, 0x2fe: 0x0008, 0x2ff: 0x0008, + // Block 0xc, offset 0x300 + 0x300: 0x0008, 0x301: 0x0008, 0x302: 0xe00f, 0x303: 0x0008, 0x304: 0x0008, 0x305: 0x0008, + 0x306: 0x0008, 0x307: 0x0008, 0x308: 0x0008, 0x309: 0x0008, 0x30a: 0x0008, 0x30b: 0x0008, + 0x30c: 0x0008, 0x30d: 0x0008, 0x30e: 0x0008, 0x30f: 0xe0c5, 0x310: 0x04b5, 0x311: 0x04cd, + 0x312: 0xe0bd, 0x313: 0xe0f5, 0x314: 0xe0fd, 0x315: 0xe09d, 0x316: 0xe0b5, 0x317: 0x0008, + 0x318: 0xe00d, 0x319: 0x0008, 0x31a: 0xe00d, 0x31b: 0x0008, 0x31c: 0xe00d, 0x31d: 0x0008, + 0x31e: 0xe00d, 0x31f: 0x0008, 0x320: 0xe00d, 0x321: 0x0008, 0x322: 0xe00d, 0x323: 0x0008, + 0x324: 0xe00d, 0x325: 0x0008, 0x326: 0xe00d, 0x327: 0x0008, 0x328: 0xe00d, 0x329: 0x0008, + 0x32a: 0xe00d, 0x32b: 0x0008, 0x32c: 0xe00d, 0x32d: 0x0008, 0x32e: 0xe00d, 0x32f: 0x0008, + 0x330: 0x04e5, 0x331: 0xe185, 0x332: 0xe18d, 0x333: 0x0008, 0x334: 0x04fd, 0x335: 0x03dd, + 0x336: 0x0018, 0x337: 0xe07d, 0x338: 0x0008, 0x339: 0xe1d5, 0x33a: 0xe00d, 0x33b: 0x0008, + 0x33c: 0x0008, 0x33d: 0x0515, 0x33e: 0x052d, 0x33f: 0x052d, + // Block 0xd, offset 0x340 + 0x340: 0x0008, 0x341: 0x0008, 0x342: 0x0008, 0x343: 0x0008, 0x344: 0x0008, 0x345: 0x0008, + 0x346: 0x0008, 0x347: 0x0008, 0x348: 0x0008, 0x349: 0x0008, 0x34a: 0x0008, 0x34b: 0x0008, + 0x34c: 0x0008, 0x34d: 0x0008, 0x34e: 0x0008, 0x34f: 0x0008, 0x350: 0x0008, 0x351: 0x0008, + 0x352: 0x0008, 0x353: 0x0008, 0x354: 0x0008, 0x355: 0x0008, 0x356: 0x0008, 0x357: 0x0008, + 0x358: 0x0008, 0x359: 0x0008, 0x35a: 0x0008, 0x35b: 0x0008, 0x35c: 0x0008, 0x35d: 0x0008, + 0x35e: 0x0008, 0x35f: 0x0008, 0x360: 0xe00d, 0x361: 0x0008, 0x362: 0xe00d, 0x363: 0x0008, + 0x364: 0xe00d, 0x365: 0x0008, 0x366: 0xe00d, 0x367: 0x0008, 0x368: 0xe00d, 0x369: 0x0008, + 0x36a: 0xe00d, 0x36b: 0x0008, 0x36c: 0xe00d, 0x36d: 0x0008, 0x36e: 0xe00d, 0x36f: 0x0008, + 0x370: 0xe00d, 0x371: 0x0008, 0x372: 0xe00d, 0x373: 0x0008, 0x374: 0xe00d, 0x375: 0x0008, + 0x376: 0xe00d, 0x377: 0x0008, 0x378: 0xe00d, 0x379: 0x0008, 0x37a: 0xe00d, 0x37b: 0x0008, + 0x37c: 0xe00d, 0x37d: 0x0008, 0x37e: 0xe00d, 0x37f: 0x0008, + // Block 0xe, offset 0x380 + 0x380: 0xe00d, 0x381: 0x0008, 0x382: 0x0018, 0x383: 0x3308, 0x384: 0x3308, 0x385: 0x3308, + 0x386: 0x3308, 0x387: 0x3308, 0x388: 0x3318, 0x389: 0x3318, 0x38a: 0xe00d, 0x38b: 0x0008, + 0x38c: 0xe00d, 0x38d: 0x0008, 0x38e: 0xe00d, 0x38f: 0x0008, 0x390: 0xe00d, 0x391: 0x0008, + 0x392: 0xe00d, 0x393: 0x0008, 0x394: 0xe00d, 0x395: 0x0008, 0x396: 0xe00d, 0x397: 0x0008, + 0x398: 0xe00d, 0x399: 0x0008, 0x39a: 0xe00d, 0x39b: 0x0008, 0x39c: 0xe00d, 0x39d: 0x0008, + 0x39e: 0xe00d, 0x39f: 0x0008, 0x3a0: 0xe00d, 0x3a1: 0x0008, 0x3a2: 0xe00d, 0x3a3: 0x0008, + 0x3a4: 0xe00d, 0x3a5: 0x0008, 0x3a6: 0xe00d, 0x3a7: 0x0008, 0x3a8: 0xe00d, 0x3a9: 0x0008, + 0x3aa: 0xe00d, 0x3ab: 0x0008, 0x3ac: 0xe00d, 0x3ad: 0x0008, 0x3ae: 0xe00d, 0x3af: 0x0008, + 0x3b0: 0xe00d, 0x3b1: 0x0008, 0x3b2: 0xe00d, 0x3b3: 0x0008, 0x3b4: 0xe00d, 0x3b5: 0x0008, + 0x3b6: 0xe00d, 0x3b7: 0x0008, 0x3b8: 0xe00d, 0x3b9: 0x0008, 0x3ba: 0xe00d, 0x3bb: 0x0008, + 0x3bc: 0xe00d, 0x3bd: 0x0008, 0x3be: 0xe00d, 0x3bf: 0x0008, + // Block 0xf, offset 0x3c0 + 0x3c0: 0x0040, 0x3c1: 0xe01d, 0x3c2: 0x0008, 0x3c3: 0xe03d, 0x3c4: 0x0008, 0x3c5: 0xe01d, + 0x3c6: 0x0008, 0x3c7: 0xe07d, 0x3c8: 0x0008, 0x3c9: 0xe01d, 0x3ca: 0x0008, 0x3cb: 0xe03d, + 0x3cc: 0x0008, 0x3cd: 0xe01d, 0x3ce: 0x0008, 0x3cf: 0x0008, 0x3d0: 0xe00d, 0x3d1: 0x0008, + 0x3d2: 0xe00d, 0x3d3: 0x0008, 0x3d4: 0xe00d, 0x3d5: 0x0008, 0x3d6: 0xe00d, 0x3d7: 0x0008, + 0x3d8: 0xe00d, 0x3d9: 0x0008, 0x3da: 0xe00d, 0x3db: 0x0008, 0x3dc: 0xe00d, 0x3dd: 0x0008, + 0x3de: 0xe00d, 0x3df: 0x0008, 0x3e0: 0xe00d, 0x3e1: 0x0008, 0x3e2: 0xe00d, 0x3e3: 0x0008, + 0x3e4: 0xe00d, 0x3e5: 0x0008, 0x3e6: 0xe00d, 0x3e7: 0x0008, 0x3e8: 0xe00d, 0x3e9: 0x0008, + 0x3ea: 0xe00d, 0x3eb: 0x0008, 0x3ec: 0xe00d, 0x3ed: 0x0008, 0x3ee: 0xe00d, 0x3ef: 0x0008, + 0x3f0: 0xe00d, 0x3f1: 0x0008, 0x3f2: 0xe00d, 0x3f3: 0x0008, 0x3f4: 0xe00d, 0x3f5: 0x0008, + 0x3f6: 0xe00d, 0x3f7: 0x0008, 0x3f8: 0xe00d, 0x3f9: 0x0008, 0x3fa: 0xe00d, 0x3fb: 0x0008, + 0x3fc: 0xe00d, 0x3fd: 0x0008, 0x3fe: 0xe00d, 0x3ff: 0x0008, + // Block 0x10, offset 0x400 + 0x400: 0xe00d, 0x401: 0x0008, 0x402: 0xe00d, 0x403: 0x0008, 0x404: 0xe00d, 0x405: 0x0008, + 0x406: 0xe00d, 0x407: 0x0008, 0x408: 0xe00d, 0x409: 0x0008, 0x40a: 0xe00d, 0x40b: 0x0008, + 0x40c: 0xe00d, 0x40d: 0x0008, 0x40e: 0xe00d, 0x40f: 0x0008, 0x410: 0xe00d, 0x411: 0x0008, + 0x412: 0xe00d, 0x413: 0x0008, 0x414: 0xe00d, 0x415: 0x0008, 0x416: 0xe00d, 0x417: 0x0008, + 0x418: 0xe00d, 0x419: 0x0008, 0x41a: 0xe00d, 0x41b: 0x0008, 0x41c: 0xe00d, 0x41d: 0x0008, + 0x41e: 0xe00d, 0x41f: 0x0008, 0x420: 0xe00d, 0x421: 0x0008, 0x422: 0xe00d, 0x423: 0x0008, + 0x424: 0xe00d, 0x425: 0x0008, 0x426: 0xe00d, 0x427: 0x0008, 0x428: 0xe00d, 0x429: 0x0008, + 0x42a: 0xe00d, 0x42b: 0x0008, 0x42c: 0xe00d, 0x42d: 0x0008, 0x42e: 0xe00d, 0x42f: 0x0008, + 0x430: 0x0040, 0x431: 0x03f5, 0x432: 0x03f5, 0x433: 0x03f5, 0x434: 0x03f5, 0x435: 0x03f5, + 0x436: 0x03f5, 0x437: 0x03f5, 0x438: 0x03f5, 0x439: 0x03f5, 0x43a: 0x03f5, 0x43b: 0x03f5, + 0x43c: 0x03f5, 0x43d: 0x03f5, 0x43e: 0x03f5, 0x43f: 0x03f5, + // Block 0x11, offset 0x440 + 0x440: 0x0840, 0x441: 0x0840, 0x442: 0x0840, 0x443: 0x0840, 0x444: 0x0840, 0x445: 0x0840, + 0x446: 0x0018, 0x447: 0x0018, 0x448: 0x0818, 0x449: 0x0018, 0x44a: 0x0018, 0x44b: 0x0818, + 0x44c: 0x0018, 0x44d: 0x0818, 0x44e: 0x0018, 0x44f: 0x0018, 0x450: 0x3308, 0x451: 0x3308, + 0x452: 0x3308, 0x453: 0x3308, 0x454: 0x3308, 0x455: 0x3308, 0x456: 0x3308, 0x457: 0x3308, + 0x458: 0x3308, 0x459: 0x3308, 0x45a: 0x3308, 0x45b: 0x0818, 0x45c: 0x0b40, 0x45d: 0x0040, + 0x45e: 0x0818, 0x45f: 0x0818, 0x460: 0x0a08, 0x461: 0x0808, 0x462: 0x0c08, 0x463: 0x0c08, + 0x464: 0x0c08, 0x465: 0x0c08, 0x466: 0x0a08, 0x467: 0x0c08, 0x468: 0x0a08, 0x469: 0x0c08, + 0x46a: 0x0a08, 0x46b: 0x0a08, 0x46c: 0x0a08, 0x46d: 0x0a08, 0x46e: 0x0a08, 0x46f: 0x0c08, + 0x470: 0x0c08, 0x471: 0x0c08, 0x472: 0x0c08, 0x473: 0x0a08, 0x474: 0x0a08, 0x475: 0x0a08, + 0x476: 0x0a08, 0x477: 0x0a08, 0x478: 0x0a08, 0x479: 0x0a08, 0x47a: 0x0a08, 0x47b: 0x0a08, + 0x47c: 0x0a08, 0x47d: 0x0a08, 0x47e: 0x0a08, 0x47f: 0x0a08, + // Block 0x12, offset 0x480 + 0x480: 0x0818, 0x481: 0x0a08, 0x482: 0x0a08, 0x483: 0x0a08, 0x484: 0x0a08, 0x485: 0x0a08, + 0x486: 0x0a08, 0x487: 0x0a08, 0x488: 0x0c08, 0x489: 0x0a08, 0x48a: 0x0a08, 0x48b: 0x3308, + 0x48c: 0x3308, 0x48d: 0x3308, 0x48e: 0x3308, 0x48f: 0x3308, 0x490: 0x3308, 0x491: 0x3308, + 0x492: 0x3308, 0x493: 0x3308, 0x494: 0x3308, 0x495: 0x3308, 0x496: 0x3308, 0x497: 0x3308, + 0x498: 0x3308, 0x499: 0x3308, 0x49a: 0x3308, 0x49b: 0x3308, 0x49c: 0x3308, 0x49d: 0x3308, + 0x49e: 0x3308, 0x49f: 0x3308, 0x4a0: 0x0808, 0x4a1: 0x0808, 0x4a2: 0x0808, 0x4a3: 0x0808, + 0x4a4: 0x0808, 0x4a5: 0x0808, 0x4a6: 0x0808, 0x4a7: 0x0808, 0x4a8: 0x0808, 0x4a9: 0x0808, + 0x4aa: 0x0018, 0x4ab: 0x0818, 0x4ac: 0x0818, 0x4ad: 0x0818, 0x4ae: 0x0a08, 0x4af: 0x0a08, + 0x4b0: 0x3308, 0x4b1: 0x0c08, 0x4b2: 0x0c08, 0x4b3: 0x0c08, 0x4b4: 0x0808, 0x4b5: 0x0429, + 0x4b6: 0x0451, 0x4b7: 0x0479, 0x4b8: 0x04a1, 0x4b9: 0x0a08, 0x4ba: 0x0a08, 0x4bb: 0x0a08, + 0x4bc: 0x0a08, 0x4bd: 0x0a08, 0x4be: 0x0a08, 0x4bf: 0x0a08, + // Block 0x13, offset 0x4c0 + 0x4c0: 0x0c08, 0x4c1: 0x0a08, 0x4c2: 0x0a08, 0x4c3: 0x0c08, 0x4c4: 0x0c08, 0x4c5: 0x0c08, + 0x4c6: 0x0c08, 0x4c7: 0x0c08, 0x4c8: 0x0c08, 0x4c9: 0x0c08, 0x4ca: 0x0c08, 0x4cb: 0x0c08, + 0x4cc: 0x0a08, 0x4cd: 0x0c08, 0x4ce: 0x0a08, 0x4cf: 0x0c08, 0x4d0: 0x0a08, 0x4d1: 0x0a08, + 0x4d2: 0x0c08, 0x4d3: 0x0c08, 0x4d4: 0x0818, 0x4d5: 0x0c08, 0x4d6: 0x3308, 0x4d7: 0x3308, + 0x4d8: 0x3308, 0x4d9: 0x3308, 0x4da: 0x3308, 0x4db: 0x3308, 0x4dc: 0x3308, 0x4dd: 0x0840, + 0x4de: 0x0018, 0x4df: 0x3308, 0x4e0: 0x3308, 0x4e1: 0x3308, 0x4e2: 0x3308, 0x4e3: 0x3308, + 0x4e4: 0x3308, 0x4e5: 0x0808, 0x4e6: 0x0808, 0x4e7: 0x3308, 0x4e8: 0x3308, 0x4e9: 0x0018, + 0x4ea: 0x3308, 0x4eb: 0x3308, 0x4ec: 0x3308, 0x4ed: 0x3308, 0x4ee: 0x0c08, 0x4ef: 0x0c08, + 0x4f0: 0x0008, 0x4f1: 0x0008, 0x4f2: 0x0008, 0x4f3: 0x0008, 0x4f4: 0x0008, 0x4f5: 0x0008, + 0x4f6: 0x0008, 0x4f7: 0x0008, 0x4f8: 0x0008, 0x4f9: 0x0008, 0x4fa: 0x0a08, 0x4fb: 0x0a08, + 0x4fc: 0x0a08, 0x4fd: 0x0808, 0x4fe: 0x0808, 0x4ff: 0x0a08, + // Block 0x14, offset 0x500 + 0x500: 0x0818, 0x501: 0x0818, 0x502: 0x0818, 0x503: 0x0818, 0x504: 0x0818, 0x505: 0x0818, + 0x506: 0x0818, 0x507: 0x0818, 0x508: 0x0818, 0x509: 0x0818, 0x50a: 0x0818, 0x50b: 0x0818, + 0x50c: 0x0818, 0x50d: 0x0818, 0x50e: 0x0040, 0x50f: 0x0b40, 0x510: 0x0c08, 0x511: 0x3308, + 0x512: 0x0a08, 0x513: 0x0a08, 0x514: 0x0a08, 0x515: 0x0c08, 0x516: 0x0c08, 0x517: 0x0c08, + 0x518: 0x0c08, 0x519: 0x0c08, 0x51a: 0x0a08, 0x51b: 0x0a08, 0x51c: 0x0a08, 0x51d: 0x0a08, + 0x51e: 0x0c08, 0x51f: 0x0a08, 0x520: 0x0a08, 0x521: 0x0a08, 0x522: 0x0a08, 0x523: 0x0a08, + 0x524: 0x0a08, 0x525: 0x0a08, 0x526: 0x0a08, 0x527: 0x0a08, 0x528: 0x0c08, 0x529: 0x0a08, + 0x52a: 0x0c08, 0x52b: 0x0a08, 0x52c: 0x0c08, 0x52d: 0x0a08, 0x52e: 0x0a08, 0x52f: 0x0c08, + 0x530: 0x3308, 0x531: 0x3308, 0x532: 0x3308, 0x533: 0x3308, 0x534: 0x3308, 0x535: 0x3308, + 0x536: 0x3308, 0x537: 0x3308, 0x538: 0x3308, 0x539: 0x3308, 0x53a: 0x3308, 0x53b: 0x3308, + 0x53c: 0x3308, 0x53d: 0x3308, 0x53e: 0x3308, 0x53f: 0x3308, + // Block 0x15, offset 0x540 + 0x540: 0x0c08, 0x541: 0x0a08, 0x542: 0x0a08, 0x543: 0x0a08, 0x544: 0x0a08, 0x545: 0x0a08, + 0x546: 0x0c08, 0x547: 0x0c08, 0x548: 0x0a08, 0x549: 0x0c08, 0x54a: 0x0a08, 0x54b: 0x0a08, + 0x54c: 0x0a08, 0x54d: 0x0a08, 0x54e: 0x0a08, 0x54f: 0x0a08, 0x550: 0x0a08, 0x551: 0x0a08, + 0x552: 0x0a08, 0x553: 0x0a08, 0x554: 0x0c08, 0x555: 0x0a08, 0x556: 0x0808, 0x557: 0x0808, + 0x558: 0x0808, 0x559: 0x3308, 0x55a: 0x3308, 0x55b: 0x3308, 0x55c: 0x0040, 0x55d: 0x0040, + 0x55e: 0x0818, 0x55f: 0x0040, 0x560: 0x0a08, 0x561: 0x0808, 0x562: 0x0a08, 0x563: 0x0a08, + 0x564: 0x0a08, 0x565: 0x0a08, 0x566: 0x0808, 0x567: 0x0c08, 0x568: 0x0a08, 0x569: 0x0c08, + 0x56a: 0x0c08, 0x56b: 0x0040, 0x56c: 0x0040, 0x56d: 0x0040, 0x56e: 0x0040, 0x56f: 0x0040, + 0x570: 0x0040, 0x571: 0x0040, 0x572: 0x0040, 0x573: 0x0040, 0x574: 0x0040, 0x575: 0x0040, + 0x576: 0x0040, 0x577: 0x0040, 0x578: 0x0040, 0x579: 0x0040, 0x57a: 0x0040, 0x57b: 0x0040, + 0x57c: 0x0040, 0x57d: 0x0040, 0x57e: 0x0040, 0x57f: 0x0040, + // Block 0x16, offset 0x580 + 0x580: 0x3008, 0x581: 0x3308, 0x582: 0x3308, 0x583: 0x3308, 0x584: 0x3308, 0x585: 0x3308, + 0x586: 0x3308, 0x587: 0x3308, 0x588: 0x3308, 0x589: 0x3008, 0x58a: 0x3008, 0x58b: 0x3008, + 0x58c: 0x3008, 0x58d: 0x3b08, 0x58e: 0x3008, 0x58f: 0x3008, 0x590: 0x0008, 0x591: 0x3308, + 0x592: 0x3308, 0x593: 0x3308, 0x594: 0x3308, 0x595: 0x3308, 0x596: 0x3308, 0x597: 0x3308, + 0x598: 0x04c9, 0x599: 0x0501, 0x59a: 0x0539, 0x59b: 0x0571, 0x59c: 0x05a9, 0x59d: 0x05e1, + 0x59e: 0x0619, 0x59f: 0x0651, 0x5a0: 0x0008, 0x5a1: 0x0008, 0x5a2: 0x3308, 0x5a3: 0x3308, + 0x5a4: 0x0018, 0x5a5: 0x0018, 0x5a6: 0x0008, 0x5a7: 0x0008, 0x5a8: 0x0008, 0x5a9: 0x0008, + 0x5aa: 0x0008, 0x5ab: 0x0008, 0x5ac: 0x0008, 0x5ad: 0x0008, 0x5ae: 0x0008, 0x5af: 0x0008, + 0x5b0: 0x0018, 0x5b1: 0x0008, 0x5b2: 0x0008, 0x5b3: 0x0008, 0x5b4: 0x0008, 0x5b5: 0x0008, + 0x5b6: 0x0008, 0x5b7: 0x0008, 0x5b8: 0x0008, 0x5b9: 0x0008, 0x5ba: 0x0008, 0x5bb: 0x0008, + 0x5bc: 0x0008, 0x5bd: 0x0008, 0x5be: 0x0008, 0x5bf: 0x0008, + // Block 0x17, offset 0x5c0 + 0x5c0: 0x0008, 0x5c1: 0x3308, 0x5c2: 0x3008, 0x5c3: 0x3008, 0x5c4: 0x0040, 0x5c5: 0x0008, + 0x5c6: 0x0008, 0x5c7: 0x0008, 0x5c8: 0x0008, 0x5c9: 0x0008, 0x5ca: 0x0008, 0x5cb: 0x0008, + 0x5cc: 0x0008, 0x5cd: 0x0040, 0x5ce: 0x0040, 0x5cf: 0x0008, 0x5d0: 0x0008, 0x5d1: 0x0040, + 0x5d2: 0x0040, 0x5d3: 0x0008, 0x5d4: 0x0008, 0x5d5: 0x0008, 0x5d6: 0x0008, 0x5d7: 0x0008, + 0x5d8: 0x0008, 0x5d9: 0x0008, 0x5da: 0x0008, 0x5db: 0x0008, 0x5dc: 0x0008, 0x5dd: 0x0008, + 0x5de: 0x0008, 0x5df: 0x0008, 0x5e0: 0x0008, 0x5e1: 0x0008, 0x5e2: 0x0008, 0x5e3: 0x0008, + 0x5e4: 0x0008, 0x5e5: 0x0008, 0x5e6: 0x0008, 0x5e7: 0x0008, 0x5e8: 0x0008, 0x5e9: 0x0040, + 0x5ea: 0x0008, 0x5eb: 0x0008, 0x5ec: 0x0008, 0x5ed: 0x0008, 0x5ee: 0x0008, 0x5ef: 0x0008, + 0x5f0: 0x0008, 0x5f1: 0x0040, 0x5f2: 0x0008, 0x5f3: 0x0040, 0x5f4: 0x0040, 0x5f5: 0x0040, + 0x5f6: 0x0008, 0x5f7: 0x0008, 0x5f8: 0x0008, 0x5f9: 0x0008, 0x5fa: 0x0040, 0x5fb: 0x0040, + 0x5fc: 0x3308, 0x5fd: 0x0008, 0x5fe: 0x3008, 0x5ff: 0x3008, + // Block 0x18, offset 0x600 + 0x600: 0x3008, 0x601: 0x3308, 0x602: 0x3308, 0x603: 0x3308, 0x604: 0x3308, 0x605: 0x0040, + 0x606: 0x0040, 0x607: 0x3008, 0x608: 0x3008, 0x609: 0x0040, 0x60a: 0x0040, 0x60b: 0x3008, + 0x60c: 0x3008, 0x60d: 0x3b08, 0x60e: 0x0008, 0x60f: 0x0040, 0x610: 0x0040, 0x611: 0x0040, + 0x612: 0x0040, 0x613: 0x0040, 0x614: 0x0040, 0x615: 0x0040, 0x616: 0x0040, 0x617: 0x3008, + 0x618: 0x0040, 0x619: 0x0040, 0x61a: 0x0040, 0x61b: 0x0040, 0x61c: 0x0689, 0x61d: 0x06c1, + 0x61e: 0x0040, 0x61f: 0x06f9, 0x620: 0x0008, 0x621: 0x0008, 0x622: 0x3308, 0x623: 0x3308, + 0x624: 0x0040, 0x625: 0x0040, 0x626: 0x0008, 0x627: 0x0008, 0x628: 0x0008, 0x629: 0x0008, + 0x62a: 0x0008, 0x62b: 0x0008, 0x62c: 0x0008, 0x62d: 0x0008, 0x62e: 0x0008, 0x62f: 0x0008, + 0x630: 0x0008, 0x631: 0x0008, 0x632: 0x0018, 0x633: 0x0018, 0x634: 0x0018, 0x635: 0x0018, + 0x636: 0x0018, 0x637: 0x0018, 0x638: 0x0018, 0x639: 0x0018, 0x63a: 0x0018, 0x63b: 0x0018, + 0x63c: 0x0008, 0x63d: 0x0018, 0x63e: 0x3308, 0x63f: 0x0040, + // Block 0x19, offset 0x640 + 0x640: 0x0040, 0x641: 0x3308, 0x642: 0x3308, 0x643: 0x3008, 0x644: 0x0040, 0x645: 0x0008, + 0x646: 0x0008, 0x647: 0x0008, 0x648: 0x0008, 0x649: 0x0008, 0x64a: 0x0008, 0x64b: 0x0040, + 0x64c: 0x0040, 0x64d: 0x0040, 0x64e: 0x0040, 0x64f: 0x0008, 0x650: 0x0008, 0x651: 0x0040, + 0x652: 0x0040, 0x653: 0x0008, 0x654: 0x0008, 0x655: 0x0008, 0x656: 0x0008, 0x657: 0x0008, + 0x658: 0x0008, 0x659: 0x0008, 0x65a: 0x0008, 0x65b: 0x0008, 0x65c: 0x0008, 0x65d: 0x0008, + 0x65e: 0x0008, 0x65f: 0x0008, 0x660: 0x0008, 0x661: 0x0008, 0x662: 0x0008, 0x663: 0x0008, + 0x664: 0x0008, 0x665: 0x0008, 0x666: 0x0008, 0x667: 0x0008, 0x668: 0x0008, 0x669: 0x0040, + 0x66a: 0x0008, 0x66b: 0x0008, 0x66c: 0x0008, 0x66d: 0x0008, 0x66e: 0x0008, 0x66f: 0x0008, + 0x670: 0x0008, 0x671: 0x0040, 0x672: 0x0008, 0x673: 0x0731, 0x674: 0x0040, 0x675: 0x0008, + 0x676: 0x0769, 0x677: 0x0040, 0x678: 0x0008, 0x679: 0x0008, 0x67a: 0x0040, 0x67b: 0x0040, + 0x67c: 0x3308, 0x67d: 0x0040, 0x67e: 0x3008, 0x67f: 0x3008, + // Block 0x1a, offset 0x680 + 0x680: 0x3008, 0x681: 0x3308, 0x682: 0x3308, 0x683: 0x0040, 0x684: 0x0040, 0x685: 0x0040, + 0x686: 0x0040, 0x687: 0x3308, 0x688: 0x3308, 0x689: 0x0040, 0x68a: 0x0040, 0x68b: 0x3308, + 0x68c: 0x3308, 0x68d: 0x3b08, 0x68e: 0x0040, 0x68f: 0x0040, 0x690: 0x0040, 0x691: 0x3308, + 0x692: 0x0040, 0x693: 0x0040, 0x694: 0x0040, 0x695: 0x0040, 0x696: 0x0040, 0x697: 0x0040, + 0x698: 0x0040, 0x699: 0x07a1, 0x69a: 0x07d9, 0x69b: 0x0811, 0x69c: 0x0008, 0x69d: 0x0040, + 0x69e: 0x0849, 0x69f: 0x0040, 0x6a0: 0x0040, 0x6a1: 0x0040, 0x6a2: 0x0040, 0x6a3: 0x0040, + 0x6a4: 0x0040, 0x6a5: 0x0040, 0x6a6: 0x0008, 0x6a7: 0x0008, 0x6a8: 0x0008, 0x6a9: 0x0008, + 0x6aa: 0x0008, 0x6ab: 0x0008, 0x6ac: 0x0008, 0x6ad: 0x0008, 0x6ae: 0x0008, 0x6af: 0x0008, + 0x6b0: 0x3308, 0x6b1: 0x3308, 0x6b2: 0x0008, 0x6b3: 0x0008, 0x6b4: 0x0008, 0x6b5: 0x3308, + 0x6b6: 0x0018, 0x6b7: 0x0040, 0x6b8: 0x0040, 0x6b9: 0x0040, 0x6ba: 0x0040, 0x6bb: 0x0040, + 0x6bc: 0x0040, 0x6bd: 0x0040, 0x6be: 0x0040, 0x6bf: 0x0040, + // Block 0x1b, offset 0x6c0 + 0x6c0: 0x0040, 0x6c1: 0x3308, 0x6c2: 0x3308, 0x6c3: 0x3008, 0x6c4: 0x0040, 0x6c5: 0x0008, + 0x6c6: 0x0008, 0x6c7: 0x0008, 0x6c8: 0x0008, 0x6c9: 0x0008, 0x6ca: 0x0008, 0x6cb: 0x0008, + 0x6cc: 0x0008, 0x6cd: 0x0008, 0x6ce: 0x0040, 0x6cf: 0x0008, 0x6d0: 0x0008, 0x6d1: 0x0008, + 0x6d2: 0x0040, 0x6d3: 0x0008, 0x6d4: 0x0008, 0x6d5: 0x0008, 0x6d6: 0x0008, 0x6d7: 0x0008, + 0x6d8: 0x0008, 0x6d9: 0x0008, 0x6da: 0x0008, 0x6db: 0x0008, 0x6dc: 0x0008, 0x6dd: 0x0008, + 0x6de: 0x0008, 0x6df: 0x0008, 0x6e0: 0x0008, 0x6e1: 0x0008, 0x6e2: 0x0008, 0x6e3: 0x0008, + 0x6e4: 0x0008, 0x6e5: 0x0008, 0x6e6: 0x0008, 0x6e7: 0x0008, 0x6e8: 0x0008, 0x6e9: 0x0040, + 0x6ea: 0x0008, 0x6eb: 0x0008, 0x6ec: 0x0008, 0x6ed: 0x0008, 0x6ee: 0x0008, 0x6ef: 0x0008, + 0x6f0: 0x0008, 0x6f1: 0x0040, 0x6f2: 0x0008, 0x6f3: 0x0008, 0x6f4: 0x0040, 0x6f5: 0x0008, + 0x6f6: 0x0008, 0x6f7: 0x0008, 0x6f8: 0x0008, 0x6f9: 0x0008, 0x6fa: 0x0040, 0x6fb: 0x0040, + 0x6fc: 0x3308, 0x6fd: 0x0008, 0x6fe: 0x3008, 0x6ff: 0x3008, + // Block 0x1c, offset 0x700 + 0x700: 0x3008, 0x701: 0x3308, 0x702: 0x3308, 0x703: 0x3308, 0x704: 0x3308, 0x705: 0x3308, + 0x706: 0x0040, 0x707: 0x3308, 0x708: 0x3308, 0x709: 0x3008, 0x70a: 0x0040, 0x70b: 0x3008, + 0x70c: 0x3008, 0x70d: 0x3b08, 0x70e: 0x0040, 0x70f: 0x0040, 0x710: 0x0008, 0x711: 0x0040, + 0x712: 0x0040, 0x713: 0x0040, 0x714: 0x0040, 0x715: 0x0040, 0x716: 0x0040, 0x717: 0x0040, + 0x718: 0x0040, 0x719: 0x0040, 0x71a: 0x0040, 0x71b: 0x0040, 0x71c: 0x0040, 0x71d: 0x0040, + 0x71e: 0x0040, 0x71f: 0x0040, 0x720: 0x0008, 0x721: 0x0008, 0x722: 0x3308, 0x723: 0x3308, + 0x724: 0x0040, 0x725: 0x0040, 0x726: 0x0008, 0x727: 0x0008, 0x728: 0x0008, 0x729: 0x0008, + 0x72a: 0x0008, 0x72b: 0x0008, 0x72c: 0x0008, 0x72d: 0x0008, 0x72e: 0x0008, 0x72f: 0x0008, + 0x730: 0x0018, 0x731: 0x0018, 0x732: 0x0040, 0x733: 0x0040, 0x734: 0x0040, 0x735: 0x0040, + 0x736: 0x0040, 0x737: 0x0040, 0x738: 0x0040, 0x739: 0x0008, 0x73a: 0x3308, 0x73b: 0x3308, + 0x73c: 0x3308, 0x73d: 0x3308, 0x73e: 0x3308, 0x73f: 0x3308, + // Block 0x1d, offset 0x740 + 0x740: 0x0040, 0x741: 0x3308, 0x742: 0x3008, 0x743: 0x3008, 0x744: 0x0040, 0x745: 0x0008, + 0x746: 0x0008, 0x747: 0x0008, 0x748: 0x0008, 0x749: 0x0008, 0x74a: 0x0008, 0x74b: 0x0008, + 0x74c: 0x0008, 0x74d: 0x0040, 0x74e: 0x0040, 0x74f: 0x0008, 0x750: 0x0008, 0x751: 0x0040, + 0x752: 0x0040, 0x753: 0x0008, 0x754: 0x0008, 0x755: 0x0008, 0x756: 0x0008, 0x757: 0x0008, + 0x758: 0x0008, 0x759: 0x0008, 0x75a: 0x0008, 0x75b: 0x0008, 0x75c: 0x0008, 0x75d: 0x0008, + 0x75e: 0x0008, 0x75f: 0x0008, 0x760: 0x0008, 0x761: 0x0008, 0x762: 0x0008, 0x763: 0x0008, + 0x764: 0x0008, 0x765: 0x0008, 0x766: 0x0008, 0x767: 0x0008, 0x768: 0x0008, 0x769: 0x0040, + 0x76a: 0x0008, 0x76b: 0x0008, 0x76c: 0x0008, 0x76d: 0x0008, 0x76e: 0x0008, 0x76f: 0x0008, + 0x770: 0x0008, 0x771: 0x0040, 0x772: 0x0008, 0x773: 0x0008, 0x774: 0x0040, 0x775: 0x0008, + 0x776: 0x0008, 0x777: 0x0008, 0x778: 0x0008, 0x779: 0x0008, 0x77a: 0x0040, 0x77b: 0x0040, + 0x77c: 0x3308, 0x77d: 0x0008, 0x77e: 0x3008, 0x77f: 0x3308, + // Block 0x1e, offset 0x780 + 0x780: 0x3008, 0x781: 0x3308, 0x782: 0x3308, 0x783: 0x3308, 0x784: 0x3308, 0x785: 0x0040, + 0x786: 0x0040, 0x787: 0x3008, 0x788: 0x3008, 0x789: 0x0040, 0x78a: 0x0040, 0x78b: 0x3008, + 0x78c: 0x3008, 0x78d: 0x3b08, 0x78e: 0x0040, 0x78f: 0x0040, 0x790: 0x0040, 0x791: 0x0040, + 0x792: 0x0040, 0x793: 0x0040, 0x794: 0x0040, 0x795: 0x0040, 0x796: 0x3308, 0x797: 0x3008, + 0x798: 0x0040, 0x799: 0x0040, 0x79a: 0x0040, 0x79b: 0x0040, 0x79c: 0x0881, 0x79d: 0x08b9, + 0x79e: 0x0040, 0x79f: 0x0008, 0x7a0: 0x0008, 0x7a1: 0x0008, 0x7a2: 0x3308, 0x7a3: 0x3308, + 0x7a4: 0x0040, 0x7a5: 0x0040, 0x7a6: 0x0008, 0x7a7: 0x0008, 0x7a8: 0x0008, 0x7a9: 0x0008, + 0x7aa: 0x0008, 0x7ab: 0x0008, 0x7ac: 0x0008, 0x7ad: 0x0008, 0x7ae: 0x0008, 0x7af: 0x0008, + 0x7b0: 0x0018, 0x7b1: 0x0008, 0x7b2: 0x0018, 0x7b3: 0x0018, 0x7b4: 0x0018, 0x7b5: 0x0018, + 0x7b6: 0x0018, 0x7b7: 0x0018, 0x7b8: 0x0040, 0x7b9: 0x0040, 0x7ba: 0x0040, 0x7bb: 0x0040, + 0x7bc: 0x0040, 0x7bd: 0x0040, 0x7be: 0x0040, 0x7bf: 0x0040, + // Block 0x1f, offset 0x7c0 + 0x7c0: 0x0040, 0x7c1: 0x0040, 0x7c2: 0x3308, 0x7c3: 0x0008, 0x7c4: 0x0040, 0x7c5: 0x0008, + 0x7c6: 0x0008, 0x7c7: 0x0008, 0x7c8: 0x0008, 0x7c9: 0x0008, 0x7ca: 0x0008, 0x7cb: 0x0040, + 0x7cc: 0x0040, 0x7cd: 0x0040, 0x7ce: 0x0008, 0x7cf: 0x0008, 0x7d0: 0x0008, 0x7d1: 0x0040, + 0x7d2: 0x0008, 0x7d3: 0x0008, 0x7d4: 0x0008, 0x7d5: 0x0008, 0x7d6: 0x0040, 0x7d7: 0x0040, + 0x7d8: 0x0040, 0x7d9: 0x0008, 0x7da: 0x0008, 0x7db: 0x0040, 0x7dc: 0x0008, 0x7dd: 0x0040, + 0x7de: 0x0008, 0x7df: 0x0008, 0x7e0: 0x0040, 0x7e1: 0x0040, 0x7e2: 0x0040, 0x7e3: 0x0008, + 0x7e4: 0x0008, 0x7e5: 0x0040, 0x7e6: 0x0040, 0x7e7: 0x0040, 0x7e8: 0x0008, 0x7e9: 0x0008, + 0x7ea: 0x0008, 0x7eb: 0x0040, 0x7ec: 0x0040, 0x7ed: 0x0040, 0x7ee: 0x0008, 0x7ef: 0x0008, + 0x7f0: 0x0008, 0x7f1: 0x0008, 0x7f2: 0x0008, 0x7f3: 0x0008, 0x7f4: 0x0008, 0x7f5: 0x0008, + 0x7f6: 0x0008, 0x7f7: 0x0008, 0x7f8: 0x0008, 0x7f9: 0x0008, 0x7fa: 0x0040, 0x7fb: 0x0040, + 0x7fc: 0x0040, 0x7fd: 0x0040, 0x7fe: 0x3008, 0x7ff: 0x3008, + // Block 0x20, offset 0x800 + 0x800: 0x3308, 0x801: 0x3008, 0x802: 0x3008, 0x803: 0x3008, 0x804: 0x3008, 0x805: 0x0040, + 0x806: 0x3308, 0x807: 0x3308, 0x808: 0x3308, 0x809: 0x0040, 0x80a: 0x3308, 0x80b: 0x3308, + 0x80c: 0x3308, 0x80d: 0x3b08, 0x80e: 0x0040, 0x80f: 0x0040, 0x810: 0x0040, 0x811: 0x0040, + 0x812: 0x0040, 0x813: 0x0040, 0x814: 0x0040, 0x815: 0x3308, 0x816: 0x3308, 0x817: 0x0040, + 0x818: 0x0008, 0x819: 0x0008, 0x81a: 0x0008, 0x81b: 0x0040, 0x81c: 0x0040, 0x81d: 0x0040, + 0x81e: 0x0040, 0x81f: 0x0040, 0x820: 0x0008, 0x821: 0x0008, 0x822: 0x3308, 0x823: 0x3308, + 0x824: 0x0040, 0x825: 0x0040, 0x826: 0x0008, 0x827: 0x0008, 0x828: 0x0008, 0x829: 0x0008, + 0x82a: 0x0008, 0x82b: 0x0008, 0x82c: 0x0008, 0x82d: 0x0008, 0x82e: 0x0008, 0x82f: 0x0008, + 0x830: 0x0040, 0x831: 0x0040, 0x832: 0x0040, 0x833: 0x0040, 0x834: 0x0040, 0x835: 0x0040, + 0x836: 0x0040, 0x837: 0x0018, 0x838: 0x0018, 0x839: 0x0018, 0x83a: 0x0018, 0x83b: 0x0018, + 0x83c: 0x0018, 0x83d: 0x0018, 0x83e: 0x0018, 0x83f: 0x0018, + // Block 0x21, offset 0x840 + 0x840: 0x0008, 0x841: 0x3308, 0x842: 0x3008, 0x843: 0x3008, 0x844: 0x0018, 0x845: 0x0008, + 0x846: 0x0008, 0x847: 0x0008, 0x848: 0x0008, 0x849: 0x0008, 0x84a: 0x0008, 0x84b: 0x0008, + 0x84c: 0x0008, 0x84d: 0x0040, 0x84e: 0x0008, 0x84f: 0x0008, 0x850: 0x0008, 0x851: 0x0040, + 0x852: 0x0008, 0x853: 0x0008, 0x854: 0x0008, 0x855: 0x0008, 0x856: 0x0008, 0x857: 0x0008, + 0x858: 0x0008, 0x859: 0x0008, 0x85a: 0x0008, 0x85b: 0x0008, 0x85c: 0x0008, 0x85d: 0x0008, + 0x85e: 0x0008, 0x85f: 0x0008, 0x860: 0x0008, 0x861: 0x0008, 0x862: 0x0008, 0x863: 0x0008, + 0x864: 0x0008, 0x865: 0x0008, 0x866: 0x0008, 0x867: 0x0008, 0x868: 0x0008, 0x869: 0x0040, + 0x86a: 0x0008, 0x86b: 0x0008, 0x86c: 0x0008, 0x86d: 0x0008, 0x86e: 0x0008, 0x86f: 0x0008, + 0x870: 0x0008, 0x871: 0x0008, 0x872: 0x0008, 0x873: 0x0008, 0x874: 0x0040, 0x875: 0x0008, + 0x876: 0x0008, 0x877: 0x0008, 0x878: 0x0008, 0x879: 0x0008, 0x87a: 0x0040, 0x87b: 0x0040, + 0x87c: 0x3308, 0x87d: 0x0008, 0x87e: 0x3008, 0x87f: 0x3308, + // Block 0x22, offset 0x880 + 0x880: 0x3008, 0x881: 0x3008, 0x882: 0x3008, 0x883: 0x3008, 0x884: 0x3008, 0x885: 0x0040, + 0x886: 0x3308, 0x887: 0x3008, 0x888: 0x3008, 0x889: 0x0040, 0x88a: 0x3008, 0x88b: 0x3008, + 0x88c: 0x3308, 0x88d: 0x3b08, 0x88e: 0x0040, 0x88f: 0x0040, 0x890: 0x0040, 0x891: 0x0040, + 0x892: 0x0040, 0x893: 0x0040, 0x894: 0x0040, 0x895: 0x3008, 0x896: 0x3008, 0x897: 0x0040, + 0x898: 0x0040, 0x899: 0x0040, 0x89a: 0x0040, 0x89b: 0x0040, 0x89c: 0x0040, 0x89d: 0x0040, + 0x89e: 0x0008, 0x89f: 0x0040, 0x8a0: 0x0008, 0x8a1: 0x0008, 0x8a2: 0x3308, 0x8a3: 0x3308, + 0x8a4: 0x0040, 0x8a5: 0x0040, 0x8a6: 0x0008, 0x8a7: 0x0008, 0x8a8: 0x0008, 0x8a9: 0x0008, + 0x8aa: 0x0008, 0x8ab: 0x0008, 0x8ac: 0x0008, 0x8ad: 0x0008, 0x8ae: 0x0008, 0x8af: 0x0008, + 0x8b0: 0x0040, 0x8b1: 0x0008, 0x8b2: 0x0008, 0x8b3: 0x0040, 0x8b4: 0x0040, 0x8b5: 0x0040, + 0x8b6: 0x0040, 0x8b7: 0x0040, 0x8b8: 0x0040, 0x8b9: 0x0040, 0x8ba: 0x0040, 0x8bb: 0x0040, + 0x8bc: 0x0040, 0x8bd: 0x0040, 0x8be: 0x0040, 0x8bf: 0x0040, + // Block 0x23, offset 0x8c0 + 0x8c0: 0x3008, 0x8c1: 0x3308, 0x8c2: 0x3308, 0x8c3: 0x3308, 0x8c4: 0x3308, 0x8c5: 0x0040, + 0x8c6: 0x3008, 0x8c7: 0x3008, 0x8c8: 0x3008, 0x8c9: 0x0040, 0x8ca: 0x3008, 0x8cb: 0x3008, + 0x8cc: 0x3008, 0x8cd: 0x3b08, 0x8ce: 0x0008, 0x8cf: 0x0018, 0x8d0: 0x0040, 0x8d1: 0x0040, + 0x8d2: 0x0040, 0x8d3: 0x0040, 0x8d4: 0x0008, 0x8d5: 0x0008, 0x8d6: 0x0008, 0x8d7: 0x3008, + 0x8d8: 0x0018, 0x8d9: 0x0018, 0x8da: 0x0018, 0x8db: 0x0018, 0x8dc: 0x0018, 0x8dd: 0x0018, + 0x8de: 0x0018, 0x8df: 0x0008, 0x8e0: 0x0008, 0x8e1: 0x0008, 0x8e2: 0x3308, 0x8e3: 0x3308, + 0x8e4: 0x0040, 0x8e5: 0x0040, 0x8e6: 0x0008, 0x8e7: 0x0008, 0x8e8: 0x0008, 0x8e9: 0x0008, + 0x8ea: 0x0008, 0x8eb: 0x0008, 0x8ec: 0x0008, 0x8ed: 0x0008, 0x8ee: 0x0008, 0x8ef: 0x0008, + 0x8f0: 0x0018, 0x8f1: 0x0018, 0x8f2: 0x0018, 0x8f3: 0x0018, 0x8f4: 0x0018, 0x8f5: 0x0018, + 0x8f6: 0x0018, 0x8f7: 0x0018, 0x8f8: 0x0018, 0x8f9: 0x0018, 0x8fa: 0x0008, 0x8fb: 0x0008, + 0x8fc: 0x0008, 0x8fd: 0x0008, 0x8fe: 0x0008, 0x8ff: 0x0008, + // Block 0x24, offset 0x900 + 0x900: 0x0040, 0x901: 0x0008, 0x902: 0x0008, 0x903: 0x0040, 0x904: 0x0008, 0x905: 0x0040, + 0x906: 0x0008, 0x907: 0x0008, 0x908: 0x0008, 0x909: 0x0008, 0x90a: 0x0008, 0x90b: 0x0040, + 0x90c: 0x0008, 0x90d: 0x0008, 0x90e: 0x0008, 0x90f: 0x0008, 0x910: 0x0008, 0x911: 0x0008, + 0x912: 0x0008, 0x913: 0x0008, 0x914: 0x0008, 0x915: 0x0008, 0x916: 0x0008, 0x917: 0x0008, + 0x918: 0x0008, 0x919: 0x0008, 0x91a: 0x0008, 0x91b: 0x0008, 0x91c: 0x0008, 0x91d: 0x0008, + 0x91e: 0x0008, 0x91f: 0x0008, 0x920: 0x0008, 0x921: 0x0008, 0x922: 0x0008, 0x923: 0x0008, + 0x924: 0x0040, 0x925: 0x0008, 0x926: 0x0040, 0x927: 0x0008, 0x928: 0x0008, 0x929: 0x0008, + 0x92a: 0x0008, 0x92b: 0x0008, 0x92c: 0x0008, 0x92d: 0x0008, 0x92e: 0x0008, 0x92f: 0x0008, + 0x930: 0x0008, 0x931: 0x3308, 0x932: 0x0008, 0x933: 0x0929, 0x934: 0x3308, 0x935: 0x3308, + 0x936: 0x3308, 0x937: 0x3308, 0x938: 0x3308, 0x939: 0x3308, 0x93a: 0x3b08, 0x93b: 0x3308, + 0x93c: 0x3308, 0x93d: 0x0008, 0x93e: 0x0040, 0x93f: 0x0040, + // Block 0x25, offset 0x940 + 0x940: 0x0008, 0x941: 0x0008, 0x942: 0x0008, 0x943: 0x09d1, 0x944: 0x0008, 0x945: 0x0008, + 0x946: 0x0008, 0x947: 0x0008, 0x948: 0x0040, 0x949: 0x0008, 0x94a: 0x0008, 0x94b: 0x0008, + 0x94c: 0x0008, 0x94d: 0x0a09, 0x94e: 0x0008, 0x94f: 0x0008, 0x950: 0x0008, 0x951: 0x0008, + 0x952: 0x0a41, 0x953: 0x0008, 0x954: 0x0008, 0x955: 0x0008, 0x956: 0x0008, 0x957: 0x0a79, + 0x958: 0x0008, 0x959: 0x0008, 0x95a: 0x0008, 0x95b: 0x0008, 0x95c: 0x0ab1, 0x95d: 0x0008, + 0x95e: 0x0008, 0x95f: 0x0008, 0x960: 0x0008, 0x961: 0x0008, 0x962: 0x0008, 0x963: 0x0008, + 0x964: 0x0008, 0x965: 0x0008, 0x966: 0x0008, 0x967: 0x0008, 0x968: 0x0008, 0x969: 0x0ae9, + 0x96a: 0x0008, 0x96b: 0x0008, 0x96c: 0x0008, 0x96d: 0x0040, 0x96e: 0x0040, 0x96f: 0x0040, + 0x970: 0x0040, 0x971: 0x3308, 0x972: 0x3308, 0x973: 0x0b21, 0x974: 0x3308, 0x975: 0x0b59, + 0x976: 0x0b91, 0x977: 0x0bc9, 0x978: 0x0c19, 0x979: 0x0c51, 0x97a: 0x3308, 0x97b: 0x3308, + 0x97c: 0x3308, 0x97d: 0x3308, 0x97e: 0x3308, 0x97f: 0x3008, + // Block 0x26, offset 0x980 + 0x980: 0x3308, 0x981: 0x0ca1, 0x982: 0x3308, 0x983: 0x3308, 0x984: 0x3b08, 0x985: 0x0018, + 0x986: 0x3308, 0x987: 0x3308, 0x988: 0x0008, 0x989: 0x0008, 0x98a: 0x0008, 0x98b: 0x0008, + 0x98c: 0x0008, 0x98d: 0x3308, 0x98e: 0x3308, 0x98f: 0x3308, 0x990: 0x3308, 0x991: 0x3308, + 0x992: 0x3308, 0x993: 0x0cd9, 0x994: 0x3308, 0x995: 0x3308, 0x996: 0x3308, 0x997: 0x3308, + 0x998: 0x0040, 0x999: 0x3308, 0x99a: 0x3308, 0x99b: 0x3308, 0x99c: 0x3308, 0x99d: 0x0d11, + 0x99e: 0x3308, 0x99f: 0x3308, 0x9a0: 0x3308, 0x9a1: 0x3308, 0x9a2: 0x0d49, 0x9a3: 0x3308, + 0x9a4: 0x3308, 0x9a5: 0x3308, 0x9a6: 0x3308, 0x9a7: 0x0d81, 0x9a8: 0x3308, 0x9a9: 0x3308, + 0x9aa: 0x3308, 0x9ab: 0x3308, 0x9ac: 0x0db9, 0x9ad: 0x3308, 0x9ae: 0x3308, 0x9af: 0x3308, + 0x9b0: 0x3308, 0x9b1: 0x3308, 0x9b2: 0x3308, 0x9b3: 0x3308, 0x9b4: 0x3308, 0x9b5: 0x3308, + 0x9b6: 0x3308, 0x9b7: 0x3308, 0x9b8: 0x3308, 0x9b9: 0x0df1, 0x9ba: 0x3308, 0x9bb: 0x3308, + 0x9bc: 0x3308, 0x9bd: 0x0040, 0x9be: 0x0018, 0x9bf: 0x0018, + // Block 0x27, offset 0x9c0 + 0x9c0: 0x0008, 0x9c1: 0x0008, 0x9c2: 0x0008, 0x9c3: 0x0008, 0x9c4: 0x0008, 0x9c5: 0x0008, + 0x9c6: 0x0008, 0x9c7: 0x0008, 0x9c8: 0x0008, 0x9c9: 0x0008, 0x9ca: 0x0008, 0x9cb: 0x0008, + 0x9cc: 0x0008, 0x9cd: 0x0008, 0x9ce: 0x0008, 0x9cf: 0x0008, 0x9d0: 0x0008, 0x9d1: 0x0008, + 0x9d2: 0x0008, 0x9d3: 0x0008, 0x9d4: 0x0008, 0x9d5: 0x0008, 0x9d6: 0x0008, 0x9d7: 0x0008, + 0x9d8: 0x0008, 0x9d9: 0x0008, 0x9da: 0x0008, 0x9db: 0x0008, 0x9dc: 0x0008, 0x9dd: 0x0008, + 0x9de: 0x0008, 0x9df: 0x0008, 0x9e0: 0x0008, 0x9e1: 0x0008, 0x9e2: 0x0008, 0x9e3: 0x0008, + 0x9e4: 0x0008, 0x9e5: 0x0008, 0x9e6: 0x0008, 0x9e7: 0x0008, 0x9e8: 0x0008, 0x9e9: 0x0008, + 0x9ea: 0x0008, 0x9eb: 0x0008, 0x9ec: 0x0039, 0x9ed: 0x0ed1, 0x9ee: 0x0ee9, 0x9ef: 0x0008, + 0x9f0: 0x0ef9, 0x9f1: 0x0f09, 0x9f2: 0x0f19, 0x9f3: 0x0f31, 0x9f4: 0x0249, 0x9f5: 0x0f41, + 0x9f6: 0x0259, 0x9f7: 0x0f51, 0x9f8: 0x0359, 0x9f9: 0x0f61, 0x9fa: 0x0f71, 0x9fb: 0x0008, + 0x9fc: 0x00d9, 0x9fd: 0x0f81, 0x9fe: 0x0f99, 0x9ff: 0x0269, + // Block 0x28, offset 0xa00 + 0xa00: 0x0fa9, 0xa01: 0x0fb9, 0xa02: 0x0279, 0xa03: 0x0039, 0xa04: 0x0fc9, 0xa05: 0x0fe1, + 0xa06: 0x05b5, 0xa07: 0x0ee9, 0xa08: 0x0ef9, 0xa09: 0x0f09, 0xa0a: 0x0ff9, 0xa0b: 0x1011, + 0xa0c: 0x1029, 0xa0d: 0x0f31, 0xa0e: 0x0008, 0xa0f: 0x0f51, 0xa10: 0x0f61, 0xa11: 0x1041, + 0xa12: 0x00d9, 0xa13: 0x1059, 0xa14: 0x05cd, 0xa15: 0x05cd, 0xa16: 0x0f99, 0xa17: 0x0fa9, + 0xa18: 0x0fb9, 0xa19: 0x05b5, 0xa1a: 0x1071, 0xa1b: 0x1089, 0xa1c: 0x05e5, 0xa1d: 0x1099, + 0xa1e: 0x10b1, 0xa1f: 0x10c9, 0xa20: 0x10e1, 0xa21: 0x10f9, 0xa22: 0x0f41, 0xa23: 0x0269, + 0xa24: 0x0fb9, 0xa25: 0x1089, 0xa26: 0x1099, 0xa27: 0x10b1, 0xa28: 0x1111, 0xa29: 0x10e1, + 0xa2a: 0x10f9, 0xa2b: 0x0008, 0xa2c: 0x0008, 0xa2d: 0x0008, 0xa2e: 0x0008, 0xa2f: 0x0008, + 0xa30: 0x0008, 0xa31: 0x0008, 0xa32: 0x0008, 0xa33: 0x0008, 0xa34: 0x0008, 0xa35: 0x0008, + 0xa36: 0x0008, 0xa37: 0x0008, 0xa38: 0x1129, 0xa39: 0x0008, 0xa3a: 0x0008, 0xa3b: 0x0008, + 0xa3c: 0x0008, 0xa3d: 0x0008, 0xa3e: 0x0008, 0xa3f: 0x0008, + // Block 0x29, offset 0xa40 + 0xa40: 0x0008, 0xa41: 0x0008, 0xa42: 0x0008, 0xa43: 0x0008, 0xa44: 0x0008, 0xa45: 0x0008, + 0xa46: 0x0008, 0xa47: 0x0008, 0xa48: 0x0008, 0xa49: 0x0008, 0xa4a: 0x0008, 0xa4b: 0x0008, + 0xa4c: 0x0008, 0xa4d: 0x0008, 0xa4e: 0x0008, 0xa4f: 0x0008, 0xa50: 0x0008, 0xa51: 0x0008, + 0xa52: 0x0008, 0xa53: 0x0008, 0xa54: 0x0008, 0xa55: 0x0008, 0xa56: 0x0008, 0xa57: 0x0008, + 0xa58: 0x0008, 0xa59: 0x0008, 0xa5a: 0x0008, 0xa5b: 0x1141, 0xa5c: 0x1159, 0xa5d: 0x1169, + 0xa5e: 0x1181, 0xa5f: 0x1029, 0xa60: 0x1199, 0xa61: 0x11a9, 0xa62: 0x11c1, 0xa63: 0x11d9, + 0xa64: 0x11f1, 0xa65: 0x1209, 0xa66: 0x1221, 0xa67: 0x05fd, 0xa68: 0x1239, 0xa69: 0x1251, + 0xa6a: 0xe17d, 0xa6b: 0x1269, 0xa6c: 0x1281, 0xa6d: 0x1299, 0xa6e: 0x12b1, 0xa6f: 0x12c9, + 0xa70: 0x12e1, 0xa71: 0x12f9, 0xa72: 0x1311, 0xa73: 0x1329, 0xa74: 0x1341, 0xa75: 0x1359, + 0xa76: 0x1371, 0xa77: 0x1389, 0xa78: 0x0615, 0xa79: 0x13a1, 0xa7a: 0x13b9, 0xa7b: 0x13d1, + 0xa7c: 0x13e1, 0xa7d: 0x13f9, 0xa7e: 0x1411, 0xa7f: 0x1429, + // Block 0x2a, offset 0xa80 + 0xa80: 0xe00d, 0xa81: 0x0008, 0xa82: 0xe00d, 0xa83: 0x0008, 0xa84: 0xe00d, 0xa85: 0x0008, + 0xa86: 0xe00d, 0xa87: 0x0008, 0xa88: 0xe00d, 0xa89: 0x0008, 0xa8a: 0xe00d, 0xa8b: 0x0008, + 0xa8c: 0xe00d, 0xa8d: 0x0008, 0xa8e: 0xe00d, 0xa8f: 0x0008, 0xa90: 0xe00d, 0xa91: 0x0008, + 0xa92: 0xe00d, 0xa93: 0x0008, 0xa94: 0xe00d, 0xa95: 0x0008, 0xa96: 0xe00d, 0xa97: 0x0008, + 0xa98: 0xe00d, 0xa99: 0x0008, 0xa9a: 0xe00d, 0xa9b: 0x0008, 0xa9c: 0xe00d, 0xa9d: 0x0008, + 0xa9e: 0xe00d, 0xa9f: 0x0008, 0xaa0: 0xe00d, 0xaa1: 0x0008, 0xaa2: 0xe00d, 0xaa3: 0x0008, + 0xaa4: 0xe00d, 0xaa5: 0x0008, 0xaa6: 0xe00d, 0xaa7: 0x0008, 0xaa8: 0xe00d, 0xaa9: 0x0008, + 0xaaa: 0xe00d, 0xaab: 0x0008, 0xaac: 0xe00d, 0xaad: 0x0008, 0xaae: 0xe00d, 0xaaf: 0x0008, + 0xab0: 0xe00d, 0xab1: 0x0008, 0xab2: 0xe00d, 0xab3: 0x0008, 0xab4: 0xe00d, 0xab5: 0x0008, + 0xab6: 0xe00d, 0xab7: 0x0008, 0xab8: 0xe00d, 0xab9: 0x0008, 0xaba: 0xe00d, 0xabb: 0x0008, + 0xabc: 0xe00d, 0xabd: 0x0008, 0xabe: 0xe00d, 0xabf: 0x0008, + // Block 0x2b, offset 0xac0 + 0xac0: 0xe00d, 0xac1: 0x0008, 0xac2: 0xe00d, 0xac3: 0x0008, 0xac4: 0xe00d, 0xac5: 0x0008, + 0xac6: 0xe00d, 0xac7: 0x0008, 0xac8: 0xe00d, 0xac9: 0x0008, 0xaca: 0xe00d, 0xacb: 0x0008, + 0xacc: 0xe00d, 0xacd: 0x0008, 0xace: 0xe00d, 0xacf: 0x0008, 0xad0: 0xe00d, 0xad1: 0x0008, + 0xad2: 0xe00d, 0xad3: 0x0008, 0xad4: 0xe00d, 0xad5: 0x0008, 0xad6: 0x0008, 0xad7: 0x0008, + 0xad8: 0x0008, 0xad9: 0x0008, 0xada: 0x062d, 0xadb: 0x064d, 0xadc: 0x0008, 0xadd: 0x0008, + 0xade: 0x1441, 0xadf: 0x0008, 0xae0: 0xe00d, 0xae1: 0x0008, 0xae2: 0xe00d, 0xae3: 0x0008, + 0xae4: 0xe00d, 0xae5: 0x0008, 0xae6: 0xe00d, 0xae7: 0x0008, 0xae8: 0xe00d, 0xae9: 0x0008, + 0xaea: 0xe00d, 0xaeb: 0x0008, 0xaec: 0xe00d, 0xaed: 0x0008, 0xaee: 0xe00d, 0xaef: 0x0008, + 0xaf0: 0xe00d, 0xaf1: 0x0008, 0xaf2: 0xe00d, 0xaf3: 0x0008, 0xaf4: 0xe00d, 0xaf5: 0x0008, + 0xaf6: 0xe00d, 0xaf7: 0x0008, 0xaf8: 0xe00d, 0xaf9: 0x0008, 0xafa: 0xe00d, 0xafb: 0x0008, + 0xafc: 0xe00d, 0xafd: 0x0008, 0xafe: 0xe00d, 0xaff: 0x0008, + // Block 0x2c, offset 0xb00 + 0xb00: 0x0008, 0xb01: 0x0008, 0xb02: 0x0008, 0xb03: 0x0008, 0xb04: 0x0008, 0xb05: 0x0008, + 0xb06: 0x0040, 0xb07: 0x0040, 0xb08: 0xe045, 0xb09: 0xe045, 0xb0a: 0xe045, 0xb0b: 0xe045, + 0xb0c: 0xe045, 0xb0d: 0xe045, 0xb0e: 0x0040, 0xb0f: 0x0040, 0xb10: 0x0008, 0xb11: 0x0008, + 0xb12: 0x0008, 0xb13: 0x0008, 0xb14: 0x0008, 0xb15: 0x0008, 0xb16: 0x0008, 0xb17: 0x0008, + 0xb18: 0x0040, 0xb19: 0xe045, 0xb1a: 0x0040, 0xb1b: 0xe045, 0xb1c: 0x0040, 0xb1d: 0xe045, + 0xb1e: 0x0040, 0xb1f: 0xe045, 0xb20: 0x0008, 0xb21: 0x0008, 0xb22: 0x0008, 0xb23: 0x0008, + 0xb24: 0x0008, 0xb25: 0x0008, 0xb26: 0x0008, 0xb27: 0x0008, 0xb28: 0xe045, 0xb29: 0xe045, + 0xb2a: 0xe045, 0xb2b: 0xe045, 0xb2c: 0xe045, 0xb2d: 0xe045, 0xb2e: 0xe045, 0xb2f: 0xe045, + 0xb30: 0x0008, 0xb31: 0x1459, 0xb32: 0x0008, 0xb33: 0x1471, 0xb34: 0x0008, 0xb35: 0x1489, + 0xb36: 0x0008, 0xb37: 0x14a1, 0xb38: 0x0008, 0xb39: 0x14b9, 0xb3a: 0x0008, 0xb3b: 0x14d1, + 0xb3c: 0x0008, 0xb3d: 0x14e9, 0xb3e: 0x0040, 0xb3f: 0x0040, + // Block 0x2d, offset 0xb40 + 0xb40: 0x1501, 0xb41: 0x1531, 0xb42: 0x1561, 0xb43: 0x1591, 0xb44: 0x15c1, 0xb45: 0x15f1, + 0xb46: 0x1621, 0xb47: 0x1651, 0xb48: 0x1501, 0xb49: 0x1531, 0xb4a: 0x1561, 0xb4b: 0x1591, + 0xb4c: 0x15c1, 0xb4d: 0x15f1, 0xb4e: 0x1621, 0xb4f: 0x1651, 0xb50: 0x1681, 0xb51: 0x16b1, + 0xb52: 0x16e1, 0xb53: 0x1711, 0xb54: 0x1741, 0xb55: 0x1771, 0xb56: 0x17a1, 0xb57: 0x17d1, + 0xb58: 0x1681, 0xb59: 0x16b1, 0xb5a: 0x16e1, 0xb5b: 0x1711, 0xb5c: 0x1741, 0xb5d: 0x1771, + 0xb5e: 0x17a1, 0xb5f: 0x17d1, 0xb60: 0x1801, 0xb61: 0x1831, 0xb62: 0x1861, 0xb63: 0x1891, + 0xb64: 0x18c1, 0xb65: 0x18f1, 0xb66: 0x1921, 0xb67: 0x1951, 0xb68: 0x1801, 0xb69: 0x1831, + 0xb6a: 0x1861, 0xb6b: 0x1891, 0xb6c: 0x18c1, 0xb6d: 0x18f1, 0xb6e: 0x1921, 0xb6f: 0x1951, + 0xb70: 0x0008, 0xb71: 0x0008, 0xb72: 0x1981, 0xb73: 0x19b1, 0xb74: 0x19d9, 0xb75: 0x0040, + 0xb76: 0x0008, 0xb77: 0x1a01, 0xb78: 0xe045, 0xb79: 0xe045, 0xb7a: 0x0665, 0xb7b: 0x1459, + 0xb7c: 0x19b1, 0xb7d: 0x067e, 0xb7e: 0x1a31, 0xb7f: 0x069e, + // Block 0x2e, offset 0xb80 + 0xb80: 0x06be, 0xb81: 0x1a4a, 0xb82: 0x1a79, 0xb83: 0x1aa9, 0xb84: 0x1ad1, 0xb85: 0x0040, + 0xb86: 0x0008, 0xb87: 0x1af9, 0xb88: 0x06dd, 0xb89: 0x1471, 0xb8a: 0x06f5, 0xb8b: 0x1489, + 0xb8c: 0x1aa9, 0xb8d: 0x1b2a, 0xb8e: 0x1b5a, 0xb8f: 0x1b8a, 0xb90: 0x0008, 0xb91: 0x0008, + 0xb92: 0x0008, 0xb93: 0x1bb9, 0xb94: 0x0040, 0xb95: 0x0040, 0xb96: 0x0008, 0xb97: 0x0008, + 0xb98: 0xe045, 0xb99: 0xe045, 0xb9a: 0x070d, 0xb9b: 0x14a1, 0xb9c: 0x0040, 0xb9d: 0x1bd2, + 0xb9e: 0x1c02, 0xb9f: 0x1c32, 0xba0: 0x0008, 0xba1: 0x0008, 0xba2: 0x0008, 0xba3: 0x1c61, + 0xba4: 0x0008, 0xba5: 0x0008, 0xba6: 0x0008, 0xba7: 0x0008, 0xba8: 0xe045, 0xba9: 0xe045, + 0xbaa: 0x0725, 0xbab: 0x14d1, 0xbac: 0xe04d, 0xbad: 0x1c7a, 0xbae: 0x03d2, 0xbaf: 0x1caa, + 0xbb0: 0x0040, 0xbb1: 0x0040, 0xbb2: 0x1cb9, 0xbb3: 0x1ce9, 0xbb4: 0x1d11, 0xbb5: 0x0040, + 0xbb6: 0x0008, 0xbb7: 0x1d39, 0xbb8: 0x073d, 0xbb9: 0x14b9, 0xbba: 0x0515, 0xbbb: 0x14e9, + 0xbbc: 0x1ce9, 0xbbd: 0x0756, 0xbbe: 0x0776, 0xbbf: 0x0040, + // Block 0x2f, offset 0xbc0 + 0xbc0: 0x000a, 0xbc1: 0x000a, 0xbc2: 0x000a, 0xbc3: 0x000a, 0xbc4: 0x000a, 0xbc5: 0x000a, + 0xbc6: 0x000a, 0xbc7: 0x000a, 0xbc8: 0x000a, 0xbc9: 0x000a, 0xbca: 0x000a, 0xbcb: 0x03c0, + 0xbcc: 0x0003, 0xbcd: 0x0003, 0xbce: 0x0340, 0xbcf: 0x0b40, 0xbd0: 0x0018, 0xbd1: 0xe00d, + 0xbd2: 0x0018, 0xbd3: 0x0018, 0xbd4: 0x0018, 0xbd5: 0x0018, 0xbd6: 0x0018, 0xbd7: 0x0796, + 0xbd8: 0x0018, 0xbd9: 0x0018, 0xbda: 0x0018, 0xbdb: 0x0018, 0xbdc: 0x0018, 0xbdd: 0x0018, + 0xbde: 0x0018, 0xbdf: 0x0018, 0xbe0: 0x0018, 0xbe1: 0x0018, 0xbe2: 0x0018, 0xbe3: 0x0018, + 0xbe4: 0x0040, 0xbe5: 0x0040, 0xbe6: 0x0040, 0xbe7: 0x0018, 0xbe8: 0x0040, 0xbe9: 0x0040, + 0xbea: 0x0340, 0xbeb: 0x0340, 0xbec: 0x0340, 0xbed: 0x0340, 0xbee: 0x0340, 0xbef: 0x000a, + 0xbf0: 0x0018, 0xbf1: 0x0018, 0xbf2: 0x0018, 0xbf3: 0x1d69, 0xbf4: 0x1da1, 0xbf5: 0x0018, + 0xbf6: 0x1df1, 0xbf7: 0x1e29, 0xbf8: 0x0018, 0xbf9: 0x0018, 0xbfa: 0x0018, 0xbfb: 0x0018, + 0xbfc: 0x1e7a, 0xbfd: 0x0018, 0xbfe: 0x07b6, 0xbff: 0x0018, + // Block 0x30, offset 0xc00 + 0xc00: 0x0018, 0xc01: 0x0018, 0xc02: 0x0018, 0xc03: 0x0018, 0xc04: 0x0018, 0xc05: 0x0018, + 0xc06: 0x0018, 0xc07: 0x1e92, 0xc08: 0x1eaa, 0xc09: 0x1ec2, 0xc0a: 0x0018, 0xc0b: 0x0018, + 0xc0c: 0x0018, 0xc0d: 0x0018, 0xc0e: 0x0018, 0xc0f: 0x0018, 0xc10: 0x0018, 0xc11: 0x0018, + 0xc12: 0x0018, 0xc13: 0x0018, 0xc14: 0x0018, 0xc15: 0x0018, 0xc16: 0x0018, 0xc17: 0x1ed9, + 0xc18: 0x0018, 0xc19: 0x0018, 0xc1a: 0x0018, 0xc1b: 0x0018, 0xc1c: 0x0018, 0xc1d: 0x0018, + 0xc1e: 0x0018, 0xc1f: 0x000a, 0xc20: 0x03c0, 0xc21: 0x0340, 0xc22: 0x0340, 0xc23: 0x0340, + 0xc24: 0x03c0, 0xc25: 0x0040, 0xc26: 0x0040, 0xc27: 0x0040, 0xc28: 0x0040, 0xc29: 0x0040, + 0xc2a: 0x0340, 0xc2b: 0x0340, 0xc2c: 0x0340, 0xc2d: 0x0340, 0xc2e: 0x0340, 0xc2f: 0x0340, + 0xc30: 0x1f41, 0xc31: 0x0f41, 0xc32: 0x0040, 0xc33: 0x0040, 0xc34: 0x1f51, 0xc35: 0x1f61, + 0xc36: 0x1f71, 0xc37: 0x1f81, 0xc38: 0x1f91, 0xc39: 0x1fa1, 0xc3a: 0x1fb2, 0xc3b: 0x07d5, + 0xc3c: 0x1fc2, 0xc3d: 0x1fd2, 0xc3e: 0x1fe2, 0xc3f: 0x0f71, + // Block 0x31, offset 0xc40 + 0xc40: 0x1f41, 0xc41: 0x00c9, 0xc42: 0x0069, 0xc43: 0x0079, 0xc44: 0x1f51, 0xc45: 0x1f61, + 0xc46: 0x1f71, 0xc47: 0x1f81, 0xc48: 0x1f91, 0xc49: 0x1fa1, 0xc4a: 0x1fb2, 0xc4b: 0x07ed, + 0xc4c: 0x1fc2, 0xc4d: 0x1fd2, 0xc4e: 0x1fe2, 0xc4f: 0x0040, 0xc50: 0x0039, 0xc51: 0x0f09, + 0xc52: 0x00d9, 0xc53: 0x0369, 0xc54: 0x0ff9, 0xc55: 0x0249, 0xc56: 0x0f51, 0xc57: 0x0359, + 0xc58: 0x0f61, 0xc59: 0x0f71, 0xc5a: 0x0f99, 0xc5b: 0x01d9, 0xc5c: 0x0fa9, 0xc5d: 0x0040, + 0xc5e: 0x0040, 0xc5f: 0x0040, 0xc60: 0x0018, 0xc61: 0x0018, 0xc62: 0x0018, 0xc63: 0x0018, + 0xc64: 0x0018, 0xc65: 0x0018, 0xc66: 0x0018, 0xc67: 0x0018, 0xc68: 0x1ff1, 0xc69: 0x0018, + 0xc6a: 0x0018, 0xc6b: 0x0018, 0xc6c: 0x0018, 0xc6d: 0x0018, 0xc6e: 0x0018, 0xc6f: 0x0018, + 0xc70: 0x0018, 0xc71: 0x0018, 0xc72: 0x0018, 0xc73: 0x0018, 0xc74: 0x0018, 0xc75: 0x0018, + 0xc76: 0x0018, 0xc77: 0x0018, 0xc78: 0x0018, 0xc79: 0x0018, 0xc7a: 0x0018, 0xc7b: 0x0018, + 0xc7c: 0x0018, 0xc7d: 0x0018, 0xc7e: 0x0018, 0xc7f: 0x0018, + // Block 0x32, offset 0xc80 + 0xc80: 0x0806, 0xc81: 0x0826, 0xc82: 0x1159, 0xc83: 0x0845, 0xc84: 0x0018, 0xc85: 0x0866, + 0xc86: 0x0886, 0xc87: 0x1011, 0xc88: 0x0018, 0xc89: 0x08a5, 0xc8a: 0x0f31, 0xc8b: 0x0249, + 0xc8c: 0x0249, 0xc8d: 0x0249, 0xc8e: 0x0249, 0xc8f: 0x2009, 0xc90: 0x0f41, 0xc91: 0x0f41, + 0xc92: 0x0359, 0xc93: 0x0359, 0xc94: 0x0018, 0xc95: 0x0f71, 0xc96: 0x2021, 0xc97: 0x0018, + 0xc98: 0x0018, 0xc99: 0x0f99, 0xc9a: 0x2039, 0xc9b: 0x0269, 0xc9c: 0x0269, 0xc9d: 0x0269, + 0xc9e: 0x0018, 0xc9f: 0x0018, 0xca0: 0x2049, 0xca1: 0x08c5, 0xca2: 0x2061, 0xca3: 0x0018, + 0xca4: 0x13d1, 0xca5: 0x0018, 0xca6: 0x2079, 0xca7: 0x0018, 0xca8: 0x13d1, 0xca9: 0x0018, + 0xcaa: 0x0f51, 0xcab: 0x2091, 0xcac: 0x0ee9, 0xcad: 0x1159, 0xcae: 0x0018, 0xcaf: 0x0f09, + 0xcb0: 0x0f09, 0xcb1: 0x1199, 0xcb2: 0x0040, 0xcb3: 0x0f61, 0xcb4: 0x00d9, 0xcb5: 0x20a9, + 0xcb6: 0x20c1, 0xcb7: 0x20d9, 0xcb8: 0x20f1, 0xcb9: 0x0f41, 0xcba: 0x0018, 0xcbb: 0x08e5, + 0xcbc: 0x2109, 0xcbd: 0x10b1, 0xcbe: 0x10b1, 0xcbf: 0x2109, + // Block 0x33, offset 0xcc0 + 0xcc0: 0x0905, 0xcc1: 0x0018, 0xcc2: 0x0018, 0xcc3: 0x0018, 0xcc4: 0x0018, 0xcc5: 0x0ef9, + 0xcc6: 0x0ef9, 0xcc7: 0x0f09, 0xcc8: 0x0f41, 0xcc9: 0x0259, 0xcca: 0x0018, 0xccb: 0x0018, + 0xccc: 0x0018, 0xccd: 0x0018, 0xcce: 0x0008, 0xccf: 0x0018, 0xcd0: 0x2121, 0xcd1: 0x2151, + 0xcd2: 0x2181, 0xcd3: 0x21b9, 0xcd4: 0x21e9, 0xcd5: 0x2219, 0xcd6: 0x2249, 0xcd7: 0x2279, + 0xcd8: 0x22a9, 0xcd9: 0x22d9, 0xcda: 0x2309, 0xcdb: 0x2339, 0xcdc: 0x2369, 0xcdd: 0x2399, + 0xcde: 0x23c9, 0xcdf: 0x23f9, 0xce0: 0x0f41, 0xce1: 0x2421, 0xce2: 0x091d, 0xce3: 0x2439, + 0xce4: 0x1089, 0xce5: 0x2451, 0xce6: 0x093d, 0xce7: 0x2469, 0xce8: 0x2491, 0xce9: 0x0369, + 0xcea: 0x24a9, 0xceb: 0x095d, 0xcec: 0x0359, 0xced: 0x1159, 0xcee: 0x0ef9, 0xcef: 0x0f61, + 0xcf0: 0x0f41, 0xcf1: 0x2421, 0xcf2: 0x097d, 0xcf3: 0x2439, 0xcf4: 0x1089, 0xcf5: 0x2451, + 0xcf6: 0x099d, 0xcf7: 0x2469, 0xcf8: 0x2491, 0xcf9: 0x0369, 0xcfa: 0x24a9, 0xcfb: 0x09bd, + 0xcfc: 0x0359, 0xcfd: 0x1159, 0xcfe: 0x0ef9, 0xcff: 0x0f61, + // Block 0x34, offset 0xd00 + 0xd00: 0x0018, 0xd01: 0x0018, 0xd02: 0x0018, 0xd03: 0x0018, 0xd04: 0x0018, 0xd05: 0x0018, + 0xd06: 0x0018, 0xd07: 0x0018, 0xd08: 0x0018, 0xd09: 0x0018, 0xd0a: 0x0018, 0xd0b: 0x0040, + 0xd0c: 0x0040, 0xd0d: 0x0040, 0xd0e: 0x0040, 0xd0f: 0x0040, 0xd10: 0x0040, 0xd11: 0x0040, + 0xd12: 0x0040, 0xd13: 0x0040, 0xd14: 0x0040, 0xd15: 0x0040, 0xd16: 0x0040, 0xd17: 0x0040, + 0xd18: 0x0040, 0xd19: 0x0040, 0xd1a: 0x0040, 0xd1b: 0x0040, 0xd1c: 0x0040, 0xd1d: 0x0040, + 0xd1e: 0x0040, 0xd1f: 0x0040, 0xd20: 0x00c9, 0xd21: 0x0069, 0xd22: 0x0079, 0xd23: 0x1f51, + 0xd24: 0x1f61, 0xd25: 0x1f71, 0xd26: 0x1f81, 0xd27: 0x1f91, 0xd28: 0x1fa1, 0xd29: 0x2601, + 0xd2a: 0x2619, 0xd2b: 0x2631, 0xd2c: 0x2649, 0xd2d: 0x2661, 0xd2e: 0x2679, 0xd2f: 0x2691, + 0xd30: 0x26a9, 0xd31: 0x26c1, 0xd32: 0x26d9, 0xd33: 0x26f1, 0xd34: 0x0a1e, 0xd35: 0x0a3e, + 0xd36: 0x0a5e, 0xd37: 0x0a7e, 0xd38: 0x0a9e, 0xd39: 0x0abe, 0xd3a: 0x0ade, 0xd3b: 0x0afe, + 0xd3c: 0x0b1e, 0xd3d: 0x270a, 0xd3e: 0x2732, 0xd3f: 0x275a, + // Block 0x35, offset 0xd40 + 0xd40: 0x2782, 0xd41: 0x27aa, 0xd42: 0x27d2, 0xd43: 0x27fa, 0xd44: 0x2822, 0xd45: 0x284a, + 0xd46: 0x2872, 0xd47: 0x289a, 0xd48: 0x0040, 0xd49: 0x0040, 0xd4a: 0x0040, 0xd4b: 0x0040, + 0xd4c: 0x0040, 0xd4d: 0x0040, 0xd4e: 0x0040, 0xd4f: 0x0040, 0xd50: 0x0040, 0xd51: 0x0040, + 0xd52: 0x0040, 0xd53: 0x0040, 0xd54: 0x0040, 0xd55: 0x0040, 0xd56: 0x0040, 0xd57: 0x0040, + 0xd58: 0x0040, 0xd59: 0x0040, 0xd5a: 0x0040, 0xd5b: 0x0040, 0xd5c: 0x0b3e, 0xd5d: 0x0b5e, + 0xd5e: 0x0b7e, 0xd5f: 0x0b9e, 0xd60: 0x0bbe, 0xd61: 0x0bde, 0xd62: 0x0bfe, 0xd63: 0x0c1e, + 0xd64: 0x0c3e, 0xd65: 0x0c5e, 0xd66: 0x0c7e, 0xd67: 0x0c9e, 0xd68: 0x0cbe, 0xd69: 0x0cde, + 0xd6a: 0x0cfe, 0xd6b: 0x0d1e, 0xd6c: 0x0d3e, 0xd6d: 0x0d5e, 0xd6e: 0x0d7e, 0xd6f: 0x0d9e, + 0xd70: 0x0dbe, 0xd71: 0x0dde, 0xd72: 0x0dfe, 0xd73: 0x0e1e, 0xd74: 0x0e3e, 0xd75: 0x0e5e, + 0xd76: 0x0039, 0xd77: 0x0ee9, 0xd78: 0x1159, 0xd79: 0x0ef9, 0xd7a: 0x0f09, 0xd7b: 0x1199, + 0xd7c: 0x0f31, 0xd7d: 0x0249, 0xd7e: 0x0f41, 0xd7f: 0x0259, + // Block 0x36, offset 0xd80 + 0xd80: 0x0f51, 0xd81: 0x0359, 0xd82: 0x0f61, 0xd83: 0x0f71, 0xd84: 0x00d9, 0xd85: 0x0f99, + 0xd86: 0x2039, 0xd87: 0x0269, 0xd88: 0x01d9, 0xd89: 0x0fa9, 0xd8a: 0x0fb9, 0xd8b: 0x1089, + 0xd8c: 0x0279, 0xd8d: 0x0369, 0xd8e: 0x0289, 0xd8f: 0x13d1, 0xd90: 0x0039, 0xd91: 0x0ee9, + 0xd92: 0x1159, 0xd93: 0x0ef9, 0xd94: 0x0f09, 0xd95: 0x1199, 0xd96: 0x0f31, 0xd97: 0x0249, + 0xd98: 0x0f41, 0xd99: 0x0259, 0xd9a: 0x0f51, 0xd9b: 0x0359, 0xd9c: 0x0f61, 0xd9d: 0x0f71, + 0xd9e: 0x00d9, 0xd9f: 0x0f99, 0xda0: 0x2039, 0xda1: 0x0269, 0xda2: 0x01d9, 0xda3: 0x0fa9, + 0xda4: 0x0fb9, 0xda5: 0x1089, 0xda6: 0x0279, 0xda7: 0x0369, 0xda8: 0x0289, 0xda9: 0x13d1, + 0xdaa: 0x1f41, 0xdab: 0x0018, 0xdac: 0x0018, 0xdad: 0x0018, 0xdae: 0x0018, 0xdaf: 0x0018, + 0xdb0: 0x0018, 0xdb1: 0x0018, 0xdb2: 0x0018, 0xdb3: 0x0018, 0xdb4: 0x0018, 0xdb5: 0x0018, + 0xdb6: 0x0018, 0xdb7: 0x0018, 0xdb8: 0x0018, 0xdb9: 0x0018, 0xdba: 0x0018, 0xdbb: 0x0018, + 0xdbc: 0x0018, 0xdbd: 0x0018, 0xdbe: 0x0018, 0xdbf: 0x0018, + // Block 0x37, offset 0xdc0 + 0xdc0: 0x0008, 0xdc1: 0x0008, 0xdc2: 0x0008, 0xdc3: 0x0008, 0xdc4: 0x0008, 0xdc5: 0x0008, + 0xdc6: 0x0008, 0xdc7: 0x0008, 0xdc8: 0x0008, 0xdc9: 0x0008, 0xdca: 0x0008, 0xdcb: 0x0008, + 0xdcc: 0x0008, 0xdcd: 0x0008, 0xdce: 0x0008, 0xdcf: 0x0008, 0xdd0: 0x0008, 0xdd1: 0x0008, + 0xdd2: 0x0008, 0xdd3: 0x0008, 0xdd4: 0x0008, 0xdd5: 0x0008, 0xdd6: 0x0008, 0xdd7: 0x0008, + 0xdd8: 0x0008, 0xdd9: 0x0008, 0xdda: 0x0008, 0xddb: 0x0008, 0xddc: 0x0008, 0xddd: 0x0008, + 0xdde: 0x0008, 0xddf: 0x0040, 0xde0: 0xe00d, 0xde1: 0x0008, 0xde2: 0x2971, 0xde3: 0x0ed5, + 0xde4: 0x2989, 0xde5: 0x0008, 0xde6: 0x0008, 0xde7: 0xe07d, 0xde8: 0x0008, 0xde9: 0xe01d, + 0xdea: 0x0008, 0xdeb: 0xe03d, 0xdec: 0x0008, 0xded: 0x0fe1, 0xdee: 0x1281, 0xdef: 0x0fc9, + 0xdf0: 0x1141, 0xdf1: 0x0008, 0xdf2: 0xe00d, 0xdf3: 0x0008, 0xdf4: 0x0008, 0xdf5: 0xe01d, + 0xdf6: 0x0008, 0xdf7: 0x0008, 0xdf8: 0x0008, 0xdf9: 0x0008, 0xdfa: 0x0008, 0xdfb: 0x0008, + 0xdfc: 0x0259, 0xdfd: 0x1089, 0xdfe: 0x29a1, 0xdff: 0x29b9, + // Block 0x38, offset 0xe00 + 0xe00: 0xe00d, 0xe01: 0x0008, 0xe02: 0xe00d, 0xe03: 0x0008, 0xe04: 0xe00d, 0xe05: 0x0008, + 0xe06: 0xe00d, 0xe07: 0x0008, 0xe08: 0xe00d, 0xe09: 0x0008, 0xe0a: 0xe00d, 0xe0b: 0x0008, + 0xe0c: 0xe00d, 0xe0d: 0x0008, 0xe0e: 0xe00d, 0xe0f: 0x0008, 0xe10: 0xe00d, 0xe11: 0x0008, + 0xe12: 0xe00d, 0xe13: 0x0008, 0xe14: 0xe00d, 0xe15: 0x0008, 0xe16: 0xe00d, 0xe17: 0x0008, + 0xe18: 0xe00d, 0xe19: 0x0008, 0xe1a: 0xe00d, 0xe1b: 0x0008, 0xe1c: 0xe00d, 0xe1d: 0x0008, + 0xe1e: 0xe00d, 0xe1f: 0x0008, 0xe20: 0xe00d, 0xe21: 0x0008, 0xe22: 0xe00d, 0xe23: 0x0008, + 0xe24: 0x0008, 0xe25: 0x0018, 0xe26: 0x0018, 0xe27: 0x0018, 0xe28: 0x0018, 0xe29: 0x0018, + 0xe2a: 0x0018, 0xe2b: 0xe03d, 0xe2c: 0x0008, 0xe2d: 0xe01d, 0xe2e: 0x0008, 0xe2f: 0x3308, + 0xe30: 0x3308, 0xe31: 0x3308, 0xe32: 0xe00d, 0xe33: 0x0008, 0xe34: 0x0040, 0xe35: 0x0040, + 0xe36: 0x0040, 0xe37: 0x0040, 0xe38: 0x0040, 0xe39: 0x0018, 0xe3a: 0x0018, 0xe3b: 0x0018, + 0xe3c: 0x0018, 0xe3d: 0x0018, 0xe3e: 0x0018, 0xe3f: 0x0018, + // Block 0x39, offset 0xe40 + 0xe40: 0x2715, 0xe41: 0x2735, 0xe42: 0x2755, 0xe43: 0x2775, 0xe44: 0x2795, 0xe45: 0x27b5, + 0xe46: 0x27d5, 0xe47: 0x27f5, 0xe48: 0x2815, 0xe49: 0x2835, 0xe4a: 0x2855, 0xe4b: 0x2875, + 0xe4c: 0x2895, 0xe4d: 0x28b5, 0xe4e: 0x28d5, 0xe4f: 0x28f5, 0xe50: 0x2915, 0xe51: 0x2935, + 0xe52: 0x2955, 0xe53: 0x2975, 0xe54: 0x2995, 0xe55: 0x29b5, 0xe56: 0x0040, 0xe57: 0x0040, + 0xe58: 0x0040, 0xe59: 0x0040, 0xe5a: 0x0040, 0xe5b: 0x0040, 0xe5c: 0x0040, 0xe5d: 0x0040, + 0xe5e: 0x0040, 0xe5f: 0x0040, 0xe60: 0x0040, 0xe61: 0x0040, 0xe62: 0x0040, 0xe63: 0x0040, + 0xe64: 0x0040, 0xe65: 0x0040, 0xe66: 0x0040, 0xe67: 0x0040, 0xe68: 0x0040, 0xe69: 0x0040, + 0xe6a: 0x0040, 0xe6b: 0x0040, 0xe6c: 0x0040, 0xe6d: 0x0040, 0xe6e: 0x0040, 0xe6f: 0x0040, + 0xe70: 0x0040, 0xe71: 0x0040, 0xe72: 0x0040, 0xe73: 0x0040, 0xe74: 0x0040, 0xe75: 0x0040, + 0xe76: 0x0040, 0xe77: 0x0040, 0xe78: 0x0040, 0xe79: 0x0040, 0xe7a: 0x0040, 0xe7b: 0x0040, + 0xe7c: 0x0040, 0xe7d: 0x0040, 0xe7e: 0x0040, 0xe7f: 0x0040, + // Block 0x3a, offset 0xe80 + 0xe80: 0x000a, 0xe81: 0x0018, 0xe82: 0x29d1, 0xe83: 0x0018, 0xe84: 0x0018, 0xe85: 0x0008, + 0xe86: 0x0008, 0xe87: 0x0008, 0xe88: 0x0018, 0xe89: 0x0018, 0xe8a: 0x0018, 0xe8b: 0x0018, + 0xe8c: 0x0018, 0xe8d: 0x0018, 0xe8e: 0x0018, 0xe8f: 0x0018, 0xe90: 0x0018, 0xe91: 0x0018, + 0xe92: 0x0018, 0xe93: 0x0018, 0xe94: 0x0018, 0xe95: 0x0018, 0xe96: 0x0018, 0xe97: 0x0018, + 0xe98: 0x0018, 0xe99: 0x0018, 0xe9a: 0x0018, 0xe9b: 0x0018, 0xe9c: 0x0018, 0xe9d: 0x0018, + 0xe9e: 0x0018, 0xe9f: 0x0018, 0xea0: 0x0018, 0xea1: 0x0018, 0xea2: 0x0018, 0xea3: 0x0018, + 0xea4: 0x0018, 0xea5: 0x0018, 0xea6: 0x0018, 0xea7: 0x0018, 0xea8: 0x0018, 0xea9: 0x0018, + 0xeaa: 0x3308, 0xeab: 0x3308, 0xeac: 0x3308, 0xead: 0x3308, 0xeae: 0x3018, 0xeaf: 0x3018, + 0xeb0: 0x0018, 0xeb1: 0x0018, 0xeb2: 0x0018, 0xeb3: 0x0018, 0xeb4: 0x0018, 0xeb5: 0x0018, + 0xeb6: 0xe125, 0xeb7: 0x0018, 0xeb8: 0x29d5, 0xeb9: 0x29f5, 0xeba: 0x2a15, 0xebb: 0x0018, + 0xebc: 0x0008, 0xebd: 0x0018, 0xebe: 0x0018, 0xebf: 0x0018, + // Block 0x3b, offset 0xec0 + 0xec0: 0x2b55, 0xec1: 0x2b75, 0xec2: 0x2b95, 0xec3: 0x2bb5, 0xec4: 0x2bd5, 0xec5: 0x2bf5, + 0xec6: 0x2bf5, 0xec7: 0x2bf5, 0xec8: 0x2c15, 0xec9: 0x2c15, 0xeca: 0x2c15, 0xecb: 0x2c15, + 0xecc: 0x2c35, 0xecd: 0x2c35, 0xece: 0x2c35, 0xecf: 0x2c55, 0xed0: 0x2c75, 0xed1: 0x2c75, + 0xed2: 0x2a95, 0xed3: 0x2a95, 0xed4: 0x2c75, 0xed5: 0x2c75, 0xed6: 0x2c95, 0xed7: 0x2c95, + 0xed8: 0x2c75, 0xed9: 0x2c75, 0xeda: 0x2a95, 0xedb: 0x2a95, 0xedc: 0x2c75, 0xedd: 0x2c75, + 0xede: 0x2c55, 0xedf: 0x2c55, 0xee0: 0x2cb5, 0xee1: 0x2cb5, 0xee2: 0x2cd5, 0xee3: 0x2cd5, + 0xee4: 0x0040, 0xee5: 0x2cf5, 0xee6: 0x2d15, 0xee7: 0x2d35, 0xee8: 0x2d35, 0xee9: 0x2d55, + 0xeea: 0x2d75, 0xeeb: 0x2d95, 0xeec: 0x2db5, 0xeed: 0x2dd5, 0xeee: 0x2df5, 0xeef: 0x2e15, + 0xef0: 0x2e35, 0xef1: 0x2e55, 0xef2: 0x2e55, 0xef3: 0x2e75, 0xef4: 0x2e95, 0xef5: 0x2e95, + 0xef6: 0x2eb5, 0xef7: 0x2ed5, 0xef8: 0x2e75, 0xef9: 0x2ef5, 0xefa: 0x2f15, 0xefb: 0x2ef5, + 0xefc: 0x2e75, 0xefd: 0x2f35, 0xefe: 0x2f55, 0xeff: 0x2f75, + // Block 0x3c, offset 0xf00 + 0xf00: 0x2f95, 0xf01: 0x2fb5, 0xf02: 0x2d15, 0xf03: 0x2cf5, 0xf04: 0x2fd5, 0xf05: 0x2ff5, + 0xf06: 0x3015, 0xf07: 0x3035, 0xf08: 0x3055, 0xf09: 0x3075, 0xf0a: 0x3095, 0xf0b: 0x30b5, + 0xf0c: 0x30d5, 0xf0d: 0x30f5, 0xf0e: 0x3115, 0xf0f: 0x0040, 0xf10: 0x0018, 0xf11: 0x0018, + 0xf12: 0x3135, 0xf13: 0x3155, 0xf14: 0x3175, 0xf15: 0x3195, 0xf16: 0x31b5, 0xf17: 0x31d5, + 0xf18: 0x31f5, 0xf19: 0x3215, 0xf1a: 0x3235, 0xf1b: 0x3255, 0xf1c: 0x3175, 0xf1d: 0x3275, + 0xf1e: 0x3295, 0xf1f: 0x32b5, 0xf20: 0x0008, 0xf21: 0x0008, 0xf22: 0x0008, 0xf23: 0x0008, + 0xf24: 0x0008, 0xf25: 0x0008, 0xf26: 0x0008, 0xf27: 0x0008, 0xf28: 0x0008, 0xf29: 0x0008, + 0xf2a: 0x0008, 0xf2b: 0x0008, 0xf2c: 0x0008, 0xf2d: 0x0008, 0xf2e: 0x0008, 0xf2f: 0x0008, + 0xf30: 0x0008, 0xf31: 0x0008, 0xf32: 0x0008, 0xf33: 0x0008, 0xf34: 0x0008, 0xf35: 0x0008, + 0xf36: 0x0008, 0xf37: 0x0008, 0xf38: 0x0008, 0xf39: 0x0008, 0xf3a: 0x0008, 0xf3b: 0x0040, + 0xf3c: 0x0040, 0xf3d: 0x0040, 0xf3e: 0x0040, 0xf3f: 0x0040, + // Block 0x3d, offset 0xf40 + 0xf40: 0x36a2, 0xf41: 0x36d2, 0xf42: 0x3702, 0xf43: 0x3732, 0xf44: 0x32d5, 0xf45: 0x32f5, + 0xf46: 0x3315, 0xf47: 0x3335, 0xf48: 0x0018, 0xf49: 0x0018, 0xf4a: 0x0018, 0xf4b: 0x0018, + 0xf4c: 0x0018, 0xf4d: 0x0018, 0xf4e: 0x0018, 0xf4f: 0x0018, 0xf50: 0x3355, 0xf51: 0x3761, + 0xf52: 0x3779, 0xf53: 0x3791, 0xf54: 0x37a9, 0xf55: 0x37c1, 0xf56: 0x37d9, 0xf57: 0x37f1, + 0xf58: 0x3809, 0xf59: 0x3821, 0xf5a: 0x3839, 0xf5b: 0x3851, 0xf5c: 0x3869, 0xf5d: 0x3881, + 0xf5e: 0x3899, 0xf5f: 0x38b1, 0xf60: 0x3375, 0xf61: 0x3395, 0xf62: 0x33b5, 0xf63: 0x33d5, + 0xf64: 0x33f5, 0xf65: 0x33f5, 0xf66: 0x3415, 0xf67: 0x3435, 0xf68: 0x3455, 0xf69: 0x3475, + 0xf6a: 0x3495, 0xf6b: 0x34b5, 0xf6c: 0x34d5, 0xf6d: 0x34f5, 0xf6e: 0x3515, 0xf6f: 0x3535, + 0xf70: 0x3555, 0xf71: 0x3575, 0xf72: 0x3595, 0xf73: 0x35b5, 0xf74: 0x35d5, 0xf75: 0x35f5, + 0xf76: 0x3615, 0xf77: 0x3635, 0xf78: 0x3655, 0xf79: 0x3675, 0xf7a: 0x3695, 0xf7b: 0x36b5, + 0xf7c: 0x38c9, 0xf7d: 0x3901, 0xf7e: 0x36d5, 0xf7f: 0x0018, + // Block 0x3e, offset 0xf80 + 0xf80: 0x36f5, 0xf81: 0x3715, 0xf82: 0x3735, 0xf83: 0x3755, 0xf84: 0x3775, 0xf85: 0x3795, + 0xf86: 0x37b5, 0xf87: 0x37d5, 0xf88: 0x37f5, 0xf89: 0x3815, 0xf8a: 0x3835, 0xf8b: 0x3855, + 0xf8c: 0x3875, 0xf8d: 0x3895, 0xf8e: 0x38b5, 0xf8f: 0x38d5, 0xf90: 0x38f5, 0xf91: 0x3915, + 0xf92: 0x3935, 0xf93: 0x3955, 0xf94: 0x3975, 0xf95: 0x3995, 0xf96: 0x39b5, 0xf97: 0x39d5, + 0xf98: 0x39f5, 0xf99: 0x3a15, 0xf9a: 0x3a35, 0xf9b: 0x3a55, 0xf9c: 0x3a75, 0xf9d: 0x3a95, + 0xf9e: 0x3ab5, 0xf9f: 0x3ad5, 0xfa0: 0x3af5, 0xfa1: 0x3b15, 0xfa2: 0x3b35, 0xfa3: 0x3b55, + 0xfa4: 0x3b75, 0xfa5: 0x3b95, 0xfa6: 0x1295, 0xfa7: 0x3bb5, 0xfa8: 0x3bd5, 0xfa9: 0x3bf5, + 0xfaa: 0x3c15, 0xfab: 0x3c35, 0xfac: 0x3c55, 0xfad: 0x3c75, 0xfae: 0x23b5, 0xfaf: 0x3c95, + 0xfb0: 0x3cb5, 0xfb1: 0x3939, 0xfb2: 0x3951, 0xfb3: 0x3969, 0xfb4: 0x3981, 0xfb5: 0x3999, + 0xfb6: 0x39b1, 0xfb7: 0x39c9, 0xfb8: 0x39e1, 0xfb9: 0x39f9, 0xfba: 0x3a11, 0xfbb: 0x3a29, + 0xfbc: 0x3a41, 0xfbd: 0x3a59, 0xfbe: 0x3a71, 0xfbf: 0x3a89, + // Block 0x3f, offset 0xfc0 + 0xfc0: 0x3aa1, 0xfc1: 0x3ac9, 0xfc2: 0x3af1, 0xfc3: 0x3b19, 0xfc4: 0x3b41, 0xfc5: 0x3b69, + 0xfc6: 0x3b91, 0xfc7: 0x3bb9, 0xfc8: 0x3be1, 0xfc9: 0x3c09, 0xfca: 0x3c39, 0xfcb: 0x3c69, + 0xfcc: 0x3c99, 0xfcd: 0x3cd5, 0xfce: 0x3cb1, 0xfcf: 0x3cf5, 0xfd0: 0x3d15, 0xfd1: 0x3d2d, + 0xfd2: 0x3d45, 0xfd3: 0x3d5d, 0xfd4: 0x3d75, 0xfd5: 0x3d75, 0xfd6: 0x3d5d, 0xfd7: 0x3d8d, + 0xfd8: 0x07d5, 0xfd9: 0x3da5, 0xfda: 0x3dbd, 0xfdb: 0x3dd5, 0xfdc: 0x3ded, 0xfdd: 0x3e05, + 0xfde: 0x3e1d, 0xfdf: 0x3e35, 0xfe0: 0x3e4d, 0xfe1: 0x3e65, 0xfe2: 0x3e7d, 0xfe3: 0x3e95, + 0xfe4: 0x3ead, 0xfe5: 0x3ead, 0xfe6: 0x3ec5, 0xfe7: 0x3ec5, 0xfe8: 0x3edd, 0xfe9: 0x3edd, + 0xfea: 0x3ef5, 0xfeb: 0x3f0d, 0xfec: 0x3f25, 0xfed: 0x3f3d, 0xfee: 0x3f55, 0xfef: 0x3f55, + 0xff0: 0x3f6d, 0xff1: 0x3f6d, 0xff2: 0x3f6d, 0xff3: 0x3f85, 0xff4: 0x3f9d, 0xff5: 0x3fb5, + 0xff6: 0x3fcd, 0xff7: 0x3fb5, 0xff8: 0x3fe5, 0xff9: 0x3ffd, 0xffa: 0x3f85, 0xffb: 0x4015, + 0xffc: 0x402d, 0xffd: 0x402d, 0xffe: 0x402d, 0xfff: 0x0040, + // Block 0x40, offset 0x1000 + 0x1000: 0x3cc9, 0x1001: 0x3d31, 0x1002: 0x3d99, 0x1003: 0x3e01, 0x1004: 0x3e51, 0x1005: 0x3eb9, + 0x1006: 0x3f09, 0x1007: 0x3f59, 0x1008: 0x3fd9, 0x1009: 0x4041, 0x100a: 0x4091, 0x100b: 0x40e1, + 0x100c: 0x4131, 0x100d: 0x4199, 0x100e: 0x4201, 0x100f: 0x4251, 0x1010: 0x42a1, 0x1011: 0x42d9, + 0x1012: 0x4329, 0x1013: 0x4391, 0x1014: 0x43f9, 0x1015: 0x4431, 0x1016: 0x44b1, 0x1017: 0x4549, + 0x1018: 0x45c9, 0x1019: 0x4619, 0x101a: 0x4699, 0x101b: 0x4719, 0x101c: 0x4781, 0x101d: 0x47d1, + 0x101e: 0x4821, 0x101f: 0x4871, 0x1020: 0x48d9, 0x1021: 0x4959, 0x1022: 0x49c1, 0x1023: 0x4a11, + 0x1024: 0x4a61, 0x1025: 0x4ab1, 0x1026: 0x4ae9, 0x1027: 0x4b21, 0x1028: 0x4b59, 0x1029: 0x4b91, + 0x102a: 0x4be1, 0x102b: 0x4c31, 0x102c: 0x4cb1, 0x102d: 0x4d01, 0x102e: 0x4d69, 0x102f: 0x4de9, + 0x1030: 0x4e39, 0x1031: 0x4e71, 0x1032: 0x4ea9, 0x1033: 0x4f29, 0x1034: 0x4f91, 0x1035: 0x5011, + 0x1036: 0x5061, 0x1037: 0x50e1, 0x1038: 0x5119, 0x1039: 0x5169, 0x103a: 0x51b9, 0x103b: 0x5209, + 0x103c: 0x5259, 0x103d: 0x52a9, 0x103e: 0x5311, 0x103f: 0x5361, + // Block 0x41, offset 0x1040 + 0x1040: 0x5399, 0x1041: 0x53e9, 0x1042: 0x5439, 0x1043: 0x5489, 0x1044: 0x54f1, 0x1045: 0x5541, + 0x1046: 0x5591, 0x1047: 0x55e1, 0x1048: 0x5661, 0x1049: 0x56c9, 0x104a: 0x5701, 0x104b: 0x5781, + 0x104c: 0x57b9, 0x104d: 0x5821, 0x104e: 0x5889, 0x104f: 0x58d9, 0x1050: 0x5929, 0x1051: 0x5979, + 0x1052: 0x59e1, 0x1053: 0x5a19, 0x1054: 0x5a69, 0x1055: 0x5ad1, 0x1056: 0x5b09, 0x1057: 0x5b89, + 0x1058: 0x5bd9, 0x1059: 0x5c01, 0x105a: 0x5c29, 0x105b: 0x5c51, 0x105c: 0x5c79, 0x105d: 0x5ca1, + 0x105e: 0x5cc9, 0x105f: 0x5cf1, 0x1060: 0x5d19, 0x1061: 0x5d41, 0x1062: 0x5d69, 0x1063: 0x5d99, + 0x1064: 0x5dc9, 0x1065: 0x5df9, 0x1066: 0x5e29, 0x1067: 0x5e59, 0x1068: 0x5e89, 0x1069: 0x5eb9, + 0x106a: 0x5ee9, 0x106b: 0x5f19, 0x106c: 0x5f49, 0x106d: 0x5f79, 0x106e: 0x5fa9, 0x106f: 0x5fd9, + 0x1070: 0x6009, 0x1071: 0x4045, 0x1072: 0x6039, 0x1073: 0x6051, 0x1074: 0x4065, 0x1075: 0x6069, + 0x1076: 0x6081, 0x1077: 0x6099, 0x1078: 0x4085, 0x1079: 0x4085, 0x107a: 0x60b1, 0x107b: 0x60c9, + 0x107c: 0x6101, 0x107d: 0x6139, 0x107e: 0x6171, 0x107f: 0x61a9, + // Block 0x42, offset 0x1080 + 0x1080: 0x6211, 0x1081: 0x6229, 0x1082: 0x40a5, 0x1083: 0x6241, 0x1084: 0x6259, 0x1085: 0x6271, + 0x1086: 0x6289, 0x1087: 0x62a1, 0x1088: 0x40c5, 0x1089: 0x62b9, 0x108a: 0x62e1, 0x108b: 0x62f9, + 0x108c: 0x40e5, 0x108d: 0x40e5, 0x108e: 0x6311, 0x108f: 0x6329, 0x1090: 0x6341, 0x1091: 0x4105, + 0x1092: 0x4125, 0x1093: 0x4145, 0x1094: 0x4165, 0x1095: 0x4185, 0x1096: 0x6359, 0x1097: 0x6371, + 0x1098: 0x6389, 0x1099: 0x63a1, 0x109a: 0x63b9, 0x109b: 0x41a5, 0x109c: 0x63d1, 0x109d: 0x63e9, + 0x109e: 0x6401, 0x109f: 0x41c5, 0x10a0: 0x41e5, 0x10a1: 0x6419, 0x10a2: 0x4205, 0x10a3: 0x4225, + 0x10a4: 0x4245, 0x10a5: 0x6431, 0x10a6: 0x4265, 0x10a7: 0x6449, 0x10a8: 0x6479, 0x10a9: 0x6211, + 0x10aa: 0x4285, 0x10ab: 0x42a5, 0x10ac: 0x42c5, 0x10ad: 0x42e5, 0x10ae: 0x64b1, 0x10af: 0x64f1, + 0x10b0: 0x6539, 0x10b1: 0x6551, 0x10b2: 0x4305, 0x10b3: 0x6569, 0x10b4: 0x6581, 0x10b5: 0x6599, + 0x10b6: 0x4325, 0x10b7: 0x65b1, 0x10b8: 0x65c9, 0x10b9: 0x65b1, 0x10ba: 0x65e1, 0x10bb: 0x65f9, + 0x10bc: 0x4345, 0x10bd: 0x6611, 0x10be: 0x6629, 0x10bf: 0x6611, + // Block 0x43, offset 0x10c0 + 0x10c0: 0x4365, 0x10c1: 0x4385, 0x10c2: 0x0040, 0x10c3: 0x6641, 0x10c4: 0x6659, 0x10c5: 0x6671, + 0x10c6: 0x6689, 0x10c7: 0x0040, 0x10c8: 0x66c1, 0x10c9: 0x66d9, 0x10ca: 0x66f1, 0x10cb: 0x6709, + 0x10cc: 0x6721, 0x10cd: 0x6739, 0x10ce: 0x6401, 0x10cf: 0x6751, 0x10d0: 0x6769, 0x10d1: 0x6781, + 0x10d2: 0x43a5, 0x10d3: 0x6799, 0x10d4: 0x6289, 0x10d5: 0x43c5, 0x10d6: 0x43e5, 0x10d7: 0x67b1, + 0x10d8: 0x0040, 0x10d9: 0x4405, 0x10da: 0x67c9, 0x10db: 0x67e1, 0x10dc: 0x67f9, 0x10dd: 0x6811, + 0x10de: 0x6829, 0x10df: 0x6859, 0x10e0: 0x6889, 0x10e1: 0x68b1, 0x10e2: 0x68d9, 0x10e3: 0x6901, + 0x10e4: 0x6929, 0x10e5: 0x6951, 0x10e6: 0x6979, 0x10e7: 0x69a1, 0x10e8: 0x69c9, 0x10e9: 0x69f1, + 0x10ea: 0x6a21, 0x10eb: 0x6a51, 0x10ec: 0x6a81, 0x10ed: 0x6ab1, 0x10ee: 0x6ae1, 0x10ef: 0x6b11, + 0x10f0: 0x6b41, 0x10f1: 0x6b71, 0x10f2: 0x6ba1, 0x10f3: 0x6bd1, 0x10f4: 0x6c01, 0x10f5: 0x6c31, + 0x10f6: 0x6c61, 0x10f7: 0x6c91, 0x10f8: 0x6cc1, 0x10f9: 0x6cf1, 0x10fa: 0x6d21, 0x10fb: 0x6d51, + 0x10fc: 0x6d81, 0x10fd: 0x6db1, 0x10fe: 0x6de1, 0x10ff: 0x4425, + // Block 0x44, offset 0x1100 + 0x1100: 0xe00d, 0x1101: 0x0008, 0x1102: 0xe00d, 0x1103: 0x0008, 0x1104: 0xe00d, 0x1105: 0x0008, + 0x1106: 0xe00d, 0x1107: 0x0008, 0x1108: 0xe00d, 0x1109: 0x0008, 0x110a: 0xe00d, 0x110b: 0x0008, + 0x110c: 0xe00d, 0x110d: 0x0008, 0x110e: 0xe00d, 0x110f: 0x0008, 0x1110: 0xe00d, 0x1111: 0x0008, + 0x1112: 0xe00d, 0x1113: 0x0008, 0x1114: 0xe00d, 0x1115: 0x0008, 0x1116: 0xe00d, 0x1117: 0x0008, + 0x1118: 0xe00d, 0x1119: 0x0008, 0x111a: 0xe00d, 0x111b: 0x0008, 0x111c: 0xe00d, 0x111d: 0x0008, + 0x111e: 0xe00d, 0x111f: 0x0008, 0x1120: 0xe00d, 0x1121: 0x0008, 0x1122: 0xe00d, 0x1123: 0x0008, + 0x1124: 0xe00d, 0x1125: 0x0008, 0x1126: 0xe00d, 0x1127: 0x0008, 0x1128: 0xe00d, 0x1129: 0x0008, + 0x112a: 0xe00d, 0x112b: 0x0008, 0x112c: 0xe00d, 0x112d: 0x0008, 0x112e: 0x0008, 0x112f: 0x3308, + 0x1130: 0x3318, 0x1131: 0x3318, 0x1132: 0x3318, 0x1133: 0x0018, 0x1134: 0x3308, 0x1135: 0x3308, + 0x1136: 0x3308, 0x1137: 0x3308, 0x1138: 0x3308, 0x1139: 0x3308, 0x113a: 0x3308, 0x113b: 0x3308, + 0x113c: 0x3308, 0x113d: 0x3308, 0x113e: 0x0018, 0x113f: 0x0008, + // Block 0x45, offset 0x1140 + 0x1140: 0xe00d, 0x1141: 0x0008, 0x1142: 0xe00d, 0x1143: 0x0008, 0x1144: 0xe00d, 0x1145: 0x0008, + 0x1146: 0xe00d, 0x1147: 0x0008, 0x1148: 0xe00d, 0x1149: 0x0008, 0x114a: 0xe00d, 0x114b: 0x0008, + 0x114c: 0xe00d, 0x114d: 0x0008, 0x114e: 0xe00d, 0x114f: 0x0008, 0x1150: 0xe00d, 0x1151: 0x0008, + 0x1152: 0xe00d, 0x1153: 0x0008, 0x1154: 0xe00d, 0x1155: 0x0008, 0x1156: 0xe00d, 0x1157: 0x0008, + 0x1158: 0xe00d, 0x1159: 0x0008, 0x115a: 0xe00d, 0x115b: 0x0008, 0x115c: 0x0ea1, 0x115d: 0x6e11, + 0x115e: 0x3308, 0x115f: 0x3308, 0x1160: 0x0008, 0x1161: 0x0008, 0x1162: 0x0008, 0x1163: 0x0008, + 0x1164: 0x0008, 0x1165: 0x0008, 0x1166: 0x0008, 0x1167: 0x0008, 0x1168: 0x0008, 0x1169: 0x0008, + 0x116a: 0x0008, 0x116b: 0x0008, 0x116c: 0x0008, 0x116d: 0x0008, 0x116e: 0x0008, 0x116f: 0x0008, + 0x1170: 0x0008, 0x1171: 0x0008, 0x1172: 0x0008, 0x1173: 0x0008, 0x1174: 0x0008, 0x1175: 0x0008, + 0x1176: 0x0008, 0x1177: 0x0008, 0x1178: 0x0008, 0x1179: 0x0008, 0x117a: 0x0008, 0x117b: 0x0008, + 0x117c: 0x0008, 0x117d: 0x0008, 0x117e: 0x0008, 0x117f: 0x0008, + // Block 0x46, offset 0x1180 + 0x1180: 0x0018, 0x1181: 0x0018, 0x1182: 0x0018, 0x1183: 0x0018, 0x1184: 0x0018, 0x1185: 0x0018, + 0x1186: 0x0018, 0x1187: 0x0018, 0x1188: 0x0018, 0x1189: 0x0018, 0x118a: 0x0018, 0x118b: 0x0018, + 0x118c: 0x0018, 0x118d: 0x0018, 0x118e: 0x0018, 0x118f: 0x0018, 0x1190: 0x0018, 0x1191: 0x0018, + 0x1192: 0x0018, 0x1193: 0x0018, 0x1194: 0x0018, 0x1195: 0x0018, 0x1196: 0x0018, 0x1197: 0x0008, + 0x1198: 0x0008, 0x1199: 0x0008, 0x119a: 0x0008, 0x119b: 0x0008, 0x119c: 0x0008, 0x119d: 0x0008, + 0x119e: 0x0008, 0x119f: 0x0008, 0x11a0: 0x0018, 0x11a1: 0x0018, 0x11a2: 0xe00d, 0x11a3: 0x0008, + 0x11a4: 0xe00d, 0x11a5: 0x0008, 0x11a6: 0xe00d, 0x11a7: 0x0008, 0x11a8: 0xe00d, 0x11a9: 0x0008, + 0x11aa: 0xe00d, 0x11ab: 0x0008, 0x11ac: 0xe00d, 0x11ad: 0x0008, 0x11ae: 0xe00d, 0x11af: 0x0008, + 0x11b0: 0x0008, 0x11b1: 0x0008, 0x11b2: 0xe00d, 0x11b3: 0x0008, 0x11b4: 0xe00d, 0x11b5: 0x0008, + 0x11b6: 0xe00d, 0x11b7: 0x0008, 0x11b8: 0xe00d, 0x11b9: 0x0008, 0x11ba: 0xe00d, 0x11bb: 0x0008, + 0x11bc: 0xe00d, 0x11bd: 0x0008, 0x11be: 0xe00d, 0x11bf: 0x0008, + // Block 0x47, offset 0x11c0 + 0x11c0: 0xe00d, 0x11c1: 0x0008, 0x11c2: 0xe00d, 0x11c3: 0x0008, 0x11c4: 0xe00d, 0x11c5: 0x0008, + 0x11c6: 0xe00d, 0x11c7: 0x0008, 0x11c8: 0xe00d, 0x11c9: 0x0008, 0x11ca: 0xe00d, 0x11cb: 0x0008, + 0x11cc: 0xe00d, 0x11cd: 0x0008, 0x11ce: 0xe00d, 0x11cf: 0x0008, 0x11d0: 0xe00d, 0x11d1: 0x0008, + 0x11d2: 0xe00d, 0x11d3: 0x0008, 0x11d4: 0xe00d, 0x11d5: 0x0008, 0x11d6: 0xe00d, 0x11d7: 0x0008, + 0x11d8: 0xe00d, 0x11d9: 0x0008, 0x11da: 0xe00d, 0x11db: 0x0008, 0x11dc: 0xe00d, 0x11dd: 0x0008, + 0x11de: 0xe00d, 0x11df: 0x0008, 0x11e0: 0xe00d, 0x11e1: 0x0008, 0x11e2: 0xe00d, 0x11e3: 0x0008, + 0x11e4: 0xe00d, 0x11e5: 0x0008, 0x11e6: 0xe00d, 0x11e7: 0x0008, 0x11e8: 0xe00d, 0x11e9: 0x0008, + 0x11ea: 0xe00d, 0x11eb: 0x0008, 0x11ec: 0xe00d, 0x11ed: 0x0008, 0x11ee: 0xe00d, 0x11ef: 0x0008, + 0x11f0: 0xe0fd, 0x11f1: 0x0008, 0x11f2: 0x0008, 0x11f3: 0x0008, 0x11f4: 0x0008, 0x11f5: 0x0008, + 0x11f6: 0x0008, 0x11f7: 0x0008, 0x11f8: 0x0008, 0x11f9: 0xe01d, 0x11fa: 0x0008, 0x11fb: 0xe03d, + 0x11fc: 0x0008, 0x11fd: 0x4445, 0x11fe: 0xe00d, 0x11ff: 0x0008, + // Block 0x48, offset 0x1200 + 0x1200: 0xe00d, 0x1201: 0x0008, 0x1202: 0xe00d, 0x1203: 0x0008, 0x1204: 0xe00d, 0x1205: 0x0008, + 0x1206: 0xe00d, 0x1207: 0x0008, 0x1208: 0x0008, 0x1209: 0x0018, 0x120a: 0x0018, 0x120b: 0xe03d, + 0x120c: 0x0008, 0x120d: 0x11d9, 0x120e: 0x0008, 0x120f: 0x0008, 0x1210: 0xe00d, 0x1211: 0x0008, + 0x1212: 0xe00d, 0x1213: 0x0008, 0x1214: 0x0008, 0x1215: 0x0008, 0x1216: 0xe00d, 0x1217: 0x0008, + 0x1218: 0xe00d, 0x1219: 0x0008, 0x121a: 0xe00d, 0x121b: 0x0008, 0x121c: 0xe00d, 0x121d: 0x0008, + 0x121e: 0xe00d, 0x121f: 0x0008, 0x1220: 0xe00d, 0x1221: 0x0008, 0x1222: 0xe00d, 0x1223: 0x0008, + 0x1224: 0xe00d, 0x1225: 0x0008, 0x1226: 0xe00d, 0x1227: 0x0008, 0x1228: 0xe00d, 0x1229: 0x0008, + 0x122a: 0x6e29, 0x122b: 0x1029, 0x122c: 0x11c1, 0x122d: 0x6e41, 0x122e: 0x1221, 0x122f: 0x0008, + 0x1230: 0x6e59, 0x1231: 0x6e71, 0x1232: 0x1239, 0x1233: 0x4465, 0x1234: 0xe00d, 0x1235: 0x0008, + 0x1236: 0xe00d, 0x1237: 0x0008, 0x1238: 0xe00d, 0x1239: 0x0008, 0x123a: 0xe00d, 0x123b: 0x0008, + 0x123c: 0xe00d, 0x123d: 0x0008, 0x123e: 0xe00d, 0x123f: 0x0008, + // Block 0x49, offset 0x1240 + 0x1240: 0x650d, 0x1241: 0x652d, 0x1242: 0x654d, 0x1243: 0x656d, 0x1244: 0x658d, 0x1245: 0x65ad, + 0x1246: 0x65cd, 0x1247: 0x65ed, 0x1248: 0x660d, 0x1249: 0x662d, 0x124a: 0x664d, 0x124b: 0x666d, + 0x124c: 0x668d, 0x124d: 0x66ad, 0x124e: 0x0008, 0x124f: 0x0008, 0x1250: 0x66cd, 0x1251: 0x0008, + 0x1252: 0x66ed, 0x1253: 0x0008, 0x1254: 0x0008, 0x1255: 0x670d, 0x1256: 0x672d, 0x1257: 0x674d, + 0x1258: 0x676d, 0x1259: 0x678d, 0x125a: 0x67ad, 0x125b: 0x67cd, 0x125c: 0x67ed, 0x125d: 0x680d, + 0x125e: 0x682d, 0x125f: 0x0008, 0x1260: 0x684d, 0x1261: 0x0008, 0x1262: 0x686d, 0x1263: 0x0008, + 0x1264: 0x0008, 0x1265: 0x688d, 0x1266: 0x68ad, 0x1267: 0x0008, 0x1268: 0x0008, 0x1269: 0x0008, + 0x126a: 0x68cd, 0x126b: 0x68ed, 0x126c: 0x690d, 0x126d: 0x692d, 0x126e: 0x694d, 0x126f: 0x696d, + 0x1270: 0x698d, 0x1271: 0x69ad, 0x1272: 0x69cd, 0x1273: 0x69ed, 0x1274: 0x6a0d, 0x1275: 0x6a2d, + 0x1276: 0x6a4d, 0x1277: 0x6a6d, 0x1278: 0x6a8d, 0x1279: 0x6aad, 0x127a: 0x6acd, 0x127b: 0x6aed, + 0x127c: 0x6b0d, 0x127d: 0x6b2d, 0x127e: 0x6b4d, 0x127f: 0x6b6d, + // Block 0x4a, offset 0x1280 + 0x1280: 0x7acd, 0x1281: 0x7aed, 0x1282: 0x7b0d, 0x1283: 0x7b2d, 0x1284: 0x7b4d, 0x1285: 0x7b6d, + 0x1286: 0x7b8d, 0x1287: 0x7bad, 0x1288: 0x7bcd, 0x1289: 0x7bed, 0x128a: 0x7c0d, 0x128b: 0x7c2d, + 0x128c: 0x7c4d, 0x128d: 0x7c6d, 0x128e: 0x7c8d, 0x128f: 0x6ec9, 0x1290: 0x6ef1, 0x1291: 0x6f19, + 0x1292: 0x7cad, 0x1293: 0x7ccd, 0x1294: 0x7ced, 0x1295: 0x6f41, 0x1296: 0x6f69, 0x1297: 0x6f91, + 0x1298: 0x7d0d, 0x1299: 0x7d2d, 0x129a: 0x0040, 0x129b: 0x0040, 0x129c: 0x0040, 0x129d: 0x0040, + 0x129e: 0x0040, 0x129f: 0x0040, 0x12a0: 0x0040, 0x12a1: 0x0040, 0x12a2: 0x0040, 0x12a3: 0x0040, + 0x12a4: 0x0040, 0x12a5: 0x0040, 0x12a6: 0x0040, 0x12a7: 0x0040, 0x12a8: 0x0040, 0x12a9: 0x0040, + 0x12aa: 0x0040, 0x12ab: 0x0040, 0x12ac: 0x0040, 0x12ad: 0x0040, 0x12ae: 0x0040, 0x12af: 0x0040, + 0x12b0: 0x0040, 0x12b1: 0x0040, 0x12b2: 0x0040, 0x12b3: 0x0040, 0x12b4: 0x0040, 0x12b5: 0x0040, + 0x12b6: 0x0040, 0x12b7: 0x0040, 0x12b8: 0x0040, 0x12b9: 0x0040, 0x12ba: 0x0040, 0x12bb: 0x0040, + 0x12bc: 0x0040, 0x12bd: 0x0040, 0x12be: 0x0040, 0x12bf: 0x0040, + // Block 0x4b, offset 0x12c0 + 0x12c0: 0x6fb9, 0x12c1: 0x6fd1, 0x12c2: 0x6fe9, 0x12c3: 0x7d4d, 0x12c4: 0x7d6d, 0x12c5: 0x7001, + 0x12c6: 0x7001, 0x12c7: 0x0040, 0x12c8: 0x0040, 0x12c9: 0x0040, 0x12ca: 0x0040, 0x12cb: 0x0040, + 0x12cc: 0x0040, 0x12cd: 0x0040, 0x12ce: 0x0040, 0x12cf: 0x0040, 0x12d0: 0x0040, 0x12d1: 0x0040, + 0x12d2: 0x0040, 0x12d3: 0x7019, 0x12d4: 0x7041, 0x12d5: 0x7069, 0x12d6: 0x7091, 0x12d7: 0x70b9, + 0x12d8: 0x0040, 0x12d9: 0x0040, 0x12da: 0x0040, 0x12db: 0x0040, 0x12dc: 0x0040, 0x12dd: 0x70e1, + 0x12de: 0x3308, 0x12df: 0x7109, 0x12e0: 0x7131, 0x12e1: 0x20a9, 0x12e2: 0x20f1, 0x12e3: 0x7149, + 0x12e4: 0x7161, 0x12e5: 0x7179, 0x12e6: 0x7191, 0x12e7: 0x71a9, 0x12e8: 0x71c1, 0x12e9: 0x1fb2, + 0x12ea: 0x71d9, 0x12eb: 0x7201, 0x12ec: 0x7229, 0x12ed: 0x7261, 0x12ee: 0x7299, 0x12ef: 0x72c1, + 0x12f0: 0x72e9, 0x12f1: 0x7311, 0x12f2: 0x7339, 0x12f3: 0x7361, 0x12f4: 0x7389, 0x12f5: 0x73b1, + 0x12f6: 0x73d9, 0x12f7: 0x0040, 0x12f8: 0x7401, 0x12f9: 0x7429, 0x12fa: 0x7451, 0x12fb: 0x7479, + 0x12fc: 0x74a1, 0x12fd: 0x0040, 0x12fe: 0x74c9, 0x12ff: 0x0040, + // Block 0x4c, offset 0x1300 + 0x1300: 0x74f1, 0x1301: 0x7519, 0x1302: 0x0040, 0x1303: 0x7541, 0x1304: 0x7569, 0x1305: 0x0040, + 0x1306: 0x7591, 0x1307: 0x75b9, 0x1308: 0x75e1, 0x1309: 0x7609, 0x130a: 0x7631, 0x130b: 0x7659, + 0x130c: 0x7681, 0x130d: 0x76a9, 0x130e: 0x76d1, 0x130f: 0x76f9, 0x1310: 0x7721, 0x1311: 0x7721, + 0x1312: 0x7739, 0x1313: 0x7739, 0x1314: 0x7739, 0x1315: 0x7739, 0x1316: 0x7751, 0x1317: 0x7751, + 0x1318: 0x7751, 0x1319: 0x7751, 0x131a: 0x7769, 0x131b: 0x7769, 0x131c: 0x7769, 0x131d: 0x7769, + 0x131e: 0x7781, 0x131f: 0x7781, 0x1320: 0x7781, 0x1321: 0x7781, 0x1322: 0x7799, 0x1323: 0x7799, + 0x1324: 0x7799, 0x1325: 0x7799, 0x1326: 0x77b1, 0x1327: 0x77b1, 0x1328: 0x77b1, 0x1329: 0x77b1, + 0x132a: 0x77c9, 0x132b: 0x77c9, 0x132c: 0x77c9, 0x132d: 0x77c9, 0x132e: 0x77e1, 0x132f: 0x77e1, + 0x1330: 0x77e1, 0x1331: 0x77e1, 0x1332: 0x77f9, 0x1333: 0x77f9, 0x1334: 0x77f9, 0x1335: 0x77f9, + 0x1336: 0x7811, 0x1337: 0x7811, 0x1338: 0x7811, 0x1339: 0x7811, 0x133a: 0x7829, 0x133b: 0x7829, + 0x133c: 0x7829, 0x133d: 0x7829, 0x133e: 0x7841, 0x133f: 0x7841, + // Block 0x4d, offset 0x1340 + 0x1340: 0x7841, 0x1341: 0x7841, 0x1342: 0x7859, 0x1343: 0x7859, 0x1344: 0x7871, 0x1345: 0x7871, + 0x1346: 0x7889, 0x1347: 0x7889, 0x1348: 0x78a1, 0x1349: 0x78a1, 0x134a: 0x78b9, 0x134b: 0x78b9, + 0x134c: 0x78d1, 0x134d: 0x78d1, 0x134e: 0x78e9, 0x134f: 0x78e9, 0x1350: 0x78e9, 0x1351: 0x78e9, + 0x1352: 0x7901, 0x1353: 0x7901, 0x1354: 0x7901, 0x1355: 0x7901, 0x1356: 0x7919, 0x1357: 0x7919, + 0x1358: 0x7919, 0x1359: 0x7919, 0x135a: 0x7931, 0x135b: 0x7931, 0x135c: 0x7931, 0x135d: 0x7931, + 0x135e: 0x7949, 0x135f: 0x7949, 0x1360: 0x7961, 0x1361: 0x7961, 0x1362: 0x7961, 0x1363: 0x7961, + 0x1364: 0x7979, 0x1365: 0x7979, 0x1366: 0x7991, 0x1367: 0x7991, 0x1368: 0x7991, 0x1369: 0x7991, + 0x136a: 0x79a9, 0x136b: 0x79a9, 0x136c: 0x79a9, 0x136d: 0x79a9, 0x136e: 0x79c1, 0x136f: 0x79c1, + 0x1370: 0x79d9, 0x1371: 0x79d9, 0x1372: 0x0818, 0x1373: 0x0818, 0x1374: 0x0818, 0x1375: 0x0818, + 0x1376: 0x0818, 0x1377: 0x0818, 0x1378: 0x0818, 0x1379: 0x0818, 0x137a: 0x0818, 0x137b: 0x0818, + 0x137c: 0x0818, 0x137d: 0x0818, 0x137e: 0x0818, 0x137f: 0x0818, + // Block 0x4e, offset 0x1380 + 0x1380: 0x0818, 0x1381: 0x0818, 0x1382: 0x0040, 0x1383: 0x0040, 0x1384: 0x0040, 0x1385: 0x0040, + 0x1386: 0x0040, 0x1387: 0x0040, 0x1388: 0x0040, 0x1389: 0x0040, 0x138a: 0x0040, 0x138b: 0x0040, + 0x138c: 0x0040, 0x138d: 0x0040, 0x138e: 0x0040, 0x138f: 0x0040, 0x1390: 0x0040, 0x1391: 0x0040, + 0x1392: 0x0040, 0x1393: 0x79f1, 0x1394: 0x79f1, 0x1395: 0x79f1, 0x1396: 0x79f1, 0x1397: 0x7a09, + 0x1398: 0x7a09, 0x1399: 0x7a21, 0x139a: 0x7a21, 0x139b: 0x7a39, 0x139c: 0x7a39, 0x139d: 0x0479, + 0x139e: 0x7a51, 0x139f: 0x7a51, 0x13a0: 0x7a69, 0x13a1: 0x7a69, 0x13a2: 0x7a81, 0x13a3: 0x7a81, + 0x13a4: 0x7a99, 0x13a5: 0x7a99, 0x13a6: 0x7a99, 0x13a7: 0x7a99, 0x13a8: 0x7ab1, 0x13a9: 0x7ab1, + 0x13aa: 0x7ac9, 0x13ab: 0x7ac9, 0x13ac: 0x7af1, 0x13ad: 0x7af1, 0x13ae: 0x7b19, 0x13af: 0x7b19, + 0x13b0: 0x7b41, 0x13b1: 0x7b41, 0x13b2: 0x7b69, 0x13b3: 0x7b69, 0x13b4: 0x7b91, 0x13b5: 0x7b91, + 0x13b6: 0x7bb9, 0x13b7: 0x7bb9, 0x13b8: 0x7bb9, 0x13b9: 0x7be1, 0x13ba: 0x7be1, 0x13bb: 0x7be1, + 0x13bc: 0x7c09, 0x13bd: 0x7c09, 0x13be: 0x7c09, 0x13bf: 0x7c09, + // Block 0x4f, offset 0x13c0 + 0x13c0: 0x85f9, 0x13c1: 0x8621, 0x13c2: 0x8649, 0x13c3: 0x8671, 0x13c4: 0x8699, 0x13c5: 0x86c1, + 0x13c6: 0x86e9, 0x13c7: 0x8711, 0x13c8: 0x8739, 0x13c9: 0x8761, 0x13ca: 0x8789, 0x13cb: 0x87b1, + 0x13cc: 0x87d9, 0x13cd: 0x8801, 0x13ce: 0x8829, 0x13cf: 0x8851, 0x13d0: 0x8879, 0x13d1: 0x88a1, + 0x13d2: 0x88c9, 0x13d3: 0x88f1, 0x13d4: 0x8919, 0x13d5: 0x8941, 0x13d6: 0x8969, 0x13d7: 0x8991, + 0x13d8: 0x89b9, 0x13d9: 0x89e1, 0x13da: 0x8a09, 0x13db: 0x8a31, 0x13dc: 0x8a59, 0x13dd: 0x8a81, + 0x13de: 0x8aaa, 0x13df: 0x8ada, 0x13e0: 0x8b0a, 0x13e1: 0x8b3a, 0x13e2: 0x8b6a, 0x13e3: 0x8b9a, + 0x13e4: 0x8bc9, 0x13e5: 0x8bf1, 0x13e6: 0x7c71, 0x13e7: 0x8c19, 0x13e8: 0x7be1, 0x13e9: 0x7c99, + 0x13ea: 0x8c41, 0x13eb: 0x8c69, 0x13ec: 0x7d39, 0x13ed: 0x8c91, 0x13ee: 0x7d61, 0x13ef: 0x7d89, + 0x13f0: 0x8cb9, 0x13f1: 0x8ce1, 0x13f2: 0x7e29, 0x13f3: 0x8d09, 0x13f4: 0x7e51, 0x13f5: 0x7e79, + 0x13f6: 0x8d31, 0x13f7: 0x8d59, 0x13f8: 0x7ec9, 0x13f9: 0x8d81, 0x13fa: 0x7ef1, 0x13fb: 0x7f19, + 0x13fc: 0x83a1, 0x13fd: 0x83c9, 0x13fe: 0x8441, 0x13ff: 0x8469, + // Block 0x50, offset 0x1400 + 0x1400: 0x8491, 0x1401: 0x8531, 0x1402: 0x8559, 0x1403: 0x8581, 0x1404: 0x85a9, 0x1405: 0x8649, + 0x1406: 0x8671, 0x1407: 0x8699, 0x1408: 0x8da9, 0x1409: 0x8739, 0x140a: 0x8dd1, 0x140b: 0x8df9, + 0x140c: 0x8829, 0x140d: 0x8e21, 0x140e: 0x8851, 0x140f: 0x8879, 0x1410: 0x8a81, 0x1411: 0x8e49, + 0x1412: 0x8e71, 0x1413: 0x89b9, 0x1414: 0x8e99, 0x1415: 0x89e1, 0x1416: 0x8a09, 0x1417: 0x7c21, + 0x1418: 0x7c49, 0x1419: 0x8ec1, 0x141a: 0x7c71, 0x141b: 0x8ee9, 0x141c: 0x7cc1, 0x141d: 0x7ce9, + 0x141e: 0x7d11, 0x141f: 0x7d39, 0x1420: 0x8f11, 0x1421: 0x7db1, 0x1422: 0x7dd9, 0x1423: 0x7e01, + 0x1424: 0x7e29, 0x1425: 0x8f39, 0x1426: 0x7ec9, 0x1427: 0x7f41, 0x1428: 0x7f69, 0x1429: 0x7f91, + 0x142a: 0x7fb9, 0x142b: 0x7fe1, 0x142c: 0x8031, 0x142d: 0x8059, 0x142e: 0x8081, 0x142f: 0x80a9, + 0x1430: 0x80d1, 0x1431: 0x80f9, 0x1432: 0x8f61, 0x1433: 0x8121, 0x1434: 0x8149, 0x1435: 0x8171, + 0x1436: 0x8199, 0x1437: 0x81c1, 0x1438: 0x81e9, 0x1439: 0x8239, 0x143a: 0x8261, 0x143b: 0x8289, + 0x143c: 0x82b1, 0x143d: 0x82d9, 0x143e: 0x8301, 0x143f: 0x8329, + // Block 0x51, offset 0x1440 + 0x1440: 0x8351, 0x1441: 0x8379, 0x1442: 0x83f1, 0x1443: 0x8419, 0x1444: 0x84b9, 0x1445: 0x84e1, + 0x1446: 0x8509, 0x1447: 0x8531, 0x1448: 0x8559, 0x1449: 0x85d1, 0x144a: 0x85f9, 0x144b: 0x8621, + 0x144c: 0x8649, 0x144d: 0x8f89, 0x144e: 0x86c1, 0x144f: 0x86e9, 0x1450: 0x8711, 0x1451: 0x8739, + 0x1452: 0x87b1, 0x1453: 0x87d9, 0x1454: 0x8801, 0x1455: 0x8829, 0x1456: 0x8fb1, 0x1457: 0x88a1, + 0x1458: 0x88c9, 0x1459: 0x8fd9, 0x145a: 0x8941, 0x145b: 0x8969, 0x145c: 0x8991, 0x145d: 0x89b9, + 0x145e: 0x9001, 0x145f: 0x7c71, 0x1460: 0x8ee9, 0x1461: 0x7d39, 0x1462: 0x8f11, 0x1463: 0x7e29, + 0x1464: 0x8f39, 0x1465: 0x7ec9, 0x1466: 0x9029, 0x1467: 0x80d1, 0x1468: 0x9051, 0x1469: 0x9079, + 0x146a: 0x90a1, 0x146b: 0x8531, 0x146c: 0x8559, 0x146d: 0x8649, 0x146e: 0x8829, 0x146f: 0x8fb1, + 0x1470: 0x89b9, 0x1471: 0x9001, 0x1472: 0x90c9, 0x1473: 0x9101, 0x1474: 0x9139, 0x1475: 0x9171, + 0x1476: 0x9199, 0x1477: 0x91c1, 0x1478: 0x91e9, 0x1479: 0x9211, 0x147a: 0x9239, 0x147b: 0x9261, + 0x147c: 0x9289, 0x147d: 0x92b1, 0x147e: 0x92d9, 0x147f: 0x9301, + // Block 0x52, offset 0x1480 + 0x1480: 0x9329, 0x1481: 0x9351, 0x1482: 0x9379, 0x1483: 0x93a1, 0x1484: 0x93c9, 0x1485: 0x93f1, + 0x1486: 0x9419, 0x1487: 0x9441, 0x1488: 0x9469, 0x1489: 0x9491, 0x148a: 0x94b9, 0x148b: 0x94e1, + 0x148c: 0x9079, 0x148d: 0x9509, 0x148e: 0x9531, 0x148f: 0x9559, 0x1490: 0x9581, 0x1491: 0x9171, + 0x1492: 0x9199, 0x1493: 0x91c1, 0x1494: 0x91e9, 0x1495: 0x9211, 0x1496: 0x9239, 0x1497: 0x9261, + 0x1498: 0x9289, 0x1499: 0x92b1, 0x149a: 0x92d9, 0x149b: 0x9301, 0x149c: 0x9329, 0x149d: 0x9351, + 0x149e: 0x9379, 0x149f: 0x93a1, 0x14a0: 0x93c9, 0x14a1: 0x93f1, 0x14a2: 0x9419, 0x14a3: 0x9441, + 0x14a4: 0x9469, 0x14a5: 0x9491, 0x14a6: 0x94b9, 0x14a7: 0x94e1, 0x14a8: 0x9079, 0x14a9: 0x9509, + 0x14aa: 0x9531, 0x14ab: 0x9559, 0x14ac: 0x9581, 0x14ad: 0x9491, 0x14ae: 0x94b9, 0x14af: 0x94e1, + 0x14b0: 0x9079, 0x14b1: 0x9051, 0x14b2: 0x90a1, 0x14b3: 0x8211, 0x14b4: 0x8059, 0x14b5: 0x8081, + 0x14b6: 0x80a9, 0x14b7: 0x9491, 0x14b8: 0x94b9, 0x14b9: 0x94e1, 0x14ba: 0x8211, 0x14bb: 0x8239, + 0x14bc: 0x95a9, 0x14bd: 0x95a9, 0x14be: 0x0018, 0x14bf: 0x0018, + // Block 0x53, offset 0x14c0 + 0x14c0: 0x0040, 0x14c1: 0x0040, 0x14c2: 0x0040, 0x14c3: 0x0040, 0x14c4: 0x0040, 0x14c5: 0x0040, + 0x14c6: 0x0040, 0x14c7: 0x0040, 0x14c8: 0x0040, 0x14c9: 0x0040, 0x14ca: 0x0040, 0x14cb: 0x0040, + 0x14cc: 0x0040, 0x14cd: 0x0040, 0x14ce: 0x0040, 0x14cf: 0x0040, 0x14d0: 0x95d1, 0x14d1: 0x9609, + 0x14d2: 0x9609, 0x14d3: 0x9641, 0x14d4: 0x9679, 0x14d5: 0x96b1, 0x14d6: 0x96e9, 0x14d7: 0x9721, + 0x14d8: 0x9759, 0x14d9: 0x9759, 0x14da: 0x9791, 0x14db: 0x97c9, 0x14dc: 0x9801, 0x14dd: 0x9839, + 0x14de: 0x9871, 0x14df: 0x98a9, 0x14e0: 0x98a9, 0x14e1: 0x98e1, 0x14e2: 0x9919, 0x14e3: 0x9919, + 0x14e4: 0x9951, 0x14e5: 0x9951, 0x14e6: 0x9989, 0x14e7: 0x99c1, 0x14e8: 0x99c1, 0x14e9: 0x99f9, + 0x14ea: 0x9a31, 0x14eb: 0x9a31, 0x14ec: 0x9a69, 0x14ed: 0x9a69, 0x14ee: 0x9aa1, 0x14ef: 0x9ad9, + 0x14f0: 0x9ad9, 0x14f1: 0x9b11, 0x14f2: 0x9b11, 0x14f3: 0x9b49, 0x14f4: 0x9b81, 0x14f5: 0x9bb9, + 0x14f6: 0x9bf1, 0x14f7: 0x9bf1, 0x14f8: 0x9c29, 0x14f9: 0x9c61, 0x14fa: 0x9c99, 0x14fb: 0x9cd1, + 0x14fc: 0x9d09, 0x14fd: 0x9d09, 0x14fe: 0x9d41, 0x14ff: 0x9d79, + // Block 0x54, offset 0x1500 + 0x1500: 0xa949, 0x1501: 0xa981, 0x1502: 0xa9b9, 0x1503: 0xa8a1, 0x1504: 0x9bb9, 0x1505: 0x9989, + 0x1506: 0xa9f1, 0x1507: 0xaa29, 0x1508: 0x0040, 0x1509: 0x0040, 0x150a: 0x0040, 0x150b: 0x0040, + 0x150c: 0x0040, 0x150d: 0x0040, 0x150e: 0x0040, 0x150f: 0x0040, 0x1510: 0x0040, 0x1511: 0x0040, + 0x1512: 0x0040, 0x1513: 0x0040, 0x1514: 0x0040, 0x1515: 0x0040, 0x1516: 0x0040, 0x1517: 0x0040, + 0x1518: 0x0040, 0x1519: 0x0040, 0x151a: 0x0040, 0x151b: 0x0040, 0x151c: 0x0040, 0x151d: 0x0040, + 0x151e: 0x0040, 0x151f: 0x0040, 0x1520: 0x0040, 0x1521: 0x0040, 0x1522: 0x0040, 0x1523: 0x0040, + 0x1524: 0x0040, 0x1525: 0x0040, 0x1526: 0x0040, 0x1527: 0x0040, 0x1528: 0x0040, 0x1529: 0x0040, + 0x152a: 0x0040, 0x152b: 0x0040, 0x152c: 0x0040, 0x152d: 0x0040, 0x152e: 0x0040, 0x152f: 0x0040, + 0x1530: 0xaa61, 0x1531: 0xaa99, 0x1532: 0xaad1, 0x1533: 0xab19, 0x1534: 0xab61, 0x1535: 0xaba9, + 0x1536: 0xabf1, 0x1537: 0xac39, 0x1538: 0xac81, 0x1539: 0xacc9, 0x153a: 0xad02, 0x153b: 0xae12, + 0x153c: 0xae91, 0x153d: 0x0018, 0x153e: 0x0040, 0x153f: 0x0040, + // Block 0x55, offset 0x1540 + 0x1540: 0x33c0, 0x1541: 0x33c0, 0x1542: 0x33c0, 0x1543: 0x33c0, 0x1544: 0x33c0, 0x1545: 0x33c0, + 0x1546: 0x33c0, 0x1547: 0x33c0, 0x1548: 0x33c0, 0x1549: 0x33c0, 0x154a: 0x33c0, 0x154b: 0x33c0, + 0x154c: 0x33c0, 0x154d: 0x33c0, 0x154e: 0x33c0, 0x154f: 0x33c0, 0x1550: 0xaeda, 0x1551: 0x7d8d, + 0x1552: 0x0040, 0x1553: 0xaeea, 0x1554: 0x03c2, 0x1555: 0xaefa, 0x1556: 0xaf0a, 0x1557: 0x7dad, + 0x1558: 0x7dcd, 0x1559: 0x0040, 0x155a: 0x0040, 0x155b: 0x0040, 0x155c: 0x0040, 0x155d: 0x0040, + 0x155e: 0x0040, 0x155f: 0x0040, 0x1560: 0x3308, 0x1561: 0x3308, 0x1562: 0x3308, 0x1563: 0x3308, + 0x1564: 0x3308, 0x1565: 0x3308, 0x1566: 0x3308, 0x1567: 0x3308, 0x1568: 0x3308, 0x1569: 0x3308, + 0x156a: 0x3308, 0x156b: 0x3308, 0x156c: 0x3308, 0x156d: 0x3308, 0x156e: 0x3308, 0x156f: 0x3308, + 0x1570: 0x0040, 0x1571: 0x7ded, 0x1572: 0x7e0d, 0x1573: 0xaf1a, 0x1574: 0xaf1a, 0x1575: 0x1fd2, + 0x1576: 0x1fe2, 0x1577: 0xaf2a, 0x1578: 0xaf3a, 0x1579: 0x7e2d, 0x157a: 0x7e4d, 0x157b: 0x7e6d, + 0x157c: 0x7e2d, 0x157d: 0x7e8d, 0x157e: 0x7ead, 0x157f: 0x7e8d, + // Block 0x56, offset 0x1580 + 0x1580: 0x7ecd, 0x1581: 0x7eed, 0x1582: 0x7f0d, 0x1583: 0x7eed, 0x1584: 0x7f2d, 0x1585: 0x0018, + 0x1586: 0x0018, 0x1587: 0xaf4a, 0x1588: 0xaf5a, 0x1589: 0x7f4e, 0x158a: 0x7f6e, 0x158b: 0x7f8e, + 0x158c: 0x7fae, 0x158d: 0xaf1a, 0x158e: 0xaf1a, 0x158f: 0xaf1a, 0x1590: 0xaeda, 0x1591: 0x7fcd, + 0x1592: 0x0040, 0x1593: 0x0040, 0x1594: 0x03c2, 0x1595: 0xaeea, 0x1596: 0xaf0a, 0x1597: 0xaefa, + 0x1598: 0x7fed, 0x1599: 0x1fd2, 0x159a: 0x1fe2, 0x159b: 0xaf2a, 0x159c: 0xaf3a, 0x159d: 0x7ecd, + 0x159e: 0x7f2d, 0x159f: 0xaf6a, 0x15a0: 0xaf7a, 0x15a1: 0xaf8a, 0x15a2: 0x1fb2, 0x15a3: 0xaf99, + 0x15a4: 0xafaa, 0x15a5: 0xafba, 0x15a6: 0x1fc2, 0x15a7: 0x0040, 0x15a8: 0xafca, 0x15a9: 0xafda, + 0x15aa: 0xafea, 0x15ab: 0xaffa, 0x15ac: 0x0040, 0x15ad: 0x0040, 0x15ae: 0x0040, 0x15af: 0x0040, + 0x15b0: 0x800e, 0x15b1: 0xb009, 0x15b2: 0x802e, 0x15b3: 0x0808, 0x15b4: 0x804e, 0x15b5: 0x0040, + 0x15b6: 0x806e, 0x15b7: 0xb031, 0x15b8: 0x808e, 0x15b9: 0xb059, 0x15ba: 0x80ae, 0x15bb: 0xb081, + 0x15bc: 0x80ce, 0x15bd: 0xb0a9, 0x15be: 0x80ee, 0x15bf: 0xb0d1, + // Block 0x57, offset 0x15c0 + 0x15c0: 0xb0f9, 0x15c1: 0xb111, 0x15c2: 0xb111, 0x15c3: 0xb129, 0x15c4: 0xb129, 0x15c5: 0xb141, + 0x15c6: 0xb141, 0x15c7: 0xb159, 0x15c8: 0xb159, 0x15c9: 0xb171, 0x15ca: 0xb171, 0x15cb: 0xb171, + 0x15cc: 0xb171, 0x15cd: 0xb189, 0x15ce: 0xb189, 0x15cf: 0xb1a1, 0x15d0: 0xb1a1, 0x15d1: 0xb1a1, + 0x15d2: 0xb1a1, 0x15d3: 0xb1b9, 0x15d4: 0xb1b9, 0x15d5: 0xb1d1, 0x15d6: 0xb1d1, 0x15d7: 0xb1d1, + 0x15d8: 0xb1d1, 0x15d9: 0xb1e9, 0x15da: 0xb1e9, 0x15db: 0xb1e9, 0x15dc: 0xb1e9, 0x15dd: 0xb201, + 0x15de: 0xb201, 0x15df: 0xb201, 0x15e0: 0xb201, 0x15e1: 0xb219, 0x15e2: 0xb219, 0x15e3: 0xb219, + 0x15e4: 0xb219, 0x15e5: 0xb231, 0x15e6: 0xb231, 0x15e7: 0xb231, 0x15e8: 0xb231, 0x15e9: 0xb249, + 0x15ea: 0xb249, 0x15eb: 0xb261, 0x15ec: 0xb261, 0x15ed: 0xb279, 0x15ee: 0xb279, 0x15ef: 0xb291, + 0x15f0: 0xb291, 0x15f1: 0xb2a9, 0x15f2: 0xb2a9, 0x15f3: 0xb2a9, 0x15f4: 0xb2a9, 0x15f5: 0xb2c1, + 0x15f6: 0xb2c1, 0x15f7: 0xb2c1, 0x15f8: 0xb2c1, 0x15f9: 0xb2d9, 0x15fa: 0xb2d9, 0x15fb: 0xb2d9, + 0x15fc: 0xb2d9, 0x15fd: 0xb2f1, 0x15fe: 0xb2f1, 0x15ff: 0xb2f1, + // Block 0x58, offset 0x1600 + 0x1600: 0xb2f1, 0x1601: 0xb309, 0x1602: 0xb309, 0x1603: 0xb309, 0x1604: 0xb309, 0x1605: 0xb321, + 0x1606: 0xb321, 0x1607: 0xb321, 0x1608: 0xb321, 0x1609: 0xb339, 0x160a: 0xb339, 0x160b: 0xb339, + 0x160c: 0xb339, 0x160d: 0xb351, 0x160e: 0xb351, 0x160f: 0xb351, 0x1610: 0xb351, 0x1611: 0xb369, + 0x1612: 0xb369, 0x1613: 0xb369, 0x1614: 0xb369, 0x1615: 0xb381, 0x1616: 0xb381, 0x1617: 0xb381, + 0x1618: 0xb381, 0x1619: 0xb399, 0x161a: 0xb399, 0x161b: 0xb399, 0x161c: 0xb399, 0x161d: 0xb3b1, + 0x161e: 0xb3b1, 0x161f: 0xb3b1, 0x1620: 0xb3b1, 0x1621: 0xb3c9, 0x1622: 0xb3c9, 0x1623: 0xb3c9, + 0x1624: 0xb3c9, 0x1625: 0xb3e1, 0x1626: 0xb3e1, 0x1627: 0xb3e1, 0x1628: 0xb3e1, 0x1629: 0xb3f9, + 0x162a: 0xb3f9, 0x162b: 0xb3f9, 0x162c: 0xb3f9, 0x162d: 0xb411, 0x162e: 0xb411, 0x162f: 0x7ab1, + 0x1630: 0x7ab1, 0x1631: 0xb429, 0x1632: 0xb429, 0x1633: 0xb429, 0x1634: 0xb429, 0x1635: 0xb441, + 0x1636: 0xb441, 0x1637: 0xb469, 0x1638: 0xb469, 0x1639: 0xb491, 0x163a: 0xb491, 0x163b: 0xb4b9, + 0x163c: 0xb4b9, 0x163d: 0x0040, 0x163e: 0x0040, 0x163f: 0x03c0, + // Block 0x59, offset 0x1640 + 0x1640: 0x0040, 0x1641: 0xaefa, 0x1642: 0xb4e2, 0x1643: 0xaf6a, 0x1644: 0xafda, 0x1645: 0xafea, + 0x1646: 0xaf7a, 0x1647: 0xb4f2, 0x1648: 0x1fd2, 0x1649: 0x1fe2, 0x164a: 0xaf8a, 0x164b: 0x1fb2, + 0x164c: 0xaeda, 0x164d: 0xaf99, 0x164e: 0x29d1, 0x164f: 0xb502, 0x1650: 0x1f41, 0x1651: 0x00c9, + 0x1652: 0x0069, 0x1653: 0x0079, 0x1654: 0x1f51, 0x1655: 0x1f61, 0x1656: 0x1f71, 0x1657: 0x1f81, + 0x1658: 0x1f91, 0x1659: 0x1fa1, 0x165a: 0xaeea, 0x165b: 0x03c2, 0x165c: 0xafaa, 0x165d: 0x1fc2, + 0x165e: 0xafba, 0x165f: 0xaf0a, 0x1660: 0xaffa, 0x1661: 0x0039, 0x1662: 0x0ee9, 0x1663: 0x1159, + 0x1664: 0x0ef9, 0x1665: 0x0f09, 0x1666: 0x1199, 0x1667: 0x0f31, 0x1668: 0x0249, 0x1669: 0x0f41, + 0x166a: 0x0259, 0x166b: 0x0f51, 0x166c: 0x0359, 0x166d: 0x0f61, 0x166e: 0x0f71, 0x166f: 0x00d9, + 0x1670: 0x0f99, 0x1671: 0x2039, 0x1672: 0x0269, 0x1673: 0x01d9, 0x1674: 0x0fa9, 0x1675: 0x0fb9, + 0x1676: 0x1089, 0x1677: 0x0279, 0x1678: 0x0369, 0x1679: 0x0289, 0x167a: 0x13d1, 0x167b: 0xaf4a, + 0x167c: 0xafca, 0x167d: 0xaf5a, 0x167e: 0xb512, 0x167f: 0xaf1a, + // Block 0x5a, offset 0x1680 + 0x1680: 0x1caa, 0x1681: 0x0039, 0x1682: 0x0ee9, 0x1683: 0x1159, 0x1684: 0x0ef9, 0x1685: 0x0f09, + 0x1686: 0x1199, 0x1687: 0x0f31, 0x1688: 0x0249, 0x1689: 0x0f41, 0x168a: 0x0259, 0x168b: 0x0f51, + 0x168c: 0x0359, 0x168d: 0x0f61, 0x168e: 0x0f71, 0x168f: 0x00d9, 0x1690: 0x0f99, 0x1691: 0x2039, + 0x1692: 0x0269, 0x1693: 0x01d9, 0x1694: 0x0fa9, 0x1695: 0x0fb9, 0x1696: 0x1089, 0x1697: 0x0279, + 0x1698: 0x0369, 0x1699: 0x0289, 0x169a: 0x13d1, 0x169b: 0xaf2a, 0x169c: 0xb522, 0x169d: 0xaf3a, + 0x169e: 0xb532, 0x169f: 0x810d, 0x16a0: 0x812d, 0x16a1: 0x29d1, 0x16a2: 0x814d, 0x16a3: 0x814d, + 0x16a4: 0x816d, 0x16a5: 0x818d, 0x16a6: 0x81ad, 0x16a7: 0x81cd, 0x16a8: 0x81ed, 0x16a9: 0x820d, + 0x16aa: 0x822d, 0x16ab: 0x824d, 0x16ac: 0x826d, 0x16ad: 0x828d, 0x16ae: 0x82ad, 0x16af: 0x82cd, + 0x16b0: 0x82ed, 0x16b1: 0x830d, 0x16b2: 0x832d, 0x16b3: 0x834d, 0x16b4: 0x836d, 0x16b5: 0x838d, + 0x16b6: 0x83ad, 0x16b7: 0x83cd, 0x16b8: 0x83ed, 0x16b9: 0x840d, 0x16ba: 0x842d, 0x16bb: 0x844d, + 0x16bc: 0x81ed, 0x16bd: 0x846d, 0x16be: 0x848d, 0x16bf: 0x824d, + // Block 0x5b, offset 0x16c0 + 0x16c0: 0x84ad, 0x16c1: 0x84cd, 0x16c2: 0x84ed, 0x16c3: 0x850d, 0x16c4: 0x852d, 0x16c5: 0x854d, + 0x16c6: 0x856d, 0x16c7: 0x858d, 0x16c8: 0x850d, 0x16c9: 0x85ad, 0x16ca: 0x850d, 0x16cb: 0x85cd, + 0x16cc: 0x85cd, 0x16cd: 0x85ed, 0x16ce: 0x85ed, 0x16cf: 0x860d, 0x16d0: 0x854d, 0x16d1: 0x862d, + 0x16d2: 0x864d, 0x16d3: 0x862d, 0x16d4: 0x866d, 0x16d5: 0x864d, 0x16d6: 0x868d, 0x16d7: 0x868d, + 0x16d8: 0x86ad, 0x16d9: 0x86ad, 0x16da: 0x86cd, 0x16db: 0x86cd, 0x16dc: 0x864d, 0x16dd: 0x814d, + 0x16de: 0x86ed, 0x16df: 0x870d, 0x16e0: 0x0040, 0x16e1: 0x872d, 0x16e2: 0x874d, 0x16e3: 0x876d, + 0x16e4: 0x878d, 0x16e5: 0x876d, 0x16e6: 0x87ad, 0x16e7: 0x87cd, 0x16e8: 0x87ed, 0x16e9: 0x87ed, + 0x16ea: 0x880d, 0x16eb: 0x880d, 0x16ec: 0x882d, 0x16ed: 0x882d, 0x16ee: 0x880d, 0x16ef: 0x880d, + 0x16f0: 0x884d, 0x16f1: 0x886d, 0x16f2: 0x888d, 0x16f3: 0x88ad, 0x16f4: 0x88cd, 0x16f5: 0x88ed, + 0x16f6: 0x88ed, 0x16f7: 0x88ed, 0x16f8: 0x890d, 0x16f9: 0x890d, 0x16fa: 0x890d, 0x16fb: 0x890d, + 0x16fc: 0x87ed, 0x16fd: 0x87ed, 0x16fe: 0x87ed, 0x16ff: 0x0040, + // Block 0x5c, offset 0x1700 + 0x1700: 0x0040, 0x1701: 0x0040, 0x1702: 0x874d, 0x1703: 0x872d, 0x1704: 0x892d, 0x1705: 0x872d, + 0x1706: 0x874d, 0x1707: 0x872d, 0x1708: 0x0040, 0x1709: 0x0040, 0x170a: 0x894d, 0x170b: 0x874d, + 0x170c: 0x896d, 0x170d: 0x892d, 0x170e: 0x896d, 0x170f: 0x874d, 0x1710: 0x0040, 0x1711: 0x0040, + 0x1712: 0x898d, 0x1713: 0x89ad, 0x1714: 0x88ad, 0x1715: 0x896d, 0x1716: 0x892d, 0x1717: 0x896d, + 0x1718: 0x0040, 0x1719: 0x0040, 0x171a: 0x89cd, 0x171b: 0x89ed, 0x171c: 0x89cd, 0x171d: 0x0040, + 0x171e: 0x0040, 0x171f: 0x0040, 0x1720: 0xb541, 0x1721: 0xb559, 0x1722: 0xb571, 0x1723: 0x8a0e, + 0x1724: 0xb589, 0x1725: 0xb5a1, 0x1726: 0x8a2d, 0x1727: 0x0040, 0x1728: 0x8a4d, 0x1729: 0x8a6d, + 0x172a: 0x8a8d, 0x172b: 0x8a6d, 0x172c: 0x8aad, 0x172d: 0x8acd, 0x172e: 0x8aed, 0x172f: 0x0040, + 0x1730: 0x0040, 0x1731: 0x0040, 0x1732: 0x0040, 0x1733: 0x0040, 0x1734: 0x0040, 0x1735: 0x0040, + 0x1736: 0x0040, 0x1737: 0x0040, 0x1738: 0x0040, 0x1739: 0x0340, 0x173a: 0x0340, 0x173b: 0x0340, + 0x173c: 0x0040, 0x173d: 0x0040, 0x173e: 0x0040, 0x173f: 0x0040, + // Block 0x5d, offset 0x1740 + 0x1740: 0x0a08, 0x1741: 0x0a08, 0x1742: 0x0a08, 0x1743: 0x0a08, 0x1744: 0x0a08, 0x1745: 0x0c08, + 0x1746: 0x0808, 0x1747: 0x0c08, 0x1748: 0x0818, 0x1749: 0x0c08, 0x174a: 0x0c08, 0x174b: 0x0808, + 0x174c: 0x0808, 0x174d: 0x0908, 0x174e: 0x0c08, 0x174f: 0x0c08, 0x1750: 0x0c08, 0x1751: 0x0c08, + 0x1752: 0x0c08, 0x1753: 0x0a08, 0x1754: 0x0a08, 0x1755: 0x0a08, 0x1756: 0x0a08, 0x1757: 0x0908, + 0x1758: 0x0a08, 0x1759: 0x0a08, 0x175a: 0x0a08, 0x175b: 0x0a08, 0x175c: 0x0a08, 0x175d: 0x0c08, + 0x175e: 0x0a08, 0x175f: 0x0a08, 0x1760: 0x0a08, 0x1761: 0x0c08, 0x1762: 0x0808, 0x1763: 0x0808, + 0x1764: 0x0c08, 0x1765: 0x3308, 0x1766: 0x3308, 0x1767: 0x0040, 0x1768: 0x0040, 0x1769: 0x0040, + 0x176a: 0x0040, 0x176b: 0x0a18, 0x176c: 0x0a18, 0x176d: 0x0a18, 0x176e: 0x0a18, 0x176f: 0x0c18, + 0x1770: 0x0818, 0x1771: 0x0818, 0x1772: 0x0818, 0x1773: 0x0818, 0x1774: 0x0818, 0x1775: 0x0818, + 0x1776: 0x0818, 0x1777: 0x0040, 0x1778: 0x0040, 0x1779: 0x0040, 0x177a: 0x0040, 0x177b: 0x0040, + 0x177c: 0x0040, 0x177d: 0x0040, 0x177e: 0x0040, 0x177f: 0x0040, + // Block 0x5e, offset 0x1780 + 0x1780: 0x0a08, 0x1781: 0x0c08, 0x1782: 0x0a08, 0x1783: 0x0c08, 0x1784: 0x0c08, 0x1785: 0x0c08, + 0x1786: 0x0a08, 0x1787: 0x0a08, 0x1788: 0x0a08, 0x1789: 0x0c08, 0x178a: 0x0a08, 0x178b: 0x0a08, + 0x178c: 0x0c08, 0x178d: 0x0a08, 0x178e: 0x0c08, 0x178f: 0x0c08, 0x1790: 0x0a08, 0x1791: 0x0c08, + 0x1792: 0x0040, 0x1793: 0x0040, 0x1794: 0x0040, 0x1795: 0x0040, 0x1796: 0x0040, 0x1797: 0x0040, + 0x1798: 0x0040, 0x1799: 0x0818, 0x179a: 0x0818, 0x179b: 0x0818, 0x179c: 0x0818, 0x179d: 0x0040, + 0x179e: 0x0040, 0x179f: 0x0040, 0x17a0: 0x0040, 0x17a1: 0x0040, 0x17a2: 0x0040, 0x17a3: 0x0040, + 0x17a4: 0x0040, 0x17a5: 0x0040, 0x17a6: 0x0040, 0x17a7: 0x0040, 0x17a8: 0x0040, 0x17a9: 0x0c18, + 0x17aa: 0x0c18, 0x17ab: 0x0c18, 0x17ac: 0x0c18, 0x17ad: 0x0a18, 0x17ae: 0x0a18, 0x17af: 0x0818, + 0x17b0: 0x0040, 0x17b1: 0x0040, 0x17b2: 0x0040, 0x17b3: 0x0040, 0x17b4: 0x0040, 0x17b5: 0x0040, + 0x17b6: 0x0040, 0x17b7: 0x0040, 0x17b8: 0x0040, 0x17b9: 0x0040, 0x17ba: 0x0040, 0x17bb: 0x0040, + 0x17bc: 0x0040, 0x17bd: 0x0040, 0x17be: 0x0040, 0x17bf: 0x0040, + // Block 0x5f, offset 0x17c0 + 0x17c0: 0x3308, 0x17c1: 0x3308, 0x17c2: 0x3008, 0x17c3: 0x3008, 0x17c4: 0x0040, 0x17c5: 0x0008, + 0x17c6: 0x0008, 0x17c7: 0x0008, 0x17c8: 0x0008, 0x17c9: 0x0008, 0x17ca: 0x0008, 0x17cb: 0x0008, + 0x17cc: 0x0008, 0x17cd: 0x0040, 0x17ce: 0x0040, 0x17cf: 0x0008, 0x17d0: 0x0008, 0x17d1: 0x0040, + 0x17d2: 0x0040, 0x17d3: 0x0008, 0x17d4: 0x0008, 0x17d5: 0x0008, 0x17d6: 0x0008, 0x17d7: 0x0008, + 0x17d8: 0x0008, 0x17d9: 0x0008, 0x17da: 0x0008, 0x17db: 0x0008, 0x17dc: 0x0008, 0x17dd: 0x0008, + 0x17de: 0x0008, 0x17df: 0x0008, 0x17e0: 0x0008, 0x17e1: 0x0008, 0x17e2: 0x0008, 0x17e3: 0x0008, + 0x17e4: 0x0008, 0x17e5: 0x0008, 0x17e6: 0x0008, 0x17e7: 0x0008, 0x17e8: 0x0008, 0x17e9: 0x0040, + 0x17ea: 0x0008, 0x17eb: 0x0008, 0x17ec: 0x0008, 0x17ed: 0x0008, 0x17ee: 0x0008, 0x17ef: 0x0008, + 0x17f0: 0x0008, 0x17f1: 0x0040, 0x17f2: 0x0008, 0x17f3: 0x0008, 0x17f4: 0x0040, 0x17f5: 0x0008, + 0x17f6: 0x0008, 0x17f7: 0x0008, 0x17f8: 0x0008, 0x17f9: 0x0008, 0x17fa: 0x0040, 0x17fb: 0x3308, + 0x17fc: 0x3308, 0x17fd: 0x0008, 0x17fe: 0x3008, 0x17ff: 0x3008, + // Block 0x60, offset 0x1800 + 0x1800: 0x3308, 0x1801: 0x3008, 0x1802: 0x3008, 0x1803: 0x3008, 0x1804: 0x3008, 0x1805: 0x0040, + 0x1806: 0x0040, 0x1807: 0x3008, 0x1808: 0x3008, 0x1809: 0x0040, 0x180a: 0x0040, 0x180b: 0x3008, + 0x180c: 0x3008, 0x180d: 0x3808, 0x180e: 0x0040, 0x180f: 0x0040, 0x1810: 0x0008, 0x1811: 0x0040, + 0x1812: 0x0040, 0x1813: 0x0040, 0x1814: 0x0040, 0x1815: 0x0040, 0x1816: 0x0040, 0x1817: 0x3008, + 0x1818: 0x0040, 0x1819: 0x0040, 0x181a: 0x0040, 0x181b: 0x0040, 0x181c: 0x0040, 0x181d: 0x0008, + 0x181e: 0x0008, 0x181f: 0x0008, 0x1820: 0x0008, 0x1821: 0x0008, 0x1822: 0x3008, 0x1823: 0x3008, + 0x1824: 0x0040, 0x1825: 0x0040, 0x1826: 0x3308, 0x1827: 0x3308, 0x1828: 0x3308, 0x1829: 0x3308, + 0x182a: 0x3308, 0x182b: 0x3308, 0x182c: 0x3308, 0x182d: 0x0040, 0x182e: 0x0040, 0x182f: 0x0040, + 0x1830: 0x3308, 0x1831: 0x3308, 0x1832: 0x3308, 0x1833: 0x3308, 0x1834: 0x3308, 0x1835: 0x0040, + 0x1836: 0x0040, 0x1837: 0x0040, 0x1838: 0x0040, 0x1839: 0x0040, 0x183a: 0x0040, 0x183b: 0x0040, + 0x183c: 0x0040, 0x183d: 0x0040, 0x183e: 0x0040, 0x183f: 0x0040, + // Block 0x61, offset 0x1840 + 0x1840: 0x0039, 0x1841: 0x0ee9, 0x1842: 0x1159, 0x1843: 0x0ef9, 0x1844: 0x0f09, 0x1845: 0x1199, + 0x1846: 0x0f31, 0x1847: 0x0249, 0x1848: 0x0f41, 0x1849: 0x0259, 0x184a: 0x0f51, 0x184b: 0x0359, + 0x184c: 0x0f61, 0x184d: 0x0f71, 0x184e: 0x00d9, 0x184f: 0x0f99, 0x1850: 0x2039, 0x1851: 0x0269, + 0x1852: 0x01d9, 0x1853: 0x0fa9, 0x1854: 0x0fb9, 0x1855: 0x1089, 0x1856: 0x0279, 0x1857: 0x0369, + 0x1858: 0x0289, 0x1859: 0x13d1, 0x185a: 0x0039, 0x185b: 0x0ee9, 0x185c: 0x1159, 0x185d: 0x0ef9, + 0x185e: 0x0f09, 0x185f: 0x1199, 0x1860: 0x0f31, 0x1861: 0x0249, 0x1862: 0x0f41, 0x1863: 0x0259, + 0x1864: 0x0f51, 0x1865: 0x0359, 0x1866: 0x0f61, 0x1867: 0x0f71, 0x1868: 0x00d9, 0x1869: 0x0f99, + 0x186a: 0x2039, 0x186b: 0x0269, 0x186c: 0x01d9, 0x186d: 0x0fa9, 0x186e: 0x0fb9, 0x186f: 0x1089, + 0x1870: 0x0279, 0x1871: 0x0369, 0x1872: 0x0289, 0x1873: 0x13d1, 0x1874: 0x0039, 0x1875: 0x0ee9, + 0x1876: 0x1159, 0x1877: 0x0ef9, 0x1878: 0x0f09, 0x1879: 0x1199, 0x187a: 0x0f31, 0x187b: 0x0249, + 0x187c: 0x0f41, 0x187d: 0x0259, 0x187e: 0x0f51, 0x187f: 0x0359, + // Block 0x62, offset 0x1880 + 0x1880: 0x0f61, 0x1881: 0x0f71, 0x1882: 0x00d9, 0x1883: 0x0f99, 0x1884: 0x2039, 0x1885: 0x0269, + 0x1886: 0x01d9, 0x1887: 0x0fa9, 0x1888: 0x0fb9, 0x1889: 0x1089, 0x188a: 0x0279, 0x188b: 0x0369, + 0x188c: 0x0289, 0x188d: 0x13d1, 0x188e: 0x0039, 0x188f: 0x0ee9, 0x1890: 0x1159, 0x1891: 0x0ef9, + 0x1892: 0x0f09, 0x1893: 0x1199, 0x1894: 0x0f31, 0x1895: 0x0040, 0x1896: 0x0f41, 0x1897: 0x0259, + 0x1898: 0x0f51, 0x1899: 0x0359, 0x189a: 0x0f61, 0x189b: 0x0f71, 0x189c: 0x00d9, 0x189d: 0x0f99, + 0x189e: 0x2039, 0x189f: 0x0269, 0x18a0: 0x01d9, 0x18a1: 0x0fa9, 0x18a2: 0x0fb9, 0x18a3: 0x1089, + 0x18a4: 0x0279, 0x18a5: 0x0369, 0x18a6: 0x0289, 0x18a7: 0x13d1, 0x18a8: 0x0039, 0x18a9: 0x0ee9, + 0x18aa: 0x1159, 0x18ab: 0x0ef9, 0x18ac: 0x0f09, 0x18ad: 0x1199, 0x18ae: 0x0f31, 0x18af: 0x0249, + 0x18b0: 0x0f41, 0x18b1: 0x0259, 0x18b2: 0x0f51, 0x18b3: 0x0359, 0x18b4: 0x0f61, 0x18b5: 0x0f71, + 0x18b6: 0x00d9, 0x18b7: 0x0f99, 0x18b8: 0x2039, 0x18b9: 0x0269, 0x18ba: 0x01d9, 0x18bb: 0x0fa9, + 0x18bc: 0x0fb9, 0x18bd: 0x1089, 0x18be: 0x0279, 0x18bf: 0x0369, + // Block 0x63, offset 0x18c0 + 0x18c0: 0x0289, 0x18c1: 0x13d1, 0x18c2: 0x0039, 0x18c3: 0x0ee9, 0x18c4: 0x1159, 0x18c5: 0x0ef9, + 0x18c6: 0x0f09, 0x18c7: 0x1199, 0x18c8: 0x0f31, 0x18c9: 0x0249, 0x18ca: 0x0f41, 0x18cb: 0x0259, + 0x18cc: 0x0f51, 0x18cd: 0x0359, 0x18ce: 0x0f61, 0x18cf: 0x0f71, 0x18d0: 0x00d9, 0x18d1: 0x0f99, + 0x18d2: 0x2039, 0x18d3: 0x0269, 0x18d4: 0x01d9, 0x18d5: 0x0fa9, 0x18d6: 0x0fb9, 0x18d7: 0x1089, + 0x18d8: 0x0279, 0x18d9: 0x0369, 0x18da: 0x0289, 0x18db: 0x13d1, 0x18dc: 0x0039, 0x18dd: 0x0040, + 0x18de: 0x1159, 0x18df: 0x0ef9, 0x18e0: 0x0040, 0x18e1: 0x0040, 0x18e2: 0x0f31, 0x18e3: 0x0040, + 0x18e4: 0x0040, 0x18e5: 0x0259, 0x18e6: 0x0f51, 0x18e7: 0x0040, 0x18e8: 0x0040, 0x18e9: 0x0f71, + 0x18ea: 0x00d9, 0x18eb: 0x0f99, 0x18ec: 0x2039, 0x18ed: 0x0040, 0x18ee: 0x01d9, 0x18ef: 0x0fa9, + 0x18f0: 0x0fb9, 0x18f1: 0x1089, 0x18f2: 0x0279, 0x18f3: 0x0369, 0x18f4: 0x0289, 0x18f5: 0x13d1, + 0x18f6: 0x0039, 0x18f7: 0x0ee9, 0x18f8: 0x1159, 0x18f9: 0x0ef9, 0x18fa: 0x0040, 0x18fb: 0x1199, + 0x18fc: 0x0040, 0x18fd: 0x0249, 0x18fe: 0x0f41, 0x18ff: 0x0259, + // Block 0x64, offset 0x1900 + 0x1900: 0x0f51, 0x1901: 0x0359, 0x1902: 0x0f61, 0x1903: 0x0f71, 0x1904: 0x0040, 0x1905: 0x0f99, + 0x1906: 0x2039, 0x1907: 0x0269, 0x1908: 0x01d9, 0x1909: 0x0fa9, 0x190a: 0x0fb9, 0x190b: 0x1089, + 0x190c: 0x0279, 0x190d: 0x0369, 0x190e: 0x0289, 0x190f: 0x13d1, 0x1910: 0x0039, 0x1911: 0x0ee9, + 0x1912: 0x1159, 0x1913: 0x0ef9, 0x1914: 0x0f09, 0x1915: 0x1199, 0x1916: 0x0f31, 0x1917: 0x0249, + 0x1918: 0x0f41, 0x1919: 0x0259, 0x191a: 0x0f51, 0x191b: 0x0359, 0x191c: 0x0f61, 0x191d: 0x0f71, + 0x191e: 0x00d9, 0x191f: 0x0f99, 0x1920: 0x2039, 0x1921: 0x0269, 0x1922: 0x01d9, 0x1923: 0x0fa9, + 0x1924: 0x0fb9, 0x1925: 0x1089, 0x1926: 0x0279, 0x1927: 0x0369, 0x1928: 0x0289, 0x1929: 0x13d1, + 0x192a: 0x0039, 0x192b: 0x0ee9, 0x192c: 0x1159, 0x192d: 0x0ef9, 0x192e: 0x0f09, 0x192f: 0x1199, + 0x1930: 0x0f31, 0x1931: 0x0249, 0x1932: 0x0f41, 0x1933: 0x0259, 0x1934: 0x0f51, 0x1935: 0x0359, + 0x1936: 0x0f61, 0x1937: 0x0f71, 0x1938: 0x00d9, 0x1939: 0x0f99, 0x193a: 0x2039, 0x193b: 0x0269, + 0x193c: 0x01d9, 0x193d: 0x0fa9, 0x193e: 0x0fb9, 0x193f: 0x1089, + // Block 0x65, offset 0x1940 + 0x1940: 0x0279, 0x1941: 0x0369, 0x1942: 0x0289, 0x1943: 0x13d1, 0x1944: 0x0039, 0x1945: 0x0ee9, + 0x1946: 0x0040, 0x1947: 0x0ef9, 0x1948: 0x0f09, 0x1949: 0x1199, 0x194a: 0x0f31, 0x194b: 0x0040, + 0x194c: 0x0040, 0x194d: 0x0259, 0x194e: 0x0f51, 0x194f: 0x0359, 0x1950: 0x0f61, 0x1951: 0x0f71, + 0x1952: 0x00d9, 0x1953: 0x0f99, 0x1954: 0x2039, 0x1955: 0x0040, 0x1956: 0x01d9, 0x1957: 0x0fa9, + 0x1958: 0x0fb9, 0x1959: 0x1089, 0x195a: 0x0279, 0x195b: 0x0369, 0x195c: 0x0289, 0x195d: 0x0040, + 0x195e: 0x0039, 0x195f: 0x0ee9, 0x1960: 0x1159, 0x1961: 0x0ef9, 0x1962: 0x0f09, 0x1963: 0x1199, + 0x1964: 0x0f31, 0x1965: 0x0249, 0x1966: 0x0f41, 0x1967: 0x0259, 0x1968: 0x0f51, 0x1969: 0x0359, + 0x196a: 0x0f61, 0x196b: 0x0f71, 0x196c: 0x00d9, 0x196d: 0x0f99, 0x196e: 0x2039, 0x196f: 0x0269, + 0x1970: 0x01d9, 0x1971: 0x0fa9, 0x1972: 0x0fb9, 0x1973: 0x1089, 0x1974: 0x0279, 0x1975: 0x0369, + 0x1976: 0x0289, 0x1977: 0x13d1, 0x1978: 0x0039, 0x1979: 0x0ee9, 0x197a: 0x0040, 0x197b: 0x0ef9, + 0x197c: 0x0f09, 0x197d: 0x1199, 0x197e: 0x0f31, 0x197f: 0x0040, + // Block 0x66, offset 0x1980 + 0x1980: 0x0f41, 0x1981: 0x0259, 0x1982: 0x0f51, 0x1983: 0x0359, 0x1984: 0x0f61, 0x1985: 0x0040, + 0x1986: 0x00d9, 0x1987: 0x0040, 0x1988: 0x0040, 0x1989: 0x0040, 0x198a: 0x01d9, 0x198b: 0x0fa9, + 0x198c: 0x0fb9, 0x198d: 0x1089, 0x198e: 0x0279, 0x198f: 0x0369, 0x1990: 0x0289, 0x1991: 0x0040, + 0x1992: 0x0039, 0x1993: 0x0ee9, 0x1994: 0x1159, 0x1995: 0x0ef9, 0x1996: 0x0f09, 0x1997: 0x1199, + 0x1998: 0x0f31, 0x1999: 0x0249, 0x199a: 0x0f41, 0x199b: 0x0259, 0x199c: 0x0f51, 0x199d: 0x0359, + 0x199e: 0x0f61, 0x199f: 0x0f71, 0x19a0: 0x00d9, 0x19a1: 0x0f99, 0x19a2: 0x2039, 0x19a3: 0x0269, + 0x19a4: 0x01d9, 0x19a5: 0x0fa9, 0x19a6: 0x0fb9, 0x19a7: 0x1089, 0x19a8: 0x0279, 0x19a9: 0x0369, + 0x19aa: 0x0289, 0x19ab: 0x13d1, 0x19ac: 0x0039, 0x19ad: 0x0ee9, 0x19ae: 0x1159, 0x19af: 0x0ef9, + 0x19b0: 0x0f09, 0x19b1: 0x1199, 0x19b2: 0x0f31, 0x19b3: 0x0249, 0x19b4: 0x0f41, 0x19b5: 0x0259, + 0x19b6: 0x0f51, 0x19b7: 0x0359, 0x19b8: 0x0f61, 0x19b9: 0x0f71, 0x19ba: 0x00d9, 0x19bb: 0x0f99, + 0x19bc: 0x2039, 0x19bd: 0x0269, 0x19be: 0x01d9, 0x19bf: 0x0fa9, + // Block 0x67, offset 0x19c0 + 0x19c0: 0x0fb9, 0x19c1: 0x1089, 0x19c2: 0x0279, 0x19c3: 0x0369, 0x19c4: 0x0289, 0x19c5: 0x13d1, + 0x19c6: 0x0039, 0x19c7: 0x0ee9, 0x19c8: 0x1159, 0x19c9: 0x0ef9, 0x19ca: 0x0f09, 0x19cb: 0x1199, + 0x19cc: 0x0f31, 0x19cd: 0x0249, 0x19ce: 0x0f41, 0x19cf: 0x0259, 0x19d0: 0x0f51, 0x19d1: 0x0359, + 0x19d2: 0x0f61, 0x19d3: 0x0f71, 0x19d4: 0x00d9, 0x19d5: 0x0f99, 0x19d6: 0x2039, 0x19d7: 0x0269, + 0x19d8: 0x01d9, 0x19d9: 0x0fa9, 0x19da: 0x0fb9, 0x19db: 0x1089, 0x19dc: 0x0279, 0x19dd: 0x0369, + 0x19de: 0x0289, 0x19df: 0x13d1, 0x19e0: 0x0039, 0x19e1: 0x0ee9, 0x19e2: 0x1159, 0x19e3: 0x0ef9, + 0x19e4: 0x0f09, 0x19e5: 0x1199, 0x19e6: 0x0f31, 0x19e7: 0x0249, 0x19e8: 0x0f41, 0x19e9: 0x0259, + 0x19ea: 0x0f51, 0x19eb: 0x0359, 0x19ec: 0x0f61, 0x19ed: 0x0f71, 0x19ee: 0x00d9, 0x19ef: 0x0f99, + 0x19f0: 0x2039, 0x19f1: 0x0269, 0x19f2: 0x01d9, 0x19f3: 0x0fa9, 0x19f4: 0x0fb9, 0x19f5: 0x1089, + 0x19f6: 0x0279, 0x19f7: 0x0369, 0x19f8: 0x0289, 0x19f9: 0x13d1, 0x19fa: 0x0039, 0x19fb: 0x0ee9, + 0x19fc: 0x1159, 0x19fd: 0x0ef9, 0x19fe: 0x0f09, 0x19ff: 0x1199, + // Block 0x68, offset 0x1a00 + 0x1a00: 0x0f31, 0x1a01: 0x0249, 0x1a02: 0x0f41, 0x1a03: 0x0259, 0x1a04: 0x0f51, 0x1a05: 0x0359, + 0x1a06: 0x0f61, 0x1a07: 0x0f71, 0x1a08: 0x00d9, 0x1a09: 0x0f99, 0x1a0a: 0x2039, 0x1a0b: 0x0269, + 0x1a0c: 0x01d9, 0x1a0d: 0x0fa9, 0x1a0e: 0x0fb9, 0x1a0f: 0x1089, 0x1a10: 0x0279, 0x1a11: 0x0369, + 0x1a12: 0x0289, 0x1a13: 0x13d1, 0x1a14: 0x0039, 0x1a15: 0x0ee9, 0x1a16: 0x1159, 0x1a17: 0x0ef9, + 0x1a18: 0x0f09, 0x1a19: 0x1199, 0x1a1a: 0x0f31, 0x1a1b: 0x0249, 0x1a1c: 0x0f41, 0x1a1d: 0x0259, + 0x1a1e: 0x0f51, 0x1a1f: 0x0359, 0x1a20: 0x0f61, 0x1a21: 0x0f71, 0x1a22: 0x00d9, 0x1a23: 0x0f99, + 0x1a24: 0x2039, 0x1a25: 0x0269, 0x1a26: 0x01d9, 0x1a27: 0x0fa9, 0x1a28: 0x0fb9, 0x1a29: 0x1089, + 0x1a2a: 0x0279, 0x1a2b: 0x0369, 0x1a2c: 0x0289, 0x1a2d: 0x13d1, 0x1a2e: 0x0039, 0x1a2f: 0x0ee9, + 0x1a30: 0x1159, 0x1a31: 0x0ef9, 0x1a32: 0x0f09, 0x1a33: 0x1199, 0x1a34: 0x0f31, 0x1a35: 0x0249, + 0x1a36: 0x0f41, 0x1a37: 0x0259, 0x1a38: 0x0f51, 0x1a39: 0x0359, 0x1a3a: 0x0f61, 0x1a3b: 0x0f71, + 0x1a3c: 0x00d9, 0x1a3d: 0x0f99, 0x1a3e: 0x2039, 0x1a3f: 0x0269, + // Block 0x69, offset 0x1a40 + 0x1a40: 0x01d9, 0x1a41: 0x0fa9, 0x1a42: 0x0fb9, 0x1a43: 0x1089, 0x1a44: 0x0279, 0x1a45: 0x0369, + 0x1a46: 0x0289, 0x1a47: 0x13d1, 0x1a48: 0x0039, 0x1a49: 0x0ee9, 0x1a4a: 0x1159, 0x1a4b: 0x0ef9, + 0x1a4c: 0x0f09, 0x1a4d: 0x1199, 0x1a4e: 0x0f31, 0x1a4f: 0x0249, 0x1a50: 0x0f41, 0x1a51: 0x0259, + 0x1a52: 0x0f51, 0x1a53: 0x0359, 0x1a54: 0x0f61, 0x1a55: 0x0f71, 0x1a56: 0x00d9, 0x1a57: 0x0f99, + 0x1a58: 0x2039, 0x1a59: 0x0269, 0x1a5a: 0x01d9, 0x1a5b: 0x0fa9, 0x1a5c: 0x0fb9, 0x1a5d: 0x1089, + 0x1a5e: 0x0279, 0x1a5f: 0x0369, 0x1a60: 0x0289, 0x1a61: 0x13d1, 0x1a62: 0x0039, 0x1a63: 0x0ee9, + 0x1a64: 0x1159, 0x1a65: 0x0ef9, 0x1a66: 0x0f09, 0x1a67: 0x1199, 0x1a68: 0x0f31, 0x1a69: 0x0249, + 0x1a6a: 0x0f41, 0x1a6b: 0x0259, 0x1a6c: 0x0f51, 0x1a6d: 0x0359, 0x1a6e: 0x0f61, 0x1a6f: 0x0f71, + 0x1a70: 0x00d9, 0x1a71: 0x0f99, 0x1a72: 0x2039, 0x1a73: 0x0269, 0x1a74: 0x01d9, 0x1a75: 0x0fa9, + 0x1a76: 0x0fb9, 0x1a77: 0x1089, 0x1a78: 0x0279, 0x1a79: 0x0369, 0x1a7a: 0x0289, 0x1a7b: 0x13d1, + 0x1a7c: 0x0039, 0x1a7d: 0x0ee9, 0x1a7e: 0x1159, 0x1a7f: 0x0ef9, + // Block 0x6a, offset 0x1a80 + 0x1a80: 0x0f09, 0x1a81: 0x1199, 0x1a82: 0x0f31, 0x1a83: 0x0249, 0x1a84: 0x0f41, 0x1a85: 0x0259, + 0x1a86: 0x0f51, 0x1a87: 0x0359, 0x1a88: 0x0f61, 0x1a89: 0x0f71, 0x1a8a: 0x00d9, 0x1a8b: 0x0f99, + 0x1a8c: 0x2039, 0x1a8d: 0x0269, 0x1a8e: 0x01d9, 0x1a8f: 0x0fa9, 0x1a90: 0x0fb9, 0x1a91: 0x1089, + 0x1a92: 0x0279, 0x1a93: 0x0369, 0x1a94: 0x0289, 0x1a95: 0x13d1, 0x1a96: 0x0039, 0x1a97: 0x0ee9, + 0x1a98: 0x1159, 0x1a99: 0x0ef9, 0x1a9a: 0x0f09, 0x1a9b: 0x1199, 0x1a9c: 0x0f31, 0x1a9d: 0x0249, + 0x1a9e: 0x0f41, 0x1a9f: 0x0259, 0x1aa0: 0x0f51, 0x1aa1: 0x0359, 0x1aa2: 0x0f61, 0x1aa3: 0x0f71, + 0x1aa4: 0x00d9, 0x1aa5: 0x0f99, 0x1aa6: 0x2039, 0x1aa7: 0x0269, 0x1aa8: 0x01d9, 0x1aa9: 0x0fa9, + 0x1aaa: 0x0fb9, 0x1aab: 0x1089, 0x1aac: 0x0279, 0x1aad: 0x0369, 0x1aae: 0x0289, 0x1aaf: 0x13d1, + 0x1ab0: 0x0039, 0x1ab1: 0x0ee9, 0x1ab2: 0x1159, 0x1ab3: 0x0ef9, 0x1ab4: 0x0f09, 0x1ab5: 0x1199, + 0x1ab6: 0x0f31, 0x1ab7: 0x0249, 0x1ab8: 0x0f41, 0x1ab9: 0x0259, 0x1aba: 0x0f51, 0x1abb: 0x0359, + 0x1abc: 0x0f61, 0x1abd: 0x0f71, 0x1abe: 0x00d9, 0x1abf: 0x0f99, + // Block 0x6b, offset 0x1ac0 + 0x1ac0: 0x2039, 0x1ac1: 0x0269, 0x1ac2: 0x01d9, 0x1ac3: 0x0fa9, 0x1ac4: 0x0fb9, 0x1ac5: 0x1089, + 0x1ac6: 0x0279, 0x1ac7: 0x0369, 0x1ac8: 0x0289, 0x1ac9: 0x13d1, 0x1aca: 0x0039, 0x1acb: 0x0ee9, + 0x1acc: 0x1159, 0x1acd: 0x0ef9, 0x1ace: 0x0f09, 0x1acf: 0x1199, 0x1ad0: 0x0f31, 0x1ad1: 0x0249, + 0x1ad2: 0x0f41, 0x1ad3: 0x0259, 0x1ad4: 0x0f51, 0x1ad5: 0x0359, 0x1ad6: 0x0f61, 0x1ad7: 0x0f71, + 0x1ad8: 0x00d9, 0x1ad9: 0x0f99, 0x1ada: 0x2039, 0x1adb: 0x0269, 0x1adc: 0x01d9, 0x1add: 0x0fa9, + 0x1ade: 0x0fb9, 0x1adf: 0x1089, 0x1ae0: 0x0279, 0x1ae1: 0x0369, 0x1ae2: 0x0289, 0x1ae3: 0x13d1, + 0x1ae4: 0xba81, 0x1ae5: 0xba99, 0x1ae6: 0x0040, 0x1ae7: 0x0040, 0x1ae8: 0xbab1, 0x1ae9: 0x1099, + 0x1aea: 0x10b1, 0x1aeb: 0x10c9, 0x1aec: 0xbac9, 0x1aed: 0xbae1, 0x1aee: 0xbaf9, 0x1aef: 0x1429, + 0x1af0: 0x1a31, 0x1af1: 0xbb11, 0x1af2: 0xbb29, 0x1af3: 0xbb41, 0x1af4: 0xbb59, 0x1af5: 0xbb71, + 0x1af6: 0xbb89, 0x1af7: 0x2109, 0x1af8: 0x1111, 0x1af9: 0x1429, 0x1afa: 0xbba1, 0x1afb: 0xbbb9, + 0x1afc: 0xbbd1, 0x1afd: 0x10e1, 0x1afe: 0x10f9, 0x1aff: 0xbbe9, + // Block 0x6c, offset 0x1b00 + 0x1b00: 0x2079, 0x1b01: 0xbc01, 0x1b02: 0xbab1, 0x1b03: 0x1099, 0x1b04: 0x10b1, 0x1b05: 0x10c9, + 0x1b06: 0xbac9, 0x1b07: 0xbae1, 0x1b08: 0xbaf9, 0x1b09: 0x1429, 0x1b0a: 0x1a31, 0x1b0b: 0xbb11, + 0x1b0c: 0xbb29, 0x1b0d: 0xbb41, 0x1b0e: 0xbb59, 0x1b0f: 0xbb71, 0x1b10: 0xbb89, 0x1b11: 0x2109, + 0x1b12: 0x1111, 0x1b13: 0xbba1, 0x1b14: 0xbba1, 0x1b15: 0xbbb9, 0x1b16: 0xbbd1, 0x1b17: 0x10e1, + 0x1b18: 0x10f9, 0x1b19: 0xbbe9, 0x1b1a: 0x2079, 0x1b1b: 0xbc21, 0x1b1c: 0xbac9, 0x1b1d: 0x1429, + 0x1b1e: 0xbb11, 0x1b1f: 0x10e1, 0x1b20: 0x1111, 0x1b21: 0x2109, 0x1b22: 0xbab1, 0x1b23: 0x1099, + 0x1b24: 0x10b1, 0x1b25: 0x10c9, 0x1b26: 0xbac9, 0x1b27: 0xbae1, 0x1b28: 0xbaf9, 0x1b29: 0x1429, + 0x1b2a: 0x1a31, 0x1b2b: 0xbb11, 0x1b2c: 0xbb29, 0x1b2d: 0xbb41, 0x1b2e: 0xbb59, 0x1b2f: 0xbb71, + 0x1b30: 0xbb89, 0x1b31: 0x2109, 0x1b32: 0x1111, 0x1b33: 0x1429, 0x1b34: 0xbba1, 0x1b35: 0xbbb9, + 0x1b36: 0xbbd1, 0x1b37: 0x10e1, 0x1b38: 0x10f9, 0x1b39: 0xbbe9, 0x1b3a: 0x2079, 0x1b3b: 0xbc01, + 0x1b3c: 0xbab1, 0x1b3d: 0x1099, 0x1b3e: 0x10b1, 0x1b3f: 0x10c9, + // Block 0x6d, offset 0x1b40 + 0x1b40: 0xbac9, 0x1b41: 0xbae1, 0x1b42: 0xbaf9, 0x1b43: 0x1429, 0x1b44: 0x1a31, 0x1b45: 0xbb11, + 0x1b46: 0xbb29, 0x1b47: 0xbb41, 0x1b48: 0xbb59, 0x1b49: 0xbb71, 0x1b4a: 0xbb89, 0x1b4b: 0x2109, + 0x1b4c: 0x1111, 0x1b4d: 0xbba1, 0x1b4e: 0xbba1, 0x1b4f: 0xbbb9, 0x1b50: 0xbbd1, 0x1b51: 0x10e1, + 0x1b52: 0x10f9, 0x1b53: 0xbbe9, 0x1b54: 0x2079, 0x1b55: 0xbc21, 0x1b56: 0xbac9, 0x1b57: 0x1429, + 0x1b58: 0xbb11, 0x1b59: 0x10e1, 0x1b5a: 0x1111, 0x1b5b: 0x2109, 0x1b5c: 0xbab1, 0x1b5d: 0x1099, + 0x1b5e: 0x10b1, 0x1b5f: 0x10c9, 0x1b60: 0xbac9, 0x1b61: 0xbae1, 0x1b62: 0xbaf9, 0x1b63: 0x1429, + 0x1b64: 0x1a31, 0x1b65: 0xbb11, 0x1b66: 0xbb29, 0x1b67: 0xbb41, 0x1b68: 0xbb59, 0x1b69: 0xbb71, + 0x1b6a: 0xbb89, 0x1b6b: 0x2109, 0x1b6c: 0x1111, 0x1b6d: 0x1429, 0x1b6e: 0xbba1, 0x1b6f: 0xbbb9, + 0x1b70: 0xbbd1, 0x1b71: 0x10e1, 0x1b72: 0x10f9, 0x1b73: 0xbbe9, 0x1b74: 0x2079, 0x1b75: 0xbc01, + 0x1b76: 0xbab1, 0x1b77: 0x1099, 0x1b78: 0x10b1, 0x1b79: 0x10c9, 0x1b7a: 0xbac9, 0x1b7b: 0xbae1, + 0x1b7c: 0xbaf9, 0x1b7d: 0x1429, 0x1b7e: 0x1a31, 0x1b7f: 0xbb11, + // Block 0x6e, offset 0x1b80 + 0x1b80: 0xbb29, 0x1b81: 0xbb41, 0x1b82: 0xbb59, 0x1b83: 0xbb71, 0x1b84: 0xbb89, 0x1b85: 0x2109, + 0x1b86: 0x1111, 0x1b87: 0xbba1, 0x1b88: 0xbba1, 0x1b89: 0xbbb9, 0x1b8a: 0xbbd1, 0x1b8b: 0x10e1, + 0x1b8c: 0x10f9, 0x1b8d: 0xbbe9, 0x1b8e: 0x2079, 0x1b8f: 0xbc21, 0x1b90: 0xbac9, 0x1b91: 0x1429, + 0x1b92: 0xbb11, 0x1b93: 0x10e1, 0x1b94: 0x1111, 0x1b95: 0x2109, 0x1b96: 0xbab1, 0x1b97: 0x1099, + 0x1b98: 0x10b1, 0x1b99: 0x10c9, 0x1b9a: 0xbac9, 0x1b9b: 0xbae1, 0x1b9c: 0xbaf9, 0x1b9d: 0x1429, + 0x1b9e: 0x1a31, 0x1b9f: 0xbb11, 0x1ba0: 0xbb29, 0x1ba1: 0xbb41, 0x1ba2: 0xbb59, 0x1ba3: 0xbb71, + 0x1ba4: 0xbb89, 0x1ba5: 0x2109, 0x1ba6: 0x1111, 0x1ba7: 0x1429, 0x1ba8: 0xbba1, 0x1ba9: 0xbbb9, + 0x1baa: 0xbbd1, 0x1bab: 0x10e1, 0x1bac: 0x10f9, 0x1bad: 0xbbe9, 0x1bae: 0x2079, 0x1baf: 0xbc01, + 0x1bb0: 0xbab1, 0x1bb1: 0x1099, 0x1bb2: 0x10b1, 0x1bb3: 0x10c9, 0x1bb4: 0xbac9, 0x1bb5: 0xbae1, + 0x1bb6: 0xbaf9, 0x1bb7: 0x1429, 0x1bb8: 0x1a31, 0x1bb9: 0xbb11, 0x1bba: 0xbb29, 0x1bbb: 0xbb41, + 0x1bbc: 0xbb59, 0x1bbd: 0xbb71, 0x1bbe: 0xbb89, 0x1bbf: 0x2109, + // Block 0x6f, offset 0x1bc0 + 0x1bc0: 0x1111, 0x1bc1: 0xbba1, 0x1bc2: 0xbba1, 0x1bc3: 0xbbb9, 0x1bc4: 0xbbd1, 0x1bc5: 0x10e1, + 0x1bc6: 0x10f9, 0x1bc7: 0xbbe9, 0x1bc8: 0x2079, 0x1bc9: 0xbc21, 0x1bca: 0xbac9, 0x1bcb: 0x1429, + 0x1bcc: 0xbb11, 0x1bcd: 0x10e1, 0x1bce: 0x1111, 0x1bcf: 0x2109, 0x1bd0: 0xbab1, 0x1bd1: 0x1099, + 0x1bd2: 0x10b1, 0x1bd3: 0x10c9, 0x1bd4: 0xbac9, 0x1bd5: 0xbae1, 0x1bd6: 0xbaf9, 0x1bd7: 0x1429, + 0x1bd8: 0x1a31, 0x1bd9: 0xbb11, 0x1bda: 0xbb29, 0x1bdb: 0xbb41, 0x1bdc: 0xbb59, 0x1bdd: 0xbb71, + 0x1bde: 0xbb89, 0x1bdf: 0x2109, 0x1be0: 0x1111, 0x1be1: 0x1429, 0x1be2: 0xbba1, 0x1be3: 0xbbb9, + 0x1be4: 0xbbd1, 0x1be5: 0x10e1, 0x1be6: 0x10f9, 0x1be7: 0xbbe9, 0x1be8: 0x2079, 0x1be9: 0xbc01, + 0x1bea: 0xbab1, 0x1beb: 0x1099, 0x1bec: 0x10b1, 0x1bed: 0x10c9, 0x1bee: 0xbac9, 0x1bef: 0xbae1, + 0x1bf0: 0xbaf9, 0x1bf1: 0x1429, 0x1bf2: 0x1a31, 0x1bf3: 0xbb11, 0x1bf4: 0xbb29, 0x1bf5: 0xbb41, + 0x1bf6: 0xbb59, 0x1bf7: 0xbb71, 0x1bf8: 0xbb89, 0x1bf9: 0x2109, 0x1bfa: 0x1111, 0x1bfb: 0xbba1, + 0x1bfc: 0xbba1, 0x1bfd: 0xbbb9, 0x1bfe: 0xbbd1, 0x1bff: 0x10e1, + // Block 0x70, offset 0x1c00 + 0x1c00: 0x10f9, 0x1c01: 0xbbe9, 0x1c02: 0x2079, 0x1c03: 0xbc21, 0x1c04: 0xbac9, 0x1c05: 0x1429, + 0x1c06: 0xbb11, 0x1c07: 0x10e1, 0x1c08: 0x1111, 0x1c09: 0x2109, 0x1c0a: 0xbc41, 0x1c0b: 0xbc41, + 0x1c0c: 0x0040, 0x1c0d: 0x0040, 0x1c0e: 0x1f41, 0x1c0f: 0x00c9, 0x1c10: 0x0069, 0x1c11: 0x0079, + 0x1c12: 0x1f51, 0x1c13: 0x1f61, 0x1c14: 0x1f71, 0x1c15: 0x1f81, 0x1c16: 0x1f91, 0x1c17: 0x1fa1, + 0x1c18: 0x1f41, 0x1c19: 0x00c9, 0x1c1a: 0x0069, 0x1c1b: 0x0079, 0x1c1c: 0x1f51, 0x1c1d: 0x1f61, + 0x1c1e: 0x1f71, 0x1c1f: 0x1f81, 0x1c20: 0x1f91, 0x1c21: 0x1fa1, 0x1c22: 0x1f41, 0x1c23: 0x00c9, + 0x1c24: 0x0069, 0x1c25: 0x0079, 0x1c26: 0x1f51, 0x1c27: 0x1f61, 0x1c28: 0x1f71, 0x1c29: 0x1f81, + 0x1c2a: 0x1f91, 0x1c2b: 0x1fa1, 0x1c2c: 0x1f41, 0x1c2d: 0x00c9, 0x1c2e: 0x0069, 0x1c2f: 0x0079, + 0x1c30: 0x1f51, 0x1c31: 0x1f61, 0x1c32: 0x1f71, 0x1c33: 0x1f81, 0x1c34: 0x1f91, 0x1c35: 0x1fa1, + 0x1c36: 0x1f41, 0x1c37: 0x00c9, 0x1c38: 0x0069, 0x1c39: 0x0079, 0x1c3a: 0x1f51, 0x1c3b: 0x1f61, + 0x1c3c: 0x1f71, 0x1c3d: 0x1f81, 0x1c3e: 0x1f91, 0x1c3f: 0x1fa1, + // Block 0x71, offset 0x1c40 + 0x1c40: 0xe115, 0x1c41: 0xe115, 0x1c42: 0xe135, 0x1c43: 0xe135, 0x1c44: 0xe115, 0x1c45: 0xe115, + 0x1c46: 0xe175, 0x1c47: 0xe175, 0x1c48: 0xe115, 0x1c49: 0xe115, 0x1c4a: 0xe135, 0x1c4b: 0xe135, + 0x1c4c: 0xe115, 0x1c4d: 0xe115, 0x1c4e: 0xe1f5, 0x1c4f: 0xe1f5, 0x1c50: 0xe115, 0x1c51: 0xe115, + 0x1c52: 0xe135, 0x1c53: 0xe135, 0x1c54: 0xe115, 0x1c55: 0xe115, 0x1c56: 0xe175, 0x1c57: 0xe175, + 0x1c58: 0xe115, 0x1c59: 0xe115, 0x1c5a: 0xe135, 0x1c5b: 0xe135, 0x1c5c: 0xe115, 0x1c5d: 0xe115, + 0x1c5e: 0x8b3d, 0x1c5f: 0x8b3d, 0x1c60: 0x04b5, 0x1c61: 0x04b5, 0x1c62: 0x0a08, 0x1c63: 0x0a08, + 0x1c64: 0x0a08, 0x1c65: 0x0a08, 0x1c66: 0x0a08, 0x1c67: 0x0a08, 0x1c68: 0x0a08, 0x1c69: 0x0a08, + 0x1c6a: 0x0a08, 0x1c6b: 0x0a08, 0x1c6c: 0x0a08, 0x1c6d: 0x0a08, 0x1c6e: 0x0a08, 0x1c6f: 0x0a08, + 0x1c70: 0x0a08, 0x1c71: 0x0a08, 0x1c72: 0x0a08, 0x1c73: 0x0a08, 0x1c74: 0x0a08, 0x1c75: 0x0a08, + 0x1c76: 0x0a08, 0x1c77: 0x0a08, 0x1c78: 0x0a08, 0x1c79: 0x0a08, 0x1c7a: 0x0a08, 0x1c7b: 0x0a08, + 0x1c7c: 0x0a08, 0x1c7d: 0x0a08, 0x1c7e: 0x0a08, 0x1c7f: 0x0a08, + // Block 0x72, offset 0x1c80 + 0x1c80: 0xb189, 0x1c81: 0xb1a1, 0x1c82: 0xb201, 0x1c83: 0xb249, 0x1c84: 0x0040, 0x1c85: 0xb411, + 0x1c86: 0xb291, 0x1c87: 0xb219, 0x1c88: 0xb309, 0x1c89: 0xb429, 0x1c8a: 0xb399, 0x1c8b: 0xb3b1, + 0x1c8c: 0xb3c9, 0x1c8d: 0xb3e1, 0x1c8e: 0xb2a9, 0x1c8f: 0xb339, 0x1c90: 0xb369, 0x1c91: 0xb2d9, + 0x1c92: 0xb381, 0x1c93: 0xb279, 0x1c94: 0xb2c1, 0x1c95: 0xb1d1, 0x1c96: 0xb1e9, 0x1c97: 0xb231, + 0x1c98: 0xb261, 0x1c99: 0xb2f1, 0x1c9a: 0xb321, 0x1c9b: 0xb351, 0x1c9c: 0xbc59, 0x1c9d: 0x7949, + 0x1c9e: 0xbc71, 0x1c9f: 0xbc89, 0x1ca0: 0x0040, 0x1ca1: 0xb1a1, 0x1ca2: 0xb201, 0x1ca3: 0x0040, + 0x1ca4: 0xb3f9, 0x1ca5: 0x0040, 0x1ca6: 0x0040, 0x1ca7: 0xb219, 0x1ca8: 0x0040, 0x1ca9: 0xb429, + 0x1caa: 0xb399, 0x1cab: 0xb3b1, 0x1cac: 0xb3c9, 0x1cad: 0xb3e1, 0x1cae: 0xb2a9, 0x1caf: 0xb339, + 0x1cb0: 0xb369, 0x1cb1: 0xb2d9, 0x1cb2: 0xb381, 0x1cb3: 0x0040, 0x1cb4: 0xb2c1, 0x1cb5: 0xb1d1, + 0x1cb6: 0xb1e9, 0x1cb7: 0xb231, 0x1cb8: 0x0040, 0x1cb9: 0xb2f1, 0x1cba: 0x0040, 0x1cbb: 0xb351, + 0x1cbc: 0x0040, 0x1cbd: 0x0040, 0x1cbe: 0x0040, 0x1cbf: 0x0040, + // Block 0x73, offset 0x1cc0 + 0x1cc0: 0x0040, 0x1cc1: 0x0040, 0x1cc2: 0xb201, 0x1cc3: 0x0040, 0x1cc4: 0x0040, 0x1cc5: 0x0040, + 0x1cc6: 0x0040, 0x1cc7: 0xb219, 0x1cc8: 0x0040, 0x1cc9: 0xb429, 0x1cca: 0x0040, 0x1ccb: 0xb3b1, + 0x1ccc: 0x0040, 0x1ccd: 0xb3e1, 0x1cce: 0xb2a9, 0x1ccf: 0xb339, 0x1cd0: 0x0040, 0x1cd1: 0xb2d9, + 0x1cd2: 0xb381, 0x1cd3: 0x0040, 0x1cd4: 0xb2c1, 0x1cd5: 0x0040, 0x1cd6: 0x0040, 0x1cd7: 0xb231, + 0x1cd8: 0x0040, 0x1cd9: 0xb2f1, 0x1cda: 0x0040, 0x1cdb: 0xb351, 0x1cdc: 0x0040, 0x1cdd: 0x7949, + 0x1cde: 0x0040, 0x1cdf: 0xbc89, 0x1ce0: 0x0040, 0x1ce1: 0xb1a1, 0x1ce2: 0xb201, 0x1ce3: 0x0040, + 0x1ce4: 0xb3f9, 0x1ce5: 0x0040, 0x1ce6: 0x0040, 0x1ce7: 0xb219, 0x1ce8: 0xb309, 0x1ce9: 0xb429, + 0x1cea: 0xb399, 0x1ceb: 0x0040, 0x1cec: 0xb3c9, 0x1ced: 0xb3e1, 0x1cee: 0xb2a9, 0x1cef: 0xb339, + 0x1cf0: 0xb369, 0x1cf1: 0xb2d9, 0x1cf2: 0xb381, 0x1cf3: 0x0040, 0x1cf4: 0xb2c1, 0x1cf5: 0xb1d1, + 0x1cf6: 0xb1e9, 0x1cf7: 0xb231, 0x1cf8: 0x0040, 0x1cf9: 0xb2f1, 0x1cfa: 0xb321, 0x1cfb: 0xb351, + 0x1cfc: 0xbc59, 0x1cfd: 0x0040, 0x1cfe: 0xbc71, 0x1cff: 0x0040, + // Block 0x74, offset 0x1d00 + 0x1d00: 0xb189, 0x1d01: 0xb1a1, 0x1d02: 0xb201, 0x1d03: 0xb249, 0x1d04: 0xb3f9, 0x1d05: 0xb411, + 0x1d06: 0xb291, 0x1d07: 0xb219, 0x1d08: 0xb309, 0x1d09: 0xb429, 0x1d0a: 0x0040, 0x1d0b: 0xb3b1, + 0x1d0c: 0xb3c9, 0x1d0d: 0xb3e1, 0x1d0e: 0xb2a9, 0x1d0f: 0xb339, 0x1d10: 0xb369, 0x1d11: 0xb2d9, + 0x1d12: 0xb381, 0x1d13: 0xb279, 0x1d14: 0xb2c1, 0x1d15: 0xb1d1, 0x1d16: 0xb1e9, 0x1d17: 0xb231, + 0x1d18: 0xb261, 0x1d19: 0xb2f1, 0x1d1a: 0xb321, 0x1d1b: 0xb351, 0x1d1c: 0x0040, 0x1d1d: 0x0040, + 0x1d1e: 0x0040, 0x1d1f: 0x0040, 0x1d20: 0x0040, 0x1d21: 0xb1a1, 0x1d22: 0xb201, 0x1d23: 0xb249, + 0x1d24: 0x0040, 0x1d25: 0xb411, 0x1d26: 0xb291, 0x1d27: 0xb219, 0x1d28: 0xb309, 0x1d29: 0xb429, + 0x1d2a: 0x0040, 0x1d2b: 0xb3b1, 0x1d2c: 0xb3c9, 0x1d2d: 0xb3e1, 0x1d2e: 0xb2a9, 0x1d2f: 0xb339, + 0x1d30: 0xb369, 0x1d31: 0xb2d9, 0x1d32: 0xb381, 0x1d33: 0xb279, 0x1d34: 0xb2c1, 0x1d35: 0xb1d1, + 0x1d36: 0xb1e9, 0x1d37: 0xb231, 0x1d38: 0xb261, 0x1d39: 0xb2f1, 0x1d3a: 0xb321, 0x1d3b: 0xb351, + 0x1d3c: 0x0040, 0x1d3d: 0x0040, 0x1d3e: 0x0040, 0x1d3f: 0x0040, + // Block 0x75, offset 0x1d40 + 0x1d40: 0x0040, 0x1d41: 0xbca2, 0x1d42: 0xbcba, 0x1d43: 0xbcd2, 0x1d44: 0xbcea, 0x1d45: 0xbd02, + 0x1d46: 0xbd1a, 0x1d47: 0xbd32, 0x1d48: 0xbd4a, 0x1d49: 0xbd62, 0x1d4a: 0xbd7a, 0x1d4b: 0x0018, + 0x1d4c: 0x0018, 0x1d4d: 0x0040, 0x1d4e: 0x0040, 0x1d4f: 0x0040, 0x1d50: 0xbd92, 0x1d51: 0xbdb2, + 0x1d52: 0xbdd2, 0x1d53: 0xbdf2, 0x1d54: 0xbe12, 0x1d55: 0xbe32, 0x1d56: 0xbe52, 0x1d57: 0xbe72, + 0x1d58: 0xbe92, 0x1d59: 0xbeb2, 0x1d5a: 0xbed2, 0x1d5b: 0xbef2, 0x1d5c: 0xbf12, 0x1d5d: 0xbf32, + 0x1d5e: 0xbf52, 0x1d5f: 0xbf72, 0x1d60: 0xbf92, 0x1d61: 0xbfb2, 0x1d62: 0xbfd2, 0x1d63: 0xbff2, + 0x1d64: 0xc012, 0x1d65: 0xc032, 0x1d66: 0xc052, 0x1d67: 0xc072, 0x1d68: 0xc092, 0x1d69: 0xc0b2, + 0x1d6a: 0xc0d1, 0x1d6b: 0x1159, 0x1d6c: 0x0269, 0x1d6d: 0x6671, 0x1d6e: 0xc111, 0x1d6f: 0x0018, + 0x1d70: 0x0039, 0x1d71: 0x0ee9, 0x1d72: 0x1159, 0x1d73: 0x0ef9, 0x1d74: 0x0f09, 0x1d75: 0x1199, + 0x1d76: 0x0f31, 0x1d77: 0x0249, 0x1d78: 0x0f41, 0x1d79: 0x0259, 0x1d7a: 0x0f51, 0x1d7b: 0x0359, + 0x1d7c: 0x0f61, 0x1d7d: 0x0f71, 0x1d7e: 0x00d9, 0x1d7f: 0x0f99, + // Block 0x76, offset 0x1d80 + 0x1d80: 0x2039, 0x1d81: 0x0269, 0x1d82: 0x01d9, 0x1d83: 0x0fa9, 0x1d84: 0x0fb9, 0x1d85: 0x1089, + 0x1d86: 0x0279, 0x1d87: 0x0369, 0x1d88: 0x0289, 0x1d89: 0x13d1, 0x1d8a: 0xc129, 0x1d8b: 0x65b1, + 0x1d8c: 0xc141, 0x1d8d: 0x1441, 0x1d8e: 0xc159, 0x1d8f: 0xc179, 0x1d90: 0x0018, 0x1d91: 0x0018, + 0x1d92: 0x0018, 0x1d93: 0x0018, 0x1d94: 0x0018, 0x1d95: 0x0018, 0x1d96: 0x0018, 0x1d97: 0x0018, + 0x1d98: 0x0018, 0x1d99: 0x0018, 0x1d9a: 0x0018, 0x1d9b: 0x0018, 0x1d9c: 0x0018, 0x1d9d: 0x0018, + 0x1d9e: 0x0018, 0x1d9f: 0x0018, 0x1da0: 0x0018, 0x1da1: 0x0018, 0x1da2: 0x0018, 0x1da3: 0x0018, + 0x1da4: 0x0018, 0x1da5: 0x0018, 0x1da6: 0x0018, 0x1da7: 0x0018, 0x1da8: 0x0018, 0x1da9: 0x0018, + 0x1daa: 0xc191, 0x1dab: 0xc1a9, 0x1dac: 0xc1c1, 0x1dad: 0x0040, 0x1dae: 0x0040, 0x1daf: 0x0040, + 0x1db0: 0x0018, 0x1db1: 0x0018, 0x1db2: 0x0018, 0x1db3: 0x0018, 0x1db4: 0x0018, 0x1db5: 0x0018, + 0x1db6: 0x0018, 0x1db7: 0x0018, 0x1db8: 0x0018, 0x1db9: 0x0018, 0x1dba: 0x0018, 0x1dbb: 0x0018, + 0x1dbc: 0x0018, 0x1dbd: 0x0018, 0x1dbe: 0x0018, 0x1dbf: 0x0018, + // Block 0x77, offset 0x1dc0 + 0x1dc0: 0xc1f1, 0x1dc1: 0xc229, 0x1dc2: 0xc261, 0x1dc3: 0x0040, 0x1dc4: 0x0040, 0x1dc5: 0x0040, + 0x1dc6: 0x0040, 0x1dc7: 0x0040, 0x1dc8: 0x0040, 0x1dc9: 0x0040, 0x1dca: 0x0040, 0x1dcb: 0x0040, + 0x1dcc: 0x0040, 0x1dcd: 0x0040, 0x1dce: 0x0040, 0x1dcf: 0x0040, 0x1dd0: 0xc281, 0x1dd1: 0xc2a1, + 0x1dd2: 0xc2c1, 0x1dd3: 0xc2e1, 0x1dd4: 0xc301, 0x1dd5: 0xc321, 0x1dd6: 0xc341, 0x1dd7: 0xc361, + 0x1dd8: 0xc381, 0x1dd9: 0xc3a1, 0x1dda: 0xc3c1, 0x1ddb: 0xc3e1, 0x1ddc: 0xc401, 0x1ddd: 0xc421, + 0x1dde: 0xc441, 0x1ddf: 0xc461, 0x1de0: 0xc481, 0x1de1: 0xc4a1, 0x1de2: 0xc4c1, 0x1de3: 0xc4e1, + 0x1de4: 0xc501, 0x1de5: 0xc521, 0x1de6: 0xc541, 0x1de7: 0xc561, 0x1de8: 0xc581, 0x1de9: 0xc5a1, + 0x1dea: 0xc5c1, 0x1deb: 0xc5e1, 0x1dec: 0xc601, 0x1ded: 0xc621, 0x1dee: 0xc641, 0x1def: 0xc661, + 0x1df0: 0xc681, 0x1df1: 0xc6a1, 0x1df2: 0xc6c1, 0x1df3: 0xc6e1, 0x1df4: 0xc701, 0x1df5: 0xc721, + 0x1df6: 0xc741, 0x1df7: 0xc761, 0x1df8: 0xc781, 0x1df9: 0xc7a1, 0x1dfa: 0xc7c1, 0x1dfb: 0xc7e1, + 0x1dfc: 0x0040, 0x1dfd: 0x0040, 0x1dfe: 0x0040, 0x1dff: 0x0040, + // Block 0x78, offset 0x1e00 + 0x1e00: 0xcb11, 0x1e01: 0xcb31, 0x1e02: 0xcb51, 0x1e03: 0x8b55, 0x1e04: 0xcb71, 0x1e05: 0xcb91, + 0x1e06: 0xcbb1, 0x1e07: 0xcbd1, 0x1e08: 0xcbf1, 0x1e09: 0xcc11, 0x1e0a: 0xcc31, 0x1e0b: 0xcc51, + 0x1e0c: 0xcc71, 0x1e0d: 0x8b75, 0x1e0e: 0xcc91, 0x1e0f: 0xccb1, 0x1e10: 0xccd1, 0x1e11: 0xccf1, + 0x1e12: 0x8b95, 0x1e13: 0xcd11, 0x1e14: 0xcd31, 0x1e15: 0xc441, 0x1e16: 0x8bb5, 0x1e17: 0xcd51, + 0x1e18: 0xcd71, 0x1e19: 0xcd91, 0x1e1a: 0xcdb1, 0x1e1b: 0xcdd1, 0x1e1c: 0x8bd5, 0x1e1d: 0xcdf1, + 0x1e1e: 0xce11, 0x1e1f: 0xce31, 0x1e20: 0xce51, 0x1e21: 0xce71, 0x1e22: 0xc7a1, 0x1e23: 0xce91, + 0x1e24: 0xceb1, 0x1e25: 0xced1, 0x1e26: 0xcef1, 0x1e27: 0xcf11, 0x1e28: 0xcf31, 0x1e29: 0xcf51, + 0x1e2a: 0xcf71, 0x1e2b: 0xcf91, 0x1e2c: 0xcfb1, 0x1e2d: 0xcfd1, 0x1e2e: 0xcff1, 0x1e2f: 0xd011, + 0x1e30: 0xd031, 0x1e31: 0xd051, 0x1e32: 0xd051, 0x1e33: 0xd051, 0x1e34: 0x8bf5, 0x1e35: 0xd071, + 0x1e36: 0xd091, 0x1e37: 0xd0b1, 0x1e38: 0x8c15, 0x1e39: 0xd0d1, 0x1e3a: 0xd0f1, 0x1e3b: 0xd111, + 0x1e3c: 0xd131, 0x1e3d: 0xd151, 0x1e3e: 0xd171, 0x1e3f: 0xd191, + // Block 0x79, offset 0x1e40 + 0x1e40: 0xd1b1, 0x1e41: 0xd1d1, 0x1e42: 0xd1f1, 0x1e43: 0xd211, 0x1e44: 0xd231, 0x1e45: 0xd251, + 0x1e46: 0xd251, 0x1e47: 0xd271, 0x1e48: 0xd291, 0x1e49: 0xd2b1, 0x1e4a: 0xd2d1, 0x1e4b: 0xd2f1, + 0x1e4c: 0xd311, 0x1e4d: 0xd331, 0x1e4e: 0xd351, 0x1e4f: 0xd371, 0x1e50: 0xd391, 0x1e51: 0xd3b1, + 0x1e52: 0xd3d1, 0x1e53: 0xd3f1, 0x1e54: 0xd411, 0x1e55: 0xd431, 0x1e56: 0xd451, 0x1e57: 0xd471, + 0x1e58: 0xd491, 0x1e59: 0x8c35, 0x1e5a: 0xd4b1, 0x1e5b: 0xd4d1, 0x1e5c: 0xd4f1, 0x1e5d: 0xc321, + 0x1e5e: 0xd511, 0x1e5f: 0xd531, 0x1e60: 0x8c55, 0x1e61: 0x8c75, 0x1e62: 0xd551, 0x1e63: 0xd571, + 0x1e64: 0xd591, 0x1e65: 0xd5b1, 0x1e66: 0xd5d1, 0x1e67: 0xd5f1, 0x1e68: 0x2040, 0x1e69: 0xd611, + 0x1e6a: 0xd631, 0x1e6b: 0xd631, 0x1e6c: 0x8c95, 0x1e6d: 0xd651, 0x1e6e: 0xd671, 0x1e6f: 0xd691, + 0x1e70: 0xd6b1, 0x1e71: 0x8cb5, 0x1e72: 0xd6d1, 0x1e73: 0xd6f1, 0x1e74: 0x2040, 0x1e75: 0xd711, + 0x1e76: 0xd731, 0x1e77: 0xd751, 0x1e78: 0xd771, 0x1e79: 0xd791, 0x1e7a: 0xd7b1, 0x1e7b: 0x8cd5, + 0x1e7c: 0xd7d1, 0x1e7d: 0x8cf5, 0x1e7e: 0xd7f1, 0x1e7f: 0xd811, + // Block 0x7a, offset 0x1e80 + 0x1e80: 0xd831, 0x1e81: 0xd851, 0x1e82: 0xd871, 0x1e83: 0xd891, 0x1e84: 0xd8b1, 0x1e85: 0xd8d1, + 0x1e86: 0xd8f1, 0x1e87: 0xd911, 0x1e88: 0xd931, 0x1e89: 0x8d15, 0x1e8a: 0xd951, 0x1e8b: 0xd971, + 0x1e8c: 0xd991, 0x1e8d: 0xd9b1, 0x1e8e: 0xd9d1, 0x1e8f: 0x8d35, 0x1e90: 0xd9f1, 0x1e91: 0x8d55, + 0x1e92: 0x8d75, 0x1e93: 0xda11, 0x1e94: 0xda31, 0x1e95: 0xda31, 0x1e96: 0xda51, 0x1e97: 0x8d95, + 0x1e98: 0x8db5, 0x1e99: 0xda71, 0x1e9a: 0xda91, 0x1e9b: 0xdab1, 0x1e9c: 0xdad1, 0x1e9d: 0xdaf1, + 0x1e9e: 0xdb11, 0x1e9f: 0xdb31, 0x1ea0: 0xdb51, 0x1ea1: 0xdb71, 0x1ea2: 0xdb91, 0x1ea3: 0xdbb1, + 0x1ea4: 0x8dd5, 0x1ea5: 0xdbd1, 0x1ea6: 0xdbf1, 0x1ea7: 0xdc11, 0x1ea8: 0xdc31, 0x1ea9: 0xdc11, + 0x1eaa: 0xdc51, 0x1eab: 0xdc71, 0x1eac: 0xdc91, 0x1ead: 0xdcb1, 0x1eae: 0xdcd1, 0x1eaf: 0xdcf1, + 0x1eb0: 0xdd11, 0x1eb1: 0xdd31, 0x1eb2: 0xdd51, 0x1eb3: 0xdd71, 0x1eb4: 0xdd91, 0x1eb5: 0xddb1, + 0x1eb6: 0xddd1, 0x1eb7: 0xddf1, 0x1eb8: 0x8df5, 0x1eb9: 0xde11, 0x1eba: 0xde31, 0x1ebb: 0xde51, + 0x1ebc: 0xde71, 0x1ebd: 0xde91, 0x1ebe: 0x8e15, 0x1ebf: 0xdeb1, + // Block 0x7b, offset 0x1ec0 + 0x1ec0: 0xe5b1, 0x1ec1: 0xe5d1, 0x1ec2: 0xe5f1, 0x1ec3: 0xe611, 0x1ec4: 0xe631, 0x1ec5: 0xe651, + 0x1ec6: 0x8f35, 0x1ec7: 0xe671, 0x1ec8: 0xe691, 0x1ec9: 0xe6b1, 0x1eca: 0xe6d1, 0x1ecb: 0xe6f1, + 0x1ecc: 0xe711, 0x1ecd: 0x8f55, 0x1ece: 0xe731, 0x1ecf: 0xe751, 0x1ed0: 0x8f75, 0x1ed1: 0x8f95, + 0x1ed2: 0xe771, 0x1ed3: 0xe791, 0x1ed4: 0xe7b1, 0x1ed5: 0xe7d1, 0x1ed6: 0xe7f1, 0x1ed7: 0xe811, + 0x1ed8: 0xe831, 0x1ed9: 0xe851, 0x1eda: 0xe871, 0x1edb: 0x8fb5, 0x1edc: 0xe891, 0x1edd: 0x8fd5, + 0x1ede: 0xe8b1, 0x1edf: 0x2040, 0x1ee0: 0xe8d1, 0x1ee1: 0xe8f1, 0x1ee2: 0xe911, 0x1ee3: 0x8ff5, + 0x1ee4: 0xe931, 0x1ee5: 0xe951, 0x1ee6: 0x9015, 0x1ee7: 0x9035, 0x1ee8: 0xe971, 0x1ee9: 0xe991, + 0x1eea: 0xe9b1, 0x1eeb: 0xe9d1, 0x1eec: 0xe9f1, 0x1eed: 0xe9f1, 0x1eee: 0xea11, 0x1eef: 0xea31, + 0x1ef0: 0xea51, 0x1ef1: 0xea71, 0x1ef2: 0xea91, 0x1ef3: 0xeab1, 0x1ef4: 0xead1, 0x1ef5: 0x9055, + 0x1ef6: 0xeaf1, 0x1ef7: 0x9075, 0x1ef8: 0xeb11, 0x1ef9: 0x9095, 0x1efa: 0xeb31, 0x1efb: 0x90b5, + 0x1efc: 0x90d5, 0x1efd: 0x90f5, 0x1efe: 0xeb51, 0x1eff: 0xeb71, + // Block 0x7c, offset 0x1f00 + 0x1f00: 0xeb91, 0x1f01: 0x9115, 0x1f02: 0x9135, 0x1f03: 0x9155, 0x1f04: 0x9175, 0x1f05: 0xebb1, + 0x1f06: 0xebd1, 0x1f07: 0xebd1, 0x1f08: 0xebf1, 0x1f09: 0xec11, 0x1f0a: 0xec31, 0x1f0b: 0xec51, + 0x1f0c: 0xec71, 0x1f0d: 0x9195, 0x1f0e: 0xec91, 0x1f0f: 0xecb1, 0x1f10: 0xecd1, 0x1f11: 0xecf1, + 0x1f12: 0x91b5, 0x1f13: 0xed11, 0x1f14: 0x91d5, 0x1f15: 0x91f5, 0x1f16: 0xed31, 0x1f17: 0xed51, + 0x1f18: 0xed71, 0x1f19: 0xed91, 0x1f1a: 0xedb1, 0x1f1b: 0xedd1, 0x1f1c: 0x9215, 0x1f1d: 0x9235, + 0x1f1e: 0x9255, 0x1f1f: 0x2040, 0x1f20: 0xedf1, 0x1f21: 0x9275, 0x1f22: 0xee11, 0x1f23: 0xee31, + 0x1f24: 0xee51, 0x1f25: 0x9295, 0x1f26: 0xee71, 0x1f27: 0xee91, 0x1f28: 0xeeb1, 0x1f29: 0xeed1, + 0x1f2a: 0xeef1, 0x1f2b: 0x92b5, 0x1f2c: 0xef11, 0x1f2d: 0xef31, 0x1f2e: 0xef51, 0x1f2f: 0xef71, + 0x1f30: 0xef91, 0x1f31: 0xefb1, 0x1f32: 0x92d5, 0x1f33: 0x92f5, 0x1f34: 0xefd1, 0x1f35: 0x9315, + 0x1f36: 0xeff1, 0x1f37: 0x9335, 0x1f38: 0xf011, 0x1f39: 0xf031, 0x1f3a: 0xf051, 0x1f3b: 0x9355, + 0x1f3c: 0x9375, 0x1f3d: 0xf071, 0x1f3e: 0x9395, 0x1f3f: 0xf091, + // Block 0x7d, offset 0x1f40 + 0x1f40: 0xf6d1, 0x1f41: 0xf6f1, 0x1f42: 0xf711, 0x1f43: 0xf731, 0x1f44: 0xf751, 0x1f45: 0x9555, + 0x1f46: 0xf771, 0x1f47: 0xf791, 0x1f48: 0xf7b1, 0x1f49: 0xf7d1, 0x1f4a: 0xf7f1, 0x1f4b: 0x9575, + 0x1f4c: 0x9595, 0x1f4d: 0xf811, 0x1f4e: 0xf831, 0x1f4f: 0xf851, 0x1f50: 0xf871, 0x1f51: 0xf891, + 0x1f52: 0xf8b1, 0x1f53: 0x95b5, 0x1f54: 0xf8d1, 0x1f55: 0xf8f1, 0x1f56: 0xf911, 0x1f57: 0xf931, + 0x1f58: 0x95d5, 0x1f59: 0x95f5, 0x1f5a: 0xf951, 0x1f5b: 0xf971, 0x1f5c: 0xf991, 0x1f5d: 0x9615, + 0x1f5e: 0xf9b1, 0x1f5f: 0xf9d1, 0x1f60: 0x684d, 0x1f61: 0x9635, 0x1f62: 0xf9f1, 0x1f63: 0xfa11, + 0x1f64: 0xfa31, 0x1f65: 0x9655, 0x1f66: 0xfa51, 0x1f67: 0xfa71, 0x1f68: 0xfa91, 0x1f69: 0xfab1, + 0x1f6a: 0xfad1, 0x1f6b: 0xfaf1, 0x1f6c: 0xfb11, 0x1f6d: 0x9675, 0x1f6e: 0xfb31, 0x1f6f: 0xfb51, + 0x1f70: 0xfb71, 0x1f71: 0x9695, 0x1f72: 0xfb91, 0x1f73: 0xfbb1, 0x1f74: 0xfbd1, 0x1f75: 0xfbf1, + 0x1f76: 0x7b6d, 0x1f77: 0x96b5, 0x1f78: 0xfc11, 0x1f79: 0xfc31, 0x1f7a: 0xfc51, 0x1f7b: 0x96d5, + 0x1f7c: 0xfc71, 0x1f7d: 0x96f5, 0x1f7e: 0xfc91, 0x1f7f: 0xfc91, + // Block 0x7e, offset 0x1f80 + 0x1f80: 0xfcb1, 0x1f81: 0x9715, 0x1f82: 0xfcd1, 0x1f83: 0xfcf1, 0x1f84: 0xfd11, 0x1f85: 0xfd31, + 0x1f86: 0xfd51, 0x1f87: 0xfd71, 0x1f88: 0xfd91, 0x1f89: 0x9735, 0x1f8a: 0xfdb1, 0x1f8b: 0xfdd1, + 0x1f8c: 0xfdf1, 0x1f8d: 0xfe11, 0x1f8e: 0xfe31, 0x1f8f: 0xfe51, 0x1f90: 0x9755, 0x1f91: 0xfe71, + 0x1f92: 0x9775, 0x1f93: 0x9795, 0x1f94: 0x97b5, 0x1f95: 0xfe91, 0x1f96: 0xfeb1, 0x1f97: 0xfed1, + 0x1f98: 0xfef1, 0x1f99: 0xff11, 0x1f9a: 0xff31, 0x1f9b: 0xff51, 0x1f9c: 0xff71, 0x1f9d: 0x97d5, + 0x1f9e: 0x0040, 0x1f9f: 0x0040, 0x1fa0: 0x0040, 0x1fa1: 0x0040, 0x1fa2: 0x0040, 0x1fa3: 0x0040, + 0x1fa4: 0x0040, 0x1fa5: 0x0040, 0x1fa6: 0x0040, 0x1fa7: 0x0040, 0x1fa8: 0x0040, 0x1fa9: 0x0040, + 0x1faa: 0x0040, 0x1fab: 0x0040, 0x1fac: 0x0040, 0x1fad: 0x0040, 0x1fae: 0x0040, 0x1faf: 0x0040, + 0x1fb0: 0x0040, 0x1fb1: 0x0040, 0x1fb2: 0x0040, 0x1fb3: 0x0040, 0x1fb4: 0x0040, 0x1fb5: 0x0040, + 0x1fb6: 0x0040, 0x1fb7: 0x0040, 0x1fb8: 0x0040, 0x1fb9: 0x0040, 0x1fba: 0x0040, 0x1fbb: 0x0040, + 0x1fbc: 0x0040, 0x1fbd: 0x0040, 0x1fbe: 0x0040, 0x1fbf: 0x0040, +} + +// idnaIndex: 36 blocks, 2304 entries, 4608 bytes +// Block 0 is the zero block. +var idnaIndex = [2304]uint16{ + // Block 0x0, offset 0x0 + // Block 0x1, offset 0x40 + // Block 0x2, offset 0x80 + // Block 0x3, offset 0xc0 + 0xc2: 0x01, 0xc3: 0x7d, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x04, 0xc7: 0x05, + 0xc8: 0x06, 0xc9: 0x7e, 0xca: 0x7f, 0xcb: 0x07, 0xcc: 0x80, 0xcd: 0x08, 0xce: 0x09, 0xcf: 0x0a, + 0xd0: 0x81, 0xd1: 0x0b, 0xd2: 0x0c, 0xd3: 0x0d, 0xd4: 0x0e, 0xd5: 0x82, 0xd6: 0x83, 0xd7: 0x84, + 0xd8: 0x0f, 0xd9: 0x10, 0xda: 0x85, 0xdb: 0x11, 0xdc: 0x12, 0xdd: 0x86, 0xde: 0x87, 0xdf: 0x88, + 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe5: 0x07, 0xe6: 0x07, 0xe7: 0x07, + 0xe8: 0x07, 0xe9: 0x08, 0xea: 0x09, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x0a, 0xee: 0x0b, 0xef: 0x0c, + 0xf0: 0x1d, 0xf1: 0x1e, 0xf2: 0x1e, 0xf3: 0x20, 0xf4: 0x21, + // Block 0x4, offset 0x100 + 0x120: 0x89, 0x121: 0x13, 0x122: 0x8a, 0x123: 0x8b, 0x124: 0x8c, 0x125: 0x14, 0x126: 0x15, 0x127: 0x16, + 0x128: 0x17, 0x129: 0x18, 0x12a: 0x19, 0x12b: 0x1a, 0x12c: 0x1b, 0x12d: 0x1c, 0x12e: 0x1d, 0x12f: 0x8d, + 0x130: 0x8e, 0x131: 0x1e, 0x132: 0x1f, 0x133: 0x20, 0x134: 0x8f, 0x135: 0x21, 0x136: 0x90, 0x137: 0x91, + 0x138: 0x92, 0x139: 0x93, 0x13a: 0x22, 0x13b: 0x94, 0x13c: 0x95, 0x13d: 0x23, 0x13e: 0x24, 0x13f: 0x96, + // Block 0x5, offset 0x140 + 0x140: 0x97, 0x141: 0x98, 0x142: 0x99, 0x143: 0x9a, 0x144: 0x9b, 0x145: 0x9c, 0x146: 0x9d, 0x147: 0x9e, + 0x148: 0x9f, 0x149: 0xa0, 0x14a: 0xa1, 0x14b: 0xa2, 0x14c: 0xa3, 0x14d: 0xa4, 0x14e: 0xa5, 0x14f: 0xa6, + 0x150: 0xa7, 0x151: 0x9f, 0x152: 0x9f, 0x153: 0x9f, 0x154: 0x9f, 0x155: 0x9f, 0x156: 0x9f, 0x157: 0x9f, + 0x158: 0x9f, 0x159: 0xa8, 0x15a: 0xa9, 0x15b: 0xaa, 0x15c: 0xab, 0x15d: 0xac, 0x15e: 0xad, 0x15f: 0xae, + 0x160: 0xaf, 0x161: 0xb0, 0x162: 0xb1, 0x163: 0xb2, 0x164: 0xb3, 0x165: 0xb4, 0x166: 0xb5, 0x167: 0xb6, + 0x168: 0xb7, 0x169: 0xb8, 0x16a: 0xb9, 0x16b: 0xba, 0x16c: 0xbb, 0x16d: 0xbc, 0x16e: 0xbd, 0x16f: 0xbe, + 0x170: 0xbf, 0x171: 0xc0, 0x172: 0xc1, 0x173: 0xc2, 0x174: 0x25, 0x175: 0x26, 0x176: 0x27, 0x177: 0xc3, + 0x178: 0x28, 0x179: 0x28, 0x17a: 0x29, 0x17b: 0x28, 0x17c: 0xc4, 0x17d: 0x2a, 0x17e: 0x2b, 0x17f: 0x2c, + // Block 0x6, offset 0x180 + 0x180: 0x2d, 0x181: 0x2e, 0x182: 0x2f, 0x183: 0xc5, 0x184: 0x30, 0x185: 0x31, 0x186: 0xc6, 0x187: 0x9b, + 0x188: 0xc7, 0x189: 0xc8, 0x18a: 0x9b, 0x18b: 0x9b, 0x18c: 0xc9, 0x18d: 0x9b, 0x18e: 0x9b, 0x18f: 0x9b, + 0x190: 0xca, 0x191: 0x32, 0x192: 0x33, 0x193: 0x34, 0x194: 0x9b, 0x195: 0x9b, 0x196: 0x9b, 0x197: 0x9b, + 0x198: 0x9b, 0x199: 0x9b, 0x19a: 0x9b, 0x19b: 0x9b, 0x19c: 0x9b, 0x19d: 0x9b, 0x19e: 0x9b, 0x19f: 0x9b, + 0x1a0: 0x9b, 0x1a1: 0x9b, 0x1a2: 0x9b, 0x1a3: 0x9b, 0x1a4: 0x9b, 0x1a5: 0x9b, 0x1a6: 0x9b, 0x1a7: 0x9b, + 0x1a8: 0xcb, 0x1a9: 0xcc, 0x1aa: 0x9b, 0x1ab: 0xcd, 0x1ac: 0x9b, 0x1ad: 0xce, 0x1ae: 0xcf, 0x1af: 0x9b, + 0x1b0: 0xd0, 0x1b1: 0x35, 0x1b2: 0x28, 0x1b3: 0x36, 0x1b4: 0xd1, 0x1b5: 0xd2, 0x1b6: 0xd3, 0x1b7: 0xd4, + 0x1b8: 0xd5, 0x1b9: 0xd6, 0x1ba: 0xd7, 0x1bb: 0xd8, 0x1bc: 0xd9, 0x1bd: 0xda, 0x1be: 0xdb, 0x1bf: 0x37, + // Block 0x7, offset 0x1c0 + 0x1c0: 0x38, 0x1c1: 0xdc, 0x1c2: 0xdd, 0x1c3: 0xde, 0x1c4: 0xdf, 0x1c5: 0x39, 0x1c6: 0x3a, 0x1c7: 0xe0, + 0x1c8: 0xe1, 0x1c9: 0x3b, 0x1ca: 0x3c, 0x1cb: 0x3d, 0x1cc: 0x3e, 0x1cd: 0x3f, 0x1ce: 0x40, 0x1cf: 0x41, + 0x1d0: 0x9f, 0x1d1: 0x9f, 0x1d2: 0x9f, 0x1d3: 0x9f, 0x1d4: 0x9f, 0x1d5: 0x9f, 0x1d6: 0x9f, 0x1d7: 0x9f, + 0x1d8: 0x9f, 0x1d9: 0x9f, 0x1da: 0x9f, 0x1db: 0x9f, 0x1dc: 0x9f, 0x1dd: 0x9f, 0x1de: 0x9f, 0x1df: 0x9f, + 0x1e0: 0x9f, 0x1e1: 0x9f, 0x1e2: 0x9f, 0x1e3: 0x9f, 0x1e4: 0x9f, 0x1e5: 0x9f, 0x1e6: 0x9f, 0x1e7: 0x9f, + 0x1e8: 0x9f, 0x1e9: 0x9f, 0x1ea: 0x9f, 0x1eb: 0x9f, 0x1ec: 0x9f, 0x1ed: 0x9f, 0x1ee: 0x9f, 0x1ef: 0x9f, + 0x1f0: 0x9f, 0x1f1: 0x9f, 0x1f2: 0x9f, 0x1f3: 0x9f, 0x1f4: 0x9f, 0x1f5: 0x9f, 0x1f6: 0x9f, 0x1f7: 0x9f, + 0x1f8: 0x9f, 0x1f9: 0x9f, 0x1fa: 0x9f, 0x1fb: 0x9f, 0x1fc: 0x9f, 0x1fd: 0x9f, 0x1fe: 0x9f, 0x1ff: 0x9f, + // Block 0x8, offset 0x200 + 0x200: 0x9f, 0x201: 0x9f, 0x202: 0x9f, 0x203: 0x9f, 0x204: 0x9f, 0x205: 0x9f, 0x206: 0x9f, 0x207: 0x9f, + 0x208: 0x9f, 0x209: 0x9f, 0x20a: 0x9f, 0x20b: 0x9f, 0x20c: 0x9f, 0x20d: 0x9f, 0x20e: 0x9f, 0x20f: 0x9f, + 0x210: 0x9f, 0x211: 0x9f, 0x212: 0x9f, 0x213: 0x9f, 0x214: 0x9f, 0x215: 0x9f, 0x216: 0x9f, 0x217: 0x9f, + 0x218: 0x9f, 0x219: 0x9f, 0x21a: 0x9f, 0x21b: 0x9f, 0x21c: 0x9f, 0x21d: 0x9f, 0x21e: 0x9f, 0x21f: 0x9f, + 0x220: 0x9f, 0x221: 0x9f, 0x222: 0x9f, 0x223: 0x9f, 0x224: 0x9f, 0x225: 0x9f, 0x226: 0x9f, 0x227: 0x9f, + 0x228: 0x9f, 0x229: 0x9f, 0x22a: 0x9f, 0x22b: 0x9f, 0x22c: 0x9f, 0x22d: 0x9f, 0x22e: 0x9f, 0x22f: 0x9f, + 0x230: 0x9f, 0x231: 0x9f, 0x232: 0x9f, 0x233: 0x9f, 0x234: 0x9f, 0x235: 0x9f, 0x236: 0xb2, 0x237: 0x9b, + 0x238: 0x9f, 0x239: 0x9f, 0x23a: 0x9f, 0x23b: 0x9f, 0x23c: 0x9f, 0x23d: 0x9f, 0x23e: 0x9f, 0x23f: 0x9f, + // Block 0x9, offset 0x240 + 0x240: 0x9f, 0x241: 0x9f, 0x242: 0x9f, 0x243: 0x9f, 0x244: 0x9f, 0x245: 0x9f, 0x246: 0x9f, 0x247: 0x9f, + 0x248: 0x9f, 0x249: 0x9f, 0x24a: 0x9f, 0x24b: 0x9f, 0x24c: 0x9f, 0x24d: 0x9f, 0x24e: 0x9f, 0x24f: 0x9f, + 0x250: 0x9f, 0x251: 0x9f, 0x252: 0x9f, 0x253: 0x9f, 0x254: 0x9f, 0x255: 0x9f, 0x256: 0x9f, 0x257: 0x9f, + 0x258: 0x9f, 0x259: 0x9f, 0x25a: 0x9f, 0x25b: 0x9f, 0x25c: 0x9f, 0x25d: 0x9f, 0x25e: 0x9f, 0x25f: 0x9f, + 0x260: 0x9f, 0x261: 0x9f, 0x262: 0x9f, 0x263: 0x9f, 0x264: 0x9f, 0x265: 0x9f, 0x266: 0x9f, 0x267: 0x9f, + 0x268: 0x9f, 0x269: 0x9f, 0x26a: 0x9f, 0x26b: 0x9f, 0x26c: 0x9f, 0x26d: 0x9f, 0x26e: 0x9f, 0x26f: 0x9f, + 0x270: 0x9f, 0x271: 0x9f, 0x272: 0x9f, 0x273: 0x9f, 0x274: 0x9f, 0x275: 0x9f, 0x276: 0x9f, 0x277: 0x9f, + 0x278: 0x9f, 0x279: 0x9f, 0x27a: 0x9f, 0x27b: 0x9f, 0x27c: 0x9f, 0x27d: 0x9f, 0x27e: 0x9f, 0x27f: 0x9f, + // Block 0xa, offset 0x280 + 0x280: 0x9f, 0x281: 0x9f, 0x282: 0x9f, 0x283: 0x9f, 0x284: 0x9f, 0x285: 0x9f, 0x286: 0x9f, 0x287: 0x9f, + 0x288: 0x9f, 0x289: 0x9f, 0x28a: 0x9f, 0x28b: 0x9f, 0x28c: 0x9f, 0x28d: 0x9f, 0x28e: 0x9f, 0x28f: 0x9f, + 0x290: 0x9f, 0x291: 0x9f, 0x292: 0x9f, 0x293: 0x9f, 0x294: 0x9f, 0x295: 0x9f, 0x296: 0x9f, 0x297: 0x9f, + 0x298: 0x9f, 0x299: 0x9f, 0x29a: 0x9f, 0x29b: 0x9f, 0x29c: 0x9f, 0x29d: 0x9f, 0x29e: 0x9f, 0x29f: 0x9f, + 0x2a0: 0x9f, 0x2a1: 0x9f, 0x2a2: 0x9f, 0x2a3: 0x9f, 0x2a4: 0x9f, 0x2a5: 0x9f, 0x2a6: 0x9f, 0x2a7: 0x9f, + 0x2a8: 0x9f, 0x2a9: 0x9f, 0x2aa: 0x9f, 0x2ab: 0x9f, 0x2ac: 0x9f, 0x2ad: 0x9f, 0x2ae: 0x9f, 0x2af: 0x9f, + 0x2b0: 0x9f, 0x2b1: 0x9f, 0x2b2: 0x9f, 0x2b3: 0x9f, 0x2b4: 0x9f, 0x2b5: 0x9f, 0x2b6: 0x9f, 0x2b7: 0x9f, + 0x2b8: 0x9f, 0x2b9: 0x9f, 0x2ba: 0x9f, 0x2bb: 0x9f, 0x2bc: 0x9f, 0x2bd: 0x9f, 0x2be: 0x9f, 0x2bf: 0xe2, + // Block 0xb, offset 0x2c0 + 0x2c0: 0x9f, 0x2c1: 0x9f, 0x2c2: 0x9f, 0x2c3: 0x9f, 0x2c4: 0x9f, 0x2c5: 0x9f, 0x2c6: 0x9f, 0x2c7: 0x9f, + 0x2c8: 0x9f, 0x2c9: 0x9f, 0x2ca: 0x9f, 0x2cb: 0x9f, 0x2cc: 0x9f, 0x2cd: 0x9f, 0x2ce: 0x9f, 0x2cf: 0x9f, + 0x2d0: 0x9f, 0x2d1: 0x9f, 0x2d2: 0xe3, 0x2d3: 0xe4, 0x2d4: 0x9f, 0x2d5: 0x9f, 0x2d6: 0x9f, 0x2d7: 0x9f, + 0x2d8: 0xe5, 0x2d9: 0x42, 0x2da: 0x43, 0x2db: 0xe6, 0x2dc: 0x44, 0x2dd: 0x45, 0x2de: 0x46, 0x2df: 0xe7, + 0x2e0: 0xe8, 0x2e1: 0xe9, 0x2e2: 0xea, 0x2e3: 0xeb, 0x2e4: 0xec, 0x2e5: 0xed, 0x2e6: 0xee, 0x2e7: 0xef, + 0x2e8: 0xf0, 0x2e9: 0xf1, 0x2ea: 0xf2, 0x2eb: 0xf3, 0x2ec: 0xf4, 0x2ed: 0xf5, 0x2ee: 0xf6, 0x2ef: 0xf7, + 0x2f0: 0x9f, 0x2f1: 0x9f, 0x2f2: 0x9f, 0x2f3: 0x9f, 0x2f4: 0x9f, 0x2f5: 0x9f, 0x2f6: 0x9f, 0x2f7: 0x9f, + 0x2f8: 0x9f, 0x2f9: 0x9f, 0x2fa: 0x9f, 0x2fb: 0x9f, 0x2fc: 0x9f, 0x2fd: 0x9f, 0x2fe: 0x9f, 0x2ff: 0x9f, + // Block 0xc, offset 0x300 + 0x300: 0x9f, 0x301: 0x9f, 0x302: 0x9f, 0x303: 0x9f, 0x304: 0x9f, 0x305: 0x9f, 0x306: 0x9f, 0x307: 0x9f, + 0x308: 0x9f, 0x309: 0x9f, 0x30a: 0x9f, 0x30b: 0x9f, 0x30c: 0x9f, 0x30d: 0x9f, 0x30e: 0x9f, 0x30f: 0x9f, + 0x310: 0x9f, 0x311: 0x9f, 0x312: 0x9f, 0x313: 0x9f, 0x314: 0x9f, 0x315: 0x9f, 0x316: 0x9f, 0x317: 0x9f, + 0x318: 0x9f, 0x319: 0x9f, 0x31a: 0x9f, 0x31b: 0x9f, 0x31c: 0x9f, 0x31d: 0x9f, 0x31e: 0xf8, 0x31f: 0xf9, + // Block 0xd, offset 0x340 + 0x340: 0xba, 0x341: 0xba, 0x342: 0xba, 0x343: 0xba, 0x344: 0xba, 0x345: 0xba, 0x346: 0xba, 0x347: 0xba, + 0x348: 0xba, 0x349: 0xba, 0x34a: 0xba, 0x34b: 0xba, 0x34c: 0xba, 0x34d: 0xba, 0x34e: 0xba, 0x34f: 0xba, + 0x350: 0xba, 0x351: 0xba, 0x352: 0xba, 0x353: 0xba, 0x354: 0xba, 0x355: 0xba, 0x356: 0xba, 0x357: 0xba, + 0x358: 0xba, 0x359: 0xba, 0x35a: 0xba, 0x35b: 0xba, 0x35c: 0xba, 0x35d: 0xba, 0x35e: 0xba, 0x35f: 0xba, + 0x360: 0xba, 0x361: 0xba, 0x362: 0xba, 0x363: 0xba, 0x364: 0xba, 0x365: 0xba, 0x366: 0xba, 0x367: 0xba, + 0x368: 0xba, 0x369: 0xba, 0x36a: 0xba, 0x36b: 0xba, 0x36c: 0xba, 0x36d: 0xba, 0x36e: 0xba, 0x36f: 0xba, + 0x370: 0xba, 0x371: 0xba, 0x372: 0xba, 0x373: 0xba, 0x374: 0xba, 0x375: 0xba, 0x376: 0xba, 0x377: 0xba, + 0x378: 0xba, 0x379: 0xba, 0x37a: 0xba, 0x37b: 0xba, 0x37c: 0xba, 0x37d: 0xba, 0x37e: 0xba, 0x37f: 0xba, + // Block 0xe, offset 0x380 + 0x380: 0xba, 0x381: 0xba, 0x382: 0xba, 0x383: 0xba, 0x384: 0xba, 0x385: 0xba, 0x386: 0xba, 0x387: 0xba, + 0x388: 0xba, 0x389: 0xba, 0x38a: 0xba, 0x38b: 0xba, 0x38c: 0xba, 0x38d: 0xba, 0x38e: 0xba, 0x38f: 0xba, + 0x390: 0xba, 0x391: 0xba, 0x392: 0xba, 0x393: 0xba, 0x394: 0xba, 0x395: 0xba, 0x396: 0xba, 0x397: 0xba, + 0x398: 0xba, 0x399: 0xba, 0x39a: 0xba, 0x39b: 0xba, 0x39c: 0xba, 0x39d: 0xba, 0x39e: 0xba, 0x39f: 0xba, + 0x3a0: 0xba, 0x3a1: 0xba, 0x3a2: 0xba, 0x3a3: 0xba, 0x3a4: 0xfa, 0x3a5: 0xfb, 0x3a6: 0xfc, 0x3a7: 0xfd, + 0x3a8: 0x47, 0x3a9: 0xfe, 0x3aa: 0xff, 0x3ab: 0x48, 0x3ac: 0x49, 0x3ad: 0x4a, 0x3ae: 0x4b, 0x3af: 0x4c, + 0x3b0: 0x100, 0x3b1: 0x4d, 0x3b2: 0x4e, 0x3b3: 0x4f, 0x3b4: 0x50, 0x3b5: 0x51, 0x3b6: 0x101, 0x3b7: 0x52, + 0x3b8: 0x53, 0x3b9: 0x54, 0x3ba: 0x55, 0x3bb: 0x56, 0x3bc: 0x57, 0x3bd: 0x58, 0x3be: 0x59, 0x3bf: 0x5a, + // Block 0xf, offset 0x3c0 + 0x3c0: 0x102, 0x3c1: 0x103, 0x3c2: 0x9f, 0x3c3: 0x104, 0x3c4: 0x105, 0x3c5: 0x9b, 0x3c6: 0x106, 0x3c7: 0x107, + 0x3c8: 0xba, 0x3c9: 0xba, 0x3ca: 0x108, 0x3cb: 0x109, 0x3cc: 0x10a, 0x3cd: 0x10b, 0x3ce: 0x10c, 0x3cf: 0x10d, + 0x3d0: 0x10e, 0x3d1: 0x9f, 0x3d2: 0x10f, 0x3d3: 0x110, 0x3d4: 0x111, 0x3d5: 0x112, 0x3d6: 0xba, 0x3d7: 0xba, + 0x3d8: 0x9f, 0x3d9: 0x9f, 0x3da: 0x9f, 0x3db: 0x9f, 0x3dc: 0x113, 0x3dd: 0x114, 0x3de: 0xba, 0x3df: 0xba, + 0x3e0: 0x115, 0x3e1: 0x116, 0x3e2: 0x117, 0x3e3: 0x118, 0x3e4: 0x119, 0x3e5: 0xba, 0x3e6: 0x11a, 0x3e7: 0x11b, + 0x3e8: 0x11c, 0x3e9: 0x11d, 0x3ea: 0x11e, 0x3eb: 0x5b, 0x3ec: 0x11f, 0x3ed: 0x120, 0x3ee: 0x5c, 0x3ef: 0xba, + 0x3f0: 0x121, 0x3f1: 0x122, 0x3f2: 0x123, 0x3f3: 0x124, 0x3f4: 0x125, 0x3f5: 0xba, 0x3f6: 0xba, 0x3f7: 0xba, + 0x3f8: 0xba, 0x3f9: 0x126, 0x3fa: 0xba, 0x3fb: 0xba, 0x3fc: 0x127, 0x3fd: 0x128, 0x3fe: 0xba, 0x3ff: 0x129, + // Block 0x10, offset 0x400 + 0x400: 0x12a, 0x401: 0x12b, 0x402: 0x12c, 0x403: 0x12d, 0x404: 0x12e, 0x405: 0x12f, 0x406: 0x130, 0x407: 0x131, + 0x408: 0x132, 0x409: 0xba, 0x40a: 0x133, 0x40b: 0x134, 0x40c: 0x5d, 0x40d: 0x5e, 0x40e: 0xba, 0x40f: 0xba, + 0x410: 0x135, 0x411: 0x136, 0x412: 0x137, 0x413: 0x138, 0x414: 0xba, 0x415: 0xba, 0x416: 0x139, 0x417: 0x13a, + 0x418: 0x13b, 0x419: 0x13c, 0x41a: 0x13d, 0x41b: 0x13e, 0x41c: 0x13f, 0x41d: 0xba, 0x41e: 0xba, 0x41f: 0xba, + 0x420: 0x140, 0x421: 0xba, 0x422: 0x141, 0x423: 0x142, 0x424: 0xba, 0x425: 0xba, 0x426: 0x143, 0x427: 0x144, + 0x428: 0x145, 0x429: 0x146, 0x42a: 0x147, 0x42b: 0x148, 0x42c: 0xba, 0x42d: 0xba, 0x42e: 0xba, 0x42f: 0xba, + 0x430: 0x149, 0x431: 0x14a, 0x432: 0x14b, 0x433: 0xba, 0x434: 0x14c, 0x435: 0x14d, 0x436: 0x14e, 0x437: 0xba, + 0x438: 0xba, 0x439: 0xba, 0x43a: 0xba, 0x43b: 0x14f, 0x43c: 0xba, 0x43d: 0xba, 0x43e: 0xba, 0x43f: 0x150, + // Block 0x11, offset 0x440 + 0x440: 0x9f, 0x441: 0x9f, 0x442: 0x9f, 0x443: 0x9f, 0x444: 0x9f, 0x445: 0x9f, 0x446: 0x9f, 0x447: 0x9f, + 0x448: 0x9f, 0x449: 0x9f, 0x44a: 0x9f, 0x44b: 0x9f, 0x44c: 0x9f, 0x44d: 0x9f, 0x44e: 0x151, 0x44f: 0xba, + 0x450: 0x9b, 0x451: 0x152, 0x452: 0x9f, 0x453: 0x9f, 0x454: 0x9f, 0x455: 0x153, 0x456: 0xba, 0x457: 0xba, + 0x458: 0xba, 0x459: 0xba, 0x45a: 0xba, 0x45b: 0xba, 0x45c: 0xba, 0x45d: 0xba, 0x45e: 0xba, 0x45f: 0xba, + 0x460: 0xba, 0x461: 0xba, 0x462: 0xba, 0x463: 0xba, 0x464: 0xba, 0x465: 0xba, 0x466: 0xba, 0x467: 0xba, + 0x468: 0xba, 0x469: 0xba, 0x46a: 0xba, 0x46b: 0xba, 0x46c: 0xba, 0x46d: 0xba, 0x46e: 0xba, 0x46f: 0xba, + 0x470: 0xba, 0x471: 0xba, 0x472: 0xba, 0x473: 0xba, 0x474: 0xba, 0x475: 0xba, 0x476: 0xba, 0x477: 0xba, + 0x478: 0xba, 0x479: 0xba, 0x47a: 0xba, 0x47b: 0xba, 0x47c: 0xba, 0x47d: 0xba, 0x47e: 0xba, 0x47f: 0xba, + // Block 0x12, offset 0x480 + 0x480: 0x9f, 0x481: 0x9f, 0x482: 0x9f, 0x483: 0x9f, 0x484: 0x9f, 0x485: 0x9f, 0x486: 0x9f, 0x487: 0x9f, + 0x488: 0x9f, 0x489: 0x9f, 0x48a: 0x9f, 0x48b: 0x9f, 0x48c: 0x9f, 0x48d: 0x9f, 0x48e: 0x9f, 0x48f: 0x9f, + 0x490: 0x154, 0x491: 0xba, 0x492: 0xba, 0x493: 0xba, 0x494: 0xba, 0x495: 0xba, 0x496: 0xba, 0x497: 0xba, + 0x498: 0xba, 0x499: 0xba, 0x49a: 0xba, 0x49b: 0xba, 0x49c: 0xba, 0x49d: 0xba, 0x49e: 0xba, 0x49f: 0xba, + 0x4a0: 0xba, 0x4a1: 0xba, 0x4a2: 0xba, 0x4a3: 0xba, 0x4a4: 0xba, 0x4a5: 0xba, 0x4a6: 0xba, 0x4a7: 0xba, + 0x4a8: 0xba, 0x4a9: 0xba, 0x4aa: 0xba, 0x4ab: 0xba, 0x4ac: 0xba, 0x4ad: 0xba, 0x4ae: 0xba, 0x4af: 0xba, + 0x4b0: 0xba, 0x4b1: 0xba, 0x4b2: 0xba, 0x4b3: 0xba, 0x4b4: 0xba, 0x4b5: 0xba, 0x4b6: 0xba, 0x4b7: 0xba, + 0x4b8: 0xba, 0x4b9: 0xba, 0x4ba: 0xba, 0x4bb: 0xba, 0x4bc: 0xba, 0x4bd: 0xba, 0x4be: 0xba, 0x4bf: 0xba, + // Block 0x13, offset 0x4c0 + 0x4c0: 0xba, 0x4c1: 0xba, 0x4c2: 0xba, 0x4c3: 0xba, 0x4c4: 0xba, 0x4c5: 0xba, 0x4c6: 0xba, 0x4c7: 0xba, + 0x4c8: 0xba, 0x4c9: 0xba, 0x4ca: 0xba, 0x4cb: 0xba, 0x4cc: 0xba, 0x4cd: 0xba, 0x4ce: 0xba, 0x4cf: 0xba, + 0x4d0: 0x9f, 0x4d1: 0x9f, 0x4d2: 0x9f, 0x4d3: 0x9f, 0x4d4: 0x9f, 0x4d5: 0x9f, 0x4d6: 0x9f, 0x4d7: 0x9f, + 0x4d8: 0x9f, 0x4d9: 0x155, 0x4da: 0xba, 0x4db: 0xba, 0x4dc: 0xba, 0x4dd: 0xba, 0x4de: 0xba, 0x4df: 0xba, + 0x4e0: 0xba, 0x4e1: 0xba, 0x4e2: 0xba, 0x4e3: 0xba, 0x4e4: 0xba, 0x4e5: 0xba, 0x4e6: 0xba, 0x4e7: 0xba, + 0x4e8: 0xba, 0x4e9: 0xba, 0x4ea: 0xba, 0x4eb: 0xba, 0x4ec: 0xba, 0x4ed: 0xba, 0x4ee: 0xba, 0x4ef: 0xba, + 0x4f0: 0xba, 0x4f1: 0xba, 0x4f2: 0xba, 0x4f3: 0xba, 0x4f4: 0xba, 0x4f5: 0xba, 0x4f6: 0xba, 0x4f7: 0xba, + 0x4f8: 0xba, 0x4f9: 0xba, 0x4fa: 0xba, 0x4fb: 0xba, 0x4fc: 0xba, 0x4fd: 0xba, 0x4fe: 0xba, 0x4ff: 0xba, + // Block 0x14, offset 0x500 + 0x500: 0xba, 0x501: 0xba, 0x502: 0xba, 0x503: 0xba, 0x504: 0xba, 0x505: 0xba, 0x506: 0xba, 0x507: 0xba, + 0x508: 0xba, 0x509: 0xba, 0x50a: 0xba, 0x50b: 0xba, 0x50c: 0xba, 0x50d: 0xba, 0x50e: 0xba, 0x50f: 0xba, + 0x510: 0xba, 0x511: 0xba, 0x512: 0xba, 0x513: 0xba, 0x514: 0xba, 0x515: 0xba, 0x516: 0xba, 0x517: 0xba, + 0x518: 0xba, 0x519: 0xba, 0x51a: 0xba, 0x51b: 0xba, 0x51c: 0xba, 0x51d: 0xba, 0x51e: 0xba, 0x51f: 0xba, + 0x520: 0x9f, 0x521: 0x9f, 0x522: 0x9f, 0x523: 0x9f, 0x524: 0x9f, 0x525: 0x9f, 0x526: 0x9f, 0x527: 0x9f, + 0x528: 0x148, 0x529: 0x156, 0x52a: 0xba, 0x52b: 0x157, 0x52c: 0x158, 0x52d: 0x159, 0x52e: 0x15a, 0x52f: 0xba, + 0x530: 0xba, 0x531: 0xba, 0x532: 0xba, 0x533: 0xba, 0x534: 0xba, 0x535: 0xba, 0x536: 0xba, 0x537: 0xba, + 0x538: 0xba, 0x539: 0x15b, 0x53a: 0x15c, 0x53b: 0xba, 0x53c: 0x9f, 0x53d: 0x15d, 0x53e: 0x15e, 0x53f: 0x15f, + // Block 0x15, offset 0x540 + 0x540: 0x9f, 0x541: 0x9f, 0x542: 0x9f, 0x543: 0x9f, 0x544: 0x9f, 0x545: 0x9f, 0x546: 0x9f, 0x547: 0x9f, + 0x548: 0x9f, 0x549: 0x9f, 0x54a: 0x9f, 0x54b: 0x9f, 0x54c: 0x9f, 0x54d: 0x9f, 0x54e: 0x9f, 0x54f: 0x9f, + 0x550: 0x9f, 0x551: 0x9f, 0x552: 0x9f, 0x553: 0x9f, 0x554: 0x9f, 0x555: 0x9f, 0x556: 0x9f, 0x557: 0x9f, + 0x558: 0x9f, 0x559: 0x9f, 0x55a: 0x9f, 0x55b: 0x9f, 0x55c: 0x9f, 0x55d: 0x9f, 0x55e: 0x9f, 0x55f: 0x160, + 0x560: 0x9f, 0x561: 0x9f, 0x562: 0x9f, 0x563: 0x9f, 0x564: 0x9f, 0x565: 0x9f, 0x566: 0x9f, 0x567: 0x9f, + 0x568: 0x9f, 0x569: 0x9f, 0x56a: 0x9f, 0x56b: 0x161, 0x56c: 0xba, 0x56d: 0xba, 0x56e: 0xba, 0x56f: 0xba, + 0x570: 0xba, 0x571: 0xba, 0x572: 0xba, 0x573: 0xba, 0x574: 0xba, 0x575: 0xba, 0x576: 0xba, 0x577: 0xba, + 0x578: 0xba, 0x579: 0xba, 0x57a: 0xba, 0x57b: 0xba, 0x57c: 0xba, 0x57d: 0xba, 0x57e: 0xba, 0x57f: 0xba, + // Block 0x16, offset 0x580 + 0x580: 0x9f, 0x581: 0x9f, 0x582: 0x9f, 0x583: 0x9f, 0x584: 0x162, 0x585: 0x163, 0x586: 0x9f, 0x587: 0x9f, + 0x588: 0x9f, 0x589: 0x9f, 0x58a: 0x9f, 0x58b: 0x164, 0x58c: 0xba, 0x58d: 0xba, 0x58e: 0xba, 0x58f: 0xba, + 0x590: 0xba, 0x591: 0xba, 0x592: 0xba, 0x593: 0xba, 0x594: 0xba, 0x595: 0xba, 0x596: 0xba, 0x597: 0xba, + 0x598: 0xba, 0x599: 0xba, 0x59a: 0xba, 0x59b: 0xba, 0x59c: 0xba, 0x59d: 0xba, 0x59e: 0xba, 0x59f: 0xba, + 0x5a0: 0xba, 0x5a1: 0xba, 0x5a2: 0xba, 0x5a3: 0xba, 0x5a4: 0xba, 0x5a5: 0xba, 0x5a6: 0xba, 0x5a7: 0xba, + 0x5a8: 0xba, 0x5a9: 0xba, 0x5aa: 0xba, 0x5ab: 0xba, 0x5ac: 0xba, 0x5ad: 0xba, 0x5ae: 0xba, 0x5af: 0xba, + 0x5b0: 0x9f, 0x5b1: 0x165, 0x5b2: 0x166, 0x5b3: 0xba, 0x5b4: 0xba, 0x5b5: 0xba, 0x5b6: 0xba, 0x5b7: 0xba, + 0x5b8: 0xba, 0x5b9: 0xba, 0x5ba: 0xba, 0x5bb: 0xba, 0x5bc: 0xba, 0x5bd: 0xba, 0x5be: 0xba, 0x5bf: 0xba, + // Block 0x17, offset 0x5c0 + 0x5c0: 0x9b, 0x5c1: 0x9b, 0x5c2: 0x9b, 0x5c3: 0x167, 0x5c4: 0x168, 0x5c5: 0x169, 0x5c6: 0x16a, 0x5c7: 0x16b, + 0x5c8: 0x9b, 0x5c9: 0x16c, 0x5ca: 0xba, 0x5cb: 0x16d, 0x5cc: 0x9b, 0x5cd: 0x16e, 0x5ce: 0xba, 0x5cf: 0xba, + 0x5d0: 0x5f, 0x5d1: 0x60, 0x5d2: 0x61, 0x5d3: 0x62, 0x5d4: 0x63, 0x5d5: 0x64, 0x5d6: 0x65, 0x5d7: 0x66, + 0x5d8: 0x67, 0x5d9: 0x68, 0x5da: 0x69, 0x5db: 0x6a, 0x5dc: 0x6b, 0x5dd: 0x6c, 0x5de: 0x6d, 0x5df: 0x6e, + 0x5e0: 0x9b, 0x5e1: 0x9b, 0x5e2: 0x9b, 0x5e3: 0x9b, 0x5e4: 0x9b, 0x5e5: 0x9b, 0x5e6: 0x9b, 0x5e7: 0x9b, + 0x5e8: 0x16f, 0x5e9: 0x170, 0x5ea: 0x171, 0x5eb: 0xba, 0x5ec: 0xba, 0x5ed: 0xba, 0x5ee: 0xba, 0x5ef: 0xba, + 0x5f0: 0xba, 0x5f1: 0xba, 0x5f2: 0xba, 0x5f3: 0xba, 0x5f4: 0xba, 0x5f5: 0xba, 0x5f6: 0xba, 0x5f7: 0xba, + 0x5f8: 0xba, 0x5f9: 0xba, 0x5fa: 0xba, 0x5fb: 0xba, 0x5fc: 0xba, 0x5fd: 0xba, 0x5fe: 0xba, 0x5ff: 0xba, + // Block 0x18, offset 0x600 + 0x600: 0x172, 0x601: 0xba, 0x602: 0xba, 0x603: 0xba, 0x604: 0x173, 0x605: 0x174, 0x606: 0xba, 0x607: 0xba, + 0x608: 0xba, 0x609: 0xba, 0x60a: 0xba, 0x60b: 0x175, 0x60c: 0xba, 0x60d: 0xba, 0x60e: 0xba, 0x60f: 0xba, + 0x610: 0xba, 0x611: 0xba, 0x612: 0xba, 0x613: 0xba, 0x614: 0xba, 0x615: 0xba, 0x616: 0xba, 0x617: 0xba, + 0x618: 0xba, 0x619: 0xba, 0x61a: 0xba, 0x61b: 0xba, 0x61c: 0xba, 0x61d: 0xba, 0x61e: 0xba, 0x61f: 0xba, + 0x620: 0x121, 0x621: 0x121, 0x622: 0x121, 0x623: 0x176, 0x624: 0x6f, 0x625: 0x177, 0x626: 0xba, 0x627: 0xba, + 0x628: 0xba, 0x629: 0xba, 0x62a: 0xba, 0x62b: 0xba, 0x62c: 0xba, 0x62d: 0xba, 0x62e: 0xba, 0x62f: 0xba, + 0x630: 0xba, 0x631: 0x178, 0x632: 0x179, 0x633: 0xba, 0x634: 0x17a, 0x635: 0xba, 0x636: 0xba, 0x637: 0xba, + 0x638: 0x70, 0x639: 0x71, 0x63a: 0x72, 0x63b: 0x17b, 0x63c: 0xba, 0x63d: 0xba, 0x63e: 0xba, 0x63f: 0xba, + // Block 0x19, offset 0x640 + 0x640: 0x17c, 0x641: 0x9b, 0x642: 0x17d, 0x643: 0x17e, 0x644: 0x73, 0x645: 0x74, 0x646: 0x17f, 0x647: 0x180, + 0x648: 0x75, 0x649: 0x181, 0x64a: 0xba, 0x64b: 0xba, 0x64c: 0x9b, 0x64d: 0x9b, 0x64e: 0x9b, 0x64f: 0x9b, + 0x650: 0x9b, 0x651: 0x9b, 0x652: 0x9b, 0x653: 0x9b, 0x654: 0x9b, 0x655: 0x9b, 0x656: 0x9b, 0x657: 0x9b, + 0x658: 0x9b, 0x659: 0x9b, 0x65a: 0x9b, 0x65b: 0x182, 0x65c: 0x9b, 0x65d: 0x183, 0x65e: 0x9b, 0x65f: 0x184, + 0x660: 0x185, 0x661: 0x186, 0x662: 0x187, 0x663: 0xba, 0x664: 0x188, 0x665: 0x189, 0x666: 0x18a, 0x667: 0x18b, + 0x668: 0x9b, 0x669: 0x18c, 0x66a: 0x18d, 0x66b: 0xba, 0x66c: 0xba, 0x66d: 0xba, 0x66e: 0xba, 0x66f: 0xba, + 0x670: 0xba, 0x671: 0xba, 0x672: 0xba, 0x673: 0xba, 0x674: 0xba, 0x675: 0xba, 0x676: 0xba, 0x677: 0xba, + 0x678: 0xba, 0x679: 0xba, 0x67a: 0xba, 0x67b: 0xba, 0x67c: 0xba, 0x67d: 0xba, 0x67e: 0xba, 0x67f: 0xba, + // Block 0x1a, offset 0x680 + 0x680: 0x9f, 0x681: 0x9f, 0x682: 0x9f, 0x683: 0x9f, 0x684: 0x9f, 0x685: 0x9f, 0x686: 0x9f, 0x687: 0x9f, + 0x688: 0x9f, 0x689: 0x9f, 0x68a: 0x9f, 0x68b: 0x9f, 0x68c: 0x9f, 0x68d: 0x9f, 0x68e: 0x9f, 0x68f: 0x9f, + 0x690: 0x9f, 0x691: 0x9f, 0x692: 0x9f, 0x693: 0x9f, 0x694: 0x9f, 0x695: 0x9f, 0x696: 0x9f, 0x697: 0x9f, + 0x698: 0x9f, 0x699: 0x9f, 0x69a: 0x9f, 0x69b: 0x18e, 0x69c: 0x9f, 0x69d: 0x9f, 0x69e: 0x9f, 0x69f: 0x9f, + 0x6a0: 0x9f, 0x6a1: 0x9f, 0x6a2: 0x9f, 0x6a3: 0x9f, 0x6a4: 0x9f, 0x6a5: 0x9f, 0x6a6: 0x9f, 0x6a7: 0x9f, + 0x6a8: 0x9f, 0x6a9: 0x9f, 0x6aa: 0x9f, 0x6ab: 0x9f, 0x6ac: 0x9f, 0x6ad: 0x9f, 0x6ae: 0x9f, 0x6af: 0x9f, + 0x6b0: 0x9f, 0x6b1: 0x9f, 0x6b2: 0x9f, 0x6b3: 0x9f, 0x6b4: 0x9f, 0x6b5: 0x9f, 0x6b6: 0x9f, 0x6b7: 0x9f, + 0x6b8: 0x9f, 0x6b9: 0x9f, 0x6ba: 0x9f, 0x6bb: 0x9f, 0x6bc: 0x9f, 0x6bd: 0x9f, 0x6be: 0x9f, 0x6bf: 0x9f, + // Block 0x1b, offset 0x6c0 + 0x6c0: 0x9f, 0x6c1: 0x9f, 0x6c2: 0x9f, 0x6c3: 0x9f, 0x6c4: 0x9f, 0x6c5: 0x9f, 0x6c6: 0x9f, 0x6c7: 0x9f, + 0x6c8: 0x9f, 0x6c9: 0x9f, 0x6ca: 0x9f, 0x6cb: 0x9f, 0x6cc: 0x9f, 0x6cd: 0x9f, 0x6ce: 0x9f, 0x6cf: 0x9f, + 0x6d0: 0x9f, 0x6d1: 0x9f, 0x6d2: 0x9f, 0x6d3: 0x9f, 0x6d4: 0x9f, 0x6d5: 0x9f, 0x6d6: 0x9f, 0x6d7: 0x9f, + 0x6d8: 0x9f, 0x6d9: 0x9f, 0x6da: 0x9f, 0x6db: 0x9f, 0x6dc: 0x18f, 0x6dd: 0x9f, 0x6de: 0x9f, 0x6df: 0x9f, + 0x6e0: 0x190, 0x6e1: 0x9f, 0x6e2: 0x9f, 0x6e3: 0x9f, 0x6e4: 0x9f, 0x6e5: 0x9f, 0x6e6: 0x9f, 0x6e7: 0x9f, + 0x6e8: 0x9f, 0x6e9: 0x9f, 0x6ea: 0x9f, 0x6eb: 0x9f, 0x6ec: 0x9f, 0x6ed: 0x9f, 0x6ee: 0x9f, 0x6ef: 0x9f, + 0x6f0: 0x9f, 0x6f1: 0x9f, 0x6f2: 0x9f, 0x6f3: 0x9f, 0x6f4: 0x9f, 0x6f5: 0x9f, 0x6f6: 0x9f, 0x6f7: 0x9f, + 0x6f8: 0x9f, 0x6f9: 0x9f, 0x6fa: 0x9f, 0x6fb: 0x9f, 0x6fc: 0x9f, 0x6fd: 0x9f, 0x6fe: 0x9f, 0x6ff: 0x9f, + // Block 0x1c, offset 0x700 + 0x700: 0x9f, 0x701: 0x9f, 0x702: 0x9f, 0x703: 0x9f, 0x704: 0x9f, 0x705: 0x9f, 0x706: 0x9f, 0x707: 0x9f, + 0x708: 0x9f, 0x709: 0x9f, 0x70a: 0x9f, 0x70b: 0x9f, 0x70c: 0x9f, 0x70d: 0x9f, 0x70e: 0x9f, 0x70f: 0x9f, + 0x710: 0x9f, 0x711: 0x9f, 0x712: 0x9f, 0x713: 0x9f, 0x714: 0x9f, 0x715: 0x9f, 0x716: 0x9f, 0x717: 0x9f, + 0x718: 0x9f, 0x719: 0x9f, 0x71a: 0x9f, 0x71b: 0x9f, 0x71c: 0x9f, 0x71d: 0x9f, 0x71e: 0x9f, 0x71f: 0x9f, + 0x720: 0x9f, 0x721: 0x9f, 0x722: 0x9f, 0x723: 0x9f, 0x724: 0x9f, 0x725: 0x9f, 0x726: 0x9f, 0x727: 0x9f, + 0x728: 0x9f, 0x729: 0x9f, 0x72a: 0x9f, 0x72b: 0x9f, 0x72c: 0x9f, 0x72d: 0x9f, 0x72e: 0x9f, 0x72f: 0x9f, + 0x730: 0x9f, 0x731: 0x9f, 0x732: 0x9f, 0x733: 0x9f, 0x734: 0x9f, 0x735: 0x9f, 0x736: 0x9f, 0x737: 0x9f, + 0x738: 0x9f, 0x739: 0x9f, 0x73a: 0x191, 0x73b: 0x9f, 0x73c: 0x9f, 0x73d: 0x9f, 0x73e: 0x9f, 0x73f: 0x9f, + // Block 0x1d, offset 0x740 + 0x740: 0x9f, 0x741: 0x9f, 0x742: 0x9f, 0x743: 0x9f, 0x744: 0x9f, 0x745: 0x9f, 0x746: 0x9f, 0x747: 0x9f, + 0x748: 0x9f, 0x749: 0x9f, 0x74a: 0x9f, 0x74b: 0x9f, 0x74c: 0x9f, 0x74d: 0x9f, 0x74e: 0x9f, 0x74f: 0x9f, + 0x750: 0x9f, 0x751: 0x9f, 0x752: 0x9f, 0x753: 0x9f, 0x754: 0x9f, 0x755: 0x9f, 0x756: 0x9f, 0x757: 0x9f, + 0x758: 0x9f, 0x759: 0x9f, 0x75a: 0x9f, 0x75b: 0x9f, 0x75c: 0x9f, 0x75d: 0x9f, 0x75e: 0x9f, 0x75f: 0x9f, + 0x760: 0x9f, 0x761: 0x9f, 0x762: 0x9f, 0x763: 0x9f, 0x764: 0x9f, 0x765: 0x9f, 0x766: 0x9f, 0x767: 0x9f, + 0x768: 0x9f, 0x769: 0x9f, 0x76a: 0x9f, 0x76b: 0x9f, 0x76c: 0x9f, 0x76d: 0x9f, 0x76e: 0x9f, 0x76f: 0x192, + 0x770: 0xba, 0x771: 0xba, 0x772: 0xba, 0x773: 0xba, 0x774: 0xba, 0x775: 0xba, 0x776: 0xba, 0x777: 0xba, + 0x778: 0xba, 0x779: 0xba, 0x77a: 0xba, 0x77b: 0xba, 0x77c: 0xba, 0x77d: 0xba, 0x77e: 0xba, 0x77f: 0xba, + // Block 0x1e, offset 0x780 + 0x780: 0xba, 0x781: 0xba, 0x782: 0xba, 0x783: 0xba, 0x784: 0xba, 0x785: 0xba, 0x786: 0xba, 0x787: 0xba, + 0x788: 0xba, 0x789: 0xba, 0x78a: 0xba, 0x78b: 0xba, 0x78c: 0xba, 0x78d: 0xba, 0x78e: 0xba, 0x78f: 0xba, + 0x790: 0xba, 0x791: 0xba, 0x792: 0xba, 0x793: 0xba, 0x794: 0xba, 0x795: 0xba, 0x796: 0xba, 0x797: 0xba, + 0x798: 0xba, 0x799: 0xba, 0x79a: 0xba, 0x79b: 0xba, 0x79c: 0xba, 0x79d: 0xba, 0x79e: 0xba, 0x79f: 0xba, + 0x7a0: 0x76, 0x7a1: 0x77, 0x7a2: 0x78, 0x7a3: 0x193, 0x7a4: 0x79, 0x7a5: 0x7a, 0x7a6: 0x194, 0x7a7: 0x7b, + 0x7a8: 0x7c, 0x7a9: 0xba, 0x7aa: 0xba, 0x7ab: 0xba, 0x7ac: 0xba, 0x7ad: 0xba, 0x7ae: 0xba, 0x7af: 0xba, + 0x7b0: 0xba, 0x7b1: 0xba, 0x7b2: 0xba, 0x7b3: 0xba, 0x7b4: 0xba, 0x7b5: 0xba, 0x7b6: 0xba, 0x7b7: 0xba, + 0x7b8: 0xba, 0x7b9: 0xba, 0x7ba: 0xba, 0x7bb: 0xba, 0x7bc: 0xba, 0x7bd: 0xba, 0x7be: 0xba, 0x7bf: 0xba, + // Block 0x1f, offset 0x7c0 + 0x7d0: 0x0d, 0x7d1: 0x0e, 0x7d2: 0x0f, 0x7d3: 0x10, 0x7d4: 0x11, 0x7d5: 0x0b, 0x7d6: 0x12, 0x7d7: 0x07, + 0x7d8: 0x13, 0x7d9: 0x0b, 0x7da: 0x0b, 0x7db: 0x14, 0x7dc: 0x0b, 0x7dd: 0x15, 0x7de: 0x16, 0x7df: 0x17, + 0x7e0: 0x07, 0x7e1: 0x07, 0x7e2: 0x07, 0x7e3: 0x07, 0x7e4: 0x07, 0x7e5: 0x07, 0x7e6: 0x07, 0x7e7: 0x07, + 0x7e8: 0x07, 0x7e9: 0x07, 0x7ea: 0x18, 0x7eb: 0x19, 0x7ec: 0x1a, 0x7ed: 0x07, 0x7ee: 0x1b, 0x7ef: 0x1c, + 0x7f0: 0x0b, 0x7f1: 0x0b, 0x7f2: 0x0b, 0x7f3: 0x0b, 0x7f4: 0x0b, 0x7f5: 0x0b, 0x7f6: 0x0b, 0x7f7: 0x0b, + 0x7f8: 0x0b, 0x7f9: 0x0b, 0x7fa: 0x0b, 0x7fb: 0x0b, 0x7fc: 0x0b, 0x7fd: 0x0b, 0x7fe: 0x0b, 0x7ff: 0x0b, + // Block 0x20, offset 0x800 + 0x800: 0x0b, 0x801: 0x0b, 0x802: 0x0b, 0x803: 0x0b, 0x804: 0x0b, 0x805: 0x0b, 0x806: 0x0b, 0x807: 0x0b, + 0x808: 0x0b, 0x809: 0x0b, 0x80a: 0x0b, 0x80b: 0x0b, 0x80c: 0x0b, 0x80d: 0x0b, 0x80e: 0x0b, 0x80f: 0x0b, + 0x810: 0x0b, 0x811: 0x0b, 0x812: 0x0b, 0x813: 0x0b, 0x814: 0x0b, 0x815: 0x0b, 0x816: 0x0b, 0x817: 0x0b, + 0x818: 0x0b, 0x819: 0x0b, 0x81a: 0x0b, 0x81b: 0x0b, 0x81c: 0x0b, 0x81d: 0x0b, 0x81e: 0x0b, 0x81f: 0x0b, + 0x820: 0x0b, 0x821: 0x0b, 0x822: 0x0b, 0x823: 0x0b, 0x824: 0x0b, 0x825: 0x0b, 0x826: 0x0b, 0x827: 0x0b, + 0x828: 0x0b, 0x829: 0x0b, 0x82a: 0x0b, 0x82b: 0x0b, 0x82c: 0x0b, 0x82d: 0x0b, 0x82e: 0x0b, 0x82f: 0x0b, + 0x830: 0x0b, 0x831: 0x0b, 0x832: 0x0b, 0x833: 0x0b, 0x834: 0x0b, 0x835: 0x0b, 0x836: 0x0b, 0x837: 0x0b, + 0x838: 0x0b, 0x839: 0x0b, 0x83a: 0x0b, 0x83b: 0x0b, 0x83c: 0x0b, 0x83d: 0x0b, 0x83e: 0x0b, 0x83f: 0x0b, + // Block 0x21, offset 0x840 + 0x840: 0x195, 0x841: 0x196, 0x842: 0xba, 0x843: 0xba, 0x844: 0x197, 0x845: 0x197, 0x846: 0x197, 0x847: 0x198, + 0x848: 0xba, 0x849: 0xba, 0x84a: 0xba, 0x84b: 0xba, 0x84c: 0xba, 0x84d: 0xba, 0x84e: 0xba, 0x84f: 0xba, + 0x850: 0xba, 0x851: 0xba, 0x852: 0xba, 0x853: 0xba, 0x854: 0xba, 0x855: 0xba, 0x856: 0xba, 0x857: 0xba, + 0x858: 0xba, 0x859: 0xba, 0x85a: 0xba, 0x85b: 0xba, 0x85c: 0xba, 0x85d: 0xba, 0x85e: 0xba, 0x85f: 0xba, + 0x860: 0xba, 0x861: 0xba, 0x862: 0xba, 0x863: 0xba, 0x864: 0xba, 0x865: 0xba, 0x866: 0xba, 0x867: 0xba, + 0x868: 0xba, 0x869: 0xba, 0x86a: 0xba, 0x86b: 0xba, 0x86c: 0xba, 0x86d: 0xba, 0x86e: 0xba, 0x86f: 0xba, + 0x870: 0xba, 0x871: 0xba, 0x872: 0xba, 0x873: 0xba, 0x874: 0xba, 0x875: 0xba, 0x876: 0xba, 0x877: 0xba, + 0x878: 0xba, 0x879: 0xba, 0x87a: 0xba, 0x87b: 0xba, 0x87c: 0xba, 0x87d: 0xba, 0x87e: 0xba, 0x87f: 0xba, + // Block 0x22, offset 0x880 + 0x880: 0x0b, 0x881: 0x0b, 0x882: 0x0b, 0x883: 0x0b, 0x884: 0x0b, 0x885: 0x0b, 0x886: 0x0b, 0x887: 0x0b, + 0x888: 0x0b, 0x889: 0x0b, 0x88a: 0x0b, 0x88b: 0x0b, 0x88c: 0x0b, 0x88d: 0x0b, 0x88e: 0x0b, 0x88f: 0x0b, + 0x890: 0x0b, 0x891: 0x0b, 0x892: 0x0b, 0x893: 0x0b, 0x894: 0x0b, 0x895: 0x0b, 0x896: 0x0b, 0x897: 0x0b, + 0x898: 0x0b, 0x899: 0x0b, 0x89a: 0x0b, 0x89b: 0x0b, 0x89c: 0x0b, 0x89d: 0x0b, 0x89e: 0x0b, 0x89f: 0x0b, + 0x8a0: 0x1f, 0x8a1: 0x0b, 0x8a2: 0x0b, 0x8a3: 0x0b, 0x8a4: 0x0b, 0x8a5: 0x0b, 0x8a6: 0x0b, 0x8a7: 0x0b, + 0x8a8: 0x0b, 0x8a9: 0x0b, 0x8aa: 0x0b, 0x8ab: 0x0b, 0x8ac: 0x0b, 0x8ad: 0x0b, 0x8ae: 0x0b, 0x8af: 0x0b, + 0x8b0: 0x0b, 0x8b1: 0x0b, 0x8b2: 0x0b, 0x8b3: 0x0b, 0x8b4: 0x0b, 0x8b5: 0x0b, 0x8b6: 0x0b, 0x8b7: 0x0b, + 0x8b8: 0x0b, 0x8b9: 0x0b, 0x8ba: 0x0b, 0x8bb: 0x0b, 0x8bc: 0x0b, 0x8bd: 0x0b, 0x8be: 0x0b, 0x8bf: 0x0b, + // Block 0x23, offset 0x8c0 + 0x8c0: 0x0b, 0x8c1: 0x0b, 0x8c2: 0x0b, 0x8c3: 0x0b, 0x8c4: 0x0b, 0x8c5: 0x0b, 0x8c6: 0x0b, 0x8c7: 0x0b, + 0x8c8: 0x0b, 0x8c9: 0x0b, 0x8ca: 0x0b, 0x8cb: 0x0b, 0x8cc: 0x0b, 0x8cd: 0x0b, 0x8ce: 0x0b, 0x8cf: 0x0b, +} + +// idnaSparseOffset: 284 entries, 568 bytes +var idnaSparseOffset = []uint16{0x0, 0x8, 0x19, 0x25, 0x27, 0x2c, 0x33, 0x3e, 0x4a, 0x4e, 0x5d, 0x62, 0x6c, 0x78, 0x86, 0x8b, 0x94, 0xa4, 0xb2, 0xbe, 0xca, 0xdb, 0xe5, 0xec, 0xf9, 0x10a, 0x111, 0x11c, 0x12b, 0x139, 0x143, 0x145, 0x14a, 0x14d, 0x150, 0x152, 0x15e, 0x169, 0x171, 0x177, 0x17d, 0x182, 0x187, 0x18a, 0x18e, 0x194, 0x199, 0x1a5, 0x1af, 0x1b5, 0x1c6, 0x1d0, 0x1d3, 0x1db, 0x1de, 0x1eb, 0x1f3, 0x1f7, 0x1fe, 0x206, 0x216, 0x222, 0x224, 0x22e, 0x23a, 0x246, 0x252, 0x25a, 0x25f, 0x26c, 0x27d, 0x281, 0x28c, 0x290, 0x299, 0x2a1, 0x2a7, 0x2ac, 0x2af, 0x2b3, 0x2b9, 0x2bd, 0x2c1, 0x2c5, 0x2cb, 0x2d3, 0x2da, 0x2e5, 0x2ef, 0x2f3, 0x2f6, 0x2fc, 0x300, 0x302, 0x305, 0x307, 0x30a, 0x314, 0x317, 0x326, 0x32a, 0x32f, 0x332, 0x336, 0x33b, 0x340, 0x346, 0x352, 0x361, 0x367, 0x36b, 0x37a, 0x37f, 0x387, 0x391, 0x39c, 0x3a4, 0x3b5, 0x3be, 0x3ce, 0x3db, 0x3e5, 0x3ea, 0x3f7, 0x3fb, 0x400, 0x402, 0x406, 0x408, 0x40c, 0x415, 0x41b, 0x41f, 0x42f, 0x439, 0x43e, 0x441, 0x447, 0x44e, 0x453, 0x457, 0x45d, 0x462, 0x46b, 0x470, 0x476, 0x47d, 0x484, 0x48b, 0x48f, 0x494, 0x497, 0x49c, 0x4a8, 0x4ae, 0x4b3, 0x4ba, 0x4c2, 0x4c7, 0x4cb, 0x4db, 0x4e2, 0x4e6, 0x4ea, 0x4f1, 0x4f3, 0x4f6, 0x4f9, 0x4fd, 0x506, 0x50a, 0x512, 0x51a, 0x51e, 0x524, 0x52d, 0x539, 0x540, 0x549, 0x553, 0x55a, 0x568, 0x575, 0x582, 0x58b, 0x58f, 0x59f, 0x5a7, 0x5b2, 0x5bb, 0x5c1, 0x5c9, 0x5d2, 0x5dd, 0x5e0, 0x5ec, 0x5f5, 0x5f8, 0x5fd, 0x602, 0x60f, 0x61a, 0x623, 0x62d, 0x630, 0x63a, 0x643, 0x64f, 0x65c, 0x669, 0x677, 0x67e, 0x682, 0x685, 0x68a, 0x68d, 0x692, 0x695, 0x69c, 0x6a3, 0x6a7, 0x6b2, 0x6b5, 0x6b8, 0x6bb, 0x6c1, 0x6c7, 0x6cd, 0x6d0, 0x6d3, 0x6d6, 0x6dd, 0x6e0, 0x6e5, 0x6ef, 0x6f2, 0x6f6, 0x705, 0x711, 0x715, 0x71a, 0x71e, 0x723, 0x727, 0x72c, 0x735, 0x740, 0x746, 0x74c, 0x752, 0x758, 0x761, 0x764, 0x767, 0x76b, 0x76f, 0x773, 0x779, 0x77f, 0x784, 0x787, 0x797, 0x79e, 0x7a1, 0x7a6, 0x7aa, 0x7b0, 0x7b5, 0x7b9, 0x7bf, 0x7c5, 0x7c9, 0x7d2, 0x7d7, 0x7da, 0x7dd, 0x7e1, 0x7e5, 0x7e8, 0x7f8, 0x809, 0x80e, 0x810, 0x812} + +// idnaSparseValues: 2069 entries, 8276 bytes +var idnaSparseValues = [2069]valueRange{ + // Block 0x0, offset 0x0 + {value: 0x0000, lo: 0x07}, + {value: 0xe105, lo: 0x80, hi: 0x96}, + {value: 0x0018, lo: 0x97, hi: 0x97}, + {value: 0xe105, lo: 0x98, hi: 0x9e}, + {value: 0x001f, lo: 0x9f, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xb7}, + {value: 0x0008, lo: 0xb8, hi: 0xbf}, + // Block 0x1, offset 0x8 + {value: 0x0000, lo: 0x10}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0xe01d, lo: 0x81, hi: 0x81}, + {value: 0x0008, lo: 0x82, hi: 0x82}, + {value: 0x0335, lo: 0x83, hi: 0x83}, + {value: 0x034d, lo: 0x84, hi: 0x84}, + {value: 0x0365, lo: 0x85, hi: 0x85}, + {value: 0xe00d, lo: 0x86, hi: 0x86}, + {value: 0x0008, lo: 0x87, hi: 0x87}, + {value: 0xe00d, lo: 0x88, hi: 0x88}, + {value: 0x0008, lo: 0x89, hi: 0x89}, + {value: 0xe00d, lo: 0x8a, hi: 0x8a}, + {value: 0x0008, lo: 0x8b, hi: 0x8b}, + {value: 0xe00d, lo: 0x8c, hi: 0x8c}, + {value: 0x0008, lo: 0x8d, hi: 0x8d}, + {value: 0xe00d, lo: 0x8e, hi: 0x8e}, + {value: 0x0008, lo: 0x8f, hi: 0xbf}, + // Block 0x2, offset 0x19 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x0249, lo: 0xb0, hi: 0xb0}, + {value: 0x037d, lo: 0xb1, hi: 0xb1}, + {value: 0x0259, lo: 0xb2, hi: 0xb2}, + {value: 0x0269, lo: 0xb3, hi: 0xb3}, + {value: 0x034d, lo: 0xb4, hi: 0xb4}, + {value: 0x0395, lo: 0xb5, hi: 0xb5}, + {value: 0xe1bd, lo: 0xb6, hi: 0xb6}, + {value: 0x0279, lo: 0xb7, hi: 0xb7}, + {value: 0x0289, lo: 0xb8, hi: 0xb8}, + {value: 0x0008, lo: 0xb9, hi: 0xbf}, + // Block 0x3, offset 0x25 + {value: 0x0000, lo: 0x01}, + {value: 0x3308, lo: 0x80, hi: 0xbf}, + // Block 0x4, offset 0x27 + {value: 0x0000, lo: 0x04}, + {value: 0x03f5, lo: 0x80, hi: 0x8f}, + {value: 0xe105, lo: 0x90, hi: 0x9f}, + {value: 0x049d, lo: 0xa0, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x5, offset 0x2c + {value: 0x0000, lo: 0x06}, + {value: 0xe185, lo: 0x80, hi: 0x8f}, + {value: 0x0545, lo: 0x90, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x98}, + {value: 0x0008, lo: 0x99, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x6, offset 0x33 + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0401, lo: 0x87, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x88}, + {value: 0x0018, lo: 0x89, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0x90}, + {value: 0x3308, lo: 0x91, hi: 0xbd}, + {value: 0x0818, lo: 0xbe, hi: 0xbe}, + {value: 0x3308, lo: 0xbf, hi: 0xbf}, + // Block 0x7, offset 0x3e + {value: 0x0000, lo: 0x0b}, + {value: 0x0818, lo: 0x80, hi: 0x80}, + {value: 0x3308, lo: 0x81, hi: 0x82}, + {value: 0x0818, lo: 0x83, hi: 0x83}, + {value: 0x3308, lo: 0x84, hi: 0x85}, + {value: 0x0818, lo: 0x86, hi: 0x86}, + {value: 0x3308, lo: 0x87, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0808, lo: 0x90, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xae}, + {value: 0x0808, lo: 0xaf, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0x8, offset 0x4a + {value: 0x0000, lo: 0x03}, + {value: 0x0a08, lo: 0x80, hi: 0x87}, + {value: 0x0c08, lo: 0x88, hi: 0x99}, + {value: 0x0a08, lo: 0x9a, hi: 0xbf}, + // Block 0x9, offset 0x4e + {value: 0x0000, lo: 0x0e}, + {value: 0x3308, lo: 0x80, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8c}, + {value: 0x0c08, lo: 0x8d, hi: 0x8d}, + {value: 0x0a08, lo: 0x8e, hi: 0x98}, + {value: 0x0c08, lo: 0x99, hi: 0x9b}, + {value: 0x0a08, lo: 0x9c, hi: 0xaa}, + {value: 0x0c08, lo: 0xab, hi: 0xac}, + {value: 0x0a08, lo: 0xad, hi: 0xb0}, + {value: 0x0c08, lo: 0xb1, hi: 0xb1}, + {value: 0x0a08, lo: 0xb2, hi: 0xb2}, + {value: 0x0c08, lo: 0xb3, hi: 0xb4}, + {value: 0x0a08, lo: 0xb5, hi: 0xb7}, + {value: 0x0c08, lo: 0xb8, hi: 0xb9}, + {value: 0x0a08, lo: 0xba, hi: 0xbf}, + // Block 0xa, offset 0x5d + {value: 0x0000, lo: 0x04}, + {value: 0x0808, lo: 0x80, hi: 0xa5}, + {value: 0x3308, lo: 0xa6, hi: 0xb0}, + {value: 0x0808, lo: 0xb1, hi: 0xb1}, + {value: 0x0040, lo: 0xb2, hi: 0xbf}, + // Block 0xb, offset 0x62 + {value: 0x0000, lo: 0x09}, + {value: 0x0808, lo: 0x80, hi: 0x89}, + {value: 0x0a08, lo: 0x8a, hi: 0xaa}, + {value: 0x3308, lo: 0xab, hi: 0xb3}, + {value: 0x0808, lo: 0xb4, hi: 0xb5}, + {value: 0x0018, lo: 0xb6, hi: 0xb9}, + {value: 0x0818, lo: 0xba, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbc}, + {value: 0x3308, lo: 0xbd, hi: 0xbd}, + {value: 0x0818, lo: 0xbe, hi: 0xbf}, + // Block 0xc, offset 0x6c + {value: 0x0000, lo: 0x0b}, + {value: 0x0808, lo: 0x80, hi: 0x95}, + {value: 0x3308, lo: 0x96, hi: 0x99}, + {value: 0x0808, lo: 0x9a, hi: 0x9a}, + {value: 0x3308, lo: 0x9b, hi: 0xa3}, + {value: 0x0808, lo: 0xa4, hi: 0xa4}, + {value: 0x3308, lo: 0xa5, hi: 0xa7}, + {value: 0x0808, lo: 0xa8, hi: 0xa8}, + {value: 0x3308, lo: 0xa9, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x0818, lo: 0xb0, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0xd, offset 0x78 + {value: 0x0000, lo: 0x0d}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0a08, lo: 0xa0, hi: 0xa9}, + {value: 0x0c08, lo: 0xaa, hi: 0xac}, + {value: 0x0808, lo: 0xad, hi: 0xad}, + {value: 0x0c08, lo: 0xae, hi: 0xae}, + {value: 0x0a08, lo: 0xaf, hi: 0xb0}, + {value: 0x0c08, lo: 0xb1, hi: 0xb2}, + {value: 0x0a08, lo: 0xb3, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xb5}, + {value: 0x0a08, lo: 0xb6, hi: 0xb8}, + {value: 0x0c08, lo: 0xb9, hi: 0xb9}, + {value: 0x0a08, lo: 0xba, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0xe, offset 0x86 + {value: 0x0000, lo: 0x04}, + {value: 0x0040, lo: 0x80, hi: 0x92}, + {value: 0x3308, lo: 0x93, hi: 0xa1}, + {value: 0x0840, lo: 0xa2, hi: 0xa2}, + {value: 0x3308, lo: 0xa3, hi: 0xbf}, + // Block 0xf, offset 0x8b + {value: 0x0000, lo: 0x08}, + {value: 0x3308, lo: 0x80, hi: 0x82}, + {value: 0x3008, lo: 0x83, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0xb9}, + {value: 0x3308, lo: 0xba, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbf}, + // Block 0x10, offset 0x94 + {value: 0x0000, lo: 0x0f}, + {value: 0x3308, lo: 0x80, hi: 0x80}, + {value: 0x3008, lo: 0x81, hi: 0x82}, + {value: 0x0040, lo: 0x83, hi: 0x85}, + {value: 0x3008, lo: 0x86, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x3008, lo: 0x8a, hi: 0x8c}, + {value: 0x3b08, lo: 0x8d, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x96}, + {value: 0x3008, lo: 0x97, hi: 0x97}, + {value: 0x0040, lo: 0x98, hi: 0xa5}, + {value: 0x0008, lo: 0xa6, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x11, offset 0xa4 + {value: 0x0000, lo: 0x0d}, + {value: 0x3308, lo: 0x80, hi: 0x80}, + {value: 0x3008, lo: 0x81, hi: 0x83}, + {value: 0x3308, lo: 0x84, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0x8c}, + {value: 0x0040, lo: 0x8d, hi: 0x8d}, + {value: 0x0008, lo: 0x8e, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x91}, + {value: 0x0008, lo: 0x92, hi: 0xa8}, + {value: 0x0040, lo: 0xa9, hi: 0xa9}, + {value: 0x0008, lo: 0xaa, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbd}, + {value: 0x3308, lo: 0xbe, hi: 0xbf}, + // Block 0x12, offset 0xb2 + {value: 0x0000, lo: 0x0b}, + {value: 0x3308, lo: 0x80, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x83}, + {value: 0x0040, lo: 0x84, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0x8c}, + {value: 0x0040, lo: 0x8d, hi: 0x8d}, + {value: 0x0008, lo: 0x8e, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x91}, + {value: 0x0008, lo: 0x92, hi: 0xba}, + {value: 0x3b08, lo: 0xbb, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbf}, + // Block 0x13, offset 0xbe + {value: 0x0000, lo: 0x0b}, + {value: 0x0040, lo: 0x80, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x83}, + {value: 0x0040, lo: 0x84, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x99}, + {value: 0x0008, lo: 0x9a, hi: 0xb1}, + {value: 0x0040, lo: 0xb2, hi: 0xb2}, + {value: 0x0008, lo: 0xb3, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0x14, offset 0xca + {value: 0x0000, lo: 0x10}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x89}, + {value: 0x3b08, lo: 0x8a, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8e}, + {value: 0x3008, lo: 0x8f, hi: 0x91}, + {value: 0x3308, lo: 0x92, hi: 0x94}, + {value: 0x0040, lo: 0x95, hi: 0x95}, + {value: 0x3308, lo: 0x96, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x97}, + {value: 0x3008, lo: 0x98, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xa5}, + {value: 0x0008, lo: 0xa6, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xb1}, + {value: 0x3008, lo: 0xb2, hi: 0xb3}, + {value: 0x0018, lo: 0xb4, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0x15, offset 0xdb + {value: 0x0000, lo: 0x09}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0xb0}, + {value: 0x3308, lo: 0xb1, hi: 0xb1}, + {value: 0x0008, lo: 0xb2, hi: 0xb2}, + {value: 0x08f1, lo: 0xb3, hi: 0xb3}, + {value: 0x3308, lo: 0xb4, hi: 0xb9}, + {value: 0x3b08, lo: 0xba, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbe}, + {value: 0x0018, lo: 0xbf, hi: 0xbf}, + // Block 0x16, offset 0xe5 + {value: 0x0000, lo: 0x06}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x3308, lo: 0x87, hi: 0x8e}, + {value: 0x0018, lo: 0x8f, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0x9b}, + {value: 0x0040, lo: 0x9c, hi: 0xbf}, + // Block 0x17, offset 0xec + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x84}, + {value: 0x0040, lo: 0x85, hi: 0x85}, + {value: 0x0008, lo: 0x86, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x87}, + {value: 0x3308, lo: 0x88, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9b}, + {value: 0x0961, lo: 0x9c, hi: 0x9c}, + {value: 0x0999, lo: 0x9d, hi: 0x9d}, + {value: 0x0008, lo: 0x9e, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0x18, offset 0xf9 + {value: 0x0000, lo: 0x10}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x8a}, + {value: 0x0008, lo: 0x8b, hi: 0x8b}, + {value: 0xe03d, lo: 0x8c, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0x97}, + {value: 0x3308, lo: 0x98, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa9}, + {value: 0x0018, lo: 0xaa, hi: 0xb4}, + {value: 0x3308, lo: 0xb5, hi: 0xb5}, + {value: 0x0018, lo: 0xb6, hi: 0xb6}, + {value: 0x3308, lo: 0xb7, hi: 0xb7}, + {value: 0x0018, lo: 0xb8, hi: 0xb8}, + {value: 0x3308, lo: 0xb9, hi: 0xb9}, + {value: 0x0018, lo: 0xba, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbf}, + // Block 0x19, offset 0x10a + {value: 0x0000, lo: 0x06}, + {value: 0x0018, lo: 0x80, hi: 0x85}, + {value: 0x3308, lo: 0x86, hi: 0x86}, + {value: 0x0018, lo: 0x87, hi: 0x8c}, + {value: 0x0040, lo: 0x8d, hi: 0x8d}, + {value: 0x0018, lo: 0x8e, hi: 0x9a}, + {value: 0x0040, lo: 0x9b, hi: 0xbf}, + // Block 0x1a, offset 0x111 + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0xaa}, + {value: 0x3008, lo: 0xab, hi: 0xac}, + {value: 0x3308, lo: 0xad, hi: 0xb0}, + {value: 0x3008, lo: 0xb1, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb7}, + {value: 0x3008, lo: 0xb8, hi: 0xb8}, + {value: 0x3b08, lo: 0xb9, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbc}, + {value: 0x3308, lo: 0xbd, hi: 0xbe}, + {value: 0x0008, lo: 0xbf, hi: 0xbf}, + // Block 0x1b, offset 0x11c + {value: 0x0000, lo: 0x0e}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0018, lo: 0x8a, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x95}, + {value: 0x3008, lo: 0x96, hi: 0x97}, + {value: 0x3308, lo: 0x98, hi: 0x99}, + {value: 0x0008, lo: 0x9a, hi: 0x9d}, + {value: 0x3308, lo: 0x9e, hi: 0xa0}, + {value: 0x0008, lo: 0xa1, hi: 0xa1}, + {value: 0x3008, lo: 0xa2, hi: 0xa4}, + {value: 0x0008, lo: 0xa5, hi: 0xa6}, + {value: 0x3008, lo: 0xa7, hi: 0xad}, + {value: 0x0008, lo: 0xae, hi: 0xb0}, + {value: 0x3308, lo: 0xb1, hi: 0xb4}, + {value: 0x0008, lo: 0xb5, hi: 0xbf}, + // Block 0x1c, offset 0x12b + {value: 0x0000, lo: 0x0d}, + {value: 0x0008, lo: 0x80, hi: 0x81}, + {value: 0x3308, lo: 0x82, hi: 0x82}, + {value: 0x3008, lo: 0x83, hi: 0x84}, + {value: 0x3308, lo: 0x85, hi: 0x86}, + {value: 0x3008, lo: 0x87, hi: 0x8c}, + {value: 0x3308, lo: 0x8d, hi: 0x8d}, + {value: 0x0008, lo: 0x8e, hi: 0x8e}, + {value: 0x3008, lo: 0x8f, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x3008, lo: 0x9a, hi: 0x9c}, + {value: 0x3308, lo: 0x9d, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0x1d, offset 0x139 + {value: 0x0000, lo: 0x09}, + {value: 0x0040, lo: 0x80, hi: 0x86}, + {value: 0x055d, lo: 0x87, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8c}, + {value: 0x055d, lo: 0x8d, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xba}, + {value: 0x0018, lo: 0xbb, hi: 0xbb}, + {value: 0xe105, lo: 0xbc, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbf}, + // Block 0x1e, offset 0x143 + {value: 0x0000, lo: 0x01}, + {value: 0x0018, lo: 0x80, hi: 0xbf}, + // Block 0x1f, offset 0x145 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0xa0}, + {value: 0x2018, lo: 0xa1, hi: 0xb5}, + {value: 0x0018, lo: 0xb6, hi: 0xbf}, + // Block 0x20, offset 0x14a + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0xa7}, + {value: 0x2018, lo: 0xa8, hi: 0xbf}, + // Block 0x21, offset 0x14d + {value: 0x0000, lo: 0x02}, + {value: 0x2018, lo: 0x80, hi: 0x82}, + {value: 0x0018, lo: 0x83, hi: 0xbf}, + // Block 0x22, offset 0x150 + {value: 0x0000, lo: 0x01}, + {value: 0x0008, lo: 0x80, hi: 0xbf}, + // Block 0x23, offset 0x152 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x0008, lo: 0x8a, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0x98}, + {value: 0x0040, lo: 0x99, hi: 0x99}, + {value: 0x0008, lo: 0x9a, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x24, offset 0x15e + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x0008, lo: 0x8a, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xb0}, + {value: 0x0040, lo: 0xb1, hi: 0xb1}, + {value: 0x0008, lo: 0xb2, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb7}, + {value: 0x0008, lo: 0xb8, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0x25, offset 0x169 + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x0040, lo: 0x81, hi: 0x81}, + {value: 0x0008, lo: 0x82, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0xbf}, + // Block 0x26, offset 0x171 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x91}, + {value: 0x0008, lo: 0x92, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0xbf}, + // Block 0x27, offset 0x177 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x9a}, + {value: 0x0040, lo: 0x9b, hi: 0x9c}, + {value: 0x3308, lo: 0x9d, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbf}, + // Block 0x28, offset 0x17d + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x29, offset 0x182 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb7}, + {value: 0xe045, lo: 0xb8, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0x2a, offset 0x187 + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0xbf}, + // Block 0x2b, offset 0x18a + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xac}, + {value: 0x0018, lo: 0xad, hi: 0xae}, + {value: 0x0008, lo: 0xaf, hi: 0xbf}, + // Block 0x2c, offset 0x18e + {value: 0x0000, lo: 0x05}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0x9c}, + {value: 0x0040, lo: 0x9d, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x2d, offset 0x194 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xaa}, + {value: 0x0018, lo: 0xab, hi: 0xb0}, + {value: 0x0008, lo: 0xb1, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0x2e, offset 0x199 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0x8c}, + {value: 0x0040, lo: 0x8d, hi: 0x8d}, + {value: 0x0008, lo: 0x8e, hi: 0x91}, + {value: 0x3308, lo: 0x92, hi: 0x93}, + {value: 0x3b08, lo: 0x94, hi: 0x94}, + {value: 0x0040, lo: 0x95, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb3}, + {value: 0x3b08, lo: 0xb4, hi: 0xb4}, + {value: 0x0018, lo: 0xb5, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0x2f, offset 0x1a5 + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x91}, + {value: 0x3308, lo: 0x92, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xad}, + {value: 0x0008, lo: 0xae, hi: 0xb0}, + {value: 0x0040, lo: 0xb1, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xbf}, + // Block 0x30, offset 0x1af + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0xb3}, + {value: 0x3340, lo: 0xb4, hi: 0xb5}, + {value: 0x3008, lo: 0xb6, hi: 0xb6}, + {value: 0x3308, lo: 0xb7, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbf}, + // Block 0x31, offset 0x1b5 + {value: 0x0000, lo: 0x10}, + {value: 0x3008, lo: 0x80, hi: 0x85}, + {value: 0x3308, lo: 0x86, hi: 0x86}, + {value: 0x3008, lo: 0x87, hi: 0x88}, + {value: 0x3308, lo: 0x89, hi: 0x91}, + {value: 0x3b08, lo: 0x92, hi: 0x92}, + {value: 0x3308, lo: 0x93, hi: 0x93}, + {value: 0x0018, lo: 0x94, hi: 0x96}, + {value: 0x0008, lo: 0x97, hi: 0x97}, + {value: 0x0018, lo: 0x98, hi: 0x9b}, + {value: 0x0008, lo: 0x9c, hi: 0x9c}, + {value: 0x3308, lo: 0x9d, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa9}, + {value: 0x0040, lo: 0xaa, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0x32, offset 0x1c6 + {value: 0x0000, lo: 0x09}, + {value: 0x0018, lo: 0x80, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x86}, + {value: 0x0218, lo: 0x87, hi: 0x87}, + {value: 0x0018, lo: 0x88, hi: 0x8a}, + {value: 0x33c0, lo: 0x8b, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0208, lo: 0xa0, hi: 0xbf}, + // Block 0x33, offset 0x1d0 + {value: 0x0000, lo: 0x02}, + {value: 0x0208, lo: 0x80, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0x34, offset 0x1d3 + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0x84}, + {value: 0x3308, lo: 0x85, hi: 0x86}, + {value: 0x0208, lo: 0x87, hi: 0xa8}, + {value: 0x3308, lo: 0xa9, hi: 0xa9}, + {value: 0x0208, lo: 0xaa, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x35, offset 0x1db + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xbf}, + // Block 0x36, offset 0x1de + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0x9f}, + {value: 0x3308, lo: 0xa0, hi: 0xa2}, + {value: 0x3008, lo: 0xa3, hi: 0xa6}, + {value: 0x3308, lo: 0xa7, hi: 0xa8}, + {value: 0x3008, lo: 0xa9, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xaf}, + {value: 0x3008, lo: 0xb0, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb2}, + {value: 0x3008, lo: 0xb3, hi: 0xb8}, + {value: 0x3308, lo: 0xb9, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0x37, offset 0x1eb + {value: 0x0000, lo: 0x07}, + {value: 0x0018, lo: 0x80, hi: 0x80}, + {value: 0x0040, lo: 0x81, hi: 0x83}, + {value: 0x0018, lo: 0x84, hi: 0x85}, + {value: 0x0008, lo: 0x86, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0x38, offset 0x1f3 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x39, offset 0x1f7 + {value: 0x0000, lo: 0x06}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0028, lo: 0x9a, hi: 0x9a}, + {value: 0x0040, lo: 0x9b, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0xbf}, + // Block 0x3a, offset 0x1fe + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0x96}, + {value: 0x3308, lo: 0x97, hi: 0x98}, + {value: 0x3008, lo: 0x99, hi: 0x9a}, + {value: 0x3308, lo: 0x9b, hi: 0x9b}, + {value: 0x0040, lo: 0x9c, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x3b, offset 0x206 + {value: 0x0000, lo: 0x0f}, + {value: 0x0008, lo: 0x80, hi: 0x94}, + {value: 0x3008, lo: 0x95, hi: 0x95}, + {value: 0x3308, lo: 0x96, hi: 0x96}, + {value: 0x3008, lo: 0x97, hi: 0x97}, + {value: 0x3308, lo: 0x98, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0x9f}, + {value: 0x3b08, lo: 0xa0, hi: 0xa0}, + {value: 0x3008, lo: 0xa1, hi: 0xa1}, + {value: 0x3308, lo: 0xa2, hi: 0xa2}, + {value: 0x3008, lo: 0xa3, hi: 0xa4}, + {value: 0x3308, lo: 0xa5, hi: 0xac}, + {value: 0x3008, lo: 0xad, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbe}, + {value: 0x3308, lo: 0xbf, hi: 0xbf}, + // Block 0x3c, offset 0x216 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xa6}, + {value: 0x0008, lo: 0xa7, hi: 0xa7}, + {value: 0x0018, lo: 0xa8, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xbd}, + {value: 0x3318, lo: 0xbe, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0x3d, offset 0x222 + {value: 0x0000, lo: 0x01}, + {value: 0x0040, lo: 0x80, hi: 0xbf}, + // Block 0x3e, offset 0x224 + {value: 0x0000, lo: 0x09}, + {value: 0x3308, lo: 0x80, hi: 0x83}, + {value: 0x3008, lo: 0x84, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0xb3}, + {value: 0x3308, lo: 0xb4, hi: 0xb4}, + {value: 0x3008, lo: 0xb5, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbc}, + {value: 0x3008, lo: 0xbd, hi: 0xbf}, + // Block 0x3f, offset 0x22e + {value: 0x0000, lo: 0x0b}, + {value: 0x3008, lo: 0x80, hi: 0x81}, + {value: 0x3308, lo: 0x82, hi: 0x82}, + {value: 0x3008, lo: 0x83, hi: 0x83}, + {value: 0x3808, lo: 0x84, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0xaa}, + {value: 0x3308, lo: 0xab, hi: 0xb3}, + {value: 0x0018, lo: 0xb4, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbf}, + // Block 0x40, offset 0x23a + {value: 0x0000, lo: 0x0b}, + {value: 0x3308, lo: 0x80, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0xa0}, + {value: 0x3008, lo: 0xa1, hi: 0xa1}, + {value: 0x3308, lo: 0xa2, hi: 0xa5}, + {value: 0x3008, lo: 0xa6, hi: 0xa7}, + {value: 0x3308, lo: 0xa8, hi: 0xa9}, + {value: 0x3808, lo: 0xaa, hi: 0xaa}, + {value: 0x3b08, lo: 0xab, hi: 0xab}, + {value: 0x3308, lo: 0xac, hi: 0xad}, + {value: 0x0008, lo: 0xae, hi: 0xbf}, + // Block 0x41, offset 0x246 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0xa5}, + {value: 0x3308, lo: 0xa6, hi: 0xa6}, + {value: 0x3008, lo: 0xa7, hi: 0xa7}, + {value: 0x3308, lo: 0xa8, hi: 0xa9}, + {value: 0x3008, lo: 0xaa, hi: 0xac}, + {value: 0x3308, lo: 0xad, hi: 0xad}, + {value: 0x3008, lo: 0xae, hi: 0xae}, + {value: 0x3308, lo: 0xaf, hi: 0xb1}, + {value: 0x3808, lo: 0xb2, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xbb}, + {value: 0x0018, lo: 0xbc, hi: 0xbf}, + // Block 0x42, offset 0x252 + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0xa3}, + {value: 0x3008, lo: 0xa4, hi: 0xab}, + {value: 0x3308, lo: 0xac, hi: 0xb3}, + {value: 0x3008, lo: 0xb4, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xba}, + {value: 0x0018, lo: 0xbb, hi: 0xbf}, + // Block 0x43, offset 0x25a + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0x8c}, + {value: 0x0008, lo: 0x8d, hi: 0xbd}, + {value: 0x0018, lo: 0xbe, hi: 0xbf}, + // Block 0x44, offset 0x25f + {value: 0x0000, lo: 0x0c}, + {value: 0x0e29, lo: 0x80, hi: 0x80}, + {value: 0x0e41, lo: 0x81, hi: 0x81}, + {value: 0x0e59, lo: 0x82, hi: 0x82}, + {value: 0x0e71, lo: 0x83, hi: 0x83}, + {value: 0x0e89, lo: 0x84, hi: 0x85}, + {value: 0x0ea1, lo: 0x86, hi: 0x86}, + {value: 0x0eb9, lo: 0x87, hi: 0x87}, + {value: 0x057d, lo: 0x88, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x8f}, + {value: 0x059d, lo: 0x90, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbc}, + {value: 0x059d, lo: 0xbd, hi: 0xbf}, + // Block 0x45, offset 0x26c + {value: 0x0000, lo: 0x10}, + {value: 0x0018, lo: 0x80, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x3308, lo: 0x90, hi: 0x92}, + {value: 0x0018, lo: 0x93, hi: 0x93}, + {value: 0x3308, lo: 0x94, hi: 0xa0}, + {value: 0x3008, lo: 0xa1, hi: 0xa1}, + {value: 0x3308, lo: 0xa2, hi: 0xa8}, + {value: 0x0008, lo: 0xa9, hi: 0xac}, + {value: 0x3308, lo: 0xad, hi: 0xad}, + {value: 0x0008, lo: 0xae, hi: 0xb3}, + {value: 0x3308, lo: 0xb4, hi: 0xb4}, + {value: 0x0008, lo: 0xb5, hi: 0xb6}, + {value: 0x3008, lo: 0xb7, hi: 0xb7}, + {value: 0x3308, lo: 0xb8, hi: 0xb9}, + {value: 0x0008, lo: 0xba, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x46, offset 0x27d + {value: 0x0000, lo: 0x03}, + {value: 0x3308, lo: 0x80, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xba}, + {value: 0x3308, lo: 0xbb, hi: 0xbf}, + // Block 0x47, offset 0x281 + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x87}, + {value: 0xe045, lo: 0x88, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x97}, + {value: 0xe045, lo: 0x98, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa7}, + {value: 0xe045, lo: 0xa8, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb7}, + {value: 0xe045, lo: 0xb8, hi: 0xbf}, + // Block 0x48, offset 0x28c + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0x8f}, + {value: 0x3318, lo: 0x90, hi: 0xb0}, + {value: 0x0040, lo: 0xb1, hi: 0xbf}, + // Block 0x49, offset 0x290 + {value: 0x0000, lo: 0x08}, + {value: 0x0018, lo: 0x80, hi: 0x82}, + {value: 0x0040, lo: 0x83, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0x84}, + {value: 0x0018, lo: 0x85, hi: 0x88}, + {value: 0x24c1, lo: 0x89, hi: 0x89}, + {value: 0x0018, lo: 0x8a, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0xbf}, + // Block 0x4a, offset 0x299 + {value: 0x0000, lo: 0x07}, + {value: 0x0018, lo: 0x80, hi: 0xab}, + {value: 0x24f1, lo: 0xac, hi: 0xac}, + {value: 0x2529, lo: 0xad, hi: 0xad}, + {value: 0x0018, lo: 0xae, hi: 0xae}, + {value: 0x2579, lo: 0xaf, hi: 0xaf}, + {value: 0x25b1, lo: 0xb0, hi: 0xb0}, + {value: 0x0018, lo: 0xb1, hi: 0xbf}, + // Block 0x4b, offset 0x2a1 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0x9f}, + {value: 0x0080, lo: 0xa0, hi: 0xa0}, + {value: 0x0018, lo: 0xa1, hi: 0xad}, + {value: 0x0080, lo: 0xae, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xbf}, + // Block 0x4c, offset 0x2a7 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0xa8}, + {value: 0x09dd, lo: 0xa9, hi: 0xa9}, + {value: 0x09fd, lo: 0xaa, hi: 0xaa}, + {value: 0x0018, lo: 0xab, hi: 0xbf}, + // Block 0x4d, offset 0x2ac + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0xa6}, + {value: 0x0040, lo: 0xa7, hi: 0xbf}, + // Block 0x4e, offset 0x2af + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x8b}, + {value: 0x28c1, lo: 0x8c, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0xbf}, + // Block 0x4f, offset 0x2b3 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0xb3}, + {value: 0x0e7e, lo: 0xb4, hi: 0xb4}, + {value: 0x292a, lo: 0xb5, hi: 0xb5}, + {value: 0x0e9e, lo: 0xb6, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xbf}, + // Block 0x50, offset 0x2b9 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x9b}, + {value: 0x2941, lo: 0x9c, hi: 0x9c}, + {value: 0x0018, lo: 0x9d, hi: 0xbf}, + // Block 0x51, offset 0x2bd + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xb5}, + {value: 0x0018, lo: 0xb6, hi: 0xbf}, + // Block 0x52, offset 0x2c1 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x97}, + {value: 0x0018, lo: 0x98, hi: 0xbf}, + // Block 0x53, offset 0x2c5 + {value: 0x0000, lo: 0x05}, + {value: 0xe185, lo: 0x80, hi: 0x8f}, + {value: 0x03f5, lo: 0x90, hi: 0x9f}, + {value: 0x0ebd, lo: 0xa0, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x54, offset 0x2cb + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0xa5}, + {value: 0x0040, lo: 0xa6, hi: 0xa6}, + {value: 0x0008, lo: 0xa7, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xac}, + {value: 0x0008, lo: 0xad, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x55, offset 0x2d3 + {value: 0x0000, lo: 0x06}, + {value: 0x0008, lo: 0x80, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xae}, + {value: 0xe075, lo: 0xaf, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb0}, + {value: 0x0040, lo: 0xb1, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0x56, offset 0x2da + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa6}, + {value: 0x0040, lo: 0xa7, hi: 0xa7}, + {value: 0x0008, lo: 0xa8, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xb7}, + {value: 0x0008, lo: 0xb8, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0x57, offset 0x2e5 + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x8e}, + {value: 0x0040, lo: 0x8f, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0x9f}, + {value: 0x3308, lo: 0xa0, hi: 0xbf}, + // Block 0x58, offset 0x2ef + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xae}, + {value: 0x0008, lo: 0xaf, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xbf}, + // Block 0x59, offset 0x2f3 + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0xbf}, + // Block 0x5a, offset 0x2f6 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0x9e}, + {value: 0x0ef5, lo: 0x9f, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xbf}, + // Block 0x5b, offset 0x2fc + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xb2}, + {value: 0x0f15, lo: 0xb3, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xbf}, + // Block 0x5c, offset 0x300 + {value: 0x0020, lo: 0x01}, + {value: 0x0f35, lo: 0x80, hi: 0xbf}, + // Block 0x5d, offset 0x302 + {value: 0x0020, lo: 0x02}, + {value: 0x1735, lo: 0x80, hi: 0x8f}, + {value: 0x1915, lo: 0x90, hi: 0xbf}, + // Block 0x5e, offset 0x305 + {value: 0x0020, lo: 0x01}, + {value: 0x1f15, lo: 0x80, hi: 0xbf}, + // Block 0x5f, offset 0x307 + {value: 0x0000, lo: 0x02}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0xbf}, + // Block 0x60, offset 0x30a + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x98}, + {value: 0x3308, lo: 0x99, hi: 0x9a}, + {value: 0x29e2, lo: 0x9b, hi: 0x9b}, + {value: 0x2a0a, lo: 0x9c, hi: 0x9c}, + {value: 0x0008, lo: 0x9d, hi: 0x9e}, + {value: 0x2a31, lo: 0x9f, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xa0}, + {value: 0x0008, lo: 0xa1, hi: 0xbf}, + // Block 0x61, offset 0x314 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xbe}, + {value: 0x2a69, lo: 0xbf, hi: 0xbf}, + // Block 0x62, offset 0x317 + {value: 0x0000, lo: 0x0e}, + {value: 0x0040, lo: 0x80, hi: 0x84}, + {value: 0x0008, lo: 0x85, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xb0}, + {value: 0x2a35, lo: 0xb1, hi: 0xb1}, + {value: 0x2a55, lo: 0xb2, hi: 0xb2}, + {value: 0x2a75, lo: 0xb3, hi: 0xb3}, + {value: 0x2a95, lo: 0xb4, hi: 0xb4}, + {value: 0x2a75, lo: 0xb5, hi: 0xb5}, + {value: 0x2ab5, lo: 0xb6, hi: 0xb6}, + {value: 0x2ad5, lo: 0xb7, hi: 0xb7}, + {value: 0x2af5, lo: 0xb8, hi: 0xb9}, + {value: 0x2b15, lo: 0xba, hi: 0xbb}, + {value: 0x2b35, lo: 0xbc, hi: 0xbd}, + {value: 0x2b15, lo: 0xbe, hi: 0xbf}, + // Block 0x63, offset 0x326 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x64, offset 0x32a + {value: 0x0030, lo: 0x04}, + {value: 0x2aa2, lo: 0x80, hi: 0x9d}, + {value: 0x305a, lo: 0x9e, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0x9f}, + {value: 0x30a2, lo: 0xa0, hi: 0xbf}, + // Block 0x65, offset 0x32f + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, + // Block 0x66, offset 0x332 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0x8c}, + {value: 0x0040, lo: 0x8d, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0xbf}, + // Block 0x67, offset 0x336 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xbd}, + {value: 0x0018, lo: 0xbe, hi: 0xbf}, + // Block 0x68, offset 0x33b + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xbf}, + // Block 0x69, offset 0x340 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0xa5}, + {value: 0x0018, lo: 0xa6, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb1}, + {value: 0x0018, lo: 0xb2, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xbf}, + // Block 0x6a, offset 0x346 + {value: 0x0000, lo: 0x0b}, + {value: 0x0040, lo: 0x80, hi: 0x81}, + {value: 0xe00d, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0x83}, + {value: 0x03f5, lo: 0x84, hi: 0x84}, + {value: 0x1329, lo: 0x85, hi: 0x85}, + {value: 0x447d, lo: 0x86, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0xb6}, + {value: 0x0008, lo: 0xb7, hi: 0xb7}, + {value: 0x2009, lo: 0xb8, hi: 0xb8}, + {value: 0x6e89, lo: 0xb9, hi: 0xb9}, + {value: 0x0008, lo: 0xba, hi: 0xbf}, + // Block 0x6b, offset 0x352 + {value: 0x0000, lo: 0x0e}, + {value: 0x0008, lo: 0x80, hi: 0x81}, + {value: 0x3308, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0x85}, + {value: 0x3b08, lo: 0x86, hi: 0x86}, + {value: 0x0008, lo: 0x87, hi: 0x8a}, + {value: 0x3308, lo: 0x8b, hi: 0x8b}, + {value: 0x0008, lo: 0x8c, hi: 0xa2}, + {value: 0x3008, lo: 0xa3, hi: 0xa4}, + {value: 0x3308, lo: 0xa5, hi: 0xa6}, + {value: 0x3008, lo: 0xa7, hi: 0xa7}, + {value: 0x0018, lo: 0xa8, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0x6c, offset 0x361 + {value: 0x0000, lo: 0x05}, + {value: 0x0208, lo: 0x80, hi: 0xb1}, + {value: 0x0108, lo: 0xb2, hi: 0xb2}, + {value: 0x0008, lo: 0xb3, hi: 0xb3}, + {value: 0x0018, lo: 0xb4, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xbf}, + // Block 0x6d, offset 0x367 + {value: 0x0000, lo: 0x03}, + {value: 0x3008, lo: 0x80, hi: 0x81}, + {value: 0x0008, lo: 0x82, hi: 0xb3}, + {value: 0x3008, lo: 0xb4, hi: 0xbf}, + // Block 0x6e, offset 0x36b + {value: 0x0000, lo: 0x0e}, + {value: 0x3008, lo: 0x80, hi: 0x83}, + {value: 0x3b08, lo: 0x84, hi: 0x84}, + {value: 0x3308, lo: 0x85, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x8d}, + {value: 0x0018, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x3308, lo: 0xa0, hi: 0xb1}, + {value: 0x0008, lo: 0xb2, hi: 0xb7}, + {value: 0x0018, lo: 0xb8, hi: 0xba}, + {value: 0x0008, lo: 0xbb, hi: 0xbb}, + {value: 0x0018, lo: 0xbc, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbe}, + {value: 0x3308, lo: 0xbf, hi: 0xbf}, + // Block 0x6f, offset 0x37a + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xa5}, + {value: 0x3308, lo: 0xa6, hi: 0xad}, + {value: 0x0018, lo: 0xae, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x70, offset 0x37f + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x3308, lo: 0x87, hi: 0x91}, + {value: 0x3008, lo: 0x92, hi: 0x92}, + {value: 0x3808, lo: 0x93, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x9e}, + {value: 0x0018, lo: 0x9f, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbf}, + // Block 0x71, offset 0x387 + {value: 0x0000, lo: 0x09}, + {value: 0x3308, lo: 0x80, hi: 0x82}, + {value: 0x3008, lo: 0x83, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb3}, + {value: 0x3008, lo: 0xb4, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xb9}, + {value: 0x3008, lo: 0xba, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbf}, + // Block 0x72, offset 0x391 + {value: 0x0000, lo: 0x0a}, + {value: 0x3808, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8e}, + {value: 0x0008, lo: 0x8f, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa4}, + {value: 0x3308, lo: 0xa5, hi: 0xa5}, + {value: 0x0008, lo: 0xa6, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0x73, offset 0x39c + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0xa8}, + {value: 0x3308, lo: 0xa9, hi: 0xae}, + {value: 0x3008, lo: 0xaf, hi: 0xb0}, + {value: 0x3308, lo: 0xb1, hi: 0xb2}, + {value: 0x3008, lo: 0xb3, hi: 0xb4}, + {value: 0x3308, lo: 0xb5, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0x74, offset 0x3a4 + {value: 0x0000, lo: 0x10}, + {value: 0x0008, lo: 0x80, hi: 0x82}, + {value: 0x3308, lo: 0x83, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0x8b}, + {value: 0x3308, lo: 0x8c, hi: 0x8c}, + {value: 0x3008, lo: 0x8d, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9b}, + {value: 0x0018, lo: 0x9c, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xb9}, + {value: 0x0008, lo: 0xba, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbc}, + {value: 0x3008, lo: 0xbd, hi: 0xbd}, + {value: 0x0008, lo: 0xbe, hi: 0xbf}, + // Block 0x75, offset 0x3b5 + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb0}, + {value: 0x0008, lo: 0xb1, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb4}, + {value: 0x0008, lo: 0xb5, hi: 0xb6}, + {value: 0x3308, lo: 0xb7, hi: 0xb8}, + {value: 0x0008, lo: 0xb9, hi: 0xbd}, + {value: 0x3308, lo: 0xbe, hi: 0xbf}, + // Block 0x76, offset 0x3be + {value: 0x0000, lo: 0x0f}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x3308, lo: 0x81, hi: 0x81}, + {value: 0x0008, lo: 0x82, hi: 0x82}, + {value: 0x0040, lo: 0x83, hi: 0x9a}, + {value: 0x0008, lo: 0x9b, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xaa}, + {value: 0x3008, lo: 0xab, hi: 0xab}, + {value: 0x3308, lo: 0xac, hi: 0xad}, + {value: 0x3008, lo: 0xae, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb1}, + {value: 0x0008, lo: 0xb2, hi: 0xb4}, + {value: 0x3008, lo: 0xb5, hi: 0xb5}, + {value: 0x3b08, lo: 0xb6, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0x77, offset 0x3ce + {value: 0x0000, lo: 0x0c}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x88}, + {value: 0x0008, lo: 0x89, hi: 0x8e}, + {value: 0x0040, lo: 0x8f, hi: 0x90}, + {value: 0x0008, lo: 0x91, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa6}, + {value: 0x0040, lo: 0xa7, hi: 0xa7}, + {value: 0x0008, lo: 0xa8, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x78, offset 0x3db + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0x9b}, + {value: 0x449d, lo: 0x9c, hi: 0x9c}, + {value: 0x44b5, lo: 0x9d, hi: 0x9d}, + {value: 0x2971, lo: 0x9e, hi: 0x9e}, + {value: 0xe06d, lo: 0x9f, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xaf}, + {value: 0x44cd, lo: 0xb0, hi: 0xbf}, + // Block 0x79, offset 0x3e5 + {value: 0x0000, lo: 0x04}, + {value: 0x44ed, lo: 0x80, hi: 0x8f}, + {value: 0x450d, lo: 0x90, hi: 0x9f}, + {value: 0x452d, lo: 0xa0, hi: 0xaf}, + {value: 0x450d, lo: 0xb0, hi: 0xbf}, + // Block 0x7a, offset 0x3ea + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0xa2}, + {value: 0x3008, lo: 0xa3, hi: 0xa4}, + {value: 0x3308, lo: 0xa5, hi: 0xa5}, + {value: 0x3008, lo: 0xa6, hi: 0xa7}, + {value: 0x3308, lo: 0xa8, hi: 0xa8}, + {value: 0x3008, lo: 0xa9, hi: 0xaa}, + {value: 0x0018, lo: 0xab, hi: 0xab}, + {value: 0x3008, lo: 0xac, hi: 0xac}, + {value: 0x3b08, lo: 0xad, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0x7b, offset 0x3f7 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xbf}, + // Block 0x7c, offset 0x3fb + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x8a}, + {value: 0x0018, lo: 0x8b, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0x7d, offset 0x400 + {value: 0x0020, lo: 0x01}, + {value: 0x454d, lo: 0x80, hi: 0xbf}, + // Block 0x7e, offset 0x402 + {value: 0x0020, lo: 0x03}, + {value: 0x4d4d, lo: 0x80, hi: 0x94}, + {value: 0x4b0d, lo: 0x95, hi: 0x95}, + {value: 0x4fed, lo: 0x96, hi: 0xbf}, + // Block 0x7f, offset 0x406 + {value: 0x0020, lo: 0x01}, + {value: 0x552d, lo: 0x80, hi: 0xbf}, + // Block 0x80, offset 0x408 + {value: 0x0020, lo: 0x03}, + {value: 0x5d2d, lo: 0x80, hi: 0x84}, + {value: 0x568d, lo: 0x85, hi: 0x85}, + {value: 0x5dcd, lo: 0x86, hi: 0xbf}, + // Block 0x81, offset 0x40c + {value: 0x0020, lo: 0x08}, + {value: 0x6b8d, lo: 0x80, hi: 0x8f}, + {value: 0x6d4d, lo: 0x90, hi: 0x90}, + {value: 0x6d8d, lo: 0x91, hi: 0xab}, + {value: 0x6ea1, lo: 0xac, hi: 0xac}, + {value: 0x70ed, lo: 0xad, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x710d, lo: 0xb0, hi: 0xbf}, + // Block 0x82, offset 0x415 + {value: 0x0020, lo: 0x05}, + {value: 0x730d, lo: 0x80, hi: 0xad}, + {value: 0x656d, lo: 0xae, hi: 0xae}, + {value: 0x78cd, lo: 0xaf, hi: 0xb5}, + {value: 0x6f8d, lo: 0xb6, hi: 0xb6}, + {value: 0x79ad, lo: 0xb7, hi: 0xbf}, + // Block 0x83, offset 0x41b + {value: 0x0028, lo: 0x03}, + {value: 0x7c21, lo: 0x80, hi: 0x82}, + {value: 0x7be1, lo: 0x83, hi: 0x83}, + {value: 0x7c99, lo: 0x84, hi: 0xbf}, + // Block 0x84, offset 0x41f + {value: 0x0038, lo: 0x0f}, + {value: 0x9db1, lo: 0x80, hi: 0x83}, + {value: 0x9e59, lo: 0x84, hi: 0x85}, + {value: 0x9e91, lo: 0x86, hi: 0x87}, + {value: 0x9ec9, lo: 0x88, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x91}, + {value: 0xa089, lo: 0x92, hi: 0x97}, + {value: 0xa1a1, lo: 0x98, hi: 0x9c}, + {value: 0xa281, lo: 0x9d, hi: 0xb3}, + {value: 0x9d41, lo: 0xb4, hi: 0xb4}, + {value: 0x9db1, lo: 0xb5, hi: 0xb5}, + {value: 0xa789, lo: 0xb6, hi: 0xbb}, + {value: 0xa869, lo: 0xbc, hi: 0xbc}, + {value: 0xa7f9, lo: 0xbd, hi: 0xbd}, + {value: 0xa8d9, lo: 0xbe, hi: 0xbf}, + // Block 0x85, offset 0x42f + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8c}, + {value: 0x0008, lo: 0x8d, hi: 0xa6}, + {value: 0x0040, lo: 0xa7, hi: 0xa7}, + {value: 0x0008, lo: 0xa8, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbb}, + {value: 0x0008, lo: 0xbc, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbe}, + {value: 0x0008, lo: 0xbf, hi: 0xbf}, + // Block 0x86, offset 0x439 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0xbf}, + // Block 0x87, offset 0x43e + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x88, offset 0x441 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0x82}, + {value: 0x0040, lo: 0x83, hi: 0x86}, + {value: 0x0018, lo: 0x87, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xbf}, + // Block 0x89, offset 0x447 + {value: 0x0000, lo: 0x06}, + {value: 0x0018, lo: 0x80, hi: 0x8e}, + {value: 0x0040, lo: 0x8f, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0x9b}, + {value: 0x0040, lo: 0x9c, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xa0}, + {value: 0x0040, lo: 0xa1, hi: 0xbf}, + // Block 0x8a, offset 0x44e + {value: 0x0000, lo: 0x04}, + {value: 0x0040, lo: 0x80, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0xbc}, + {value: 0x3308, lo: 0xbd, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0x8b, offset 0x453 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0x9c}, + {value: 0x0040, lo: 0x9d, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x8c, offset 0x457 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x90}, + {value: 0x0040, lo: 0x91, hi: 0x9f}, + {value: 0x3308, lo: 0xa0, hi: 0xa0}, + {value: 0x0018, lo: 0xa1, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0x8d, offset 0x45d + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xac}, + {value: 0x0008, lo: 0xad, hi: 0xbf}, + // Block 0x8e, offset 0x462 + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x81}, + {value: 0x0008, lo: 0x82, hi: 0x89}, + {value: 0x0018, lo: 0x8a, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x8f, offset 0x46b + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9e}, + {value: 0x0018, lo: 0x9f, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x90, offset 0x470 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x83}, + {value: 0x0040, lo: 0x84, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0xbf}, + // Block 0x91, offset 0x476 + {value: 0x0000, lo: 0x06}, + {value: 0xe145, lo: 0x80, hi: 0x87}, + {value: 0xe1c5, lo: 0x88, hi: 0x8f}, + {value: 0xe145, lo: 0x90, hi: 0x97}, + {value: 0x8b0d, lo: 0x98, hi: 0x9f}, + {value: 0x8b25, lo: 0xa0, hi: 0xa7}, + {value: 0x0008, lo: 0xa8, hi: 0xbf}, + // Block 0x92, offset 0x47d + {value: 0x0000, lo: 0x06}, + {value: 0x0008, lo: 0x80, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa9}, + {value: 0x0040, lo: 0xaa, hi: 0xaf}, + {value: 0x8b25, lo: 0xb0, hi: 0xb7}, + {value: 0x8b0d, lo: 0xb8, hi: 0xbf}, + // Block 0x93, offset 0x484 + {value: 0x0000, lo: 0x06}, + {value: 0xe145, lo: 0x80, hi: 0x87}, + {value: 0xe1c5, lo: 0x88, hi: 0x8f}, + {value: 0xe145, lo: 0x90, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0x94, offset 0x48b + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x95, offset 0x48f + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xae}, + {value: 0x0018, lo: 0xaf, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, + // Block 0x96, offset 0x494 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0x97, offset 0x497 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xbf}, + // Block 0x98, offset 0x49c + {value: 0x0000, lo: 0x0b}, + {value: 0x0808, lo: 0x80, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x87}, + {value: 0x0808, lo: 0x88, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x0808, lo: 0x8a, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb6}, + {value: 0x0808, lo: 0xb7, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbb}, + {value: 0x0808, lo: 0xbc, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbe}, + {value: 0x0808, lo: 0xbf, hi: 0xbf}, + // Block 0x99, offset 0x4a8 + {value: 0x0000, lo: 0x05}, + {value: 0x0808, lo: 0x80, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x96}, + {value: 0x0818, lo: 0x97, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xb6}, + {value: 0x0818, lo: 0xb7, hi: 0xbf}, + // Block 0x9a, offset 0x4ae + {value: 0x0000, lo: 0x04}, + {value: 0x0808, lo: 0x80, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0xa6}, + {value: 0x0818, lo: 0xa7, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, + // Block 0x9b, offset 0x4b3 + {value: 0x0000, lo: 0x06}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xb3}, + {value: 0x0808, lo: 0xb4, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xba}, + {value: 0x0818, lo: 0xbb, hi: 0xbf}, + // Block 0x9c, offset 0x4ba + {value: 0x0000, lo: 0x07}, + {value: 0x0808, lo: 0x80, hi: 0x95}, + {value: 0x0818, lo: 0x96, hi: 0x9b}, + {value: 0x0040, lo: 0x9c, hi: 0x9e}, + {value: 0x0018, lo: 0x9f, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbe}, + {value: 0x0818, lo: 0xbf, hi: 0xbf}, + // Block 0x9d, offset 0x4c2 + {value: 0x0000, lo: 0x04}, + {value: 0x0808, lo: 0x80, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xbb}, + {value: 0x0818, lo: 0xbc, hi: 0xbd}, + {value: 0x0808, lo: 0xbe, hi: 0xbf}, + // Block 0x9e, offset 0x4c7 + {value: 0x0000, lo: 0x03}, + {value: 0x0818, lo: 0x80, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0x91}, + {value: 0x0818, lo: 0x92, hi: 0xbf}, + // Block 0x9f, offset 0x4cb + {value: 0x0000, lo: 0x0f}, + {value: 0x0808, lo: 0x80, hi: 0x80}, + {value: 0x3308, lo: 0x81, hi: 0x83}, + {value: 0x0040, lo: 0x84, hi: 0x84}, + {value: 0x3308, lo: 0x85, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x8b}, + {value: 0x3308, lo: 0x8c, hi: 0x8f}, + {value: 0x0808, lo: 0x90, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x94}, + {value: 0x0808, lo: 0x95, hi: 0x97}, + {value: 0x0040, lo: 0x98, hi: 0x98}, + {value: 0x0808, lo: 0x99, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb7}, + {value: 0x3308, lo: 0xb8, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0xa0, offset 0x4db + {value: 0x0000, lo: 0x06}, + {value: 0x0818, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x8f}, + {value: 0x0818, lo: 0x90, hi: 0x98}, + {value: 0x0040, lo: 0x99, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xbc}, + {value: 0x0818, lo: 0xbd, hi: 0xbf}, + // Block 0xa1, offset 0x4e2 + {value: 0x0000, lo: 0x03}, + {value: 0x0808, lo: 0x80, hi: 0x9c}, + {value: 0x0818, lo: 0x9d, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0xa2, offset 0x4e6 + {value: 0x0000, lo: 0x03}, + {value: 0x0808, lo: 0x80, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb8}, + {value: 0x0018, lo: 0xb9, hi: 0xbf}, + // Block 0xa3, offset 0x4ea + {value: 0x0000, lo: 0x06}, + {value: 0x0808, lo: 0x80, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x97}, + {value: 0x0818, lo: 0x98, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xb7}, + {value: 0x0818, lo: 0xb8, hi: 0xbf}, + // Block 0xa4, offset 0x4f1 + {value: 0x0000, lo: 0x01}, + {value: 0x0808, lo: 0x80, hi: 0xbf}, + // Block 0xa5, offset 0x4f3 + {value: 0x0000, lo: 0x02}, + {value: 0x0808, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0xbf}, + // Block 0xa6, offset 0x4f6 + {value: 0x0000, lo: 0x02}, + {value: 0x03dd, lo: 0x80, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xbf}, + // Block 0xa7, offset 0x4f9 + {value: 0x0000, lo: 0x03}, + {value: 0x0808, lo: 0x80, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xb9}, + {value: 0x0818, lo: 0xba, hi: 0xbf}, + // Block 0xa8, offset 0x4fd + {value: 0x0000, lo: 0x08}, + {value: 0x0908, lo: 0x80, hi: 0x80}, + {value: 0x0a08, lo: 0x81, hi: 0xa1}, + {value: 0x0c08, lo: 0xa2, hi: 0xa2}, + {value: 0x0a08, lo: 0xa3, hi: 0xa3}, + {value: 0x3308, lo: 0xa4, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xaf}, + {value: 0x0808, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0xa9, offset 0x506 + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0818, lo: 0xa0, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0xaa, offset 0x50a + {value: 0x0000, lo: 0x07}, + {value: 0x0808, lo: 0x80, hi: 0x9c}, + {value: 0x0818, lo: 0x9d, hi: 0xa6}, + {value: 0x0808, lo: 0xa7, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xaf}, + {value: 0x0a08, lo: 0xb0, hi: 0xb2}, + {value: 0x0c08, lo: 0xb3, hi: 0xb3}, + {value: 0x0a08, lo: 0xb4, hi: 0xbf}, + // Block 0xab, offset 0x512 + {value: 0x0000, lo: 0x07}, + {value: 0x0a08, lo: 0x80, hi: 0x84}, + {value: 0x0808, lo: 0x85, hi: 0x85}, + {value: 0x3308, lo: 0x86, hi: 0x90}, + {value: 0x0a18, lo: 0x91, hi: 0x93}, + {value: 0x0c18, lo: 0x94, hi: 0x94}, + {value: 0x0818, lo: 0x95, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0xbf}, + // Block 0xac, offset 0x51a + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0808, lo: 0xa0, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0xad, offset 0x51e + {value: 0x0000, lo: 0x05}, + {value: 0x3008, lo: 0x80, hi: 0x80}, + {value: 0x3308, lo: 0x81, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0xb7}, + {value: 0x3308, lo: 0xb8, hi: 0xbf}, + // Block 0xae, offset 0x524 + {value: 0x0000, lo: 0x08}, + {value: 0x3308, lo: 0x80, hi: 0x85}, + {value: 0x3b08, lo: 0x86, hi: 0x86}, + {value: 0x0018, lo: 0x87, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x91}, + {value: 0x0018, lo: 0x92, hi: 0xa5}, + {value: 0x0008, lo: 0xa6, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0xaf, offset 0x52d + {value: 0x0000, lo: 0x0b}, + {value: 0x3308, lo: 0x80, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0xaf}, + {value: 0x3008, lo: 0xb0, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb6}, + {value: 0x3008, lo: 0xb7, hi: 0xb8}, + {value: 0x3b08, lo: 0xb9, hi: 0xb9}, + {value: 0x3308, lo: 0xba, hi: 0xba}, + {value: 0x0018, lo: 0xbb, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbd}, + {value: 0x0018, lo: 0xbe, hi: 0xbf}, + // Block 0xb0, offset 0x539 + {value: 0x0000, lo: 0x06}, + {value: 0x0018, lo: 0x80, hi: 0x81}, + {value: 0x0040, lo: 0x82, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xa8}, + {value: 0x0040, lo: 0xa9, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0xb1, offset 0x540 + {value: 0x0000, lo: 0x08}, + {value: 0x3308, lo: 0x80, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0xa6}, + {value: 0x3308, lo: 0xa7, hi: 0xab}, + {value: 0x3008, lo: 0xac, hi: 0xac}, + {value: 0x3308, lo: 0xad, hi: 0xb2}, + {value: 0x3b08, lo: 0xb3, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xb5}, + {value: 0x0008, lo: 0xb6, hi: 0xbf}, + // Block 0xb2, offset 0x549 + {value: 0x0000, lo: 0x09}, + {value: 0x0018, lo: 0x80, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0x84}, + {value: 0x3008, lo: 0x85, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb3}, + {value: 0x0018, lo: 0xb4, hi: 0xb5}, + {value: 0x0008, lo: 0xb6, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0xb3, offset 0x553 + {value: 0x0000, lo: 0x06}, + {value: 0x3308, lo: 0x80, hi: 0x81}, + {value: 0x3008, lo: 0x82, hi: 0x82}, + {value: 0x0008, lo: 0x83, hi: 0xb2}, + {value: 0x3008, lo: 0xb3, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xbe}, + {value: 0x3008, lo: 0xbf, hi: 0xbf}, + // Block 0xb4, offset 0x55a + {value: 0x0000, lo: 0x0d}, + {value: 0x3808, lo: 0x80, hi: 0x80}, + {value: 0x0008, lo: 0x81, hi: 0x84}, + {value: 0x0018, lo: 0x85, hi: 0x88}, + {value: 0x3308, lo: 0x89, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0x9b}, + {value: 0x0008, lo: 0x9c, hi: 0x9c}, + {value: 0x0018, lo: 0x9d, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xa0}, + {value: 0x0018, lo: 0xa1, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0xb5, offset 0x568 + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x91}, + {value: 0x0040, lo: 0x92, hi: 0x92}, + {value: 0x0008, lo: 0x93, hi: 0xab}, + {value: 0x3008, lo: 0xac, hi: 0xae}, + {value: 0x3308, lo: 0xaf, hi: 0xb1}, + {value: 0x3008, lo: 0xb2, hi: 0xb3}, + {value: 0x3308, lo: 0xb4, hi: 0xb4}, + {value: 0x3808, lo: 0xb5, hi: 0xb5}, + {value: 0x3308, lo: 0xb6, hi: 0xb7}, + {value: 0x0018, lo: 0xb8, hi: 0xbd}, + {value: 0x3308, lo: 0xbe, hi: 0xbe}, + {value: 0x0040, lo: 0xbf, hi: 0xbf}, + // Block 0xb6, offset 0x575 + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x0008, lo: 0x8a, hi: 0x8d}, + {value: 0x0040, lo: 0x8e, hi: 0x8e}, + {value: 0x0008, lo: 0x8f, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9e}, + {value: 0x0008, lo: 0x9f, hi: 0xa8}, + {value: 0x0018, lo: 0xa9, hi: 0xa9}, + {value: 0x0040, lo: 0xaa, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0xb7, offset 0x582 + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0x9e}, + {value: 0x3308, lo: 0x9f, hi: 0x9f}, + {value: 0x3008, lo: 0xa0, hi: 0xa2}, + {value: 0x3308, lo: 0xa3, hi: 0xa9}, + {value: 0x3b08, lo: 0xaa, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbf}, + // Block 0xb8, offset 0x58b + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xb4}, + {value: 0x3008, lo: 0xb5, hi: 0xb7}, + {value: 0x3308, lo: 0xb8, hi: 0xbf}, + // Block 0xb9, offset 0x58f + {value: 0x0000, lo: 0x0f}, + {value: 0x3008, lo: 0x80, hi: 0x81}, + {value: 0x3b08, lo: 0x82, hi: 0x82}, + {value: 0x3308, lo: 0x83, hi: 0x84}, + {value: 0x3008, lo: 0x85, hi: 0x85}, + {value: 0x3308, lo: 0x86, hi: 0x86}, + {value: 0x0008, lo: 0x87, hi: 0x8a}, + {value: 0x0018, lo: 0x8b, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0x9b}, + {value: 0x0040, lo: 0x9c, hi: 0x9c}, + {value: 0x0018, lo: 0x9d, hi: 0x9d}, + {value: 0x3308, lo: 0x9e, hi: 0x9e}, + {value: 0x0008, lo: 0x9f, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0xba, offset 0x59f + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x3008, lo: 0xb0, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb8}, + {value: 0x3008, lo: 0xb9, hi: 0xb9}, + {value: 0x3308, lo: 0xba, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbe}, + {value: 0x3308, lo: 0xbf, hi: 0xbf}, + // Block 0xbb, offset 0x5a7 + {value: 0x0000, lo: 0x0a}, + {value: 0x3308, lo: 0x80, hi: 0x80}, + {value: 0x3008, lo: 0x81, hi: 0x81}, + {value: 0x3b08, lo: 0x82, hi: 0x82}, + {value: 0x3308, lo: 0x83, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0x85}, + {value: 0x0018, lo: 0x86, hi: 0x86}, + {value: 0x0008, lo: 0x87, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0xbf}, + // Block 0xbc, offset 0x5b2 + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0xae}, + {value: 0x3008, lo: 0xaf, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xb7}, + {value: 0x3008, lo: 0xb8, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0xbd, offset 0x5bb + {value: 0x0000, lo: 0x05}, + {value: 0x3308, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0x9b}, + {value: 0x3308, lo: 0x9c, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0xbf}, + // Block 0xbe, offset 0x5c1 + {value: 0x0000, lo: 0x07}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x3008, lo: 0xb0, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xba}, + {value: 0x3008, lo: 0xbb, hi: 0xbc}, + {value: 0x3308, lo: 0xbd, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0xbf, offset 0x5c9 + {value: 0x0000, lo: 0x08}, + {value: 0x3308, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x83}, + {value: 0x0008, lo: 0x84, hi: 0x84}, + {value: 0x0040, lo: 0x85, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xbf}, + // Block 0xc0, offset 0x5d2 + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0xaa}, + {value: 0x3308, lo: 0xab, hi: 0xab}, + {value: 0x3008, lo: 0xac, hi: 0xac}, + {value: 0x3308, lo: 0xad, hi: 0xad}, + {value: 0x3008, lo: 0xae, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb5}, + {value: 0x3808, lo: 0xb6, hi: 0xb6}, + {value: 0x3308, lo: 0xb7, hi: 0xb7}, + {value: 0x0008, lo: 0xb8, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0xc1, offset 0x5dd + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0xbf}, + // Block 0xc2, offset 0x5e0 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0x9a}, + {value: 0x0040, lo: 0x9b, hi: 0x9c}, + {value: 0x3308, lo: 0x9d, hi: 0x9f}, + {value: 0x3008, lo: 0xa0, hi: 0xa1}, + {value: 0x3308, lo: 0xa2, hi: 0xa5}, + {value: 0x3008, lo: 0xa6, hi: 0xa6}, + {value: 0x3308, lo: 0xa7, hi: 0xaa}, + {value: 0x3b08, lo: 0xab, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb9}, + {value: 0x0018, lo: 0xba, hi: 0xbf}, + // Block 0xc3, offset 0x5ec + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0xab}, + {value: 0x3008, lo: 0xac, hi: 0xae}, + {value: 0x3308, lo: 0xaf, hi: 0xb7}, + {value: 0x3008, lo: 0xb8, hi: 0xb8}, + {value: 0x3b08, lo: 0xb9, hi: 0xb9}, + {value: 0x3308, lo: 0xba, hi: 0xba}, + {value: 0x0018, lo: 0xbb, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0xc4, offset 0x5f5 + {value: 0x0000, lo: 0x02}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x049d, lo: 0xa0, hi: 0xbf}, + // Block 0xc5, offset 0x5f8 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xa9}, + {value: 0x0018, lo: 0xaa, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xbe}, + {value: 0x0008, lo: 0xbf, hi: 0xbf}, + // Block 0xc6, offset 0x5fd + {value: 0x0000, lo: 0x04}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xa9}, + {value: 0x0008, lo: 0xaa, hi: 0xbf}, + // Block 0xc7, offset 0x602 + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x90}, + {value: 0x3008, lo: 0x91, hi: 0x93}, + {value: 0x3308, lo: 0x94, hi: 0x97}, + {value: 0x0040, lo: 0x98, hi: 0x99}, + {value: 0x3308, lo: 0x9a, hi: 0x9b}, + {value: 0x3008, lo: 0x9c, hi: 0x9f}, + {value: 0x3b08, lo: 0xa0, hi: 0xa0}, + {value: 0x0008, lo: 0xa1, hi: 0xa1}, + {value: 0x0018, lo: 0xa2, hi: 0xa2}, + {value: 0x0008, lo: 0xa3, hi: 0xa3}, + {value: 0x3008, lo: 0xa4, hi: 0xa4}, + {value: 0x0040, lo: 0xa5, hi: 0xbf}, + // Block 0xc8, offset 0x60f + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x3308, lo: 0x81, hi: 0x8a}, + {value: 0x0008, lo: 0x8b, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb3}, + {value: 0x3b08, lo: 0xb4, hi: 0xb4}, + {value: 0x3308, lo: 0xb5, hi: 0xb8}, + {value: 0x3008, lo: 0xb9, hi: 0xb9}, + {value: 0x0008, lo: 0xba, hi: 0xba}, + {value: 0x3308, lo: 0xbb, hi: 0xbe}, + {value: 0x0018, lo: 0xbf, hi: 0xbf}, + // Block 0xc9, offset 0x61a + {value: 0x0000, lo: 0x08}, + {value: 0x0018, lo: 0x80, hi: 0x86}, + {value: 0x3b08, lo: 0x87, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x90}, + {value: 0x3308, lo: 0x91, hi: 0x96}, + {value: 0x3008, lo: 0x97, hi: 0x98}, + {value: 0x3308, lo: 0x99, hi: 0x9b}, + {value: 0x0008, lo: 0x9c, hi: 0xbf}, + // Block 0xca, offset 0x623 + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x3308, lo: 0x8a, hi: 0x96}, + {value: 0x3008, lo: 0x97, hi: 0x97}, + {value: 0x3308, lo: 0x98, hi: 0x98}, + {value: 0x3b08, lo: 0x99, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0x9c}, + {value: 0x0008, lo: 0x9d, hi: 0x9d}, + {value: 0x0018, lo: 0x9e, hi: 0xa2}, + {value: 0x0040, lo: 0xa3, hi: 0xbf}, + // Block 0xcb, offset 0x62d + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0xcc, offset 0x630 + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x89}, + {value: 0x0008, lo: 0x8a, hi: 0xae}, + {value: 0x3008, lo: 0xaf, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xb7}, + {value: 0x3308, lo: 0xb8, hi: 0xbd}, + {value: 0x3008, lo: 0xbe, hi: 0xbe}, + {value: 0x3b08, lo: 0xbf, hi: 0xbf}, + // Block 0xcd, offset 0x63a + {value: 0x0000, lo: 0x08}, + {value: 0x0008, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0018, lo: 0x9a, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb1}, + {value: 0x0008, lo: 0xb2, hi: 0xbf}, + // Block 0xce, offset 0x643 + {value: 0x0000, lo: 0x0b}, + {value: 0x0008, lo: 0x80, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0x91}, + {value: 0x3308, lo: 0x92, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xa8}, + {value: 0x3008, lo: 0xa9, hi: 0xa9}, + {value: 0x3308, lo: 0xaa, hi: 0xb0}, + {value: 0x3008, lo: 0xb1, hi: 0xb1}, + {value: 0x3308, lo: 0xb2, hi: 0xb3}, + {value: 0x3008, lo: 0xb4, hi: 0xb4}, + {value: 0x3308, lo: 0xb5, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xbf}, + // Block 0xcf, offset 0x64f + {value: 0x0000, lo: 0x0c}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x87}, + {value: 0x0008, lo: 0x88, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0x8a}, + {value: 0x0008, lo: 0x8b, hi: 0xb0}, + {value: 0x3308, lo: 0xb1, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xb9}, + {value: 0x3308, lo: 0xba, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbb}, + {value: 0x3308, lo: 0xbc, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbe}, + {value: 0x3308, lo: 0xbf, hi: 0xbf}, + // Block 0xd0, offset 0x65c + {value: 0x0000, lo: 0x0c}, + {value: 0x3308, lo: 0x80, hi: 0x83}, + {value: 0x3b08, lo: 0x84, hi: 0x85}, + {value: 0x0008, lo: 0x86, hi: 0x86}, + {value: 0x3308, lo: 0x87, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa5}, + {value: 0x0040, lo: 0xa6, hi: 0xa6}, + {value: 0x0008, lo: 0xa7, hi: 0xa8}, + {value: 0x0040, lo: 0xa9, hi: 0xa9}, + {value: 0x0008, lo: 0xaa, hi: 0xbf}, + // Block 0xd1, offset 0x669 + {value: 0x0000, lo: 0x0d}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x3008, lo: 0x8a, hi: 0x8e}, + {value: 0x0040, lo: 0x8f, hi: 0x8f}, + {value: 0x3308, lo: 0x90, hi: 0x91}, + {value: 0x0040, lo: 0x92, hi: 0x92}, + {value: 0x3008, lo: 0x93, hi: 0x94}, + {value: 0x3308, lo: 0x95, hi: 0x95}, + {value: 0x3008, lo: 0x96, hi: 0x96}, + {value: 0x3b08, lo: 0x97, hi: 0x97}, + {value: 0x0008, lo: 0x98, hi: 0x98}, + {value: 0x0040, lo: 0x99, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa9}, + {value: 0x0040, lo: 0xaa, hi: 0xbf}, + // Block 0xd2, offset 0x677 + {value: 0x0000, lo: 0x06}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xb2}, + {value: 0x3308, lo: 0xb3, hi: 0xb4}, + {value: 0x3008, lo: 0xb5, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0xd3, offset 0x67e + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xb1}, + {value: 0x0040, lo: 0xb2, hi: 0xbe}, + {value: 0x0018, lo: 0xbf, hi: 0xbf}, + // Block 0xd4, offset 0x682 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0xbf}, + // Block 0xd5, offset 0x685 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0xd6, offset 0x68a + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x83}, + {value: 0x0040, lo: 0x84, hi: 0xbf}, + // Block 0xd7, offset 0x68d + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xaf}, + {value: 0x0340, lo: 0xb0, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0xd8, offset 0x692 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0xbf}, + // Block 0xd9, offset 0x695 + {value: 0x0000, lo: 0x06}, + {value: 0x0008, lo: 0x80, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa9}, + {value: 0x0040, lo: 0xaa, hi: 0xad}, + {value: 0x0018, lo: 0xae, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, + // Block 0xda, offset 0x69c + {value: 0x0000, lo: 0x06}, + {value: 0x0040, lo: 0x80, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb4}, + {value: 0x0018, lo: 0xb5, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xbf}, + // Block 0xdb, offset 0x6a3 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xbf}, + // Block 0xdc, offset 0x6a7 + {value: 0x0000, lo: 0x0a}, + {value: 0x0008, lo: 0x80, hi: 0x83}, + {value: 0x0018, lo: 0x84, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9a}, + {value: 0x0018, lo: 0x9b, hi: 0xa1}, + {value: 0x0040, lo: 0xa2, hi: 0xa2}, + {value: 0x0008, lo: 0xa3, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xbc}, + {value: 0x0008, lo: 0xbd, hi: 0xbf}, + // Block 0xdd, offset 0x6b2 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0xbf}, + // Block 0xde, offset 0x6b5 + {value: 0x0000, lo: 0x02}, + {value: 0xe105, lo: 0x80, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0xdf, offset 0x6b8 + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0x9a}, + {value: 0x0040, lo: 0x9b, hi: 0xbf}, + // Block 0xe0, offset 0x6bb + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8e}, + {value: 0x3308, lo: 0x8f, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x90}, + {value: 0x3008, lo: 0x91, hi: 0xbf}, + // Block 0xe1, offset 0x6c1 + {value: 0x0000, lo: 0x05}, + {value: 0x3008, lo: 0x80, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8e}, + {value: 0x3308, lo: 0x8f, hi: 0x92}, + {value: 0x0008, lo: 0x93, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0xe2, offset 0x6c7 + {value: 0x0000, lo: 0x05}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xa1}, + {value: 0x0018, lo: 0xa2, hi: 0xa2}, + {value: 0x0008, lo: 0xa3, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xbf}, + // Block 0xe3, offset 0x6cd + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb7}, + {value: 0x0040, lo: 0xb8, hi: 0xbf}, + // Block 0xe4, offset 0x6d0 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb2}, + {value: 0x0040, lo: 0xb3, hi: 0xbf}, + // Block 0xe5, offset 0x6d3 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x9e}, + {value: 0x0040, lo: 0x9f, hi: 0xbf}, + // Block 0xe6, offset 0x6d6 + {value: 0x0000, lo: 0x06}, + {value: 0x0040, lo: 0x80, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x92}, + {value: 0x0040, lo: 0x93, hi: 0xa3}, + {value: 0x0008, lo: 0xa4, hi: 0xa7}, + {value: 0x0040, lo: 0xa8, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0xe7, offset 0x6dd + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xbb}, + {value: 0x0040, lo: 0xbc, hi: 0xbf}, + // Block 0xe8, offset 0x6e0 + {value: 0x0000, lo: 0x04}, + {value: 0x0008, lo: 0x80, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbc}, + {value: 0x0040, lo: 0xbd, hi: 0xbf}, + // Block 0xe9, offset 0x6e5 + {value: 0x0000, lo: 0x09}, + {value: 0x0008, lo: 0x80, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x8f}, + {value: 0x0008, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9b}, + {value: 0x0018, lo: 0x9c, hi: 0x9c}, + {value: 0x3308, lo: 0x9d, hi: 0x9e}, + {value: 0x0018, lo: 0x9f, hi: 0x9f}, + {value: 0x03c0, lo: 0xa0, hi: 0xa3}, + {value: 0x0040, lo: 0xa4, hi: 0xbf}, + // Block 0xea, offset 0x6ef + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xbf}, + // Block 0xeb, offset 0x6f2 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xa6}, + {value: 0x0040, lo: 0xa7, hi: 0xa8}, + {value: 0x0018, lo: 0xa9, hi: 0xbf}, + // Block 0xec, offset 0x6f6 + {value: 0x0000, lo: 0x0e}, + {value: 0x0018, lo: 0x80, hi: 0x9d}, + {value: 0xb5b9, lo: 0x9e, hi: 0x9e}, + {value: 0xb601, lo: 0x9f, hi: 0x9f}, + {value: 0xb649, lo: 0xa0, hi: 0xa0}, + {value: 0xb6b1, lo: 0xa1, hi: 0xa1}, + {value: 0xb719, lo: 0xa2, hi: 0xa2}, + {value: 0xb781, lo: 0xa3, hi: 0xa3}, + {value: 0xb7e9, lo: 0xa4, hi: 0xa4}, + {value: 0x3018, lo: 0xa5, hi: 0xa6}, + {value: 0x3318, lo: 0xa7, hi: 0xa9}, + {value: 0x0018, lo: 0xaa, hi: 0xac}, + {value: 0x3018, lo: 0xad, hi: 0xb2}, + {value: 0x0340, lo: 0xb3, hi: 0xba}, + {value: 0x3318, lo: 0xbb, hi: 0xbf}, + // Block 0xed, offset 0x705 + {value: 0x0000, lo: 0x0b}, + {value: 0x3318, lo: 0x80, hi: 0x82}, + {value: 0x0018, lo: 0x83, hi: 0x84}, + {value: 0x3318, lo: 0x85, hi: 0x8b}, + {value: 0x0018, lo: 0x8c, hi: 0xa9}, + {value: 0x3318, lo: 0xaa, hi: 0xad}, + {value: 0x0018, lo: 0xae, hi: 0xba}, + {value: 0xb851, lo: 0xbb, hi: 0xbb}, + {value: 0xb899, lo: 0xbc, hi: 0xbc}, + {value: 0xb8e1, lo: 0xbd, hi: 0xbd}, + {value: 0xb949, lo: 0xbe, hi: 0xbe}, + {value: 0xb9b1, lo: 0xbf, hi: 0xbf}, + // Block 0xee, offset 0x711 + {value: 0x0000, lo: 0x03}, + {value: 0xba19, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0xa8}, + {value: 0x0040, lo: 0xa9, hi: 0xbf}, + // Block 0xef, offset 0x715 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x81}, + {value: 0x3318, lo: 0x82, hi: 0x84}, + {value: 0x0018, lo: 0x85, hi: 0x85}, + {value: 0x0040, lo: 0x86, hi: 0xbf}, + // Block 0xf0, offset 0x71a + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xbf}, + // Block 0xf1, offset 0x71e + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xb8}, + {value: 0x0040, lo: 0xb9, hi: 0xbf}, + // Block 0xf2, offset 0x723 + {value: 0x0000, lo: 0x03}, + {value: 0x3308, lo: 0x80, hi: 0xb6}, + {value: 0x0018, lo: 0xb7, hi: 0xba}, + {value: 0x3308, lo: 0xbb, hi: 0xbf}, + // Block 0xf3, offset 0x727 + {value: 0x0000, lo: 0x04}, + {value: 0x3308, lo: 0x80, hi: 0xac}, + {value: 0x0018, lo: 0xad, hi: 0xb4}, + {value: 0x3308, lo: 0xb5, hi: 0xb5}, + {value: 0x0018, lo: 0xb6, hi: 0xbf}, + // Block 0xf4, offset 0x72c + {value: 0x0000, lo: 0x08}, + {value: 0x0018, lo: 0x80, hi: 0x83}, + {value: 0x3308, lo: 0x84, hi: 0x84}, + {value: 0x0018, lo: 0x85, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x9a}, + {value: 0x3308, lo: 0x9b, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xa0}, + {value: 0x3308, lo: 0xa1, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, + // Block 0xf5, offset 0x735 + {value: 0x0000, lo: 0x0a}, + {value: 0x3308, lo: 0x80, hi: 0x86}, + {value: 0x0040, lo: 0x87, hi: 0x87}, + {value: 0x3308, lo: 0x88, hi: 0x98}, + {value: 0x0040, lo: 0x99, hi: 0x9a}, + {value: 0x3308, lo: 0x9b, hi: 0xa1}, + {value: 0x0040, lo: 0xa2, hi: 0xa2}, + {value: 0x3308, lo: 0xa3, hi: 0xa4}, + {value: 0x0040, lo: 0xa5, hi: 0xa5}, + {value: 0x3308, lo: 0xa6, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xbf}, + // Block 0xf6, offset 0x740 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xaf}, + {value: 0x3308, lo: 0xb0, hi: 0xb6}, + {value: 0x0008, lo: 0xb7, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0xf7, offset 0x746 + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0x89}, + {value: 0x0040, lo: 0x8a, hi: 0x8d}, + {value: 0x0008, lo: 0x8e, hi: 0x8e}, + {value: 0x0018, lo: 0x8f, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0xbf}, + // Block 0xf8, offset 0x74c + {value: 0x0000, lo: 0x05}, + {value: 0x0008, lo: 0x80, hi: 0xab}, + {value: 0x3308, lo: 0xac, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xb9}, + {value: 0x0040, lo: 0xba, hi: 0xbe}, + {value: 0x0018, lo: 0xbf, hi: 0xbf}, + // Block 0xf9, offset 0x752 + {value: 0x0000, lo: 0x05}, + {value: 0x0808, lo: 0x80, hi: 0x84}, + {value: 0x0040, lo: 0x85, hi: 0x86}, + {value: 0x0818, lo: 0x87, hi: 0x8f}, + {value: 0x3308, lo: 0x90, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0xbf}, + // Block 0xfa, offset 0x758 + {value: 0x0000, lo: 0x08}, + {value: 0x0a08, lo: 0x80, hi: 0x83}, + {value: 0x3308, lo: 0x84, hi: 0x8a}, + {value: 0x0b08, lo: 0x8b, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8f}, + {value: 0x0808, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9d}, + {value: 0x0818, lo: 0x9e, hi: 0x9f}, + {value: 0x0040, lo: 0xa0, hi: 0xbf}, + // Block 0xfb, offset 0x761 + {value: 0x0000, lo: 0x02}, + {value: 0x0040, lo: 0x80, hi: 0xb0}, + {value: 0x0818, lo: 0xb1, hi: 0xbf}, + // Block 0xfc, offset 0x764 + {value: 0x0000, lo: 0x02}, + {value: 0x0818, lo: 0x80, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0xfd, offset 0x767 + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0818, lo: 0x81, hi: 0xbd}, + {value: 0x0040, lo: 0xbe, hi: 0xbf}, + // Block 0xfe, offset 0x76b + {value: 0x0000, lo: 0x03}, + {value: 0x0040, lo: 0x80, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb1}, + {value: 0x0040, lo: 0xb2, hi: 0xbf}, + // Block 0xff, offset 0x76f + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xbf}, + // Block 0x100, offset 0x773 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xae}, + {value: 0x0040, lo: 0xaf, hi: 0xb0}, + {value: 0x0018, lo: 0xb1, hi: 0xbf}, + // Block 0x101, offset 0x779 + {value: 0x0000, lo: 0x05}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0018, lo: 0x81, hi: 0x8f}, + {value: 0x0040, lo: 0x90, hi: 0x90}, + {value: 0x0018, lo: 0x91, hi: 0xb5}, + {value: 0x0040, lo: 0xb6, hi: 0xbf}, + // Block 0x102, offset 0x77f + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x8f}, + {value: 0xc1d9, lo: 0x90, hi: 0x90}, + {value: 0x0018, lo: 0x91, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xbf}, + // Block 0x103, offset 0x784 + {value: 0x0000, lo: 0x02}, + {value: 0x0040, lo: 0x80, hi: 0xa5}, + {value: 0x0018, lo: 0xa6, hi: 0xbf}, + // Block 0x104, offset 0x787 + {value: 0x0000, lo: 0x0f}, + {value: 0xc801, lo: 0x80, hi: 0x80}, + {value: 0xc851, lo: 0x81, hi: 0x81}, + {value: 0xc8a1, lo: 0x82, hi: 0x82}, + {value: 0xc8f1, lo: 0x83, hi: 0x83}, + {value: 0xc941, lo: 0x84, hi: 0x84}, + {value: 0xc991, lo: 0x85, hi: 0x85}, + {value: 0xc9e1, lo: 0x86, hi: 0x86}, + {value: 0xca31, lo: 0x87, hi: 0x87}, + {value: 0xca81, lo: 0x88, hi: 0x88}, + {value: 0x0040, lo: 0x89, hi: 0x8f}, + {value: 0xcad1, lo: 0x90, hi: 0x90}, + {value: 0xcaf1, lo: 0x91, hi: 0x91}, + {value: 0x0040, lo: 0x92, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xa5}, + {value: 0x0040, lo: 0xa6, hi: 0xbf}, + // Block 0x105, offset 0x797 + {value: 0x0000, lo: 0x06}, + {value: 0x0018, lo: 0x80, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xac}, + {value: 0x0040, lo: 0xad, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x106, offset 0x79e + {value: 0x0000, lo: 0x02}, + {value: 0x0018, lo: 0x80, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xbf}, + // Block 0x107, offset 0x7a1 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x98}, + {value: 0x0040, lo: 0x99, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xab}, + {value: 0x0040, lo: 0xac, hi: 0xbf}, + // Block 0x108, offset 0x7a6 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0xbf}, + // Block 0x109, offset 0x7aa + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0x99}, + {value: 0x0040, lo: 0x9a, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xbf}, + // Block 0x10a, offset 0x7b0 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x87}, + {value: 0x0040, lo: 0x88, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xbf}, + // Block 0x10b, offset 0x7b5 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x8b}, + {value: 0x0040, lo: 0x8c, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0xbf}, + // Block 0x10c, offset 0x7b9 + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0xb1}, + {value: 0x0040, lo: 0xb2, hi: 0xb2}, + {value: 0x0018, lo: 0xb3, hi: 0xb6}, + {value: 0x0040, lo: 0xb7, hi: 0xb9}, + {value: 0x0018, lo: 0xba, hi: 0xbf}, + // Block 0x10d, offset 0x7bf + {value: 0x0000, lo: 0x05}, + {value: 0x0018, lo: 0x80, hi: 0xa2}, + {value: 0x0040, lo: 0xa3, hi: 0xa4}, + {value: 0x0018, lo: 0xa5, hi: 0xaa}, + {value: 0x0040, lo: 0xab, hi: 0xad}, + {value: 0x0018, lo: 0xae, hi: 0xbf}, + // Block 0x10e, offset 0x7c5 + {value: 0x0000, lo: 0x03}, + {value: 0x0018, lo: 0x80, hi: 0x8a}, + {value: 0x0040, lo: 0x8b, hi: 0x8c}, + {value: 0x0018, lo: 0x8d, hi: 0xbf}, + // Block 0x10f, offset 0x7c9 + {value: 0x0000, lo: 0x08}, + {value: 0x0018, lo: 0x80, hi: 0x93}, + {value: 0x0040, lo: 0x94, hi: 0x9f}, + {value: 0x0018, lo: 0xa0, hi: 0xad}, + {value: 0x0040, lo: 0xae, hi: 0xaf}, + {value: 0x0018, lo: 0xb0, hi: 0xb3}, + {value: 0x0040, lo: 0xb4, hi: 0xb7}, + {value: 0x0018, lo: 0xb8, hi: 0xba}, + {value: 0x0040, lo: 0xbb, hi: 0xbf}, + // Block 0x110, offset 0x7d2 + {value: 0x0000, lo: 0x04}, + {value: 0x0018, lo: 0x80, hi: 0x82}, + {value: 0x0040, lo: 0x83, hi: 0x8f}, + {value: 0x0018, lo: 0x90, hi: 0x95}, + {value: 0x0040, lo: 0x96, hi: 0xbf}, + // Block 0x111, offset 0x7d7 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0x96}, + {value: 0x0040, lo: 0x97, hi: 0xbf}, + // Block 0x112, offset 0x7da + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xb4}, + {value: 0x0040, lo: 0xb5, hi: 0xbf}, + // Block 0x113, offset 0x7dd + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0x9d}, + {value: 0x0040, lo: 0x9e, hi: 0x9f}, + {value: 0x0008, lo: 0xa0, hi: 0xbf}, + // Block 0x114, offset 0x7e1 + {value: 0x0000, lo: 0x03}, + {value: 0x0008, lo: 0x80, hi: 0xa1}, + {value: 0x0040, lo: 0xa2, hi: 0xaf}, + {value: 0x0008, lo: 0xb0, hi: 0xbf}, + // Block 0x115, offset 0x7e5 + {value: 0x0000, lo: 0x02}, + {value: 0x0008, lo: 0x80, hi: 0xa0}, + {value: 0x0040, lo: 0xa1, hi: 0xbf}, + // Block 0x116, offset 0x7e8 + {value: 0x0020, lo: 0x0f}, + {value: 0xded1, lo: 0x80, hi: 0x89}, + {value: 0x8e35, lo: 0x8a, hi: 0x8a}, + {value: 0xe011, lo: 0x8b, hi: 0x9c}, + {value: 0x8e55, lo: 0x9d, hi: 0x9d}, + {value: 0xe251, lo: 0x9e, hi: 0xa2}, + {value: 0x8e75, lo: 0xa3, hi: 0xa3}, + {value: 0xe2f1, lo: 0xa4, hi: 0xab}, + {value: 0x7f0d, lo: 0xac, hi: 0xac}, + {value: 0xe3f1, lo: 0xad, hi: 0xaf}, + {value: 0x8e95, lo: 0xb0, hi: 0xb0}, + {value: 0xe451, lo: 0xb1, hi: 0xb6}, + {value: 0x8eb5, lo: 0xb7, hi: 0xb9}, + {value: 0xe511, lo: 0xba, hi: 0xba}, + {value: 0x8f15, lo: 0xbb, hi: 0xbb}, + {value: 0xe531, lo: 0xbc, hi: 0xbf}, + // Block 0x117, offset 0x7f8 + {value: 0x0020, lo: 0x10}, + {value: 0x93b5, lo: 0x80, hi: 0x80}, + {value: 0xf0b1, lo: 0x81, hi: 0x86}, + {value: 0x93d5, lo: 0x87, hi: 0x8a}, + {value: 0xda11, lo: 0x8b, hi: 0x8b}, + {value: 0xf171, lo: 0x8c, hi: 0x96}, + {value: 0x9455, lo: 0x97, hi: 0x97}, + {value: 0xf2d1, lo: 0x98, hi: 0xa3}, + {value: 0x9475, lo: 0xa4, hi: 0xa6}, + {value: 0xf451, lo: 0xa7, hi: 0xaa}, + {value: 0x94d5, lo: 0xab, hi: 0xab}, + {value: 0xf4d1, lo: 0xac, hi: 0xac}, + {value: 0x94f5, lo: 0xad, hi: 0xad}, + {value: 0xf4f1, lo: 0xae, hi: 0xaf}, + {value: 0x9515, lo: 0xb0, hi: 0xb1}, + {value: 0xf531, lo: 0xb2, hi: 0xbe}, + {value: 0x2040, lo: 0xbf, hi: 0xbf}, + // Block 0x118, offset 0x809 + {value: 0x0000, lo: 0x04}, + {value: 0x0040, lo: 0x80, hi: 0x80}, + {value: 0x0340, lo: 0x81, hi: 0x81}, + {value: 0x0040, lo: 0x82, hi: 0x9f}, + {value: 0x0340, lo: 0xa0, hi: 0xbf}, + // Block 0x119, offset 0x80e + {value: 0x0000, lo: 0x01}, + {value: 0x0340, lo: 0x80, hi: 0xbf}, + // Block 0x11a, offset 0x810 + {value: 0x0000, lo: 0x01}, + {value: 0x33c0, lo: 0x80, hi: 0xbf}, + // Block 0x11b, offset 0x812 + {value: 0x0000, lo: 0x02}, + {value: 0x33c0, lo: 0x80, hi: 0xaf}, + {value: 0x0040, lo: 0xb0, hi: 0xbf}, +} + +// Total table size 42780 bytes (41KiB); checksum: 29936AB9 diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go index 6929a9fd5c..97db2340ec 100644 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ b/vendor/golang.org/x/net/internal/socks/socks.go @@ -127,7 +127,7 @@ type Dialer struct { // establishing the transport connection. ProxyDial func(context.Context, string, string) (net.Conn, error) - // AuthMethods specifies the list of request authention + // AuthMethods specifies the list of request authentication // methods. // If empty, SOCKS client requests only AuthMethodNotRequired. AuthMethods []AuthMethod diff --git a/vendor/golang.org/x/net/publicsuffix/example_test.go b/vendor/golang.org/x/net/publicsuffix/example_test.go deleted file mode 100755 index 3f44dcfe75..0000000000 --- a/vendor/golang.org/x/net/publicsuffix/example_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package publicsuffix_test - -import ( - "fmt" - "strings" - - "golang.org/x/net/publicsuffix" -) - -// This example demonstrates looking up several domains' eTLDs (effective Top -// Level Domains) in the PSL (Public Suffix List) snapshot. For each eTLD, the -// example also determines whether the eTLD is ICANN managed, privately -// managed, or unmanaged (not explicitly in the PSL). -// -// See https://publicsuffix.org/ for the underlying PSL data. -func ExamplePublicSuffix_manager() { - domains := []string{ - "amazon.co.uk", - "books.amazon.co.uk", - "www.books.amazon.co.uk", - "amazon.com", - "", - "example0.debian.net", - "example1.debian.org", - "", - "golang.dev", - "golang.net", - "play.golang.org", - "gophers.in.space.museum", - "", - "0emm.com", - "a.0emm.com", - "b.c.d.0emm.com", - "", - "there.is.no.such-tld", - "", - // Examples from the PublicSuffix function's documentation. - "foo.org", - "foo.co.uk", - "foo.dyndns.org", - "foo.blogspot.co.uk", - "cromulent", - } - - for _, domain := range domains { - if domain == "" { - fmt.Println(">") - continue - } - eTLD, icann := publicsuffix.PublicSuffix(domain) - - // Only ICANN managed domains can have a single label. Privately - // managed domains must have multiple labels. - manager := "Unmanaged" - if icann { - manager = "ICANN Managed" - } else if strings.IndexByte(eTLD, '.') >= 0 { - manager = "Privately Managed" - } - - fmt.Printf("> %24s%16s is %s\n", domain, eTLD, manager) - } - - // Output: - // > amazon.co.uk co.uk is ICANN Managed - // > books.amazon.co.uk co.uk is ICANN Managed - // > www.books.amazon.co.uk co.uk is ICANN Managed - // > amazon.com com is ICANN Managed - // > - // > example0.debian.net debian.net is Privately Managed - // > example1.debian.org org is ICANN Managed - // > - // > golang.dev dev is ICANN Managed - // > golang.net net is ICANN Managed - // > play.golang.org org is ICANN Managed - // > gophers.in.space.museum space.museum is ICANN Managed - // > - // > 0emm.com com is ICANN Managed - // > a.0emm.com a.0emm.com is Privately Managed - // > b.c.d.0emm.com d.0emm.com is Privately Managed - // > - // > there.is.no.such-tld such-tld is Unmanaged - // > - // > foo.org org is ICANN Managed - // > foo.co.uk co.uk is ICANN Managed - // > foo.dyndns.org dyndns.org is Privately Managed - // > foo.blogspot.co.uk blogspot.co.uk is Privately Managed - // > cromulent cromulent is Unmanaged -} diff --git a/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/golang.org/x/net/publicsuffix/gen.go deleted file mode 100755 index 372ffbb24c..0000000000 --- a/vendor/golang.org/x/net/publicsuffix/gen.go +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates table.go and table_test.go based on the authoritative -// public suffix list at https://publicsuffix.org/list/effective_tld_names.dat -// -// The version is derived from -// https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat -// and a human-readable form is at -// https://github.com/publicsuffix/list/commits/master/public_suffix_list.dat -// -// To fetch a particular git revision, such as 5c70ccd250, pass -// -url "https://raw.githubusercontent.com/publicsuffix/list/5c70ccd250/public_suffix_list.dat" -// and -version "an explicit version string". - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "go/format" - "io" - "io/ioutil" - "net/http" - "os" - "regexp" - "sort" - "strings" - - "golang.org/x/net/idna" -) - -const ( - // These sum of these four values must be no greater than 32. - nodesBitsChildren = 10 - nodesBitsICANN = 1 - nodesBitsTextOffset = 15 - nodesBitsTextLength = 6 - - // These sum of these four values must be no greater than 32. - childrenBitsWildcard = 1 - childrenBitsNodeType = 2 - childrenBitsHi = 14 - childrenBitsLo = 14 -) - -var ( - maxChildren int - maxTextOffset int - maxTextLength int - maxHi uint32 - maxLo uint32 -) - -func max(a, b int) int { - if a < b { - return b - } - return a -} - -func u32max(a, b uint32) uint32 { - if a < b { - return b - } - return a -} - -const ( - nodeTypeNormal = 0 - nodeTypeException = 1 - nodeTypeParentOnly = 2 - numNodeType = 3 -) - -func nodeTypeStr(n int) string { - switch n { - case nodeTypeNormal: - return "+" - case nodeTypeException: - return "!" - case nodeTypeParentOnly: - return "o" - } - panic("unreachable") -} - -const ( - defaultURL = "https://publicsuffix.org/list/effective_tld_names.dat" - gitCommitURL = "https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat" -) - -var ( - labelEncoding = map[string]uint32{} - labelsList = []string{} - labelsMap = map[string]bool{} - rules = []string{} - numICANNRules = 0 - - // validSuffixRE is used to check that the entries in the public suffix - // list are in canonical form (after Punycode encoding). Specifically, - // capital letters are not allowed. - validSuffixRE = regexp.MustCompile(`^[a-z0-9_\!\*\-\.]+$`) - - shaRE = regexp.MustCompile(`"sha":"([^"]+)"`) - dateRE = regexp.MustCompile(`"committer":{[^{]+"date":"([^"]+)"`) - - comments = flag.Bool("comments", false, "generate table.go comments, for debugging") - subset = flag.Bool("subset", false, "generate only a subset of the full table, for debugging") - url = flag.String("url", defaultURL, "URL of the publicsuffix.org list. If empty, stdin is read instead") - v = flag.Bool("v", false, "verbose output (to stderr)") - version = flag.String("version", "", "the effective_tld_names.dat version") -) - -func main() { - if err := main1(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func main1() error { - flag.Parse() - if nodesBitsTextLength+nodesBitsTextOffset+nodesBitsICANN+nodesBitsChildren > 32 { - return fmt.Errorf("not enough bits to encode the nodes table") - } - if childrenBitsLo+childrenBitsHi+childrenBitsNodeType+childrenBitsWildcard > 32 { - return fmt.Errorf("not enough bits to encode the children table") - } - if *version == "" { - if *url != defaultURL { - return fmt.Errorf("-version was not specified, and the -url is not the default one") - } - sha, date, err := gitCommit() - if err != nil { - return err - } - *version = fmt.Sprintf("publicsuffix.org's public_suffix_list.dat, git revision %s (%s)", sha, date) - } - var r io.Reader = os.Stdin - if *url != "" { - res, err := http.Get(*url) - if err != nil { - return err - } - if res.StatusCode != http.StatusOK { - return fmt.Errorf("bad GET status for %s: %d", *url, res.Status) - } - r = res.Body - defer res.Body.Close() - } - - var root node - icann := false - br := bufio.NewReader(r) - for { - s, err := br.ReadString('\n') - if err != nil { - if err == io.EOF { - break - } - return err - } - s = strings.TrimSpace(s) - if strings.Contains(s, "BEGIN ICANN DOMAINS") { - if len(rules) != 0 { - return fmt.Errorf(`expected no rules before "BEGIN ICANN DOMAINS"`) - } - icann = true - continue - } - if strings.Contains(s, "END ICANN DOMAINS") { - icann, numICANNRules = false, len(rules) - continue - } - if s == "" || strings.HasPrefix(s, "//") { - continue - } - s, err = idna.ToASCII(s) - if err != nil { - return err - } - if !validSuffixRE.MatchString(s) { - return fmt.Errorf("bad publicsuffix.org list data: %q", s) - } - - if *subset { - switch { - case s == "ac.jp" || strings.HasSuffix(s, ".ac.jp"): - case s == "ak.us" || strings.HasSuffix(s, ".ak.us"): - case s == "ao" || strings.HasSuffix(s, ".ao"): - case s == "ar" || strings.HasSuffix(s, ".ar"): - case s == "arpa" || strings.HasSuffix(s, ".arpa"): - case s == "cy" || strings.HasSuffix(s, ".cy"): - case s == "dyndns.org" || strings.HasSuffix(s, ".dyndns.org"): - case s == "jp": - case s == "kobe.jp" || strings.HasSuffix(s, ".kobe.jp"): - case s == "kyoto.jp" || strings.HasSuffix(s, ".kyoto.jp"): - case s == "om" || strings.HasSuffix(s, ".om"): - case s == "uk" || strings.HasSuffix(s, ".uk"): - case s == "uk.com" || strings.HasSuffix(s, ".uk.com"): - case s == "tw" || strings.HasSuffix(s, ".tw"): - case s == "zw" || strings.HasSuffix(s, ".zw"): - case s == "xn--p1ai" || strings.HasSuffix(s, ".xn--p1ai"): - // xn--p1ai is Russian-Cyrillic "рф". - default: - continue - } - } - - rules = append(rules, s) - - nt, wildcard := nodeTypeNormal, false - switch { - case strings.HasPrefix(s, "*."): - s, nt = s[2:], nodeTypeParentOnly - wildcard = true - case strings.HasPrefix(s, "!"): - s, nt = s[1:], nodeTypeException - } - labels := strings.Split(s, ".") - for n, i := &root, len(labels)-1; i >= 0; i-- { - label := labels[i] - n = n.child(label) - if i == 0 { - if nt != nodeTypeParentOnly && n.nodeType == nodeTypeParentOnly { - n.nodeType = nt - } - n.icann = n.icann && icann - n.wildcard = n.wildcard || wildcard - } - labelsMap[label] = true - } - } - labelsList = make([]string, 0, len(labelsMap)) - for label := range labelsMap { - labelsList = append(labelsList, label) - } - sort.Strings(labelsList) - - if err := generate(printReal, &root, "table.go"); err != nil { - return err - } - if err := generate(printTest, &root, "table_test.go"); err != nil { - return err - } - return nil -} - -func generate(p func(io.Writer, *node) error, root *node, filename string) error { - buf := new(bytes.Buffer) - if err := p(buf, root); err != nil { - return err - } - b, err := format.Source(buf.Bytes()) - if err != nil { - return err - } - return ioutil.WriteFile(filename, b, 0644) -} - -func gitCommit() (sha, date string, retErr error) { - res, err := http.Get(gitCommitURL) - if err != nil { - return "", "", err - } - if res.StatusCode != http.StatusOK { - return "", "", fmt.Errorf("bad GET status for %s: %d", gitCommitURL, res.Status) - } - defer res.Body.Close() - b, err := ioutil.ReadAll(res.Body) - if err != nil { - return "", "", err - } - if m := shaRE.FindSubmatch(b); m != nil { - sha = string(m[1]) - } - if m := dateRE.FindSubmatch(b); m != nil { - date = string(m[1]) - } - if sha == "" || date == "" { - retErr = fmt.Errorf("could not find commit SHA and date in %s", gitCommitURL) - } - return sha, date, retErr -} - -func printTest(w io.Writer, n *node) error { - fmt.Fprintf(w, "// generated by go run gen.go; DO NOT EDIT\n\n") - fmt.Fprintf(w, "package publicsuffix\n\nconst numICANNRules = %d\n\nvar rules = [...]string{\n", numICANNRules) - for _, rule := range rules { - fmt.Fprintf(w, "%q,\n", rule) - } - fmt.Fprintf(w, "}\n\nvar nodeLabels = [...]string{\n") - if err := n.walk(w, printNodeLabel); err != nil { - return err - } - fmt.Fprintf(w, "}\n") - return nil -} - -func printReal(w io.Writer, n *node) error { - const header = `// generated by go run gen.go; DO NOT EDIT - -package publicsuffix - -const version = %q - -const ( - nodesBitsChildren = %d - nodesBitsICANN = %d - nodesBitsTextOffset = %d - nodesBitsTextLength = %d - - childrenBitsWildcard = %d - childrenBitsNodeType = %d - childrenBitsHi = %d - childrenBitsLo = %d -) - -const ( - nodeTypeNormal = %d - nodeTypeException = %d - nodeTypeParentOnly = %d -) - -// numTLD is the number of top level domains. -const numTLD = %d - -` - fmt.Fprintf(w, header, *version, - nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength, - childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo, - nodeTypeNormal, nodeTypeException, nodeTypeParentOnly, len(n.children)) - - text := combineText(labelsList) - if text == "" { - return fmt.Errorf("internal error: makeText returned no text") - } - for _, label := range labelsList { - offset, length := strings.Index(text, label), len(label) - if offset < 0 { - return fmt.Errorf("internal error: could not find %q in text %q", label, text) - } - maxTextOffset, maxTextLength = max(maxTextOffset, offset), max(maxTextLength, length) - if offset >= 1<= 1< 64 { - n, plus = 64, " +" - } - fmt.Fprintf(w, "%q%s\n", text[:n], plus) - text = text[n:] - } - - if err := n.walk(w, assignIndexes); err != nil { - return err - } - - fmt.Fprintf(w, ` - -// nodes is the list of nodes. Each node is represented as a uint32, which -// encodes the node's children, wildcard bit and node type (as an index into -// the children array), ICANN bit and text. -// -// If the table was generated with the -comments flag, there is a //-comment -// after each node's data. In it is the nodes-array indexes of the children, -// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The -// nodeType is printed as + for normal, ! for exception, and o for parent-only -// nodes that have children but don't match a domain label in their own right. -// An I denotes an ICANN domain. -// -// The layout within the uint32, from MSB to LSB, is: -// [%2d bits] unused -// [%2d bits] children index -// [%2d bits] ICANN bit -// [%2d bits] text index -// [%2d bits] text length -var nodes = [...]uint32{ -`, - 32-nodesBitsChildren-nodesBitsICANN-nodesBitsTextOffset-nodesBitsTextLength, - nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength) - if err := n.walk(w, printNode); err != nil { - return err - } - fmt.Fprintf(w, `} - -// children is the list of nodes' children, the parent's wildcard bit and the -// parent's node type. If a node has no children then their children index -// will be in the range [0, 6), depending on the wildcard bit and node type. -// -// The layout within the uint32, from MSB to LSB, is: -// [%2d bits] unused -// [%2d bits] wildcard bit -// [%2d bits] node type -// [%2d bits] high nodes index (exclusive) of children -// [%2d bits] low nodes index (inclusive) of children -var children=[...]uint32{ -`, - 32-childrenBitsWildcard-childrenBitsNodeType-childrenBitsHi-childrenBitsLo, - childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo) - for i, c := range childrenEncoding { - s := "---------------" - lo := c & (1<> childrenBitsLo) & (1<>(childrenBitsLo+childrenBitsHi)) & (1<>(childrenBitsLo+childrenBitsHi+childrenBitsNodeType) != 0 - if *comments { - fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n", - c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType)) - } else { - fmt.Fprintf(w, "0x%x,\n", c) - } - } - fmt.Fprintf(w, "}\n\n") - fmt.Fprintf(w, "// max children %d (capacity %d)\n", maxChildren, 1<= 1<= 1<= 1< 0 && ss[0] == "" { - ss = ss[1:] - } - return ss -} - -// crush combines a list of strings, taking advantage of overlaps. It returns a -// single string that contains each input string as a substring. -func crush(ss []string) string { - maxLabelLen := 0 - for _, s := range ss { - if maxLabelLen < len(s) { - maxLabelLen = len(s) - } - } - - for prefixLen := maxLabelLen; prefixLen > 0; prefixLen-- { - prefixes := makePrefixMap(ss, prefixLen) - for i, s := range ss { - if len(s) <= prefixLen { - continue - } - mergeLabel(ss, i, prefixLen, prefixes) - } - } - - return strings.Join(ss, "") -} - -// mergeLabel merges the label at ss[i] with the first available matching label -// in prefixMap, where the last "prefixLen" characters in ss[i] match the first -// "prefixLen" characters in the matching label. -// It will merge ss[i] repeatedly until no more matches are available. -// All matching labels merged into ss[i] are replaced by "". -func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) { - s := ss[i] - suffix := s[len(s)-prefixLen:] - for _, j := range prefixes[suffix] { - // Empty strings mean "already used." Also avoid merging with self. - if ss[j] == "" || i == j { - continue - } - if *v { - fmt.Fprintf(os.Stderr, "%d-length overlap at (%4d,%4d): %q and %q share %q\n", - prefixLen, i, j, ss[i], ss[j], suffix) - } - ss[i] += ss[j][prefixLen:] - ss[j] = "" - // ss[i] has a new suffix, so merge again if possible. - // Note: we only have to merge again at the same prefix length. Shorter - // prefix lengths will be handled in the next iteration of crush's for loop. - // Can there be matches for longer prefix lengths, introduced by the merge? - // I believe that any such matches would by necessity have been eliminated - // during substring removal or merged at a higher prefix length. For - // instance, in crush("abc", "cde", "bcdef"), combining "abc" and "cde" - // would yield "abcde", which could be merged with "bcdef." However, in - // practice "cde" would already have been elimintated by removeSubstrings. - mergeLabel(ss, i, prefixLen, prefixes) - return - } -} - -// prefixMap maps from a prefix to a list of strings containing that prefix. The -// list of strings is represented as indexes into a slice of strings stored -// elsewhere. -type prefixMap map[string][]int - -// makePrefixMap constructs a prefixMap from a slice of strings. -func makePrefixMap(ss []string, prefixLen int) prefixMap { - prefixes := make(prefixMap) - for i, s := range ss { - // We use < rather than <= because if a label matches on a prefix equal to - // its full length, that's actually a substring match handled by - // removeSubstrings. - if prefixLen < len(s) { - prefix := s[:prefixLen] - prefixes[prefix] = append(prefixes[prefix], i) - } - } - - return prefixes -} diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/net/publicsuffix/list_test.go b/vendor/golang.org/x/net/publicsuffix/list_test.go deleted file mode 100755 index 090c431139..0000000000 --- a/vendor/golang.org/x/net/publicsuffix/list_test.go +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package publicsuffix - -import ( - "sort" - "strings" - "testing" -) - -func TestNodeLabel(t *testing.T) { - for i, want := range nodeLabels { - got := nodeLabel(uint32(i)) - if got != want { - t.Errorf("%d: got %q, want %q", i, got, want) - } - } -} - -func TestFind(t *testing.T) { - testCases := []string{ - "", - "a", - "a0", - "aaaa", - "ao", - "ap", - "ar", - "aro", - "arp", - "arpa", - "arpaa", - "arpb", - "az", - "b", - "b0", - "ba", - "z", - "zu", - "zv", - "zw", - "zx", - "zy", - "zz", - "zzzz", - } - for _, tc := range testCases { - got := find(tc, 0, numTLD) - want := notFound - for i := uint32(0); i < numTLD; i++ { - if tc == nodeLabel(i) { - want = i - break - } - } - if got != want { - t.Errorf("%q: got %d, want %d", tc, got, want) - } - } -} - -func TestICANN(t *testing.T) { - testCases := map[string]bool{ - "foo.org": true, - "foo.co.uk": true, - "foo.dyndns.org": false, - "foo.go.dyndns.org": false, - "foo.blogspot.co.uk": false, - "foo.intranet": false, - } - for domain, want := range testCases { - _, got := PublicSuffix(domain) - if got != want { - t.Errorf("%q: got %v, want %v", domain, got, want) - } - } -} - -var publicSuffixTestCases = []struct { - domain string - wantPS string - wantICANN bool -}{ - // Empty string. - {"", "", false}, - - // The .ao rules are: - // ao - // ed.ao - // gv.ao - // og.ao - // co.ao - // pb.ao - // it.ao - {"ao", "ao", true}, - {"www.ao", "ao", true}, - {"pb.ao", "pb.ao", true}, - {"www.pb.ao", "pb.ao", true}, - {"www.xxx.yyy.zzz.pb.ao", "pb.ao", true}, - - // The .ar rules are: - // ar - // com.ar - // edu.ar - // gob.ar - // gov.ar - // int.ar - // mil.ar - // net.ar - // org.ar - // tur.ar - // blogspot.com.ar (in the PRIVATE DOMAIN section). - {"ar", "ar", true}, - {"www.ar", "ar", true}, - {"nic.ar", "ar", true}, - {"www.nic.ar", "ar", true}, - {"com.ar", "com.ar", true}, - {"www.com.ar", "com.ar", true}, - {"blogspot.com.ar", "blogspot.com.ar", false}, // PRIVATE DOMAIN. - {"www.blogspot.com.ar", "blogspot.com.ar", false}, // PRIVATE DOMAIN. - {"www.xxx.yyy.zzz.blogspot.com.ar", "blogspot.com.ar", false}, // PRIVATE DOMAIN. - {"logspot.com.ar", "com.ar", true}, - {"zlogspot.com.ar", "com.ar", true}, - {"zblogspot.com.ar", "com.ar", true}, - - // The .arpa rules are: - // arpa - // e164.arpa - // in-addr.arpa - // ip6.arpa - // iris.arpa - // uri.arpa - // urn.arpa - {"arpa", "arpa", true}, - {"www.arpa", "arpa", true}, - {"urn.arpa", "urn.arpa", true}, - {"www.urn.arpa", "urn.arpa", true}, - {"www.xxx.yyy.zzz.urn.arpa", "urn.arpa", true}, - - // The relevant {kobe,kyoto}.jp rules are: - // jp - // *.kobe.jp - // !city.kobe.jp - // kyoto.jp - // ide.kyoto.jp - {"jp", "jp", true}, - {"kobe.jp", "jp", true}, - {"c.kobe.jp", "c.kobe.jp", true}, - {"b.c.kobe.jp", "c.kobe.jp", true}, - {"a.b.c.kobe.jp", "c.kobe.jp", true}, - {"city.kobe.jp", "kobe.jp", true}, - {"www.city.kobe.jp", "kobe.jp", true}, - {"kyoto.jp", "kyoto.jp", true}, - {"test.kyoto.jp", "kyoto.jp", true}, - {"ide.kyoto.jp", "ide.kyoto.jp", true}, - {"b.ide.kyoto.jp", "ide.kyoto.jp", true}, - {"a.b.ide.kyoto.jp", "ide.kyoto.jp", true}, - - // The .tw rules are: - // tw - // edu.tw - // gov.tw - // mil.tw - // com.tw - // net.tw - // org.tw - // idv.tw - // game.tw - // ebiz.tw - // club.tw - // 網路.tw (xn--zf0ao64a.tw) - // 組織.tw (xn--uc0atv.tw) - // 商業.tw (xn--czrw28b.tw) - // blogspot.tw - {"tw", "tw", true}, - {"aaa.tw", "tw", true}, - {"www.aaa.tw", "tw", true}, - {"xn--czrw28b.aaa.tw", "tw", true}, - {"edu.tw", "edu.tw", true}, - {"www.edu.tw", "edu.tw", true}, - {"xn--czrw28b.edu.tw", "edu.tw", true}, - {"xn--czrw28b.tw", "xn--czrw28b.tw", true}, - {"www.xn--czrw28b.tw", "xn--czrw28b.tw", true}, - {"xn--uc0atv.xn--czrw28b.tw", "xn--czrw28b.tw", true}, - {"xn--kpry57d.tw", "tw", true}, - - // The .uk rules are: - // uk - // ac.uk - // co.uk - // gov.uk - // ltd.uk - // me.uk - // net.uk - // nhs.uk - // org.uk - // plc.uk - // police.uk - // *.sch.uk - // blogspot.co.uk (in the PRIVATE DOMAIN section). - {"uk", "uk", true}, - {"aaa.uk", "uk", true}, - {"www.aaa.uk", "uk", true}, - {"mod.uk", "uk", true}, - {"www.mod.uk", "uk", true}, - {"sch.uk", "uk", true}, - {"mod.sch.uk", "mod.sch.uk", true}, - {"www.sch.uk", "www.sch.uk", true}, - {"co.uk", "co.uk", true}, - {"www.co.uk", "co.uk", true}, - {"blogspot.co.uk", "blogspot.co.uk", false}, // PRIVATE DOMAIN. - {"blogspot.nic.uk", "uk", true}, - {"blogspot.sch.uk", "blogspot.sch.uk", true}, - - // The .рф rules are - // рф (xn--p1ai) - {"xn--p1ai", "xn--p1ai", true}, - {"aaa.xn--p1ai", "xn--p1ai", true}, - {"www.xxx.yyy.xn--p1ai", "xn--p1ai", true}, - - // The .bd rules are: - // *.bd - {"bd", "bd", false}, // The catch-all "*" rule is not in the ICANN DOMAIN section. See footnote (†). - {"www.bd", "www.bd", true}, - {"xxx.www.bd", "www.bd", true}, - {"zzz.bd", "zzz.bd", true}, - {"www.zzz.bd", "zzz.bd", true}, - {"www.xxx.yyy.zzz.bd", "zzz.bd", true}, - - // The .ck rules are: - // *.ck - // !www.ck - {"ck", "ck", false}, // The catch-all "*" rule is not in the ICANN DOMAIN section. See footnote (†). - {"www.ck", "ck", true}, - {"xxx.www.ck", "ck", true}, - {"zzz.ck", "zzz.ck", true}, - {"www.zzz.ck", "zzz.ck", true}, - {"www.xxx.yyy.zzz.ck", "zzz.ck", true}, - - // The .myjino.ru rules (in the PRIVATE DOMAIN section) are: - // myjino.ru - // *.hosting.myjino.ru - // *.landing.myjino.ru - // *.spectrum.myjino.ru - // *.vps.myjino.ru - {"myjino.ru", "myjino.ru", false}, - {"aaa.myjino.ru", "myjino.ru", false}, - {"bbb.ccc.myjino.ru", "myjino.ru", false}, - {"hosting.ddd.myjino.ru", "myjino.ru", false}, - {"landing.myjino.ru", "myjino.ru", false}, - {"www.landing.myjino.ru", "www.landing.myjino.ru", false}, - {"spectrum.vps.myjino.ru", "spectrum.vps.myjino.ru", false}, - - // The .uberspace.de rules (in the PRIVATE DOMAIN section) are: - // *.uberspace.de - {"uberspace.de", "de", true}, // "de" is in the ICANN DOMAIN section. See footnote (†). - {"aaa.uberspace.de", "aaa.uberspace.de", false}, - {"bbb.ccc.uberspace.de", "ccc.uberspace.de", false}, - - // There are no .nosuchtld rules. - {"nosuchtld", "nosuchtld", false}, - {"foo.nosuchtld", "nosuchtld", false}, - {"bar.foo.nosuchtld", "nosuchtld", false}, - - // (†) There is some disagreement on how wildcards behave: what should the - // public suffix of "platform.sh" be when both "*.platform.sh" and "sh" is - // in the PSL, but "platform.sh" is not? Two possible answers are - // "platform.sh" and "sh", there are valid arguments for either behavior, - // and different browsers have implemented different behaviors. - // - // This implementation, Go's golang.org/x/net/publicsuffix, returns "sh", - // the same as a literal interpretation of the "Formal Algorithm" section - // of https://publicsuffix.org/list/ - // - // Together, the TestPublicSuffix and TestSlowPublicSuffix tests check that - // the Go implementation (func PublicSuffix in list.go) and the literal - // interpretation (func slowPublicSuffix in list_test.go) produce the same - // (golden) results on every test case in this publicSuffixTestCases slice, - // including some "platform.sh" style cases. - // - // More discussion of "the platform.sh problem" is at: - // - https://github.com/publicsuffix/list/issues/694 - // - https://bugzilla.mozilla.org/show_bug.cgi?id=1124625#c6 - // - https://wiki.mozilla.org/Public_Suffix_List/platform.sh_Problem -} - -func BenchmarkPublicSuffix(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, tc := range publicSuffixTestCases { - List.PublicSuffix(tc.domain) - } - } -} - -func TestPublicSuffix(t *testing.T) { - for _, tc := range publicSuffixTestCases { - gotPS, gotICANN := PublicSuffix(tc.domain) - if gotPS != tc.wantPS || gotICANN != tc.wantICANN { - t.Errorf("%q: got (%q, %t), want (%q, %t)", tc.domain, gotPS, gotICANN, tc.wantPS, tc.wantICANN) - } - } -} - -func TestSlowPublicSuffix(t *testing.T) { - for _, tc := range publicSuffixTestCases { - gotPS, gotICANN := slowPublicSuffix(tc.domain) - if gotPS != tc.wantPS || gotICANN != tc.wantICANN { - t.Errorf("%q: got (%q, %t), want (%q, %t)", tc.domain, gotPS, gotICANN, tc.wantPS, tc.wantICANN) - } - } -} - -func TestNumICANNRules(t *testing.T) { - if numICANNRules <= 0 { - t.Fatal("no ICANN rules") - } - if numICANNRules >= len(rules) { - t.Fatal("no Private rules") - } - // Check the last ICANN and first Private rules. If the underlying public - // suffix list changes, we may need to update these hard-coded checks. - if got, want := rules[numICANNRules-1], "zuerich"; got != want { - t.Errorf("last ICANN rule: got %q, wawnt %q", got, want) - } - if got, want := rules[numICANNRules], "cc.ua"; got != want { - t.Errorf("first Private rule: got %q, wawnt %q", got, want) - } -} - -type slowPublicSuffixRule struct { - ruleParts []string - icann bool -} - -// slowPublicSuffix implements the canonical (but O(number of rules)) public -// suffix algorithm described at http://publicsuffix.org/list/. -// -// 1. Match domain against all rules and take note of the matching ones. -// 2. If no rules match, the prevailing rule is "*". -// 3. If more than one rule matches, the prevailing rule is the one which is an exception rule. -// 4. If there is no matching exception rule, the prevailing rule is the one with the most labels. -// 5. If the prevailing rule is a exception rule, modify it by removing the leftmost label. -// 6. The public suffix is the set of labels from the domain which directly match the labels of the prevailing rule (joined by dots). -// 7. The registered or registrable domain is the public suffix plus one additional label. -// -// This function returns the public suffix, not the registrable domain, and so -// it stops after step 6. -func slowPublicSuffix(domain string) (string, bool) { - match := func(rulePart, domainPart string) bool { - switch rulePart[0] { - case '*': - return true - case '!': - return rulePart[1:] == domainPart - } - return rulePart == domainPart - } - - domainParts := strings.Split(domain, ".") - var matchingRules []slowPublicSuffixRule - -loop: - for i, rule := range rules { - ruleParts := strings.Split(rule, ".") - if len(domainParts) < len(ruleParts) { - continue - } - for i := range ruleParts { - rulePart := ruleParts[len(ruleParts)-1-i] - domainPart := domainParts[len(domainParts)-1-i] - if !match(rulePart, domainPart) { - continue loop - } - } - matchingRules = append(matchingRules, slowPublicSuffixRule{ - ruleParts: ruleParts, - icann: i < numICANNRules, - }) - } - if len(matchingRules) == 0 { - matchingRules = append(matchingRules, slowPublicSuffixRule{ - ruleParts: []string{"*"}, - icann: false, - }) - } else { - sort.Sort(byPriority(matchingRules)) - } - - prevailing := matchingRules[0] - if prevailing.ruleParts[0][0] == '!' { - prevailing.ruleParts = prevailing.ruleParts[1:] - } - if prevailing.ruleParts[0][0] == '*' { - replaced := domainParts[len(domainParts)-len(prevailing.ruleParts)] - prevailing.ruleParts = append([]string{replaced}, prevailing.ruleParts[1:]...) - } - return strings.Join(prevailing.ruleParts, "."), prevailing.icann -} - -type byPriority []slowPublicSuffixRule - -func (b byPriority) Len() int { return len(b) } -func (b byPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b byPriority) Less(i, j int) bool { - if b[i].ruleParts[0][0] == '!' { - return true - } - if b[j].ruleParts[0][0] == '!' { - return false - } - return len(b[i].ruleParts) > len(b[j].ruleParts) -} - -// eTLDPlusOneTestCases come from -// https://github.com/publicsuffix/list/blob/master/tests/test_psl.txt -var eTLDPlusOneTestCases = []struct { - domain, want string -}{ - // Empty input. - {"", ""}, - // Unlisted TLD. - {"example", ""}, - {"example.example", "example.example"}, - {"b.example.example", "example.example"}, - {"a.b.example.example", "example.example"}, - // TLD with only 1 rule. - {"biz", ""}, - {"domain.biz", "domain.biz"}, - {"b.domain.biz", "domain.biz"}, - {"a.b.domain.biz", "domain.biz"}, - // TLD with some 2-level rules. - {"com", ""}, - {"example.com", "example.com"}, - {"b.example.com", "example.com"}, - {"a.b.example.com", "example.com"}, - {"uk.com", ""}, - {"example.uk.com", "example.uk.com"}, - {"b.example.uk.com", "example.uk.com"}, - {"a.b.example.uk.com", "example.uk.com"}, - {"test.ac", "test.ac"}, - // TLD with only 1 (wildcard) rule. - {"mm", ""}, - {"c.mm", ""}, - {"b.c.mm", "b.c.mm"}, - {"a.b.c.mm", "b.c.mm"}, - // More complex TLD. - {"jp", ""}, - {"test.jp", "test.jp"}, - {"www.test.jp", "test.jp"}, - {"ac.jp", ""}, - {"test.ac.jp", "test.ac.jp"}, - {"www.test.ac.jp", "test.ac.jp"}, - {"kyoto.jp", ""}, - {"test.kyoto.jp", "test.kyoto.jp"}, - {"ide.kyoto.jp", ""}, - {"b.ide.kyoto.jp", "b.ide.kyoto.jp"}, - {"a.b.ide.kyoto.jp", "b.ide.kyoto.jp"}, - {"c.kobe.jp", ""}, - {"b.c.kobe.jp", "b.c.kobe.jp"}, - {"a.b.c.kobe.jp", "b.c.kobe.jp"}, - {"city.kobe.jp", "city.kobe.jp"}, - {"www.city.kobe.jp", "city.kobe.jp"}, - // TLD with a wildcard rule and exceptions. - {"ck", ""}, - {"test.ck", ""}, - {"b.test.ck", "b.test.ck"}, - {"a.b.test.ck", "b.test.ck"}, - {"www.ck", "www.ck"}, - {"www.www.ck", "www.ck"}, - // US K12. - {"us", ""}, - {"test.us", "test.us"}, - {"www.test.us", "test.us"}, - {"ak.us", ""}, - {"test.ak.us", "test.ak.us"}, - {"www.test.ak.us", "test.ak.us"}, - {"k12.ak.us", ""}, - {"test.k12.ak.us", "test.k12.ak.us"}, - {"www.test.k12.ak.us", "test.k12.ak.us"}, - // Punycoded IDN labels - {"xn--85x722f.com.cn", "xn--85x722f.com.cn"}, - {"xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"}, - {"www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"}, - {"shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn"}, - {"xn--55qx5d.cn", ""}, - {"xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"}, - {"www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"}, - {"shishi.xn--fiqs8s", "shishi.xn--fiqs8s"}, - {"xn--fiqs8s", ""}, - - // Invalid input - {".", ""}, - {"de.", ""}, - {".de", ""}, - {".com.au", ""}, - {"com.au.", ""}, - {"com..au", ""}, -} - -func TestEffectiveTLDPlusOne(t *testing.T) { - for _, tc := range eTLDPlusOneTestCases { - got, _ := EffectiveTLDPlusOne(tc.domain) - if got != tc.want { - t.Errorf("%q: got %q, want %q", tc.domain, got, tc.want) - } - } -} diff --git a/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/golang.org/x/net/publicsuffix/table.go old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/net/publicsuffix/table_test.go b/vendor/golang.org/x/net/publicsuffix/table_test.go deleted file mode 100755 index 8fa1cd1f2c..0000000000 --- a/vendor/golang.org/x/net/publicsuffix/table_test.go +++ /dev/null @@ -1,17632 +0,0 @@ -// generated by go run gen.go; DO NOT EDIT - -package publicsuffix - -const numICANNRules = 7336 - -var rules = [...]string{ - "ac", - "com.ac", - "edu.ac", - "gov.ac", - "net.ac", - "mil.ac", - "org.ac", - "ad", - "nom.ad", - "ae", - "co.ae", - "net.ae", - "org.ae", - "sch.ae", - "ac.ae", - "gov.ae", - "mil.ae", - "aero", - "accident-investigation.aero", - "accident-prevention.aero", - "aerobatic.aero", - "aeroclub.aero", - "aerodrome.aero", - "agents.aero", - "aircraft.aero", - "airline.aero", - "airport.aero", - "air-surveillance.aero", - "airtraffic.aero", - "air-traffic-control.aero", - "ambulance.aero", - "amusement.aero", - "association.aero", - "author.aero", - "ballooning.aero", - "broker.aero", - "caa.aero", - "cargo.aero", - "catering.aero", - "certification.aero", - "championship.aero", - "charter.aero", - "civilaviation.aero", - "club.aero", - "conference.aero", - "consultant.aero", - "consulting.aero", - "control.aero", - "council.aero", - "crew.aero", - "design.aero", - "dgca.aero", - "educator.aero", - "emergency.aero", - "engine.aero", - "engineer.aero", - "entertainment.aero", - "equipment.aero", - "exchange.aero", - "express.aero", - "federation.aero", - "flight.aero", - "freight.aero", - "fuel.aero", - "gliding.aero", - "government.aero", - "groundhandling.aero", - "group.aero", - "hanggliding.aero", - "homebuilt.aero", - "insurance.aero", - "journal.aero", - "journalist.aero", - "leasing.aero", - "logistics.aero", - "magazine.aero", - "maintenance.aero", - "media.aero", - "microlight.aero", - "modelling.aero", - "navigation.aero", - "parachuting.aero", - "paragliding.aero", - "passenger-association.aero", - "pilot.aero", - "press.aero", - "production.aero", - "recreation.aero", - "repbody.aero", - "res.aero", - "research.aero", - "rotorcraft.aero", - "safety.aero", - "scientist.aero", - "services.aero", - "show.aero", - "skydiving.aero", - "software.aero", - "student.aero", - "trader.aero", - "trading.aero", - "trainer.aero", - "union.aero", - "workinggroup.aero", - "works.aero", - "af", - "gov.af", - "com.af", - "org.af", - "net.af", - "edu.af", - "ag", - "com.ag", - "org.ag", - "net.ag", - "co.ag", - "nom.ag", - "ai", - "off.ai", - "com.ai", - "net.ai", - "org.ai", - "al", - "com.al", - "edu.al", - "gov.al", - "mil.al", - "net.al", - "org.al", - "am", - "co.am", - "com.am", - "commune.am", - "net.am", - "org.am", - "ao", - "ed.ao", - "gv.ao", - "og.ao", - "co.ao", - "pb.ao", - "it.ao", - "aq", - "ar", - "com.ar", - "edu.ar", - "gob.ar", - "gov.ar", - "int.ar", - "mil.ar", - "musica.ar", - "net.ar", - "org.ar", - "tur.ar", - "arpa", - "e164.arpa", - "in-addr.arpa", - "ip6.arpa", - "iris.arpa", - "uri.arpa", - "urn.arpa", - "as", - "gov.as", - "asia", - "at", - "ac.at", - "co.at", - "gv.at", - "or.at", - "au", - "com.au", - "net.au", - "org.au", - "edu.au", - "gov.au", - "asn.au", - "id.au", - "info.au", - "conf.au", - "oz.au", - "act.au", - "nsw.au", - "nt.au", - "qld.au", - "sa.au", - "tas.au", - "vic.au", - "wa.au", - "act.edu.au", - "nsw.edu.au", - "nt.edu.au", - "qld.edu.au", - "sa.edu.au", - "tas.edu.au", - "vic.edu.au", - "wa.edu.au", - "qld.gov.au", - "sa.gov.au", - "tas.gov.au", - "vic.gov.au", - "wa.gov.au", - "aw", - "com.aw", - "ax", - "az", - "com.az", - "net.az", - "int.az", - "gov.az", - "org.az", - "edu.az", - "info.az", - "pp.az", - "mil.az", - "name.az", - "pro.az", - "biz.az", - "ba", - "com.ba", - "edu.ba", - "gov.ba", - "mil.ba", - "net.ba", - "org.ba", - "bb", - "biz.bb", - "co.bb", - "com.bb", - "edu.bb", - "gov.bb", - "info.bb", - "net.bb", - "org.bb", - "store.bb", - "tv.bb", - "*.bd", - "be", - "ac.be", - "bf", - "gov.bf", - "bg", - "a.bg", - "b.bg", - "c.bg", - "d.bg", - "e.bg", - "f.bg", - "g.bg", - "h.bg", - "i.bg", - "j.bg", - "k.bg", - "l.bg", - "m.bg", - "n.bg", - "o.bg", - "p.bg", - "q.bg", - "r.bg", - "s.bg", - "t.bg", - "u.bg", - "v.bg", - "w.bg", - "x.bg", - "y.bg", - "z.bg", - "0.bg", - "1.bg", - "2.bg", - "3.bg", - "4.bg", - "5.bg", - "6.bg", - "7.bg", - "8.bg", - "9.bg", - "bh", - "com.bh", - "edu.bh", - "net.bh", - "org.bh", - "gov.bh", - "bi", - "co.bi", - "com.bi", - "edu.bi", - "or.bi", - "org.bi", - "biz", - "bj", - "asso.bj", - "barreau.bj", - "gouv.bj", - "bm", - "com.bm", - "edu.bm", - "gov.bm", - "net.bm", - "org.bm", - "bn", - "com.bn", - "edu.bn", - "gov.bn", - "net.bn", - "org.bn", - "bo", - "com.bo", - "edu.bo", - "gob.bo", - "int.bo", - "org.bo", - "net.bo", - "mil.bo", - "tv.bo", - "web.bo", - "academia.bo", - "agro.bo", - "arte.bo", - "blog.bo", - "bolivia.bo", - "ciencia.bo", - "cooperativa.bo", - "democracia.bo", - "deporte.bo", - "ecologia.bo", - "economia.bo", - "empresa.bo", - "indigena.bo", - "industria.bo", - "info.bo", - "medicina.bo", - "movimiento.bo", - "musica.bo", - "natural.bo", - "nombre.bo", - "noticias.bo", - "patria.bo", - "politica.bo", - "profesional.bo", - "plurinacional.bo", - "pueblo.bo", - "revista.bo", - "salud.bo", - "tecnologia.bo", - "tksat.bo", - "transporte.bo", - "wiki.bo", - "br", - "9guacu.br", - "abc.br", - "adm.br", - "adv.br", - "agr.br", - "aju.br", - "am.br", - "anani.br", - "aparecida.br", - "arq.br", - "art.br", - "ato.br", - "b.br", - "barueri.br", - "belem.br", - "bhz.br", - "bio.br", - "blog.br", - "bmd.br", - "boavista.br", - "bsb.br", - "campinagrande.br", - "campinas.br", - "caxias.br", - "cim.br", - "cng.br", - "cnt.br", - "com.br", - "contagem.br", - "coop.br", - "cri.br", - "cuiaba.br", - "curitiba.br", - "def.br", - "ecn.br", - "eco.br", - "edu.br", - "emp.br", - "eng.br", - "esp.br", - "etc.br", - "eti.br", - "far.br", - "feira.br", - "flog.br", - "floripa.br", - "fm.br", - "fnd.br", - "fortal.br", - "fot.br", - "foz.br", - "fst.br", - "g12.br", - "ggf.br", - "goiania.br", - "gov.br", - "ac.gov.br", - "al.gov.br", - "am.gov.br", - "ap.gov.br", - "ba.gov.br", - "ce.gov.br", - "df.gov.br", - "es.gov.br", - "go.gov.br", - "ma.gov.br", - "mg.gov.br", - "ms.gov.br", - "mt.gov.br", - "pa.gov.br", - "pb.gov.br", - "pe.gov.br", - "pi.gov.br", - "pr.gov.br", - "rj.gov.br", - "rn.gov.br", - "ro.gov.br", - "rr.gov.br", - "rs.gov.br", - "sc.gov.br", - "se.gov.br", - "sp.gov.br", - "to.gov.br", - "gru.br", - "imb.br", - "ind.br", - "inf.br", - "jab.br", - "jampa.br", - "jdf.br", - "joinville.br", - "jor.br", - "jus.br", - "leg.br", - "lel.br", - "londrina.br", - "macapa.br", - "maceio.br", - "manaus.br", - "maringa.br", - "mat.br", - "med.br", - "mil.br", - "morena.br", - "mp.br", - "mus.br", - "natal.br", - "net.br", - "niteroi.br", - "*.nom.br", - "not.br", - "ntr.br", - "odo.br", - "ong.br", - "org.br", - "osasco.br", - "palmas.br", - "poa.br", - "ppg.br", - "pro.br", - "psc.br", - "psi.br", - "pvh.br", - "qsl.br", - "radio.br", - "rec.br", - "recife.br", - "ribeirao.br", - "rio.br", - "riobranco.br", - "riopreto.br", - "salvador.br", - "sampa.br", - "santamaria.br", - "santoandre.br", - "saobernardo.br", - "saogonca.br", - "sjc.br", - "slg.br", - "slz.br", - "sorocaba.br", - "srv.br", - "taxi.br", - "tc.br", - "teo.br", - "the.br", - "tmp.br", - "trd.br", - "tur.br", - "tv.br", - "udi.br", - "vet.br", - "vix.br", - "vlog.br", - "wiki.br", - "zlg.br", - "bs", - "com.bs", - "net.bs", - "org.bs", - "edu.bs", - "gov.bs", - "bt", - "com.bt", - "edu.bt", - "gov.bt", - "net.bt", - "org.bt", - "bv", - "bw", - "co.bw", - "org.bw", - "by", - "gov.by", - "mil.by", - "com.by", - "of.by", - "bz", - "com.bz", - "net.bz", - "org.bz", - "edu.bz", - "gov.bz", - "ca", - "ab.ca", - "bc.ca", - "mb.ca", - "nb.ca", - "nf.ca", - "nl.ca", - "ns.ca", - "nt.ca", - "nu.ca", - "on.ca", - "pe.ca", - "qc.ca", - "sk.ca", - "yk.ca", - "gc.ca", - "cat", - "cc", - "cd", - "gov.cd", - "cf", - "cg", - "ch", - "ci", - "org.ci", - "or.ci", - "com.ci", - "co.ci", - "edu.ci", - "ed.ci", - "ac.ci", - "net.ci", - "go.ci", - "asso.ci", - "xn--aroport-bya.ci", - "int.ci", - "presse.ci", - "md.ci", - "gouv.ci", - "*.ck", - "!www.ck", - "cl", - "gov.cl", - "gob.cl", - "co.cl", - "mil.cl", - "cm", - "co.cm", - "com.cm", - "gov.cm", - "net.cm", - "cn", - "ac.cn", - "com.cn", - "edu.cn", - "gov.cn", - "net.cn", - "org.cn", - "mil.cn", - "xn--55qx5d.cn", - "xn--io0a7i.cn", - "xn--od0alg.cn", - "ah.cn", - "bj.cn", - "cq.cn", - "fj.cn", - "gd.cn", - "gs.cn", - "gz.cn", - "gx.cn", - "ha.cn", - "hb.cn", - "he.cn", - "hi.cn", - "hl.cn", - "hn.cn", - "jl.cn", - "js.cn", - "jx.cn", - "ln.cn", - "nm.cn", - "nx.cn", - "qh.cn", - "sc.cn", - "sd.cn", - "sh.cn", - "sn.cn", - "sx.cn", - "tj.cn", - "xj.cn", - "xz.cn", - "yn.cn", - "zj.cn", - "hk.cn", - "mo.cn", - "tw.cn", - "co", - "arts.co", - "com.co", - "edu.co", - "firm.co", - "gov.co", - "info.co", - "int.co", - "mil.co", - "net.co", - "nom.co", - "org.co", - "rec.co", - "web.co", - "com", - "coop", - "cr", - "ac.cr", - "co.cr", - "ed.cr", - "fi.cr", - "go.cr", - "or.cr", - "sa.cr", - "cu", - "com.cu", - "edu.cu", - "org.cu", - "net.cu", - "gov.cu", - "inf.cu", - "cv", - "cw", - "com.cw", - "edu.cw", - "net.cw", - "org.cw", - "cx", - "gov.cx", - "cy", - "ac.cy", - "biz.cy", - "com.cy", - "ekloges.cy", - "gov.cy", - "ltd.cy", - "name.cy", - "net.cy", - "org.cy", - "parliament.cy", - "press.cy", - "pro.cy", - "tm.cy", - "cz", - "de", - "dj", - "dk", - "dm", - "com.dm", - "net.dm", - "org.dm", - "edu.dm", - "gov.dm", - "do", - "art.do", - "com.do", - "edu.do", - "gob.do", - "gov.do", - "mil.do", - "net.do", - "org.do", - "sld.do", - "web.do", - "dz", - "com.dz", - "org.dz", - "net.dz", - "gov.dz", - "edu.dz", - "asso.dz", - "pol.dz", - "art.dz", - "ec", - "com.ec", - "info.ec", - "net.ec", - "fin.ec", - "k12.ec", - "med.ec", - "pro.ec", - "org.ec", - "edu.ec", - "gov.ec", - "gob.ec", - "mil.ec", - "edu", - "ee", - "edu.ee", - "gov.ee", - "riik.ee", - "lib.ee", - "med.ee", - "com.ee", - "pri.ee", - "aip.ee", - "org.ee", - "fie.ee", - "eg", - "com.eg", - "edu.eg", - "eun.eg", - "gov.eg", - "mil.eg", - "name.eg", - "net.eg", - "org.eg", - "sci.eg", - "*.er", - "es", - "com.es", - "nom.es", - "org.es", - "gob.es", - "edu.es", - "et", - "com.et", - "gov.et", - "org.et", - "edu.et", - "biz.et", - "name.et", - "info.et", - "net.et", - "eu", - "fi", - "aland.fi", - "*.fj", - "*.fk", - "fm", - "fo", - "fr", - "asso.fr", - "com.fr", - "gouv.fr", - "nom.fr", - "prd.fr", - "tm.fr", - "aeroport.fr", - "avocat.fr", - "avoues.fr", - "cci.fr", - "chambagri.fr", - "chirurgiens-dentistes.fr", - "experts-comptables.fr", - "geometre-expert.fr", - "greta.fr", - "huissier-justice.fr", - "medecin.fr", - "notaires.fr", - "pharmacien.fr", - "port.fr", - "veterinaire.fr", - "ga", - "gb", - "gd", - "ge", - "com.ge", - "edu.ge", - "gov.ge", - "org.ge", - "mil.ge", - "net.ge", - "pvt.ge", - "gf", - "gg", - "co.gg", - "net.gg", - "org.gg", - "gh", - "com.gh", - "edu.gh", - "gov.gh", - "org.gh", - "mil.gh", - "gi", - "com.gi", - "ltd.gi", - "gov.gi", - "mod.gi", - "edu.gi", - "org.gi", - "gl", - "co.gl", - "com.gl", - "edu.gl", - "net.gl", - "org.gl", - "gm", - "gn", - "ac.gn", - "com.gn", - "edu.gn", - "gov.gn", - "org.gn", - "net.gn", - "gov", - "gp", - "com.gp", - "net.gp", - "mobi.gp", - "edu.gp", - "org.gp", - "asso.gp", - "gq", - "gr", - "com.gr", - "edu.gr", - "net.gr", - "org.gr", - "gov.gr", - "gs", - "gt", - "com.gt", - "edu.gt", - "gob.gt", - "ind.gt", - "mil.gt", - "net.gt", - "org.gt", - "gu", - "com.gu", - "edu.gu", - "gov.gu", - "guam.gu", - "info.gu", - "net.gu", - "org.gu", - "web.gu", - "gw", - "gy", - "co.gy", - "com.gy", - "edu.gy", - "gov.gy", - "net.gy", - "org.gy", - "hk", - "com.hk", - "edu.hk", - "gov.hk", - "idv.hk", - "net.hk", - "org.hk", - "xn--55qx5d.hk", - "xn--wcvs22d.hk", - "xn--lcvr32d.hk", - "xn--mxtq1m.hk", - "xn--gmqw5a.hk", - "xn--ciqpn.hk", - "xn--gmq050i.hk", - "xn--zf0avx.hk", - "xn--io0a7i.hk", - "xn--mk0axi.hk", - "xn--od0alg.hk", - "xn--od0aq3b.hk", - "xn--tn0ag.hk", - "xn--uc0atv.hk", - "xn--uc0ay4a.hk", - "hm", - "hn", - "com.hn", - "edu.hn", - "org.hn", - "net.hn", - "mil.hn", - "gob.hn", - "hr", - "iz.hr", - "from.hr", - "name.hr", - "com.hr", - "ht", - "com.ht", - "shop.ht", - "firm.ht", - "info.ht", - "adult.ht", - "net.ht", - "pro.ht", - "org.ht", - "med.ht", - "art.ht", - "coop.ht", - "pol.ht", - "asso.ht", - "edu.ht", - "rel.ht", - "gouv.ht", - "perso.ht", - "hu", - "co.hu", - "info.hu", - "org.hu", - "priv.hu", - "sport.hu", - "tm.hu", - "2000.hu", - "agrar.hu", - "bolt.hu", - "casino.hu", - "city.hu", - "erotica.hu", - "erotika.hu", - "film.hu", - "forum.hu", - "games.hu", - "hotel.hu", - "ingatlan.hu", - "jogasz.hu", - "konyvelo.hu", - "lakas.hu", - "media.hu", - "news.hu", - "reklam.hu", - "sex.hu", - "shop.hu", - "suli.hu", - "szex.hu", - "tozsde.hu", - "utazas.hu", - "video.hu", - "id", - "ac.id", - "biz.id", - "co.id", - "desa.id", - "go.id", - "mil.id", - "my.id", - "net.id", - "or.id", - "ponpes.id", - "sch.id", - "web.id", - "ie", - "gov.ie", - "il", - "ac.il", - "co.il", - "gov.il", - "idf.il", - "k12.il", - "muni.il", - "net.il", - "org.il", - "im", - "ac.im", - "co.im", - "com.im", - "ltd.co.im", - "net.im", - "org.im", - "plc.co.im", - "tt.im", - "tv.im", - "in", - "co.in", - "firm.in", - "net.in", - "org.in", - "gen.in", - "ind.in", - "nic.in", - "ac.in", - "edu.in", - "res.in", - "gov.in", - "mil.in", - "info", - "int", - "eu.int", - "io", - "com.io", - "iq", - "gov.iq", - "edu.iq", - "mil.iq", - "com.iq", - "org.iq", - "net.iq", - "ir", - "ac.ir", - "co.ir", - "gov.ir", - "id.ir", - "net.ir", - "org.ir", - "sch.ir", - "xn--mgba3a4f16a.ir", - "xn--mgba3a4fra.ir", - "is", - "net.is", - "com.is", - "edu.is", - "gov.is", - "org.is", - "int.is", - "it", - "gov.it", - "edu.it", - "abr.it", - "abruzzo.it", - "aosta-valley.it", - "aostavalley.it", - "bas.it", - "basilicata.it", - "cal.it", - "calabria.it", - "cam.it", - "campania.it", - "emilia-romagna.it", - "emiliaromagna.it", - "emr.it", - "friuli-v-giulia.it", - "friuli-ve-giulia.it", - "friuli-vegiulia.it", - "friuli-venezia-giulia.it", - "friuli-veneziagiulia.it", - "friuli-vgiulia.it", - "friuliv-giulia.it", - "friulive-giulia.it", - "friulivegiulia.it", - "friulivenezia-giulia.it", - "friuliveneziagiulia.it", - "friulivgiulia.it", - "fvg.it", - "laz.it", - "lazio.it", - "lig.it", - "liguria.it", - "lom.it", - "lombardia.it", - "lombardy.it", - "lucania.it", - "mar.it", - "marche.it", - "mol.it", - "molise.it", - "piedmont.it", - "piemonte.it", - "pmn.it", - "pug.it", - "puglia.it", - "sar.it", - "sardegna.it", - "sardinia.it", - "sic.it", - "sicilia.it", - "sicily.it", - "taa.it", - "tos.it", - "toscana.it", - "trentin-sud-tirol.it", - "xn--trentin-sd-tirol-rzb.it", - "trentin-sudtirol.it", - "xn--trentin-sdtirol-7vb.it", - "trentin-sued-tirol.it", - "trentin-suedtirol.it", - "trentino-a-adige.it", - "trentino-aadige.it", - "trentino-alto-adige.it", - "trentino-altoadige.it", - "trentino-s-tirol.it", - "trentino-stirol.it", - "trentino-sud-tirol.it", - "xn--trentino-sd-tirol-c3b.it", - "trentino-sudtirol.it", - "xn--trentino-sdtirol-szb.it", - "trentino-sued-tirol.it", - "trentino-suedtirol.it", - "trentino.it", - "trentinoa-adige.it", - "trentinoaadige.it", - "trentinoalto-adige.it", - "trentinoaltoadige.it", - "trentinos-tirol.it", - "trentinostirol.it", - "trentinosud-tirol.it", - "xn--trentinosd-tirol-rzb.it", - "trentinosudtirol.it", - "xn--trentinosdtirol-7vb.it", - "trentinosued-tirol.it", - "trentinosuedtirol.it", - "trentinsud-tirol.it", - "xn--trentinsd-tirol-6vb.it", - "trentinsudtirol.it", - "xn--trentinsdtirol-nsb.it", - "trentinsued-tirol.it", - "trentinsuedtirol.it", - "tuscany.it", - "umb.it", - "umbria.it", - "val-d-aosta.it", - "val-daosta.it", - "vald-aosta.it", - "valdaosta.it", - "valle-aosta.it", - "valle-d-aosta.it", - "valle-daosta.it", - "valleaosta.it", - "valled-aosta.it", - "valledaosta.it", - "vallee-aoste.it", - "xn--valle-aoste-ebb.it", - "vallee-d-aoste.it", - "xn--valle-d-aoste-ehb.it", - "valleeaoste.it", - "xn--valleaoste-e7a.it", - "valleedaoste.it", - "xn--valledaoste-ebb.it", - "vao.it", - "vda.it", - "ven.it", - "veneto.it", - "ag.it", - "agrigento.it", - "al.it", - "alessandria.it", - "alto-adige.it", - "altoadige.it", - "an.it", - "ancona.it", - "andria-barletta-trani.it", - "andria-trani-barletta.it", - "andriabarlettatrani.it", - "andriatranibarletta.it", - "ao.it", - "aosta.it", - "aoste.it", - "ap.it", - "aq.it", - "aquila.it", - "ar.it", - "arezzo.it", - "ascoli-piceno.it", - "ascolipiceno.it", - "asti.it", - "at.it", - "av.it", - "avellino.it", - "ba.it", - "balsan-sudtirol.it", - "xn--balsan-sdtirol-nsb.it", - "balsan-suedtirol.it", - "balsan.it", - "bari.it", - "barletta-trani-andria.it", - "barlettatraniandria.it", - "belluno.it", - "benevento.it", - "bergamo.it", - "bg.it", - "bi.it", - "biella.it", - "bl.it", - "bn.it", - "bo.it", - "bologna.it", - "bolzano-altoadige.it", - "bolzano.it", - "bozen-sudtirol.it", - "xn--bozen-sdtirol-2ob.it", - "bozen-suedtirol.it", - "bozen.it", - "br.it", - "brescia.it", - "brindisi.it", - "bs.it", - "bt.it", - "bulsan-sudtirol.it", - "xn--bulsan-sdtirol-nsb.it", - "bulsan-suedtirol.it", - "bulsan.it", - "bz.it", - "ca.it", - "cagliari.it", - "caltanissetta.it", - "campidano-medio.it", - "campidanomedio.it", - "campobasso.it", - "carbonia-iglesias.it", - "carboniaiglesias.it", - "carrara-massa.it", - "carraramassa.it", - "caserta.it", - "catania.it", - "catanzaro.it", - "cb.it", - "ce.it", - "cesena-forli.it", - "xn--cesena-forl-mcb.it", - "cesenaforli.it", - "xn--cesenaforl-i8a.it", - "ch.it", - "chieti.it", - "ci.it", - "cl.it", - "cn.it", - "co.it", - "como.it", - "cosenza.it", - "cr.it", - "cremona.it", - "crotone.it", - "cs.it", - "ct.it", - "cuneo.it", - "cz.it", - "dell-ogliastra.it", - "dellogliastra.it", - "en.it", - "enna.it", - "fc.it", - "fe.it", - "fermo.it", - "ferrara.it", - "fg.it", - "fi.it", - "firenze.it", - "florence.it", - "fm.it", - "foggia.it", - "forli-cesena.it", - "xn--forl-cesena-fcb.it", - "forlicesena.it", - "xn--forlcesena-c8a.it", - "fr.it", - "frosinone.it", - "ge.it", - "genoa.it", - "genova.it", - "go.it", - "gorizia.it", - "gr.it", - "grosseto.it", - "iglesias-carbonia.it", - "iglesiascarbonia.it", - "im.it", - "imperia.it", - "is.it", - "isernia.it", - "kr.it", - "la-spezia.it", - "laquila.it", - "laspezia.it", - "latina.it", - "lc.it", - "le.it", - "lecce.it", - "lecco.it", - "li.it", - "livorno.it", - "lo.it", - "lodi.it", - "lt.it", - "lu.it", - "lucca.it", - "macerata.it", - "mantova.it", - "massa-carrara.it", - "massacarrara.it", - "matera.it", - "mb.it", - "mc.it", - "me.it", - "medio-campidano.it", - "mediocampidano.it", - "messina.it", - "mi.it", - "milan.it", - "milano.it", - "mn.it", - "mo.it", - "modena.it", - "monza-brianza.it", - "monza-e-della-brianza.it", - "monza.it", - "monzabrianza.it", - "monzaebrianza.it", - "monzaedellabrianza.it", - "ms.it", - "mt.it", - "na.it", - "naples.it", - "napoli.it", - "no.it", - "novara.it", - "nu.it", - "nuoro.it", - "og.it", - "ogliastra.it", - "olbia-tempio.it", - "olbiatempio.it", - "or.it", - "oristano.it", - "ot.it", - "pa.it", - "padova.it", - "padua.it", - "palermo.it", - "parma.it", - "pavia.it", - "pc.it", - "pd.it", - "pe.it", - "perugia.it", - "pesaro-urbino.it", - "pesarourbino.it", - "pescara.it", - "pg.it", - "pi.it", - "piacenza.it", - "pisa.it", - "pistoia.it", - "pn.it", - "po.it", - "pordenone.it", - "potenza.it", - "pr.it", - "prato.it", - "pt.it", - "pu.it", - "pv.it", - "pz.it", - "ra.it", - "ragusa.it", - "ravenna.it", - "rc.it", - "re.it", - "reggio-calabria.it", - "reggio-emilia.it", - "reggiocalabria.it", - "reggioemilia.it", - "rg.it", - "ri.it", - "rieti.it", - "rimini.it", - "rm.it", - "rn.it", - "ro.it", - "roma.it", - "rome.it", - "rovigo.it", - "sa.it", - "salerno.it", - "sassari.it", - "savona.it", - "si.it", - "siena.it", - "siracusa.it", - "so.it", - "sondrio.it", - "sp.it", - "sr.it", - "ss.it", - "suedtirol.it", - "xn--sdtirol-n2a.it", - "sv.it", - "ta.it", - "taranto.it", - "te.it", - "tempio-olbia.it", - "tempioolbia.it", - "teramo.it", - "terni.it", - "tn.it", - "to.it", - "torino.it", - "tp.it", - "tr.it", - "trani-andria-barletta.it", - "trani-barletta-andria.it", - "traniandriabarletta.it", - "tranibarlettaandria.it", - "trapani.it", - "trento.it", - "treviso.it", - "trieste.it", - "ts.it", - "turin.it", - "tv.it", - "ud.it", - "udine.it", - "urbino-pesaro.it", - "urbinopesaro.it", - "va.it", - "varese.it", - "vb.it", - "vc.it", - "ve.it", - "venezia.it", - "venice.it", - "verbania.it", - "vercelli.it", - "verona.it", - "vi.it", - "vibo-valentia.it", - "vibovalentia.it", - "vicenza.it", - "viterbo.it", - "vr.it", - "vs.it", - "vt.it", - "vv.it", - "je", - "co.je", - "net.je", - "org.je", - "*.jm", - "jo", - "com.jo", - "org.jo", - "net.jo", - "edu.jo", - "sch.jo", - "gov.jo", - "mil.jo", - "name.jo", - "jobs", - "jp", - "ac.jp", - "ad.jp", - "co.jp", - "ed.jp", - "go.jp", - "gr.jp", - "lg.jp", - "ne.jp", - "or.jp", - "aichi.jp", - "akita.jp", - "aomori.jp", - "chiba.jp", - "ehime.jp", - "fukui.jp", - "fukuoka.jp", - "fukushima.jp", - "gifu.jp", - "gunma.jp", - "hiroshima.jp", - "hokkaido.jp", - "hyogo.jp", - "ibaraki.jp", - "ishikawa.jp", - "iwate.jp", - "kagawa.jp", - "kagoshima.jp", - "kanagawa.jp", - "kochi.jp", - "kumamoto.jp", - "kyoto.jp", - "mie.jp", - "miyagi.jp", - "miyazaki.jp", - "nagano.jp", - "nagasaki.jp", - "nara.jp", - "niigata.jp", - "oita.jp", - "okayama.jp", - "okinawa.jp", - "osaka.jp", - "saga.jp", - "saitama.jp", - "shiga.jp", - "shimane.jp", - "shizuoka.jp", - "tochigi.jp", - "tokushima.jp", - "tokyo.jp", - "tottori.jp", - "toyama.jp", - "wakayama.jp", - "yamagata.jp", - "yamaguchi.jp", - "yamanashi.jp", - "xn--4pvxs.jp", - "xn--vgu402c.jp", - "xn--c3s14m.jp", - "xn--f6qx53a.jp", - "xn--8pvr4u.jp", - "xn--uist22h.jp", - "xn--djrs72d6uy.jp", - "xn--mkru45i.jp", - "xn--0trq7p7nn.jp", - "xn--8ltr62k.jp", - "xn--2m4a15e.jp", - "xn--efvn9s.jp", - "xn--32vp30h.jp", - "xn--4it797k.jp", - "xn--1lqs71d.jp", - "xn--5rtp49c.jp", - "xn--5js045d.jp", - "xn--ehqz56n.jp", - "xn--1lqs03n.jp", - "xn--qqqt11m.jp", - "xn--kbrq7o.jp", - "xn--pssu33l.jp", - "xn--ntsq17g.jp", - "xn--uisz3g.jp", - "xn--6btw5a.jp", - "xn--1ctwo.jp", - "xn--6orx2r.jp", - "xn--rht61e.jp", - "xn--rht27z.jp", - "xn--djty4k.jp", - "xn--nit225k.jp", - "xn--rht3d.jp", - "xn--klty5x.jp", - "xn--kltx9a.jp", - "xn--kltp7d.jp", - "xn--uuwu58a.jp", - "xn--zbx025d.jp", - "xn--ntso0iqx3a.jp", - "xn--elqq16h.jp", - "xn--4it168d.jp", - "xn--klt787d.jp", - "xn--rny31h.jp", - "xn--7t0a264c.jp", - "xn--5rtq34k.jp", - "xn--k7yn95e.jp", - "xn--tor131o.jp", - "xn--d5qv7z876c.jp", - "*.kawasaki.jp", - "*.kitakyushu.jp", - "*.kobe.jp", - "*.nagoya.jp", - "*.sapporo.jp", - "*.sendai.jp", - "*.yokohama.jp", - "!city.kawasaki.jp", - "!city.kitakyushu.jp", - "!city.kobe.jp", - "!city.nagoya.jp", - "!city.sapporo.jp", - "!city.sendai.jp", - "!city.yokohama.jp", - "aisai.aichi.jp", - "ama.aichi.jp", - "anjo.aichi.jp", - "asuke.aichi.jp", - "chiryu.aichi.jp", - "chita.aichi.jp", - "fuso.aichi.jp", - "gamagori.aichi.jp", - "handa.aichi.jp", - "hazu.aichi.jp", - "hekinan.aichi.jp", - "higashiura.aichi.jp", - "ichinomiya.aichi.jp", - "inazawa.aichi.jp", - "inuyama.aichi.jp", - "isshiki.aichi.jp", - "iwakura.aichi.jp", - "kanie.aichi.jp", - "kariya.aichi.jp", - "kasugai.aichi.jp", - "kira.aichi.jp", - "kiyosu.aichi.jp", - "komaki.aichi.jp", - "konan.aichi.jp", - "kota.aichi.jp", - "mihama.aichi.jp", - "miyoshi.aichi.jp", - "nishio.aichi.jp", - "nisshin.aichi.jp", - "obu.aichi.jp", - "oguchi.aichi.jp", - "oharu.aichi.jp", - "okazaki.aichi.jp", - "owariasahi.aichi.jp", - "seto.aichi.jp", - "shikatsu.aichi.jp", - "shinshiro.aichi.jp", - "shitara.aichi.jp", - "tahara.aichi.jp", - "takahama.aichi.jp", - "tobishima.aichi.jp", - "toei.aichi.jp", - "togo.aichi.jp", - "tokai.aichi.jp", - "tokoname.aichi.jp", - "toyoake.aichi.jp", - "toyohashi.aichi.jp", - "toyokawa.aichi.jp", - "toyone.aichi.jp", - "toyota.aichi.jp", - "tsushima.aichi.jp", - "yatomi.aichi.jp", - "akita.akita.jp", - "daisen.akita.jp", - "fujisato.akita.jp", - "gojome.akita.jp", - "hachirogata.akita.jp", - "happou.akita.jp", - "higashinaruse.akita.jp", - "honjo.akita.jp", - "honjyo.akita.jp", - "ikawa.akita.jp", - "kamikoani.akita.jp", - "kamioka.akita.jp", - "katagami.akita.jp", - "kazuno.akita.jp", - "kitaakita.akita.jp", - "kosaka.akita.jp", - "kyowa.akita.jp", - "misato.akita.jp", - "mitane.akita.jp", - "moriyoshi.akita.jp", - "nikaho.akita.jp", - "noshiro.akita.jp", - "odate.akita.jp", - "oga.akita.jp", - "ogata.akita.jp", - "semboku.akita.jp", - "yokote.akita.jp", - "yurihonjo.akita.jp", - "aomori.aomori.jp", - "gonohe.aomori.jp", - "hachinohe.aomori.jp", - "hashikami.aomori.jp", - "hiranai.aomori.jp", - "hirosaki.aomori.jp", - "itayanagi.aomori.jp", - "kuroishi.aomori.jp", - "misawa.aomori.jp", - "mutsu.aomori.jp", - "nakadomari.aomori.jp", - "noheji.aomori.jp", - "oirase.aomori.jp", - "owani.aomori.jp", - "rokunohe.aomori.jp", - "sannohe.aomori.jp", - "shichinohe.aomori.jp", - "shingo.aomori.jp", - "takko.aomori.jp", - "towada.aomori.jp", - "tsugaru.aomori.jp", - "tsuruta.aomori.jp", - "abiko.chiba.jp", - "asahi.chiba.jp", - "chonan.chiba.jp", - "chosei.chiba.jp", - "choshi.chiba.jp", - "chuo.chiba.jp", - "funabashi.chiba.jp", - "futtsu.chiba.jp", - "hanamigawa.chiba.jp", - "ichihara.chiba.jp", - "ichikawa.chiba.jp", - "ichinomiya.chiba.jp", - "inzai.chiba.jp", - "isumi.chiba.jp", - "kamagaya.chiba.jp", - "kamogawa.chiba.jp", - "kashiwa.chiba.jp", - "katori.chiba.jp", - "katsuura.chiba.jp", - "kimitsu.chiba.jp", - "kisarazu.chiba.jp", - "kozaki.chiba.jp", - "kujukuri.chiba.jp", - "kyonan.chiba.jp", - "matsudo.chiba.jp", - "midori.chiba.jp", - "mihama.chiba.jp", - "minamiboso.chiba.jp", - "mobara.chiba.jp", - "mutsuzawa.chiba.jp", - "nagara.chiba.jp", - "nagareyama.chiba.jp", - "narashino.chiba.jp", - "narita.chiba.jp", - "noda.chiba.jp", - "oamishirasato.chiba.jp", - "omigawa.chiba.jp", - "onjuku.chiba.jp", - "otaki.chiba.jp", - "sakae.chiba.jp", - "sakura.chiba.jp", - "shimofusa.chiba.jp", - "shirako.chiba.jp", - "shiroi.chiba.jp", - "shisui.chiba.jp", - "sodegaura.chiba.jp", - "sosa.chiba.jp", - "tako.chiba.jp", - "tateyama.chiba.jp", - "togane.chiba.jp", - "tohnosho.chiba.jp", - "tomisato.chiba.jp", - "urayasu.chiba.jp", - "yachimata.chiba.jp", - "yachiyo.chiba.jp", - "yokaichiba.chiba.jp", - "yokoshibahikari.chiba.jp", - "yotsukaido.chiba.jp", - "ainan.ehime.jp", - "honai.ehime.jp", - "ikata.ehime.jp", - "imabari.ehime.jp", - "iyo.ehime.jp", - "kamijima.ehime.jp", - "kihoku.ehime.jp", - "kumakogen.ehime.jp", - "masaki.ehime.jp", - "matsuno.ehime.jp", - "matsuyama.ehime.jp", - "namikata.ehime.jp", - "niihama.ehime.jp", - "ozu.ehime.jp", - "saijo.ehime.jp", - "seiyo.ehime.jp", - "shikokuchuo.ehime.jp", - "tobe.ehime.jp", - "toon.ehime.jp", - "uchiko.ehime.jp", - "uwajima.ehime.jp", - "yawatahama.ehime.jp", - "echizen.fukui.jp", - "eiheiji.fukui.jp", - "fukui.fukui.jp", - "ikeda.fukui.jp", - "katsuyama.fukui.jp", - "mihama.fukui.jp", - "minamiechizen.fukui.jp", - "obama.fukui.jp", - "ohi.fukui.jp", - "ono.fukui.jp", - "sabae.fukui.jp", - "sakai.fukui.jp", - "takahama.fukui.jp", - "tsuruga.fukui.jp", - "wakasa.fukui.jp", - "ashiya.fukuoka.jp", - "buzen.fukuoka.jp", - "chikugo.fukuoka.jp", - "chikuho.fukuoka.jp", - "chikujo.fukuoka.jp", - "chikushino.fukuoka.jp", - "chikuzen.fukuoka.jp", - "chuo.fukuoka.jp", - "dazaifu.fukuoka.jp", - "fukuchi.fukuoka.jp", - "hakata.fukuoka.jp", - "higashi.fukuoka.jp", - "hirokawa.fukuoka.jp", - "hisayama.fukuoka.jp", - "iizuka.fukuoka.jp", - "inatsuki.fukuoka.jp", - "kaho.fukuoka.jp", - "kasuga.fukuoka.jp", - "kasuya.fukuoka.jp", - "kawara.fukuoka.jp", - "keisen.fukuoka.jp", - "koga.fukuoka.jp", - "kurate.fukuoka.jp", - "kurogi.fukuoka.jp", - "kurume.fukuoka.jp", - "minami.fukuoka.jp", - "miyako.fukuoka.jp", - "miyama.fukuoka.jp", - "miyawaka.fukuoka.jp", - "mizumaki.fukuoka.jp", - "munakata.fukuoka.jp", - "nakagawa.fukuoka.jp", - "nakama.fukuoka.jp", - "nishi.fukuoka.jp", - "nogata.fukuoka.jp", - "ogori.fukuoka.jp", - "okagaki.fukuoka.jp", - "okawa.fukuoka.jp", - "oki.fukuoka.jp", - "omuta.fukuoka.jp", - "onga.fukuoka.jp", - "onojo.fukuoka.jp", - "oto.fukuoka.jp", - "saigawa.fukuoka.jp", - "sasaguri.fukuoka.jp", - "shingu.fukuoka.jp", - "shinyoshitomi.fukuoka.jp", - "shonai.fukuoka.jp", - "soeda.fukuoka.jp", - "sue.fukuoka.jp", - "tachiarai.fukuoka.jp", - "tagawa.fukuoka.jp", - "takata.fukuoka.jp", - "toho.fukuoka.jp", - "toyotsu.fukuoka.jp", - "tsuiki.fukuoka.jp", - "ukiha.fukuoka.jp", - "umi.fukuoka.jp", - "usui.fukuoka.jp", - "yamada.fukuoka.jp", - "yame.fukuoka.jp", - "yanagawa.fukuoka.jp", - "yukuhashi.fukuoka.jp", - "aizubange.fukushima.jp", - "aizumisato.fukushima.jp", - "aizuwakamatsu.fukushima.jp", - "asakawa.fukushima.jp", - "bandai.fukushima.jp", - "date.fukushima.jp", - "fukushima.fukushima.jp", - "furudono.fukushima.jp", - "futaba.fukushima.jp", - "hanawa.fukushima.jp", - "higashi.fukushima.jp", - "hirata.fukushima.jp", - "hirono.fukushima.jp", - "iitate.fukushima.jp", - "inawashiro.fukushima.jp", - "ishikawa.fukushima.jp", - "iwaki.fukushima.jp", - "izumizaki.fukushima.jp", - "kagamiishi.fukushima.jp", - "kaneyama.fukushima.jp", - "kawamata.fukushima.jp", - "kitakata.fukushima.jp", - "kitashiobara.fukushima.jp", - "koori.fukushima.jp", - "koriyama.fukushima.jp", - "kunimi.fukushima.jp", - "miharu.fukushima.jp", - "mishima.fukushima.jp", - "namie.fukushima.jp", - "nango.fukushima.jp", - "nishiaizu.fukushima.jp", - "nishigo.fukushima.jp", - "okuma.fukushima.jp", - "omotego.fukushima.jp", - "ono.fukushima.jp", - "otama.fukushima.jp", - "samegawa.fukushima.jp", - "shimogo.fukushima.jp", - "shirakawa.fukushima.jp", - "showa.fukushima.jp", - "soma.fukushima.jp", - "sukagawa.fukushima.jp", - "taishin.fukushima.jp", - "tamakawa.fukushima.jp", - "tanagura.fukushima.jp", - "tenei.fukushima.jp", - "yabuki.fukushima.jp", - "yamato.fukushima.jp", - "yamatsuri.fukushima.jp", - "yanaizu.fukushima.jp", - "yugawa.fukushima.jp", - "anpachi.gifu.jp", - "ena.gifu.jp", - "gifu.gifu.jp", - "ginan.gifu.jp", - "godo.gifu.jp", - "gujo.gifu.jp", - "hashima.gifu.jp", - "hichiso.gifu.jp", - "hida.gifu.jp", - "higashishirakawa.gifu.jp", - "ibigawa.gifu.jp", - "ikeda.gifu.jp", - "kakamigahara.gifu.jp", - "kani.gifu.jp", - "kasahara.gifu.jp", - "kasamatsu.gifu.jp", - "kawaue.gifu.jp", - "kitagata.gifu.jp", - "mino.gifu.jp", - "minokamo.gifu.jp", - "mitake.gifu.jp", - "mizunami.gifu.jp", - "motosu.gifu.jp", - "nakatsugawa.gifu.jp", - "ogaki.gifu.jp", - "sakahogi.gifu.jp", - "seki.gifu.jp", - "sekigahara.gifu.jp", - "shirakawa.gifu.jp", - "tajimi.gifu.jp", - "takayama.gifu.jp", - "tarui.gifu.jp", - "toki.gifu.jp", - "tomika.gifu.jp", - "wanouchi.gifu.jp", - "yamagata.gifu.jp", - "yaotsu.gifu.jp", - "yoro.gifu.jp", - "annaka.gunma.jp", - "chiyoda.gunma.jp", - "fujioka.gunma.jp", - "higashiagatsuma.gunma.jp", - "isesaki.gunma.jp", - "itakura.gunma.jp", - "kanna.gunma.jp", - "kanra.gunma.jp", - "katashina.gunma.jp", - "kawaba.gunma.jp", - "kiryu.gunma.jp", - "kusatsu.gunma.jp", - "maebashi.gunma.jp", - "meiwa.gunma.jp", - "midori.gunma.jp", - "minakami.gunma.jp", - "naganohara.gunma.jp", - "nakanojo.gunma.jp", - "nanmoku.gunma.jp", - "numata.gunma.jp", - "oizumi.gunma.jp", - "ora.gunma.jp", - "ota.gunma.jp", - "shibukawa.gunma.jp", - "shimonita.gunma.jp", - "shinto.gunma.jp", - "showa.gunma.jp", - "takasaki.gunma.jp", - "takayama.gunma.jp", - "tamamura.gunma.jp", - "tatebayashi.gunma.jp", - "tomioka.gunma.jp", - "tsukiyono.gunma.jp", - "tsumagoi.gunma.jp", - "ueno.gunma.jp", - "yoshioka.gunma.jp", - "asaminami.hiroshima.jp", - "daiwa.hiroshima.jp", - "etajima.hiroshima.jp", - "fuchu.hiroshima.jp", - "fukuyama.hiroshima.jp", - "hatsukaichi.hiroshima.jp", - "higashihiroshima.hiroshima.jp", - "hongo.hiroshima.jp", - "jinsekikogen.hiroshima.jp", - "kaita.hiroshima.jp", - "kui.hiroshima.jp", - "kumano.hiroshima.jp", - "kure.hiroshima.jp", - "mihara.hiroshima.jp", - "miyoshi.hiroshima.jp", - "naka.hiroshima.jp", - "onomichi.hiroshima.jp", - "osakikamijima.hiroshima.jp", - "otake.hiroshima.jp", - "saka.hiroshima.jp", - "sera.hiroshima.jp", - "seranishi.hiroshima.jp", - "shinichi.hiroshima.jp", - "shobara.hiroshima.jp", - "takehara.hiroshima.jp", - "abashiri.hokkaido.jp", - "abira.hokkaido.jp", - "aibetsu.hokkaido.jp", - "akabira.hokkaido.jp", - "akkeshi.hokkaido.jp", - "asahikawa.hokkaido.jp", - "ashibetsu.hokkaido.jp", - "ashoro.hokkaido.jp", - "assabu.hokkaido.jp", - "atsuma.hokkaido.jp", - "bibai.hokkaido.jp", - "biei.hokkaido.jp", - "bifuka.hokkaido.jp", - "bihoro.hokkaido.jp", - "biratori.hokkaido.jp", - "chippubetsu.hokkaido.jp", - "chitose.hokkaido.jp", - "date.hokkaido.jp", - "ebetsu.hokkaido.jp", - "embetsu.hokkaido.jp", - "eniwa.hokkaido.jp", - "erimo.hokkaido.jp", - "esan.hokkaido.jp", - "esashi.hokkaido.jp", - "fukagawa.hokkaido.jp", - "fukushima.hokkaido.jp", - "furano.hokkaido.jp", - "furubira.hokkaido.jp", - "haboro.hokkaido.jp", - "hakodate.hokkaido.jp", - "hamatonbetsu.hokkaido.jp", - "hidaka.hokkaido.jp", - "higashikagura.hokkaido.jp", - "higashikawa.hokkaido.jp", - "hiroo.hokkaido.jp", - "hokuryu.hokkaido.jp", - "hokuto.hokkaido.jp", - "honbetsu.hokkaido.jp", - "horokanai.hokkaido.jp", - "horonobe.hokkaido.jp", - "ikeda.hokkaido.jp", - "imakane.hokkaido.jp", - "ishikari.hokkaido.jp", - "iwamizawa.hokkaido.jp", - "iwanai.hokkaido.jp", - "kamifurano.hokkaido.jp", - "kamikawa.hokkaido.jp", - "kamishihoro.hokkaido.jp", - "kamisunagawa.hokkaido.jp", - "kamoenai.hokkaido.jp", - "kayabe.hokkaido.jp", - "kembuchi.hokkaido.jp", - "kikonai.hokkaido.jp", - "kimobetsu.hokkaido.jp", - "kitahiroshima.hokkaido.jp", - "kitami.hokkaido.jp", - "kiyosato.hokkaido.jp", - "koshimizu.hokkaido.jp", - "kunneppu.hokkaido.jp", - "kuriyama.hokkaido.jp", - "kuromatsunai.hokkaido.jp", - "kushiro.hokkaido.jp", - "kutchan.hokkaido.jp", - "kyowa.hokkaido.jp", - "mashike.hokkaido.jp", - "matsumae.hokkaido.jp", - "mikasa.hokkaido.jp", - "minamifurano.hokkaido.jp", - "mombetsu.hokkaido.jp", - "moseushi.hokkaido.jp", - "mukawa.hokkaido.jp", - "muroran.hokkaido.jp", - "naie.hokkaido.jp", - "nakagawa.hokkaido.jp", - "nakasatsunai.hokkaido.jp", - "nakatombetsu.hokkaido.jp", - "nanae.hokkaido.jp", - "nanporo.hokkaido.jp", - "nayoro.hokkaido.jp", - "nemuro.hokkaido.jp", - "niikappu.hokkaido.jp", - "niki.hokkaido.jp", - "nishiokoppe.hokkaido.jp", - "noboribetsu.hokkaido.jp", - "numata.hokkaido.jp", - "obihiro.hokkaido.jp", - "obira.hokkaido.jp", - "oketo.hokkaido.jp", - "okoppe.hokkaido.jp", - "otaru.hokkaido.jp", - "otobe.hokkaido.jp", - "otofuke.hokkaido.jp", - "otoineppu.hokkaido.jp", - "oumu.hokkaido.jp", - "ozora.hokkaido.jp", - "pippu.hokkaido.jp", - "rankoshi.hokkaido.jp", - "rebun.hokkaido.jp", - "rikubetsu.hokkaido.jp", - "rishiri.hokkaido.jp", - "rishirifuji.hokkaido.jp", - "saroma.hokkaido.jp", - "sarufutsu.hokkaido.jp", - "shakotan.hokkaido.jp", - "shari.hokkaido.jp", - "shibecha.hokkaido.jp", - "shibetsu.hokkaido.jp", - "shikabe.hokkaido.jp", - "shikaoi.hokkaido.jp", - "shimamaki.hokkaido.jp", - "shimizu.hokkaido.jp", - "shimokawa.hokkaido.jp", - "shinshinotsu.hokkaido.jp", - "shintoku.hokkaido.jp", - "shiranuka.hokkaido.jp", - "shiraoi.hokkaido.jp", - "shiriuchi.hokkaido.jp", - "sobetsu.hokkaido.jp", - "sunagawa.hokkaido.jp", - "taiki.hokkaido.jp", - "takasu.hokkaido.jp", - "takikawa.hokkaido.jp", - "takinoue.hokkaido.jp", - "teshikaga.hokkaido.jp", - "tobetsu.hokkaido.jp", - "tohma.hokkaido.jp", - "tomakomai.hokkaido.jp", - "tomari.hokkaido.jp", - "toya.hokkaido.jp", - "toyako.hokkaido.jp", - "toyotomi.hokkaido.jp", - "toyoura.hokkaido.jp", - "tsubetsu.hokkaido.jp", - "tsukigata.hokkaido.jp", - "urakawa.hokkaido.jp", - "urausu.hokkaido.jp", - "uryu.hokkaido.jp", - "utashinai.hokkaido.jp", - "wakkanai.hokkaido.jp", - "wassamu.hokkaido.jp", - "yakumo.hokkaido.jp", - "yoichi.hokkaido.jp", - "aioi.hyogo.jp", - "akashi.hyogo.jp", - "ako.hyogo.jp", - "amagasaki.hyogo.jp", - "aogaki.hyogo.jp", - "asago.hyogo.jp", - "ashiya.hyogo.jp", - "awaji.hyogo.jp", - "fukusaki.hyogo.jp", - "goshiki.hyogo.jp", - "harima.hyogo.jp", - "himeji.hyogo.jp", - "ichikawa.hyogo.jp", - "inagawa.hyogo.jp", - "itami.hyogo.jp", - "kakogawa.hyogo.jp", - "kamigori.hyogo.jp", - "kamikawa.hyogo.jp", - "kasai.hyogo.jp", - "kasuga.hyogo.jp", - "kawanishi.hyogo.jp", - "miki.hyogo.jp", - "minamiawaji.hyogo.jp", - "nishinomiya.hyogo.jp", - "nishiwaki.hyogo.jp", - "ono.hyogo.jp", - "sanda.hyogo.jp", - "sannan.hyogo.jp", - "sasayama.hyogo.jp", - "sayo.hyogo.jp", - "shingu.hyogo.jp", - "shinonsen.hyogo.jp", - "shiso.hyogo.jp", - "sumoto.hyogo.jp", - "taishi.hyogo.jp", - "taka.hyogo.jp", - "takarazuka.hyogo.jp", - "takasago.hyogo.jp", - "takino.hyogo.jp", - "tamba.hyogo.jp", - "tatsuno.hyogo.jp", - "toyooka.hyogo.jp", - "yabu.hyogo.jp", - "yashiro.hyogo.jp", - "yoka.hyogo.jp", - "yokawa.hyogo.jp", - "ami.ibaraki.jp", - "asahi.ibaraki.jp", - "bando.ibaraki.jp", - "chikusei.ibaraki.jp", - "daigo.ibaraki.jp", - "fujishiro.ibaraki.jp", - "hitachi.ibaraki.jp", - "hitachinaka.ibaraki.jp", - "hitachiomiya.ibaraki.jp", - "hitachiota.ibaraki.jp", - "ibaraki.ibaraki.jp", - "ina.ibaraki.jp", - "inashiki.ibaraki.jp", - "itako.ibaraki.jp", - "iwama.ibaraki.jp", - "joso.ibaraki.jp", - "kamisu.ibaraki.jp", - "kasama.ibaraki.jp", - "kashima.ibaraki.jp", - "kasumigaura.ibaraki.jp", - "koga.ibaraki.jp", - "miho.ibaraki.jp", - "mito.ibaraki.jp", - "moriya.ibaraki.jp", - "naka.ibaraki.jp", - "namegata.ibaraki.jp", - "oarai.ibaraki.jp", - "ogawa.ibaraki.jp", - "omitama.ibaraki.jp", - "ryugasaki.ibaraki.jp", - "sakai.ibaraki.jp", - "sakuragawa.ibaraki.jp", - "shimodate.ibaraki.jp", - "shimotsuma.ibaraki.jp", - "shirosato.ibaraki.jp", - "sowa.ibaraki.jp", - "suifu.ibaraki.jp", - "takahagi.ibaraki.jp", - "tamatsukuri.ibaraki.jp", - "tokai.ibaraki.jp", - "tomobe.ibaraki.jp", - "tone.ibaraki.jp", - "toride.ibaraki.jp", - "tsuchiura.ibaraki.jp", - "tsukuba.ibaraki.jp", - "uchihara.ibaraki.jp", - "ushiku.ibaraki.jp", - "yachiyo.ibaraki.jp", - "yamagata.ibaraki.jp", - "yawara.ibaraki.jp", - "yuki.ibaraki.jp", - "anamizu.ishikawa.jp", - "hakui.ishikawa.jp", - "hakusan.ishikawa.jp", - "kaga.ishikawa.jp", - "kahoku.ishikawa.jp", - "kanazawa.ishikawa.jp", - "kawakita.ishikawa.jp", - "komatsu.ishikawa.jp", - "nakanoto.ishikawa.jp", - "nanao.ishikawa.jp", - "nomi.ishikawa.jp", - "nonoichi.ishikawa.jp", - "noto.ishikawa.jp", - "shika.ishikawa.jp", - "suzu.ishikawa.jp", - "tsubata.ishikawa.jp", - "tsurugi.ishikawa.jp", - "uchinada.ishikawa.jp", - "wajima.ishikawa.jp", - "fudai.iwate.jp", - "fujisawa.iwate.jp", - "hanamaki.iwate.jp", - "hiraizumi.iwate.jp", - "hirono.iwate.jp", - "ichinohe.iwate.jp", - "ichinoseki.iwate.jp", - "iwaizumi.iwate.jp", - "iwate.iwate.jp", - "joboji.iwate.jp", - "kamaishi.iwate.jp", - "kanegasaki.iwate.jp", - "karumai.iwate.jp", - "kawai.iwate.jp", - "kitakami.iwate.jp", - "kuji.iwate.jp", - "kunohe.iwate.jp", - "kuzumaki.iwate.jp", - "miyako.iwate.jp", - "mizusawa.iwate.jp", - "morioka.iwate.jp", - "ninohe.iwate.jp", - "noda.iwate.jp", - "ofunato.iwate.jp", - "oshu.iwate.jp", - "otsuchi.iwate.jp", - "rikuzentakata.iwate.jp", - "shiwa.iwate.jp", - "shizukuishi.iwate.jp", - "sumita.iwate.jp", - "tanohata.iwate.jp", - "tono.iwate.jp", - "yahaba.iwate.jp", - "yamada.iwate.jp", - "ayagawa.kagawa.jp", - "higashikagawa.kagawa.jp", - "kanonji.kagawa.jp", - "kotohira.kagawa.jp", - "manno.kagawa.jp", - "marugame.kagawa.jp", - "mitoyo.kagawa.jp", - "naoshima.kagawa.jp", - "sanuki.kagawa.jp", - "tadotsu.kagawa.jp", - "takamatsu.kagawa.jp", - "tonosho.kagawa.jp", - "uchinomi.kagawa.jp", - "utazu.kagawa.jp", - "zentsuji.kagawa.jp", - "akune.kagoshima.jp", - "amami.kagoshima.jp", - "hioki.kagoshima.jp", - "isa.kagoshima.jp", - "isen.kagoshima.jp", - "izumi.kagoshima.jp", - "kagoshima.kagoshima.jp", - "kanoya.kagoshima.jp", - "kawanabe.kagoshima.jp", - "kinko.kagoshima.jp", - "kouyama.kagoshima.jp", - "makurazaki.kagoshima.jp", - "matsumoto.kagoshima.jp", - "minamitane.kagoshima.jp", - "nakatane.kagoshima.jp", - "nishinoomote.kagoshima.jp", - "satsumasendai.kagoshima.jp", - "soo.kagoshima.jp", - "tarumizu.kagoshima.jp", - "yusui.kagoshima.jp", - "aikawa.kanagawa.jp", - "atsugi.kanagawa.jp", - "ayase.kanagawa.jp", - "chigasaki.kanagawa.jp", - "ebina.kanagawa.jp", - "fujisawa.kanagawa.jp", - "hadano.kanagawa.jp", - "hakone.kanagawa.jp", - "hiratsuka.kanagawa.jp", - "isehara.kanagawa.jp", - "kaisei.kanagawa.jp", - "kamakura.kanagawa.jp", - "kiyokawa.kanagawa.jp", - "matsuda.kanagawa.jp", - "minamiashigara.kanagawa.jp", - "miura.kanagawa.jp", - "nakai.kanagawa.jp", - "ninomiya.kanagawa.jp", - "odawara.kanagawa.jp", - "oi.kanagawa.jp", - "oiso.kanagawa.jp", - "sagamihara.kanagawa.jp", - "samukawa.kanagawa.jp", - "tsukui.kanagawa.jp", - "yamakita.kanagawa.jp", - "yamato.kanagawa.jp", - "yokosuka.kanagawa.jp", - "yugawara.kanagawa.jp", - "zama.kanagawa.jp", - "zushi.kanagawa.jp", - "aki.kochi.jp", - "geisei.kochi.jp", - "hidaka.kochi.jp", - "higashitsuno.kochi.jp", - "ino.kochi.jp", - "kagami.kochi.jp", - "kami.kochi.jp", - "kitagawa.kochi.jp", - "kochi.kochi.jp", - "mihara.kochi.jp", - "motoyama.kochi.jp", - "muroto.kochi.jp", - "nahari.kochi.jp", - "nakamura.kochi.jp", - "nankoku.kochi.jp", - "nishitosa.kochi.jp", - "niyodogawa.kochi.jp", - "ochi.kochi.jp", - "okawa.kochi.jp", - "otoyo.kochi.jp", - "otsuki.kochi.jp", - "sakawa.kochi.jp", - "sukumo.kochi.jp", - "susaki.kochi.jp", - "tosa.kochi.jp", - "tosashimizu.kochi.jp", - "toyo.kochi.jp", - "tsuno.kochi.jp", - "umaji.kochi.jp", - "yasuda.kochi.jp", - "yusuhara.kochi.jp", - "amakusa.kumamoto.jp", - "arao.kumamoto.jp", - "aso.kumamoto.jp", - "choyo.kumamoto.jp", - "gyokuto.kumamoto.jp", - "kamiamakusa.kumamoto.jp", - "kikuchi.kumamoto.jp", - "kumamoto.kumamoto.jp", - "mashiki.kumamoto.jp", - "mifune.kumamoto.jp", - "minamata.kumamoto.jp", - "minamioguni.kumamoto.jp", - "nagasu.kumamoto.jp", - "nishihara.kumamoto.jp", - "oguni.kumamoto.jp", - "ozu.kumamoto.jp", - "sumoto.kumamoto.jp", - "takamori.kumamoto.jp", - "uki.kumamoto.jp", - "uto.kumamoto.jp", - "yamaga.kumamoto.jp", - "yamato.kumamoto.jp", - "yatsushiro.kumamoto.jp", - "ayabe.kyoto.jp", - "fukuchiyama.kyoto.jp", - "higashiyama.kyoto.jp", - "ide.kyoto.jp", - "ine.kyoto.jp", - "joyo.kyoto.jp", - "kameoka.kyoto.jp", - "kamo.kyoto.jp", - "kita.kyoto.jp", - "kizu.kyoto.jp", - "kumiyama.kyoto.jp", - "kyotamba.kyoto.jp", - "kyotanabe.kyoto.jp", - "kyotango.kyoto.jp", - "maizuru.kyoto.jp", - "minami.kyoto.jp", - "minamiyamashiro.kyoto.jp", - "miyazu.kyoto.jp", - "muko.kyoto.jp", - "nagaokakyo.kyoto.jp", - "nakagyo.kyoto.jp", - "nantan.kyoto.jp", - "oyamazaki.kyoto.jp", - "sakyo.kyoto.jp", - "seika.kyoto.jp", - "tanabe.kyoto.jp", - "uji.kyoto.jp", - "ujitawara.kyoto.jp", - "wazuka.kyoto.jp", - "yamashina.kyoto.jp", - "yawata.kyoto.jp", - "asahi.mie.jp", - "inabe.mie.jp", - "ise.mie.jp", - "kameyama.mie.jp", - "kawagoe.mie.jp", - "kiho.mie.jp", - "kisosaki.mie.jp", - "kiwa.mie.jp", - "komono.mie.jp", - "kumano.mie.jp", - "kuwana.mie.jp", - "matsusaka.mie.jp", - "meiwa.mie.jp", - "mihama.mie.jp", - "minamiise.mie.jp", - "misugi.mie.jp", - "miyama.mie.jp", - "nabari.mie.jp", - "shima.mie.jp", - "suzuka.mie.jp", - "tado.mie.jp", - "taiki.mie.jp", - "taki.mie.jp", - "tamaki.mie.jp", - "toba.mie.jp", - "tsu.mie.jp", - "udono.mie.jp", - "ureshino.mie.jp", - "watarai.mie.jp", - "yokkaichi.mie.jp", - "furukawa.miyagi.jp", - "higashimatsushima.miyagi.jp", - "ishinomaki.miyagi.jp", - "iwanuma.miyagi.jp", - "kakuda.miyagi.jp", - "kami.miyagi.jp", - "kawasaki.miyagi.jp", - "marumori.miyagi.jp", - "matsushima.miyagi.jp", - "minamisanriku.miyagi.jp", - "misato.miyagi.jp", - "murata.miyagi.jp", - "natori.miyagi.jp", - "ogawara.miyagi.jp", - "ohira.miyagi.jp", - "onagawa.miyagi.jp", - "osaki.miyagi.jp", - "rifu.miyagi.jp", - "semine.miyagi.jp", - "shibata.miyagi.jp", - "shichikashuku.miyagi.jp", - "shikama.miyagi.jp", - "shiogama.miyagi.jp", - "shiroishi.miyagi.jp", - "tagajo.miyagi.jp", - "taiwa.miyagi.jp", - "tome.miyagi.jp", - "tomiya.miyagi.jp", - "wakuya.miyagi.jp", - "watari.miyagi.jp", - "yamamoto.miyagi.jp", - "zao.miyagi.jp", - "aya.miyazaki.jp", - "ebino.miyazaki.jp", - "gokase.miyazaki.jp", - "hyuga.miyazaki.jp", - "kadogawa.miyazaki.jp", - "kawaminami.miyazaki.jp", - "kijo.miyazaki.jp", - "kitagawa.miyazaki.jp", - "kitakata.miyazaki.jp", - "kitaura.miyazaki.jp", - "kobayashi.miyazaki.jp", - "kunitomi.miyazaki.jp", - "kushima.miyazaki.jp", - "mimata.miyazaki.jp", - "miyakonojo.miyazaki.jp", - "miyazaki.miyazaki.jp", - "morotsuka.miyazaki.jp", - "nichinan.miyazaki.jp", - "nishimera.miyazaki.jp", - "nobeoka.miyazaki.jp", - "saito.miyazaki.jp", - "shiiba.miyazaki.jp", - "shintomi.miyazaki.jp", - "takaharu.miyazaki.jp", - "takanabe.miyazaki.jp", - "takazaki.miyazaki.jp", - "tsuno.miyazaki.jp", - "achi.nagano.jp", - "agematsu.nagano.jp", - "anan.nagano.jp", - "aoki.nagano.jp", - "asahi.nagano.jp", - "azumino.nagano.jp", - "chikuhoku.nagano.jp", - "chikuma.nagano.jp", - "chino.nagano.jp", - "fujimi.nagano.jp", - "hakuba.nagano.jp", - "hara.nagano.jp", - "hiraya.nagano.jp", - "iida.nagano.jp", - "iijima.nagano.jp", - "iiyama.nagano.jp", - "iizuna.nagano.jp", - "ikeda.nagano.jp", - "ikusaka.nagano.jp", - "ina.nagano.jp", - "karuizawa.nagano.jp", - "kawakami.nagano.jp", - "kiso.nagano.jp", - "kisofukushima.nagano.jp", - "kitaaiki.nagano.jp", - "komagane.nagano.jp", - "komoro.nagano.jp", - "matsukawa.nagano.jp", - "matsumoto.nagano.jp", - "miasa.nagano.jp", - "minamiaiki.nagano.jp", - "minamimaki.nagano.jp", - "minamiminowa.nagano.jp", - "minowa.nagano.jp", - "miyada.nagano.jp", - "miyota.nagano.jp", - "mochizuki.nagano.jp", - "nagano.nagano.jp", - "nagawa.nagano.jp", - "nagiso.nagano.jp", - "nakagawa.nagano.jp", - "nakano.nagano.jp", - "nozawaonsen.nagano.jp", - "obuse.nagano.jp", - "ogawa.nagano.jp", - "okaya.nagano.jp", - "omachi.nagano.jp", - "omi.nagano.jp", - "ookuwa.nagano.jp", - "ooshika.nagano.jp", - "otaki.nagano.jp", - "otari.nagano.jp", - "sakae.nagano.jp", - "sakaki.nagano.jp", - "saku.nagano.jp", - "sakuho.nagano.jp", - "shimosuwa.nagano.jp", - "shinanomachi.nagano.jp", - "shiojiri.nagano.jp", - "suwa.nagano.jp", - "suzaka.nagano.jp", - "takagi.nagano.jp", - "takamori.nagano.jp", - "takayama.nagano.jp", - "tateshina.nagano.jp", - "tatsuno.nagano.jp", - "togakushi.nagano.jp", - "togura.nagano.jp", - "tomi.nagano.jp", - "ueda.nagano.jp", - "wada.nagano.jp", - "yamagata.nagano.jp", - "yamanouchi.nagano.jp", - "yasaka.nagano.jp", - "yasuoka.nagano.jp", - "chijiwa.nagasaki.jp", - "futsu.nagasaki.jp", - "goto.nagasaki.jp", - "hasami.nagasaki.jp", - "hirado.nagasaki.jp", - "iki.nagasaki.jp", - "isahaya.nagasaki.jp", - "kawatana.nagasaki.jp", - "kuchinotsu.nagasaki.jp", - "matsuura.nagasaki.jp", - "nagasaki.nagasaki.jp", - "obama.nagasaki.jp", - "omura.nagasaki.jp", - "oseto.nagasaki.jp", - "saikai.nagasaki.jp", - "sasebo.nagasaki.jp", - "seihi.nagasaki.jp", - "shimabara.nagasaki.jp", - "shinkamigoto.nagasaki.jp", - "togitsu.nagasaki.jp", - "tsushima.nagasaki.jp", - "unzen.nagasaki.jp", - "ando.nara.jp", - "gose.nara.jp", - "heguri.nara.jp", - "higashiyoshino.nara.jp", - "ikaruga.nara.jp", - "ikoma.nara.jp", - "kamikitayama.nara.jp", - "kanmaki.nara.jp", - "kashiba.nara.jp", - "kashihara.nara.jp", - "katsuragi.nara.jp", - "kawai.nara.jp", - "kawakami.nara.jp", - "kawanishi.nara.jp", - "koryo.nara.jp", - "kurotaki.nara.jp", - "mitsue.nara.jp", - "miyake.nara.jp", - "nara.nara.jp", - "nosegawa.nara.jp", - "oji.nara.jp", - "ouda.nara.jp", - "oyodo.nara.jp", - "sakurai.nara.jp", - "sango.nara.jp", - "shimoichi.nara.jp", - "shimokitayama.nara.jp", - "shinjo.nara.jp", - "soni.nara.jp", - "takatori.nara.jp", - "tawaramoto.nara.jp", - "tenkawa.nara.jp", - "tenri.nara.jp", - "uda.nara.jp", - "yamatokoriyama.nara.jp", - "yamatotakada.nara.jp", - "yamazoe.nara.jp", - "yoshino.nara.jp", - "aga.niigata.jp", - "agano.niigata.jp", - "gosen.niigata.jp", - "itoigawa.niigata.jp", - "izumozaki.niigata.jp", - "joetsu.niigata.jp", - "kamo.niigata.jp", - "kariwa.niigata.jp", - "kashiwazaki.niigata.jp", - "minamiuonuma.niigata.jp", - "mitsuke.niigata.jp", - "muika.niigata.jp", - "murakami.niigata.jp", - "myoko.niigata.jp", - "nagaoka.niigata.jp", - "niigata.niigata.jp", - "ojiya.niigata.jp", - "omi.niigata.jp", - "sado.niigata.jp", - "sanjo.niigata.jp", - "seiro.niigata.jp", - "seirou.niigata.jp", - "sekikawa.niigata.jp", - "shibata.niigata.jp", - "tagami.niigata.jp", - "tainai.niigata.jp", - "tochio.niigata.jp", - "tokamachi.niigata.jp", - "tsubame.niigata.jp", - "tsunan.niigata.jp", - "uonuma.niigata.jp", - "yahiko.niigata.jp", - "yoita.niigata.jp", - "yuzawa.niigata.jp", - "beppu.oita.jp", - "bungoono.oita.jp", - "bungotakada.oita.jp", - "hasama.oita.jp", - "hiji.oita.jp", - "himeshima.oita.jp", - "hita.oita.jp", - "kamitsue.oita.jp", - "kokonoe.oita.jp", - "kuju.oita.jp", - "kunisaki.oita.jp", - "kusu.oita.jp", - "oita.oita.jp", - "saiki.oita.jp", - "taketa.oita.jp", - "tsukumi.oita.jp", - "usa.oita.jp", - "usuki.oita.jp", - "yufu.oita.jp", - "akaiwa.okayama.jp", - "asakuchi.okayama.jp", - "bizen.okayama.jp", - "hayashima.okayama.jp", - "ibara.okayama.jp", - "kagamino.okayama.jp", - "kasaoka.okayama.jp", - "kibichuo.okayama.jp", - "kumenan.okayama.jp", - "kurashiki.okayama.jp", - "maniwa.okayama.jp", - "misaki.okayama.jp", - "nagi.okayama.jp", - "niimi.okayama.jp", - "nishiawakura.okayama.jp", - "okayama.okayama.jp", - "satosho.okayama.jp", - "setouchi.okayama.jp", - "shinjo.okayama.jp", - "shoo.okayama.jp", - "soja.okayama.jp", - "takahashi.okayama.jp", - "tamano.okayama.jp", - "tsuyama.okayama.jp", - "wake.okayama.jp", - "yakage.okayama.jp", - "aguni.okinawa.jp", - "ginowan.okinawa.jp", - "ginoza.okinawa.jp", - "gushikami.okinawa.jp", - "haebaru.okinawa.jp", - "higashi.okinawa.jp", - "hirara.okinawa.jp", - "iheya.okinawa.jp", - "ishigaki.okinawa.jp", - "ishikawa.okinawa.jp", - "itoman.okinawa.jp", - "izena.okinawa.jp", - "kadena.okinawa.jp", - "kin.okinawa.jp", - "kitadaito.okinawa.jp", - "kitanakagusuku.okinawa.jp", - "kumejima.okinawa.jp", - "kunigami.okinawa.jp", - "minamidaito.okinawa.jp", - "motobu.okinawa.jp", - "nago.okinawa.jp", - "naha.okinawa.jp", - "nakagusuku.okinawa.jp", - "nakijin.okinawa.jp", - "nanjo.okinawa.jp", - "nishihara.okinawa.jp", - "ogimi.okinawa.jp", - "okinawa.okinawa.jp", - "onna.okinawa.jp", - "shimoji.okinawa.jp", - "taketomi.okinawa.jp", - "tarama.okinawa.jp", - "tokashiki.okinawa.jp", - "tomigusuku.okinawa.jp", - "tonaki.okinawa.jp", - "urasoe.okinawa.jp", - "uruma.okinawa.jp", - "yaese.okinawa.jp", - "yomitan.okinawa.jp", - "yonabaru.okinawa.jp", - "yonaguni.okinawa.jp", - "zamami.okinawa.jp", - "abeno.osaka.jp", - "chihayaakasaka.osaka.jp", - "chuo.osaka.jp", - "daito.osaka.jp", - "fujiidera.osaka.jp", - "habikino.osaka.jp", - "hannan.osaka.jp", - "higashiosaka.osaka.jp", - "higashisumiyoshi.osaka.jp", - "higashiyodogawa.osaka.jp", - "hirakata.osaka.jp", - "ibaraki.osaka.jp", - "ikeda.osaka.jp", - "izumi.osaka.jp", - "izumiotsu.osaka.jp", - "izumisano.osaka.jp", - "kadoma.osaka.jp", - "kaizuka.osaka.jp", - "kanan.osaka.jp", - "kashiwara.osaka.jp", - "katano.osaka.jp", - "kawachinagano.osaka.jp", - "kishiwada.osaka.jp", - "kita.osaka.jp", - "kumatori.osaka.jp", - "matsubara.osaka.jp", - "minato.osaka.jp", - "minoh.osaka.jp", - "misaki.osaka.jp", - "moriguchi.osaka.jp", - "neyagawa.osaka.jp", - "nishi.osaka.jp", - "nose.osaka.jp", - "osakasayama.osaka.jp", - "sakai.osaka.jp", - "sayama.osaka.jp", - "sennan.osaka.jp", - "settsu.osaka.jp", - "shijonawate.osaka.jp", - "shimamoto.osaka.jp", - "suita.osaka.jp", - "tadaoka.osaka.jp", - "taishi.osaka.jp", - "tajiri.osaka.jp", - "takaishi.osaka.jp", - "takatsuki.osaka.jp", - "tondabayashi.osaka.jp", - "toyonaka.osaka.jp", - "toyono.osaka.jp", - "yao.osaka.jp", - "ariake.saga.jp", - "arita.saga.jp", - "fukudomi.saga.jp", - "genkai.saga.jp", - "hamatama.saga.jp", - "hizen.saga.jp", - "imari.saga.jp", - "kamimine.saga.jp", - "kanzaki.saga.jp", - "karatsu.saga.jp", - "kashima.saga.jp", - "kitagata.saga.jp", - "kitahata.saga.jp", - "kiyama.saga.jp", - "kouhoku.saga.jp", - "kyuragi.saga.jp", - "nishiarita.saga.jp", - "ogi.saga.jp", - "omachi.saga.jp", - "ouchi.saga.jp", - "saga.saga.jp", - "shiroishi.saga.jp", - "taku.saga.jp", - "tara.saga.jp", - "tosu.saga.jp", - "yoshinogari.saga.jp", - "arakawa.saitama.jp", - "asaka.saitama.jp", - "chichibu.saitama.jp", - "fujimi.saitama.jp", - "fujimino.saitama.jp", - "fukaya.saitama.jp", - "hanno.saitama.jp", - "hanyu.saitama.jp", - "hasuda.saitama.jp", - "hatogaya.saitama.jp", - "hatoyama.saitama.jp", - "hidaka.saitama.jp", - "higashichichibu.saitama.jp", - "higashimatsuyama.saitama.jp", - "honjo.saitama.jp", - "ina.saitama.jp", - "iruma.saitama.jp", - "iwatsuki.saitama.jp", - "kamiizumi.saitama.jp", - "kamikawa.saitama.jp", - "kamisato.saitama.jp", - "kasukabe.saitama.jp", - "kawagoe.saitama.jp", - "kawaguchi.saitama.jp", - "kawajima.saitama.jp", - "kazo.saitama.jp", - "kitamoto.saitama.jp", - "koshigaya.saitama.jp", - "kounosu.saitama.jp", - "kuki.saitama.jp", - "kumagaya.saitama.jp", - "matsubushi.saitama.jp", - "minano.saitama.jp", - "misato.saitama.jp", - "miyashiro.saitama.jp", - "miyoshi.saitama.jp", - "moroyama.saitama.jp", - "nagatoro.saitama.jp", - "namegawa.saitama.jp", - "niiza.saitama.jp", - "ogano.saitama.jp", - "ogawa.saitama.jp", - "ogose.saitama.jp", - "okegawa.saitama.jp", - "omiya.saitama.jp", - "otaki.saitama.jp", - "ranzan.saitama.jp", - "ryokami.saitama.jp", - "saitama.saitama.jp", - "sakado.saitama.jp", - "satte.saitama.jp", - "sayama.saitama.jp", - "shiki.saitama.jp", - "shiraoka.saitama.jp", - "soka.saitama.jp", - "sugito.saitama.jp", - "toda.saitama.jp", - "tokigawa.saitama.jp", - "tokorozawa.saitama.jp", - "tsurugashima.saitama.jp", - "urawa.saitama.jp", - "warabi.saitama.jp", - "yashio.saitama.jp", - "yokoze.saitama.jp", - "yono.saitama.jp", - "yorii.saitama.jp", - "yoshida.saitama.jp", - "yoshikawa.saitama.jp", - "yoshimi.saitama.jp", - "aisho.shiga.jp", - "gamo.shiga.jp", - "higashiomi.shiga.jp", - "hikone.shiga.jp", - "koka.shiga.jp", - "konan.shiga.jp", - "kosei.shiga.jp", - "koto.shiga.jp", - "kusatsu.shiga.jp", - "maibara.shiga.jp", - "moriyama.shiga.jp", - "nagahama.shiga.jp", - "nishiazai.shiga.jp", - "notogawa.shiga.jp", - "omihachiman.shiga.jp", - "otsu.shiga.jp", - "ritto.shiga.jp", - "ryuoh.shiga.jp", - "takashima.shiga.jp", - "takatsuki.shiga.jp", - "torahime.shiga.jp", - "toyosato.shiga.jp", - "yasu.shiga.jp", - "akagi.shimane.jp", - "ama.shimane.jp", - "gotsu.shimane.jp", - "hamada.shimane.jp", - "higashiizumo.shimane.jp", - "hikawa.shimane.jp", - "hikimi.shimane.jp", - "izumo.shimane.jp", - "kakinoki.shimane.jp", - "masuda.shimane.jp", - "matsue.shimane.jp", - "misato.shimane.jp", - "nishinoshima.shimane.jp", - "ohda.shimane.jp", - "okinoshima.shimane.jp", - "okuizumo.shimane.jp", - "shimane.shimane.jp", - "tamayu.shimane.jp", - "tsuwano.shimane.jp", - "unnan.shimane.jp", - "yakumo.shimane.jp", - "yasugi.shimane.jp", - "yatsuka.shimane.jp", - "arai.shizuoka.jp", - "atami.shizuoka.jp", - "fuji.shizuoka.jp", - "fujieda.shizuoka.jp", - "fujikawa.shizuoka.jp", - "fujinomiya.shizuoka.jp", - "fukuroi.shizuoka.jp", - "gotemba.shizuoka.jp", - "haibara.shizuoka.jp", - "hamamatsu.shizuoka.jp", - "higashiizu.shizuoka.jp", - "ito.shizuoka.jp", - "iwata.shizuoka.jp", - "izu.shizuoka.jp", - "izunokuni.shizuoka.jp", - "kakegawa.shizuoka.jp", - "kannami.shizuoka.jp", - "kawanehon.shizuoka.jp", - "kawazu.shizuoka.jp", - "kikugawa.shizuoka.jp", - "kosai.shizuoka.jp", - "makinohara.shizuoka.jp", - "matsuzaki.shizuoka.jp", - "minamiizu.shizuoka.jp", - "mishima.shizuoka.jp", - "morimachi.shizuoka.jp", - "nishiizu.shizuoka.jp", - "numazu.shizuoka.jp", - "omaezaki.shizuoka.jp", - "shimada.shizuoka.jp", - "shimizu.shizuoka.jp", - "shimoda.shizuoka.jp", - "shizuoka.shizuoka.jp", - "susono.shizuoka.jp", - "yaizu.shizuoka.jp", - "yoshida.shizuoka.jp", - "ashikaga.tochigi.jp", - "bato.tochigi.jp", - "haga.tochigi.jp", - "ichikai.tochigi.jp", - "iwafune.tochigi.jp", - "kaminokawa.tochigi.jp", - "kanuma.tochigi.jp", - "karasuyama.tochigi.jp", - "kuroiso.tochigi.jp", - "mashiko.tochigi.jp", - "mibu.tochigi.jp", - "moka.tochigi.jp", - "motegi.tochigi.jp", - "nasu.tochigi.jp", - "nasushiobara.tochigi.jp", - "nikko.tochigi.jp", - "nishikata.tochigi.jp", - "nogi.tochigi.jp", - "ohira.tochigi.jp", - "ohtawara.tochigi.jp", - "oyama.tochigi.jp", - "sakura.tochigi.jp", - "sano.tochigi.jp", - "shimotsuke.tochigi.jp", - "shioya.tochigi.jp", - "takanezawa.tochigi.jp", - "tochigi.tochigi.jp", - "tsuga.tochigi.jp", - "ujiie.tochigi.jp", - "utsunomiya.tochigi.jp", - "yaita.tochigi.jp", - "aizumi.tokushima.jp", - "anan.tokushima.jp", - "ichiba.tokushima.jp", - "itano.tokushima.jp", - "kainan.tokushima.jp", - "komatsushima.tokushima.jp", - "matsushige.tokushima.jp", - "mima.tokushima.jp", - "minami.tokushima.jp", - "miyoshi.tokushima.jp", - "mugi.tokushima.jp", - "nakagawa.tokushima.jp", - "naruto.tokushima.jp", - "sanagochi.tokushima.jp", - "shishikui.tokushima.jp", - "tokushima.tokushima.jp", - "wajiki.tokushima.jp", - "adachi.tokyo.jp", - "akiruno.tokyo.jp", - "akishima.tokyo.jp", - "aogashima.tokyo.jp", - "arakawa.tokyo.jp", - "bunkyo.tokyo.jp", - "chiyoda.tokyo.jp", - "chofu.tokyo.jp", - "chuo.tokyo.jp", - "edogawa.tokyo.jp", - "fuchu.tokyo.jp", - "fussa.tokyo.jp", - "hachijo.tokyo.jp", - "hachioji.tokyo.jp", - "hamura.tokyo.jp", - "higashikurume.tokyo.jp", - "higashimurayama.tokyo.jp", - "higashiyamato.tokyo.jp", - "hino.tokyo.jp", - "hinode.tokyo.jp", - "hinohara.tokyo.jp", - "inagi.tokyo.jp", - "itabashi.tokyo.jp", - "katsushika.tokyo.jp", - "kita.tokyo.jp", - "kiyose.tokyo.jp", - "kodaira.tokyo.jp", - "koganei.tokyo.jp", - "kokubunji.tokyo.jp", - "komae.tokyo.jp", - "koto.tokyo.jp", - "kouzushima.tokyo.jp", - "kunitachi.tokyo.jp", - "machida.tokyo.jp", - "meguro.tokyo.jp", - "minato.tokyo.jp", - "mitaka.tokyo.jp", - "mizuho.tokyo.jp", - "musashimurayama.tokyo.jp", - "musashino.tokyo.jp", - "nakano.tokyo.jp", - "nerima.tokyo.jp", - "ogasawara.tokyo.jp", - "okutama.tokyo.jp", - "ome.tokyo.jp", - "oshima.tokyo.jp", - "ota.tokyo.jp", - "setagaya.tokyo.jp", - "shibuya.tokyo.jp", - "shinagawa.tokyo.jp", - "shinjuku.tokyo.jp", - "suginami.tokyo.jp", - "sumida.tokyo.jp", - "tachikawa.tokyo.jp", - "taito.tokyo.jp", - "tama.tokyo.jp", - "toshima.tokyo.jp", - "chizu.tottori.jp", - "hino.tottori.jp", - "kawahara.tottori.jp", - "koge.tottori.jp", - "kotoura.tottori.jp", - "misasa.tottori.jp", - "nanbu.tottori.jp", - "nichinan.tottori.jp", - "sakaiminato.tottori.jp", - "tottori.tottori.jp", - "wakasa.tottori.jp", - "yazu.tottori.jp", - "yonago.tottori.jp", - "asahi.toyama.jp", - "fuchu.toyama.jp", - "fukumitsu.toyama.jp", - "funahashi.toyama.jp", - "himi.toyama.jp", - "imizu.toyama.jp", - "inami.toyama.jp", - "johana.toyama.jp", - "kamiichi.toyama.jp", - "kurobe.toyama.jp", - "nakaniikawa.toyama.jp", - "namerikawa.toyama.jp", - "nanto.toyama.jp", - "nyuzen.toyama.jp", - "oyabe.toyama.jp", - "taira.toyama.jp", - "takaoka.toyama.jp", - "tateyama.toyama.jp", - "toga.toyama.jp", - "tonami.toyama.jp", - "toyama.toyama.jp", - "unazuki.toyama.jp", - "uozu.toyama.jp", - "yamada.toyama.jp", - "arida.wakayama.jp", - "aridagawa.wakayama.jp", - "gobo.wakayama.jp", - "hashimoto.wakayama.jp", - "hidaka.wakayama.jp", - "hirogawa.wakayama.jp", - "inami.wakayama.jp", - "iwade.wakayama.jp", - "kainan.wakayama.jp", - "kamitonda.wakayama.jp", - "katsuragi.wakayama.jp", - "kimino.wakayama.jp", - "kinokawa.wakayama.jp", - "kitayama.wakayama.jp", - "koya.wakayama.jp", - "koza.wakayama.jp", - "kozagawa.wakayama.jp", - "kudoyama.wakayama.jp", - "kushimoto.wakayama.jp", - "mihama.wakayama.jp", - "misato.wakayama.jp", - "nachikatsuura.wakayama.jp", - "shingu.wakayama.jp", - "shirahama.wakayama.jp", - "taiji.wakayama.jp", - "tanabe.wakayama.jp", - "wakayama.wakayama.jp", - "yuasa.wakayama.jp", - "yura.wakayama.jp", - "asahi.yamagata.jp", - "funagata.yamagata.jp", - "higashine.yamagata.jp", - "iide.yamagata.jp", - "kahoku.yamagata.jp", - "kaminoyama.yamagata.jp", - "kaneyama.yamagata.jp", - "kawanishi.yamagata.jp", - "mamurogawa.yamagata.jp", - "mikawa.yamagata.jp", - "murayama.yamagata.jp", - "nagai.yamagata.jp", - "nakayama.yamagata.jp", - "nanyo.yamagata.jp", - "nishikawa.yamagata.jp", - "obanazawa.yamagata.jp", - "oe.yamagata.jp", - "oguni.yamagata.jp", - "ohkura.yamagata.jp", - "oishida.yamagata.jp", - "sagae.yamagata.jp", - "sakata.yamagata.jp", - "sakegawa.yamagata.jp", - "shinjo.yamagata.jp", - "shirataka.yamagata.jp", - "shonai.yamagata.jp", - "takahata.yamagata.jp", - "tendo.yamagata.jp", - "tozawa.yamagata.jp", - "tsuruoka.yamagata.jp", - "yamagata.yamagata.jp", - "yamanobe.yamagata.jp", - "yonezawa.yamagata.jp", - "yuza.yamagata.jp", - "abu.yamaguchi.jp", - "hagi.yamaguchi.jp", - "hikari.yamaguchi.jp", - "hofu.yamaguchi.jp", - "iwakuni.yamaguchi.jp", - "kudamatsu.yamaguchi.jp", - "mitou.yamaguchi.jp", - "nagato.yamaguchi.jp", - "oshima.yamaguchi.jp", - "shimonoseki.yamaguchi.jp", - "shunan.yamaguchi.jp", - "tabuse.yamaguchi.jp", - "tokuyama.yamaguchi.jp", - "toyota.yamaguchi.jp", - "ube.yamaguchi.jp", - "yuu.yamaguchi.jp", - "chuo.yamanashi.jp", - "doshi.yamanashi.jp", - "fuefuki.yamanashi.jp", - "fujikawa.yamanashi.jp", - "fujikawaguchiko.yamanashi.jp", - "fujiyoshida.yamanashi.jp", - "hayakawa.yamanashi.jp", - "hokuto.yamanashi.jp", - "ichikawamisato.yamanashi.jp", - "kai.yamanashi.jp", - "kofu.yamanashi.jp", - "koshu.yamanashi.jp", - "kosuge.yamanashi.jp", - "minami-alps.yamanashi.jp", - "minobu.yamanashi.jp", - "nakamichi.yamanashi.jp", - "nanbu.yamanashi.jp", - "narusawa.yamanashi.jp", - "nirasaki.yamanashi.jp", - "nishikatsura.yamanashi.jp", - "oshino.yamanashi.jp", - "otsuki.yamanashi.jp", - "showa.yamanashi.jp", - "tabayama.yamanashi.jp", - "tsuru.yamanashi.jp", - "uenohara.yamanashi.jp", - "yamanakako.yamanashi.jp", - "yamanashi.yamanashi.jp", - "ke", - "ac.ke", - "co.ke", - "go.ke", - "info.ke", - "me.ke", - "mobi.ke", - "ne.ke", - "or.ke", - "sc.ke", - "kg", - "org.kg", - "net.kg", - "com.kg", - "edu.kg", - "gov.kg", - "mil.kg", - "*.kh", - "ki", - "edu.ki", - "biz.ki", - "net.ki", - "org.ki", - "gov.ki", - "info.ki", - "com.ki", - "km", - "org.km", - "nom.km", - "gov.km", - "prd.km", - "tm.km", - "edu.km", - "mil.km", - "ass.km", - "com.km", - "coop.km", - "asso.km", - "presse.km", - "medecin.km", - "notaires.km", - "pharmaciens.km", - "veterinaire.km", - "gouv.km", - "kn", - "net.kn", - "org.kn", - "edu.kn", - "gov.kn", - "kp", - "com.kp", - "edu.kp", - "gov.kp", - "org.kp", - "rep.kp", - "tra.kp", - "kr", - "ac.kr", - "co.kr", - "es.kr", - "go.kr", - "hs.kr", - "kg.kr", - "mil.kr", - "ms.kr", - "ne.kr", - "or.kr", - "pe.kr", - "re.kr", - "sc.kr", - "busan.kr", - "chungbuk.kr", - "chungnam.kr", - "daegu.kr", - "daejeon.kr", - "gangwon.kr", - "gwangju.kr", - "gyeongbuk.kr", - "gyeonggi.kr", - "gyeongnam.kr", - "incheon.kr", - "jeju.kr", - "jeonbuk.kr", - "jeonnam.kr", - "seoul.kr", - "ulsan.kr", - "kw", - "com.kw", - "edu.kw", - "emb.kw", - "gov.kw", - "ind.kw", - "net.kw", - "org.kw", - "ky", - "edu.ky", - "gov.ky", - "com.ky", - "org.ky", - "net.ky", - "kz", - "org.kz", - "edu.kz", - "net.kz", - "gov.kz", - "mil.kz", - "com.kz", - "la", - "int.la", - "net.la", - "info.la", - "edu.la", - "gov.la", - "per.la", - "com.la", - "org.la", - "lb", - "com.lb", - "edu.lb", - "gov.lb", - "net.lb", - "org.lb", - "lc", - "com.lc", - "net.lc", - "co.lc", - "org.lc", - "edu.lc", - "gov.lc", - "li", - "lk", - "gov.lk", - "sch.lk", - "net.lk", - "int.lk", - "com.lk", - "org.lk", - "edu.lk", - "ngo.lk", - "soc.lk", - "web.lk", - "ltd.lk", - "assn.lk", - "grp.lk", - "hotel.lk", - "ac.lk", - "lr", - "com.lr", - "edu.lr", - "gov.lr", - "org.lr", - "net.lr", - "ls", - "ac.ls", - "biz.ls", - "co.ls", - "edu.ls", - "gov.ls", - "info.ls", - "net.ls", - "org.ls", - "sc.ls", - "lt", - "gov.lt", - "lu", - "lv", - "com.lv", - "edu.lv", - "gov.lv", - "org.lv", - "mil.lv", - "id.lv", - "net.lv", - "asn.lv", - "conf.lv", - "ly", - "com.ly", - "net.ly", - "gov.ly", - "plc.ly", - "edu.ly", - "sch.ly", - "med.ly", - "org.ly", - "id.ly", - "ma", - "co.ma", - "net.ma", - "gov.ma", - "org.ma", - "ac.ma", - "press.ma", - "mc", - "tm.mc", - "asso.mc", - "md", - "me", - "co.me", - "net.me", - "org.me", - "edu.me", - "ac.me", - "gov.me", - "its.me", - "priv.me", - "mg", - "org.mg", - "nom.mg", - "gov.mg", - "prd.mg", - "tm.mg", - "edu.mg", - "mil.mg", - "com.mg", - "co.mg", - "mh", - "mil", - "mk", - "com.mk", - "org.mk", - "net.mk", - "edu.mk", - "gov.mk", - "inf.mk", - "name.mk", - "ml", - "com.ml", - "edu.ml", - "gouv.ml", - "gov.ml", - "net.ml", - "org.ml", - "presse.ml", - "*.mm", - "mn", - "gov.mn", - "edu.mn", - "org.mn", - "mo", - "com.mo", - "net.mo", - "org.mo", - "edu.mo", - "gov.mo", - "mobi", - "mp", - "mq", - "mr", - "gov.mr", - "ms", - "com.ms", - "edu.ms", - "gov.ms", - "net.ms", - "org.ms", - "mt", - "com.mt", - "edu.mt", - "net.mt", - "org.mt", - "mu", - "com.mu", - "net.mu", - "org.mu", - "gov.mu", - "ac.mu", - "co.mu", - "or.mu", - "museum", - "academy.museum", - "agriculture.museum", - "air.museum", - "airguard.museum", - "alabama.museum", - "alaska.museum", - "amber.museum", - "ambulance.museum", - "american.museum", - "americana.museum", - "americanantiques.museum", - "americanart.museum", - "amsterdam.museum", - "and.museum", - "annefrank.museum", - "anthro.museum", - "anthropology.museum", - "antiques.museum", - "aquarium.museum", - "arboretum.museum", - "archaeological.museum", - "archaeology.museum", - "architecture.museum", - "art.museum", - "artanddesign.museum", - "artcenter.museum", - "artdeco.museum", - "arteducation.museum", - "artgallery.museum", - "arts.museum", - "artsandcrafts.museum", - "asmatart.museum", - "assassination.museum", - "assisi.museum", - "association.museum", - "astronomy.museum", - "atlanta.museum", - "austin.museum", - "australia.museum", - "automotive.museum", - "aviation.museum", - "axis.museum", - "badajoz.museum", - "baghdad.museum", - "bahn.museum", - "bale.museum", - "baltimore.museum", - "barcelona.museum", - "baseball.museum", - "basel.museum", - "baths.museum", - "bauern.museum", - "beauxarts.museum", - "beeldengeluid.museum", - "bellevue.museum", - "bergbau.museum", - "berkeley.museum", - "berlin.museum", - "bern.museum", - "bible.museum", - "bilbao.museum", - "bill.museum", - "birdart.museum", - "birthplace.museum", - "bonn.museum", - "boston.museum", - "botanical.museum", - "botanicalgarden.museum", - "botanicgarden.museum", - "botany.museum", - "brandywinevalley.museum", - "brasil.museum", - "bristol.museum", - "british.museum", - "britishcolumbia.museum", - "broadcast.museum", - "brunel.museum", - "brussel.museum", - "brussels.museum", - "bruxelles.museum", - "building.museum", - "burghof.museum", - "bus.museum", - "bushey.museum", - "cadaques.museum", - "california.museum", - "cambridge.museum", - "can.museum", - "canada.museum", - "capebreton.museum", - "carrier.museum", - "cartoonart.museum", - "casadelamoneda.museum", - "castle.museum", - "castres.museum", - "celtic.museum", - "center.museum", - "chattanooga.museum", - "cheltenham.museum", - "chesapeakebay.museum", - "chicago.museum", - "children.museum", - "childrens.museum", - "childrensgarden.museum", - "chiropractic.museum", - "chocolate.museum", - "christiansburg.museum", - "cincinnati.museum", - "cinema.museum", - "circus.museum", - "civilisation.museum", - "civilization.museum", - "civilwar.museum", - "clinton.museum", - "clock.museum", - "coal.museum", - "coastaldefence.museum", - "cody.museum", - "coldwar.museum", - "collection.museum", - "colonialwilliamsburg.museum", - "coloradoplateau.museum", - "columbia.museum", - "columbus.museum", - "communication.museum", - "communications.museum", - "community.museum", - "computer.museum", - "computerhistory.museum", - "xn--comunicaes-v6a2o.museum", - "contemporary.museum", - "contemporaryart.museum", - "convent.museum", - "copenhagen.museum", - "corporation.museum", - "xn--correios-e-telecomunicaes-ghc29a.museum", - "corvette.museum", - "costume.museum", - "countryestate.museum", - "county.museum", - "crafts.museum", - "cranbrook.museum", - "creation.museum", - "cultural.museum", - "culturalcenter.museum", - "culture.museum", - "cyber.museum", - "cymru.museum", - "dali.museum", - "dallas.museum", - "database.museum", - "ddr.museum", - "decorativearts.museum", - "delaware.museum", - "delmenhorst.museum", - "denmark.museum", - "depot.museum", - "design.museum", - "detroit.museum", - "dinosaur.museum", - "discovery.museum", - "dolls.museum", - "donostia.museum", - "durham.museum", - "eastafrica.museum", - "eastcoast.museum", - "education.museum", - "educational.museum", - "egyptian.museum", - "eisenbahn.museum", - "elburg.museum", - "elvendrell.museum", - "embroidery.museum", - "encyclopedic.museum", - "england.museum", - "entomology.museum", - "environment.museum", - "environmentalconservation.museum", - "epilepsy.museum", - "essex.museum", - "estate.museum", - "ethnology.museum", - "exeter.museum", - "exhibition.museum", - "family.museum", - "farm.museum", - "farmequipment.museum", - "farmers.museum", - "farmstead.museum", - "field.museum", - "figueres.museum", - "filatelia.museum", - "film.museum", - "fineart.museum", - "finearts.museum", - "finland.museum", - "flanders.museum", - "florida.museum", - "force.museum", - "fortmissoula.museum", - "fortworth.museum", - "foundation.museum", - "francaise.museum", - "frankfurt.museum", - "franziskaner.museum", - "freemasonry.museum", - "freiburg.museum", - "fribourg.museum", - "frog.museum", - "fundacio.museum", - "furniture.museum", - "gallery.museum", - "garden.museum", - "gateway.museum", - "geelvinck.museum", - "gemological.museum", - "geology.museum", - "georgia.museum", - "giessen.museum", - "glas.museum", - "glass.museum", - "gorge.museum", - "grandrapids.museum", - "graz.museum", - "guernsey.museum", - "halloffame.museum", - "hamburg.museum", - "handson.museum", - "harvestcelebration.museum", - "hawaii.museum", - "health.museum", - "heimatunduhren.museum", - "hellas.museum", - "helsinki.museum", - "hembygdsforbund.museum", - "heritage.museum", - "histoire.museum", - "historical.museum", - "historicalsociety.museum", - "historichouses.museum", - "historisch.museum", - "historisches.museum", - "history.museum", - "historyofscience.museum", - "horology.museum", - "house.museum", - "humanities.museum", - "illustration.museum", - "imageandsound.museum", - "indian.museum", - "indiana.museum", - "indianapolis.museum", - "indianmarket.museum", - "intelligence.museum", - "interactive.museum", - "iraq.museum", - "iron.museum", - "isleofman.museum", - "jamison.museum", - "jefferson.museum", - "jerusalem.museum", - "jewelry.museum", - "jewish.museum", - "jewishart.museum", - "jfk.museum", - "journalism.museum", - "judaica.museum", - "judygarland.museum", - "juedisches.museum", - "juif.museum", - "karate.museum", - "karikatur.museum", - "kids.museum", - "koebenhavn.museum", - "koeln.museum", - "kunst.museum", - "kunstsammlung.museum", - "kunstunddesign.museum", - "labor.museum", - "labour.museum", - "lajolla.museum", - "lancashire.museum", - "landes.museum", - "lans.museum", - "xn--lns-qla.museum", - "larsson.museum", - "lewismiller.museum", - "lincoln.museum", - "linz.museum", - "living.museum", - "livinghistory.museum", - "localhistory.museum", - "london.museum", - "losangeles.museum", - "louvre.museum", - "loyalist.museum", - "lucerne.museum", - "luxembourg.museum", - "luzern.museum", - "mad.museum", - "madrid.museum", - "mallorca.museum", - "manchester.museum", - "mansion.museum", - "mansions.museum", - "manx.museum", - "marburg.museum", - "maritime.museum", - "maritimo.museum", - "maryland.museum", - "marylhurst.museum", - "media.museum", - "medical.museum", - "medizinhistorisches.museum", - "meeres.museum", - "memorial.museum", - "mesaverde.museum", - "michigan.museum", - "midatlantic.museum", - "military.museum", - "mill.museum", - "miners.museum", - "mining.museum", - "minnesota.museum", - "missile.museum", - "missoula.museum", - "modern.museum", - "moma.museum", - "money.museum", - "monmouth.museum", - "monticello.museum", - "montreal.museum", - "moscow.museum", - "motorcycle.museum", - "muenchen.museum", - "muenster.museum", - "mulhouse.museum", - "muncie.museum", - "museet.museum", - "museumcenter.museum", - "museumvereniging.museum", - "music.museum", - "national.museum", - "nationalfirearms.museum", - "nationalheritage.museum", - "nativeamerican.museum", - "naturalhistory.museum", - "naturalhistorymuseum.museum", - "naturalsciences.museum", - "nature.museum", - "naturhistorisches.museum", - "natuurwetenschappen.museum", - "naumburg.museum", - "naval.museum", - "nebraska.museum", - "neues.museum", - "newhampshire.museum", - "newjersey.museum", - "newmexico.museum", - "newport.museum", - "newspaper.museum", - "newyork.museum", - "niepce.museum", - "norfolk.museum", - "north.museum", - "nrw.museum", - "nuernberg.museum", - "nuremberg.museum", - "nyc.museum", - "nyny.museum", - "oceanographic.museum", - "oceanographique.museum", - "omaha.museum", - "online.museum", - "ontario.museum", - "openair.museum", - "oregon.museum", - "oregontrail.museum", - "otago.museum", - "oxford.museum", - "pacific.museum", - "paderborn.museum", - "palace.museum", - "paleo.museum", - "palmsprings.museum", - "panama.museum", - "paris.museum", - "pasadena.museum", - "pharmacy.museum", - "philadelphia.museum", - "philadelphiaarea.museum", - "philately.museum", - "phoenix.museum", - "photography.museum", - "pilots.museum", - "pittsburgh.museum", - "planetarium.museum", - "plantation.museum", - "plants.museum", - "plaza.museum", - "portal.museum", - "portland.museum", - "portlligat.museum", - "posts-and-telecommunications.museum", - "preservation.museum", - "presidio.museum", - "press.museum", - "project.museum", - "public.museum", - "pubol.museum", - "quebec.museum", - "railroad.museum", - "railway.museum", - "research.museum", - "resistance.museum", - "riodejaneiro.museum", - "rochester.museum", - "rockart.museum", - "roma.museum", - "russia.museum", - "saintlouis.museum", - "salem.museum", - "salvadordali.museum", - "salzburg.museum", - "sandiego.museum", - "sanfrancisco.museum", - "santabarbara.museum", - "santacruz.museum", - "santafe.museum", - "saskatchewan.museum", - "satx.museum", - "savannahga.museum", - "schlesisches.museum", - "schoenbrunn.museum", - "schokoladen.museum", - "school.museum", - "schweiz.museum", - "science.museum", - "scienceandhistory.museum", - "scienceandindustry.museum", - "sciencecenter.museum", - "sciencecenters.museum", - "science-fiction.museum", - "sciencehistory.museum", - "sciences.museum", - "sciencesnaturelles.museum", - "scotland.museum", - "seaport.museum", - "settlement.museum", - "settlers.museum", - "shell.museum", - "sherbrooke.museum", - "sibenik.museum", - "silk.museum", - "ski.museum", - "skole.museum", - "society.museum", - "sologne.museum", - "soundandvision.museum", - "southcarolina.museum", - "southwest.museum", - "space.museum", - "spy.museum", - "square.museum", - "stadt.museum", - "stalbans.museum", - "starnberg.museum", - "state.museum", - "stateofdelaware.museum", - "station.museum", - "steam.museum", - "steiermark.museum", - "stjohn.museum", - "stockholm.museum", - "stpetersburg.museum", - "stuttgart.museum", - "suisse.museum", - "surgeonshall.museum", - "surrey.museum", - "svizzera.museum", - "sweden.museum", - "sydney.museum", - "tank.museum", - "tcm.museum", - "technology.museum", - "telekommunikation.museum", - "television.museum", - "texas.museum", - "textile.museum", - "theater.museum", - "time.museum", - "timekeeping.museum", - "topology.museum", - "torino.museum", - "touch.museum", - "town.museum", - "transport.museum", - "tree.museum", - "trolley.museum", - "trust.museum", - "trustee.museum", - "uhren.museum", - "ulm.museum", - "undersea.museum", - "university.museum", - "usa.museum", - "usantiques.museum", - "usarts.museum", - "uscountryestate.museum", - "usculture.museum", - "usdecorativearts.museum", - "usgarden.museum", - "ushistory.museum", - "ushuaia.museum", - "uslivinghistory.museum", - "utah.museum", - "uvic.museum", - "valley.museum", - "vantaa.museum", - "versailles.museum", - "viking.museum", - "village.museum", - "virginia.museum", - "virtual.museum", - "virtuel.museum", - "vlaanderen.museum", - "volkenkunde.museum", - "wales.museum", - "wallonie.museum", - "war.museum", - "washingtondc.museum", - "watchandclock.museum", - "watch-and-clock.museum", - "western.museum", - "westfalen.museum", - "whaling.museum", - "wildlife.museum", - "williamsburg.museum", - "windmill.museum", - "workshop.museum", - "york.museum", - "yorkshire.museum", - "yosemite.museum", - "youth.museum", - "zoological.museum", - "zoology.museum", - "xn--9dbhblg6di.museum", - "xn--h1aegh.museum", - "mv", - "aero.mv", - "biz.mv", - "com.mv", - "coop.mv", - "edu.mv", - "gov.mv", - "info.mv", - "int.mv", - "mil.mv", - "museum.mv", - "name.mv", - "net.mv", - "org.mv", - "pro.mv", - "mw", - "ac.mw", - "biz.mw", - "co.mw", - "com.mw", - "coop.mw", - "edu.mw", - "gov.mw", - "int.mw", - "museum.mw", - "net.mw", - "org.mw", - "mx", - "com.mx", - "org.mx", - "gob.mx", - "edu.mx", - "net.mx", - "my", - "com.my", - "net.my", - "org.my", - "gov.my", - "edu.my", - "mil.my", - "name.my", - "mz", - "ac.mz", - "adv.mz", - "co.mz", - "edu.mz", - "gov.mz", - "mil.mz", - "net.mz", - "org.mz", - "na", - "info.na", - "pro.na", - "name.na", - "school.na", - "or.na", - "dr.na", - "us.na", - "mx.na", - "ca.na", - "in.na", - "cc.na", - "tv.na", - "ws.na", - "mobi.na", - "co.na", - "com.na", - "org.na", - "name", - "nc", - "asso.nc", - "nom.nc", - "ne", - "net", - "nf", - "com.nf", - "net.nf", - "per.nf", - "rec.nf", - "web.nf", - "arts.nf", - "firm.nf", - "info.nf", - "other.nf", - "store.nf", - "ng", - "com.ng", - "edu.ng", - "gov.ng", - "i.ng", - "mil.ng", - "mobi.ng", - "name.ng", - "net.ng", - "org.ng", - "sch.ng", - "ni", - "ac.ni", - "biz.ni", - "co.ni", - "com.ni", - "edu.ni", - "gob.ni", - "in.ni", - "info.ni", - "int.ni", - "mil.ni", - "net.ni", - "nom.ni", - "org.ni", - "web.ni", - "nl", - "no", - "fhs.no", - "vgs.no", - "fylkesbibl.no", - "folkebibl.no", - "museum.no", - "idrett.no", - "priv.no", - "mil.no", - "stat.no", - "dep.no", - "kommune.no", - "herad.no", - "aa.no", - "ah.no", - "bu.no", - "fm.no", - "hl.no", - "hm.no", - "jan-mayen.no", - "mr.no", - "nl.no", - "nt.no", - "of.no", - "ol.no", - "oslo.no", - "rl.no", - "sf.no", - "st.no", - "svalbard.no", - "tm.no", - "tr.no", - "va.no", - "vf.no", - "gs.aa.no", - "gs.ah.no", - "gs.bu.no", - "gs.fm.no", - "gs.hl.no", - "gs.hm.no", - "gs.jan-mayen.no", - "gs.mr.no", - "gs.nl.no", - "gs.nt.no", - "gs.of.no", - "gs.ol.no", - "gs.oslo.no", - "gs.rl.no", - "gs.sf.no", - "gs.st.no", - "gs.svalbard.no", - "gs.tm.no", - "gs.tr.no", - "gs.va.no", - "gs.vf.no", - "akrehamn.no", - "xn--krehamn-dxa.no", - "algard.no", - "xn--lgrd-poac.no", - "arna.no", - "brumunddal.no", - "bryne.no", - "bronnoysund.no", - "xn--brnnysund-m8ac.no", - "drobak.no", - "xn--drbak-wua.no", - "egersund.no", - "fetsund.no", - "floro.no", - "xn--flor-jra.no", - "fredrikstad.no", - "hokksund.no", - "honefoss.no", - "xn--hnefoss-q1a.no", - "jessheim.no", - "jorpeland.no", - "xn--jrpeland-54a.no", - "kirkenes.no", - "kopervik.no", - "krokstadelva.no", - "langevag.no", - "xn--langevg-jxa.no", - "leirvik.no", - "mjondalen.no", - "xn--mjndalen-64a.no", - "mo-i-rana.no", - "mosjoen.no", - "xn--mosjen-eya.no", - "nesoddtangen.no", - "orkanger.no", - "osoyro.no", - "xn--osyro-wua.no", - "raholt.no", - "xn--rholt-mra.no", - "sandnessjoen.no", - "xn--sandnessjen-ogb.no", - "skedsmokorset.no", - "slattum.no", - "spjelkavik.no", - "stathelle.no", - "stavern.no", - "stjordalshalsen.no", - "xn--stjrdalshalsen-sqb.no", - "tananger.no", - "tranby.no", - "vossevangen.no", - "afjord.no", - "xn--fjord-lra.no", - "agdenes.no", - "al.no", - "xn--l-1fa.no", - "alesund.no", - "xn--lesund-hua.no", - "alstahaug.no", - "alta.no", - "xn--lt-liac.no", - "alaheadju.no", - "xn--laheadju-7ya.no", - "alvdal.no", - "amli.no", - "xn--mli-tla.no", - "amot.no", - "xn--mot-tla.no", - "andebu.no", - "andoy.no", - "xn--andy-ira.no", - "andasuolo.no", - "ardal.no", - "xn--rdal-poa.no", - "aremark.no", - "arendal.no", - "xn--s-1fa.no", - "aseral.no", - "xn--seral-lra.no", - "asker.no", - "askim.no", - "askvoll.no", - "askoy.no", - "xn--asky-ira.no", - "asnes.no", - "xn--snes-poa.no", - "audnedaln.no", - "aukra.no", - "aure.no", - "aurland.no", - "aurskog-holand.no", - "xn--aurskog-hland-jnb.no", - "austevoll.no", - "austrheim.no", - "averoy.no", - "xn--avery-yua.no", - "balestrand.no", - "ballangen.no", - "balat.no", - "xn--blt-elab.no", - "balsfjord.no", - "bahccavuotna.no", - "xn--bhccavuotna-k7a.no", - "bamble.no", - "bardu.no", - "beardu.no", - "beiarn.no", - "bajddar.no", - "xn--bjddar-pta.no", - "baidar.no", - "xn--bidr-5nac.no", - "berg.no", - "bergen.no", - "berlevag.no", - "xn--berlevg-jxa.no", - "bearalvahki.no", - "xn--bearalvhki-y4a.no", - "bindal.no", - "birkenes.no", - "bjarkoy.no", - "xn--bjarky-fya.no", - "bjerkreim.no", - "bjugn.no", - "bodo.no", - "xn--bod-2na.no", - "badaddja.no", - "xn--bdddj-mrabd.no", - "budejju.no", - "bokn.no", - "bremanger.no", - "bronnoy.no", - "xn--brnny-wuac.no", - "bygland.no", - "bykle.no", - "barum.no", - "xn--brum-voa.no", - "bo.telemark.no", - "xn--b-5ga.telemark.no", - "bo.nordland.no", - "xn--b-5ga.nordland.no", - "bievat.no", - "xn--bievt-0qa.no", - "bomlo.no", - "xn--bmlo-gra.no", - "batsfjord.no", - "xn--btsfjord-9za.no", - "bahcavuotna.no", - "xn--bhcavuotna-s4a.no", - "dovre.no", - "drammen.no", - "drangedal.no", - "dyroy.no", - "xn--dyry-ira.no", - "donna.no", - "xn--dnna-gra.no", - "eid.no", - "eidfjord.no", - "eidsberg.no", - "eidskog.no", - "eidsvoll.no", - "eigersund.no", - "elverum.no", - "enebakk.no", - "engerdal.no", - "etne.no", - "etnedal.no", - "evenes.no", - "evenassi.no", - "xn--eveni-0qa01ga.no", - "evje-og-hornnes.no", - "farsund.no", - "fauske.no", - "fuossko.no", - "fuoisku.no", - "fedje.no", - "fet.no", - "finnoy.no", - "xn--finny-yua.no", - "fitjar.no", - "fjaler.no", - "fjell.no", - "flakstad.no", - "flatanger.no", - "flekkefjord.no", - "flesberg.no", - "flora.no", - "fla.no", - "xn--fl-zia.no", - "folldal.no", - "forsand.no", - "fosnes.no", - "frei.no", - "frogn.no", - "froland.no", - "frosta.no", - "frana.no", - "xn--frna-woa.no", - "froya.no", - "xn--frya-hra.no", - "fusa.no", - "fyresdal.no", - "forde.no", - "xn--frde-gra.no", - "gamvik.no", - "gangaviika.no", - "xn--ggaviika-8ya47h.no", - "gaular.no", - "gausdal.no", - "gildeskal.no", - "xn--gildeskl-g0a.no", - "giske.no", - "gjemnes.no", - "gjerdrum.no", - "gjerstad.no", - "gjesdal.no", - "gjovik.no", - "xn--gjvik-wua.no", - "gloppen.no", - "gol.no", - "gran.no", - "grane.no", - "granvin.no", - "gratangen.no", - "grimstad.no", - "grong.no", - "kraanghke.no", - "xn--kranghke-b0a.no", - "grue.no", - "gulen.no", - "hadsel.no", - "halden.no", - "halsa.no", - "hamar.no", - "hamaroy.no", - "habmer.no", - "xn--hbmer-xqa.no", - "hapmir.no", - "xn--hpmir-xqa.no", - "hammerfest.no", - "hammarfeasta.no", - "xn--hmmrfeasta-s4ac.no", - "haram.no", - "hareid.no", - "harstad.no", - "hasvik.no", - "aknoluokta.no", - "xn--koluokta-7ya57h.no", - "hattfjelldal.no", - "aarborte.no", - "haugesund.no", - "hemne.no", - "hemnes.no", - "hemsedal.no", - "heroy.more-og-romsdal.no", - "xn--hery-ira.xn--mre-og-romsdal-qqb.no", - "heroy.nordland.no", - "xn--hery-ira.nordland.no", - "hitra.no", - "hjartdal.no", - "hjelmeland.no", - "hobol.no", - "xn--hobl-ira.no", - "hof.no", - "hol.no", - "hole.no", - "holmestrand.no", - "holtalen.no", - "xn--holtlen-hxa.no", - "hornindal.no", - "horten.no", - "hurdal.no", - "hurum.no", - "hvaler.no", - "hyllestad.no", - "hagebostad.no", - "xn--hgebostad-g3a.no", - "hoyanger.no", - "xn--hyanger-q1a.no", - "hoylandet.no", - "xn--hylandet-54a.no", - "ha.no", - "xn--h-2fa.no", - "ibestad.no", - "inderoy.no", - "xn--indery-fya.no", - "iveland.no", - "jevnaker.no", - "jondal.no", - "jolster.no", - "xn--jlster-bya.no", - "karasjok.no", - "karasjohka.no", - "xn--krjohka-hwab49j.no", - "karlsoy.no", - "galsa.no", - "xn--gls-elac.no", - "karmoy.no", - "xn--karmy-yua.no", - "kautokeino.no", - "guovdageaidnu.no", - "klepp.no", - "klabu.no", - "xn--klbu-woa.no", - "kongsberg.no", - "kongsvinger.no", - "kragero.no", - "xn--krager-gya.no", - "kristiansand.no", - "kristiansund.no", - "krodsherad.no", - "xn--krdsherad-m8a.no", - "kvalsund.no", - "rahkkeravju.no", - "xn--rhkkervju-01af.no", - "kvam.no", - "kvinesdal.no", - "kvinnherad.no", - "kviteseid.no", - "kvitsoy.no", - "xn--kvitsy-fya.no", - "kvafjord.no", - "xn--kvfjord-nxa.no", - "giehtavuoatna.no", - "kvanangen.no", - "xn--kvnangen-k0a.no", - "navuotna.no", - "xn--nvuotna-hwa.no", - "kafjord.no", - "xn--kfjord-iua.no", - "gaivuotna.no", - "xn--givuotna-8ya.no", - "larvik.no", - "lavangen.no", - "lavagis.no", - "loabat.no", - "xn--loabt-0qa.no", - "lebesby.no", - "davvesiida.no", - "leikanger.no", - "leirfjord.no", - "leka.no", - "leksvik.no", - "lenvik.no", - "leangaviika.no", - "xn--leagaviika-52b.no", - "lesja.no", - "levanger.no", - "lier.no", - "lierne.no", - "lillehammer.no", - "lillesand.no", - "lindesnes.no", - "lindas.no", - "xn--linds-pra.no", - "lom.no", - "loppa.no", - "lahppi.no", - "xn--lhppi-xqa.no", - "lund.no", - "lunner.no", - "luroy.no", - "xn--lury-ira.no", - "luster.no", - "lyngdal.no", - "lyngen.no", - "ivgu.no", - "lardal.no", - "lerdal.no", - "xn--lrdal-sra.no", - "lodingen.no", - "xn--ldingen-q1a.no", - "lorenskog.no", - "xn--lrenskog-54a.no", - "loten.no", - "xn--lten-gra.no", - "malvik.no", - "masoy.no", - "xn--msy-ula0h.no", - "muosat.no", - "xn--muost-0qa.no", - "mandal.no", - "marker.no", - "marnardal.no", - "masfjorden.no", - "meland.no", - "meldal.no", - "melhus.no", - "meloy.no", - "xn--mely-ira.no", - "meraker.no", - "xn--merker-kua.no", - "moareke.no", - "xn--moreke-jua.no", - "midsund.no", - "midtre-gauldal.no", - "modalen.no", - "modum.no", - "molde.no", - "moskenes.no", - "moss.no", - "mosvik.no", - "malselv.no", - "xn--mlselv-iua.no", - "malatvuopmi.no", - "xn--mlatvuopmi-s4a.no", - "namdalseid.no", - "aejrie.no", - "namsos.no", - "namsskogan.no", - "naamesjevuemie.no", - "xn--nmesjevuemie-tcba.no", - "laakesvuemie.no", - "nannestad.no", - "narvik.no", - "narviika.no", - "naustdal.no", - "nedre-eiker.no", - "nes.akershus.no", - "nes.buskerud.no", - "nesna.no", - "nesodden.no", - "nesseby.no", - "unjarga.no", - "xn--unjrga-rta.no", - "nesset.no", - "nissedal.no", - "nittedal.no", - "nord-aurdal.no", - "nord-fron.no", - "nord-odal.no", - "norddal.no", - "nordkapp.no", - "davvenjarga.no", - "xn--davvenjrga-y4a.no", - "nordre-land.no", - "nordreisa.no", - "raisa.no", - "xn--risa-5na.no", - "nore-og-uvdal.no", - "notodden.no", - "naroy.no", - "xn--nry-yla5g.no", - "notteroy.no", - "xn--nttery-byae.no", - "odda.no", - "oksnes.no", - "xn--ksnes-uua.no", - "oppdal.no", - "oppegard.no", - "xn--oppegrd-ixa.no", - "orkdal.no", - "orland.no", - "xn--rland-uua.no", - "orskog.no", - "xn--rskog-uua.no", - "orsta.no", - "xn--rsta-fra.no", - "os.hedmark.no", - "os.hordaland.no", - "osen.no", - "osteroy.no", - "xn--ostery-fya.no", - "ostre-toten.no", - "xn--stre-toten-zcb.no", - "overhalla.no", - "ovre-eiker.no", - "xn--vre-eiker-k8a.no", - "oyer.no", - "xn--yer-zna.no", - "oygarden.no", - "xn--ygarden-p1a.no", - "oystre-slidre.no", - "xn--ystre-slidre-ujb.no", - "porsanger.no", - "porsangu.no", - "xn--porsgu-sta26f.no", - "porsgrunn.no", - "radoy.no", - "xn--rady-ira.no", - "rakkestad.no", - "rana.no", - "ruovat.no", - "randaberg.no", - "rauma.no", - "rendalen.no", - "rennebu.no", - "rennesoy.no", - "xn--rennesy-v1a.no", - "rindal.no", - "ringebu.no", - "ringerike.no", - "ringsaker.no", - "rissa.no", - "risor.no", - "xn--risr-ira.no", - "roan.no", - "rollag.no", - "rygge.no", - "ralingen.no", - "xn--rlingen-mxa.no", - "rodoy.no", - "xn--rdy-0nab.no", - "romskog.no", - "xn--rmskog-bya.no", - "roros.no", - "xn--rros-gra.no", - "rost.no", - "xn--rst-0na.no", - "royken.no", - "xn--ryken-vua.no", - "royrvik.no", - "xn--ryrvik-bya.no", - "rade.no", - "xn--rde-ula.no", - "salangen.no", - "siellak.no", - "saltdal.no", - "salat.no", - "xn--slt-elab.no", - "xn--slat-5na.no", - "samnanger.no", - "sande.more-og-romsdal.no", - "sande.xn--mre-og-romsdal-qqb.no", - "sande.vestfold.no", - "sandefjord.no", - "sandnes.no", - "sandoy.no", - "xn--sandy-yua.no", - "sarpsborg.no", - "sauda.no", - "sauherad.no", - "sel.no", - "selbu.no", - "selje.no", - "seljord.no", - "sigdal.no", - "siljan.no", - "sirdal.no", - "skaun.no", - "skedsmo.no", - "ski.no", - "skien.no", - "skiptvet.no", - "skjervoy.no", - "xn--skjervy-v1a.no", - "skierva.no", - "xn--skierv-uta.no", - "skjak.no", - "xn--skjk-soa.no", - "skodje.no", - "skanland.no", - "xn--sknland-fxa.no", - "skanit.no", - "xn--sknit-yqa.no", - "smola.no", - "xn--smla-hra.no", - "snillfjord.no", - "snasa.no", - "xn--snsa-roa.no", - "snoasa.no", - "snaase.no", - "xn--snase-nra.no", - "sogndal.no", - "sokndal.no", - "sola.no", - "solund.no", - "songdalen.no", - "sortland.no", - "spydeberg.no", - "stange.no", - "stavanger.no", - "steigen.no", - "steinkjer.no", - "stjordal.no", - "xn--stjrdal-s1a.no", - "stokke.no", - "stor-elvdal.no", - "stord.no", - "stordal.no", - "storfjord.no", - "omasvuotna.no", - "strand.no", - "stranda.no", - "stryn.no", - "sula.no", - "suldal.no", - "sund.no", - "sunndal.no", - "surnadal.no", - "sveio.no", - "svelvik.no", - "sykkylven.no", - "sogne.no", - "xn--sgne-gra.no", - "somna.no", - "xn--smna-gra.no", - "sondre-land.no", - "xn--sndre-land-0cb.no", - "sor-aurdal.no", - "xn--sr-aurdal-l8a.no", - "sor-fron.no", - "xn--sr-fron-q1a.no", - "sor-odal.no", - "xn--sr-odal-q1a.no", - "sor-varanger.no", - "xn--sr-varanger-ggb.no", - "matta-varjjat.no", - "xn--mtta-vrjjat-k7af.no", - "sorfold.no", - "xn--srfold-bya.no", - "sorreisa.no", - "xn--srreisa-q1a.no", - "sorum.no", - "xn--srum-gra.no", - "tana.no", - "deatnu.no", - "time.no", - "tingvoll.no", - "tinn.no", - "tjeldsund.no", - "dielddanuorri.no", - "tjome.no", - "xn--tjme-hra.no", - "tokke.no", - "tolga.no", - "torsken.no", - "tranoy.no", - "xn--trany-yua.no", - "tromso.no", - "xn--troms-zua.no", - "tromsa.no", - "romsa.no", - "trondheim.no", - "troandin.no", - "trysil.no", - "trana.no", - "xn--trna-woa.no", - "trogstad.no", - "xn--trgstad-r1a.no", - "tvedestrand.no", - "tydal.no", - "tynset.no", - "tysfjord.no", - "divtasvuodna.no", - "divttasvuotna.no", - "tysnes.no", - "tysvar.no", - "xn--tysvr-vra.no", - "tonsberg.no", - "xn--tnsberg-q1a.no", - "ullensaker.no", - "ullensvang.no", - "ulvik.no", - "utsira.no", - "vadso.no", - "xn--vads-jra.no", - "cahcesuolo.no", - "xn--hcesuolo-7ya35b.no", - "vaksdal.no", - "valle.no", - "vang.no", - "vanylven.no", - "vardo.no", - "xn--vard-jra.no", - "varggat.no", - "xn--vrggt-xqad.no", - "vefsn.no", - "vaapste.no", - "vega.no", - "vegarshei.no", - "xn--vegrshei-c0a.no", - "vennesla.no", - "verdal.no", - "verran.no", - "vestby.no", - "vestnes.no", - "vestre-slidre.no", - "vestre-toten.no", - "vestvagoy.no", - "xn--vestvgy-ixa6o.no", - "vevelstad.no", - "vik.no", - "vikna.no", - "vindafjord.no", - "volda.no", - "voss.no", - "varoy.no", - "xn--vry-yla5g.no", - "vagan.no", - "xn--vgan-qoa.no", - "voagat.no", - "vagsoy.no", - "xn--vgsy-qoa0j.no", - "vaga.no", - "xn--vg-yiab.no", - "valer.ostfold.no", - "xn--vler-qoa.xn--stfold-9xa.no", - "valer.hedmark.no", - "xn--vler-qoa.hedmark.no", - "*.np", - "nr", - "biz.nr", - "info.nr", - "gov.nr", - "edu.nr", - "org.nr", - "net.nr", - "com.nr", - "nu", - "nz", - "ac.nz", - "co.nz", - "cri.nz", - "geek.nz", - "gen.nz", - "govt.nz", - "health.nz", - "iwi.nz", - "kiwi.nz", - "maori.nz", - "mil.nz", - "xn--mori-qsa.nz", - "net.nz", - "org.nz", - "parliament.nz", - "school.nz", - "om", - "co.om", - "com.om", - "edu.om", - "gov.om", - "med.om", - "museum.om", - "net.om", - "org.om", - "pro.om", - "onion", - "org", - "pa", - "ac.pa", - "gob.pa", - "com.pa", - "org.pa", - "sld.pa", - "edu.pa", - "net.pa", - "ing.pa", - "abo.pa", - "med.pa", - "nom.pa", - "pe", - "edu.pe", - "gob.pe", - "nom.pe", - "mil.pe", - "org.pe", - "com.pe", - "net.pe", - "pf", - "com.pf", - "org.pf", - "edu.pf", - "*.pg", - "ph", - "com.ph", - "net.ph", - "org.ph", - "gov.ph", - "edu.ph", - "ngo.ph", - "mil.ph", - "i.ph", - "pk", - "com.pk", - "net.pk", - "edu.pk", - "org.pk", - "fam.pk", - "biz.pk", - "web.pk", - "gov.pk", - "gob.pk", - "gok.pk", - "gon.pk", - "gop.pk", - "gos.pk", - "info.pk", - "pl", - "com.pl", - "net.pl", - "org.pl", - "aid.pl", - "agro.pl", - "atm.pl", - "auto.pl", - "biz.pl", - "edu.pl", - "gmina.pl", - "gsm.pl", - "info.pl", - "mail.pl", - "miasta.pl", - "media.pl", - "mil.pl", - "nieruchomosci.pl", - "nom.pl", - "pc.pl", - "powiat.pl", - "priv.pl", - "realestate.pl", - "rel.pl", - "sex.pl", - "shop.pl", - "sklep.pl", - "sos.pl", - "szkola.pl", - "targi.pl", - "tm.pl", - "tourism.pl", - "travel.pl", - "turystyka.pl", - "gov.pl", - "ap.gov.pl", - "ic.gov.pl", - "is.gov.pl", - "us.gov.pl", - "kmpsp.gov.pl", - "kppsp.gov.pl", - "kwpsp.gov.pl", - "psp.gov.pl", - "wskr.gov.pl", - "kwp.gov.pl", - "mw.gov.pl", - "ug.gov.pl", - "um.gov.pl", - "umig.gov.pl", - "ugim.gov.pl", - "upow.gov.pl", - "uw.gov.pl", - "starostwo.gov.pl", - "pa.gov.pl", - "po.gov.pl", - "psse.gov.pl", - "pup.gov.pl", - "rzgw.gov.pl", - "sa.gov.pl", - "so.gov.pl", - "sr.gov.pl", - "wsa.gov.pl", - "sko.gov.pl", - "uzs.gov.pl", - "wiih.gov.pl", - "winb.gov.pl", - "pinb.gov.pl", - "wios.gov.pl", - "witd.gov.pl", - "wzmiuw.gov.pl", - "piw.gov.pl", - "wiw.gov.pl", - "griw.gov.pl", - "wif.gov.pl", - "oum.gov.pl", - "sdn.gov.pl", - "zp.gov.pl", - "uppo.gov.pl", - "mup.gov.pl", - "wuoz.gov.pl", - "konsulat.gov.pl", - "oirm.gov.pl", - "augustow.pl", - "babia-gora.pl", - "bedzin.pl", - "beskidy.pl", - "bialowieza.pl", - "bialystok.pl", - "bielawa.pl", - "bieszczady.pl", - "boleslawiec.pl", - "bydgoszcz.pl", - "bytom.pl", - "cieszyn.pl", - "czeladz.pl", - "czest.pl", - "dlugoleka.pl", - "elblag.pl", - "elk.pl", - "glogow.pl", - "gniezno.pl", - "gorlice.pl", - "grajewo.pl", - "ilawa.pl", - "jaworzno.pl", - "jelenia-gora.pl", - "jgora.pl", - "kalisz.pl", - "kazimierz-dolny.pl", - "karpacz.pl", - "kartuzy.pl", - "kaszuby.pl", - "katowice.pl", - "kepno.pl", - "ketrzyn.pl", - "klodzko.pl", - "kobierzyce.pl", - "kolobrzeg.pl", - "konin.pl", - "konskowola.pl", - "kutno.pl", - "lapy.pl", - "lebork.pl", - "legnica.pl", - "lezajsk.pl", - "limanowa.pl", - "lomza.pl", - "lowicz.pl", - "lubin.pl", - "lukow.pl", - "malbork.pl", - "malopolska.pl", - "mazowsze.pl", - "mazury.pl", - "mielec.pl", - "mielno.pl", - "mragowo.pl", - "naklo.pl", - "nowaruda.pl", - "nysa.pl", - "olawa.pl", - "olecko.pl", - "olkusz.pl", - "olsztyn.pl", - "opoczno.pl", - "opole.pl", - "ostroda.pl", - "ostroleka.pl", - "ostrowiec.pl", - "ostrowwlkp.pl", - "pila.pl", - "pisz.pl", - "podhale.pl", - "podlasie.pl", - "polkowice.pl", - "pomorze.pl", - "pomorskie.pl", - "prochowice.pl", - "pruszkow.pl", - "przeworsk.pl", - "pulawy.pl", - "radom.pl", - "rawa-maz.pl", - "rybnik.pl", - "rzeszow.pl", - "sanok.pl", - "sejny.pl", - "slask.pl", - "slupsk.pl", - "sosnowiec.pl", - "stalowa-wola.pl", - "skoczow.pl", - "starachowice.pl", - "stargard.pl", - "suwalki.pl", - "swidnica.pl", - "swiebodzin.pl", - "swinoujscie.pl", - "szczecin.pl", - "szczytno.pl", - "tarnobrzeg.pl", - "tgory.pl", - "turek.pl", - "tychy.pl", - "ustka.pl", - "walbrzych.pl", - "warmia.pl", - "warszawa.pl", - "waw.pl", - "wegrow.pl", - "wielun.pl", - "wlocl.pl", - "wloclawek.pl", - "wodzislaw.pl", - "wolomin.pl", - "wroclaw.pl", - "zachpomor.pl", - "zagan.pl", - "zarow.pl", - "zgora.pl", - "zgorzelec.pl", - "pm", - "pn", - "gov.pn", - "co.pn", - "org.pn", - "edu.pn", - "net.pn", - "post", - "pr", - "com.pr", - "net.pr", - "org.pr", - "gov.pr", - "edu.pr", - "isla.pr", - "pro.pr", - "biz.pr", - "info.pr", - "name.pr", - "est.pr", - "prof.pr", - "ac.pr", - "pro", - "aaa.pro", - "aca.pro", - "acct.pro", - "avocat.pro", - "bar.pro", - "cpa.pro", - "eng.pro", - "jur.pro", - "law.pro", - "med.pro", - "recht.pro", - "ps", - "edu.ps", - "gov.ps", - "sec.ps", - "plo.ps", - "com.ps", - "org.ps", - "net.ps", - "pt", - "net.pt", - "gov.pt", - "org.pt", - "edu.pt", - "int.pt", - "publ.pt", - "com.pt", - "nome.pt", - "pw", - "co.pw", - "ne.pw", - "or.pw", - "ed.pw", - "go.pw", - "belau.pw", - "py", - "com.py", - "coop.py", - "edu.py", - "gov.py", - "mil.py", - "net.py", - "org.py", - "qa", - "com.qa", - "edu.qa", - "gov.qa", - "mil.qa", - "name.qa", - "net.qa", - "org.qa", - "sch.qa", - "re", - "asso.re", - "com.re", - "nom.re", - "ro", - "arts.ro", - "com.ro", - "firm.ro", - "info.ro", - "nom.ro", - "nt.ro", - "org.ro", - "rec.ro", - "store.ro", - "tm.ro", - "www.ro", - "rs", - "ac.rs", - "co.rs", - "edu.rs", - "gov.rs", - "in.rs", - "org.rs", - "ru", - "ac.ru", - "edu.ru", - "gov.ru", - "int.ru", - "mil.ru", - "test.ru", - "rw", - "ac.rw", - "co.rw", - "coop.rw", - "gov.rw", - "mil.rw", - "net.rw", - "org.rw", - "sa", - "com.sa", - "net.sa", - "org.sa", - "gov.sa", - "med.sa", - "pub.sa", - "edu.sa", - "sch.sa", - "sb", - "com.sb", - "edu.sb", - "gov.sb", - "net.sb", - "org.sb", - "sc", - "com.sc", - "gov.sc", - "net.sc", - "org.sc", - "edu.sc", - "sd", - "com.sd", - "net.sd", - "org.sd", - "edu.sd", - "med.sd", - "tv.sd", - "gov.sd", - "info.sd", - "se", - "a.se", - "ac.se", - "b.se", - "bd.se", - "brand.se", - "c.se", - "d.se", - "e.se", - "f.se", - "fh.se", - "fhsk.se", - "fhv.se", - "g.se", - "h.se", - "i.se", - "k.se", - "komforb.se", - "kommunalforbund.se", - "komvux.se", - "l.se", - "lanbib.se", - "m.se", - "n.se", - "naturbruksgymn.se", - "o.se", - "org.se", - "p.se", - "parti.se", - "pp.se", - "press.se", - "r.se", - "s.se", - "t.se", - "tm.se", - "u.se", - "w.se", - "x.se", - "y.se", - "z.se", - "sg", - "com.sg", - "net.sg", - "org.sg", - "gov.sg", - "edu.sg", - "per.sg", - "sh", - "com.sh", - "net.sh", - "gov.sh", - "org.sh", - "mil.sh", - "si", - "sj", - "sk", - "sl", - "com.sl", - "net.sl", - "edu.sl", - "gov.sl", - "org.sl", - "sm", - "sn", - "art.sn", - "com.sn", - "edu.sn", - "gouv.sn", - "org.sn", - "perso.sn", - "univ.sn", - "so", - "com.so", - "net.so", - "org.so", - "sr", - "st", - "co.st", - "com.st", - "consulado.st", - "edu.st", - "embaixada.st", - "gov.st", - "mil.st", - "net.st", - "org.st", - "principe.st", - "saotome.st", - "store.st", - "su", - "sv", - "com.sv", - "edu.sv", - "gob.sv", - "org.sv", - "red.sv", - "sx", - "gov.sx", - "sy", - "edu.sy", - "gov.sy", - "net.sy", - "mil.sy", - "com.sy", - "org.sy", - "sz", - "co.sz", - "ac.sz", - "org.sz", - "tc", - "td", - "tel", - "tf", - "tg", - "th", - "ac.th", - "co.th", - "go.th", - "in.th", - "mi.th", - "net.th", - "or.th", - "tj", - "ac.tj", - "biz.tj", - "co.tj", - "com.tj", - "edu.tj", - "go.tj", - "gov.tj", - "int.tj", - "mil.tj", - "name.tj", - "net.tj", - "nic.tj", - "org.tj", - "test.tj", - "web.tj", - "tk", - "tl", - "gov.tl", - "tm", - "com.tm", - "co.tm", - "org.tm", - "net.tm", - "nom.tm", - "gov.tm", - "mil.tm", - "edu.tm", - "tn", - "com.tn", - "ens.tn", - "fin.tn", - "gov.tn", - "ind.tn", - "intl.tn", - "nat.tn", - "net.tn", - "org.tn", - "info.tn", - "perso.tn", - "tourism.tn", - "edunet.tn", - "rnrt.tn", - "rns.tn", - "rnu.tn", - "mincom.tn", - "agrinet.tn", - "defense.tn", - "turen.tn", - "to", - "com.to", - "gov.to", - "net.to", - "org.to", - "edu.to", - "mil.to", - "tr", - "av.tr", - "bbs.tr", - "bel.tr", - "biz.tr", - "com.tr", - "dr.tr", - "edu.tr", - "gen.tr", - "gov.tr", - "info.tr", - "mil.tr", - "k12.tr", - "kep.tr", - "name.tr", - "net.tr", - "org.tr", - "pol.tr", - "tel.tr", - "tsk.tr", - "tv.tr", - "web.tr", - "nc.tr", - "gov.nc.tr", - "tt", - "co.tt", - "com.tt", - "org.tt", - "net.tt", - "biz.tt", - "info.tt", - "pro.tt", - "int.tt", - "coop.tt", - "jobs.tt", - "mobi.tt", - "travel.tt", - "museum.tt", - "aero.tt", - "name.tt", - "gov.tt", - "edu.tt", - "tv", - "tw", - "edu.tw", - "gov.tw", - "mil.tw", - "com.tw", - "net.tw", - "org.tw", - "idv.tw", - "game.tw", - "ebiz.tw", - "club.tw", - "xn--zf0ao64a.tw", - "xn--uc0atv.tw", - "xn--czrw28b.tw", - "tz", - "ac.tz", - "co.tz", - "go.tz", - "hotel.tz", - "info.tz", - "me.tz", - "mil.tz", - "mobi.tz", - "ne.tz", - "or.tz", - "sc.tz", - "tv.tz", - "ua", - "com.ua", - "edu.ua", - "gov.ua", - "in.ua", - "net.ua", - "org.ua", - "cherkassy.ua", - "cherkasy.ua", - "chernigov.ua", - "chernihiv.ua", - "chernivtsi.ua", - "chernovtsy.ua", - "ck.ua", - "cn.ua", - "cr.ua", - "crimea.ua", - "cv.ua", - "dn.ua", - "dnepropetrovsk.ua", - "dnipropetrovsk.ua", - "dominic.ua", - "donetsk.ua", - "dp.ua", - "if.ua", - "ivano-frankivsk.ua", - "kh.ua", - "kharkiv.ua", - "kharkov.ua", - "kherson.ua", - "khmelnitskiy.ua", - "khmelnytskyi.ua", - "kiev.ua", - "kirovograd.ua", - "km.ua", - "kr.ua", - "krym.ua", - "ks.ua", - "kv.ua", - "kyiv.ua", - "lg.ua", - "lt.ua", - "lugansk.ua", - "lutsk.ua", - "lv.ua", - "lviv.ua", - "mk.ua", - "mykolaiv.ua", - "nikolaev.ua", - "od.ua", - "odesa.ua", - "odessa.ua", - "pl.ua", - "poltava.ua", - "rivne.ua", - "rovno.ua", - "rv.ua", - "sb.ua", - "sebastopol.ua", - "sevastopol.ua", - "sm.ua", - "sumy.ua", - "te.ua", - "ternopil.ua", - "uz.ua", - "uzhgorod.ua", - "vinnica.ua", - "vinnytsia.ua", - "vn.ua", - "volyn.ua", - "yalta.ua", - "zaporizhzhe.ua", - "zaporizhzhia.ua", - "zhitomir.ua", - "zhytomyr.ua", - "zp.ua", - "zt.ua", - "ug", - "co.ug", - "or.ug", - "ac.ug", - "sc.ug", - "go.ug", - "ne.ug", - "com.ug", - "org.ug", - "uk", - "ac.uk", - "co.uk", - "gov.uk", - "ltd.uk", - "me.uk", - "net.uk", - "nhs.uk", - "org.uk", - "plc.uk", - "police.uk", - "*.sch.uk", - "us", - "dni.us", - "fed.us", - "isa.us", - "kids.us", - "nsn.us", - "ak.us", - "al.us", - "ar.us", - "as.us", - "az.us", - "ca.us", - "co.us", - "ct.us", - "dc.us", - "de.us", - "fl.us", - "ga.us", - "gu.us", - "hi.us", - "ia.us", - "id.us", - "il.us", - "in.us", - "ks.us", - "ky.us", - "la.us", - "ma.us", - "md.us", - "me.us", - "mi.us", - "mn.us", - "mo.us", - "ms.us", - "mt.us", - "nc.us", - "nd.us", - "ne.us", - "nh.us", - "nj.us", - "nm.us", - "nv.us", - "ny.us", - "oh.us", - "ok.us", - "or.us", - "pa.us", - "pr.us", - "ri.us", - "sc.us", - "sd.us", - "tn.us", - "tx.us", - "ut.us", - "vi.us", - "vt.us", - "va.us", - "wa.us", - "wi.us", - "wv.us", - "wy.us", - "k12.ak.us", - "k12.al.us", - "k12.ar.us", - "k12.as.us", - "k12.az.us", - "k12.ca.us", - "k12.co.us", - "k12.ct.us", - "k12.dc.us", - "k12.de.us", - "k12.fl.us", - "k12.ga.us", - "k12.gu.us", - "k12.ia.us", - "k12.id.us", - "k12.il.us", - "k12.in.us", - "k12.ks.us", - "k12.ky.us", - "k12.la.us", - "k12.ma.us", - "k12.md.us", - "k12.me.us", - "k12.mi.us", - "k12.mn.us", - "k12.mo.us", - "k12.ms.us", - "k12.mt.us", - "k12.nc.us", - "k12.ne.us", - "k12.nh.us", - "k12.nj.us", - "k12.nm.us", - "k12.nv.us", - "k12.ny.us", - "k12.oh.us", - "k12.ok.us", - "k12.or.us", - "k12.pa.us", - "k12.pr.us", - "k12.ri.us", - "k12.sc.us", - "k12.tn.us", - "k12.tx.us", - "k12.ut.us", - "k12.vi.us", - "k12.vt.us", - "k12.va.us", - "k12.wa.us", - "k12.wi.us", - "k12.wy.us", - "cc.ak.us", - "cc.al.us", - "cc.ar.us", - "cc.as.us", - "cc.az.us", - "cc.ca.us", - "cc.co.us", - "cc.ct.us", - "cc.dc.us", - "cc.de.us", - "cc.fl.us", - "cc.ga.us", - "cc.gu.us", - "cc.hi.us", - "cc.ia.us", - "cc.id.us", - "cc.il.us", - "cc.in.us", - "cc.ks.us", - "cc.ky.us", - "cc.la.us", - "cc.ma.us", - "cc.md.us", - "cc.me.us", - "cc.mi.us", - "cc.mn.us", - "cc.mo.us", - "cc.ms.us", - "cc.mt.us", - "cc.nc.us", - "cc.nd.us", - "cc.ne.us", - "cc.nh.us", - "cc.nj.us", - "cc.nm.us", - "cc.nv.us", - "cc.ny.us", - "cc.oh.us", - "cc.ok.us", - "cc.or.us", - "cc.pa.us", - "cc.pr.us", - "cc.ri.us", - "cc.sc.us", - "cc.sd.us", - "cc.tn.us", - "cc.tx.us", - "cc.ut.us", - "cc.vi.us", - "cc.vt.us", - "cc.va.us", - "cc.wa.us", - "cc.wi.us", - "cc.wv.us", - "cc.wy.us", - "lib.ak.us", - "lib.al.us", - "lib.ar.us", - "lib.as.us", - "lib.az.us", - "lib.ca.us", - "lib.co.us", - "lib.ct.us", - "lib.dc.us", - "lib.fl.us", - "lib.ga.us", - "lib.gu.us", - "lib.hi.us", - "lib.ia.us", - "lib.id.us", - "lib.il.us", - "lib.in.us", - "lib.ks.us", - "lib.ky.us", - "lib.la.us", - "lib.ma.us", - "lib.md.us", - "lib.me.us", - "lib.mi.us", - "lib.mn.us", - "lib.mo.us", - "lib.ms.us", - "lib.mt.us", - "lib.nc.us", - "lib.nd.us", - "lib.ne.us", - "lib.nh.us", - "lib.nj.us", - "lib.nm.us", - "lib.nv.us", - "lib.ny.us", - "lib.oh.us", - "lib.ok.us", - "lib.or.us", - "lib.pa.us", - "lib.pr.us", - "lib.ri.us", - "lib.sc.us", - "lib.sd.us", - "lib.tn.us", - "lib.tx.us", - "lib.ut.us", - "lib.vi.us", - "lib.vt.us", - "lib.va.us", - "lib.wa.us", - "lib.wi.us", - "lib.wy.us", - "pvt.k12.ma.us", - "chtr.k12.ma.us", - "paroch.k12.ma.us", - "ann-arbor.mi.us", - "cog.mi.us", - "dst.mi.us", - "eaton.mi.us", - "gen.mi.us", - "mus.mi.us", - "tec.mi.us", - "washtenaw.mi.us", - "uy", - "com.uy", - "edu.uy", - "gub.uy", - "mil.uy", - "net.uy", - "org.uy", - "uz", - "co.uz", - "com.uz", - "net.uz", - "org.uz", - "va", - "vc", - "com.vc", - "net.vc", - "org.vc", - "gov.vc", - "mil.vc", - "edu.vc", - "ve", - "arts.ve", - "co.ve", - "com.ve", - "e12.ve", - "edu.ve", - "firm.ve", - "gob.ve", - "gov.ve", - "info.ve", - "int.ve", - "mil.ve", - "net.ve", - "org.ve", - "rec.ve", - "store.ve", - "tec.ve", - "web.ve", - "vg", - "vi", - "co.vi", - "com.vi", - "k12.vi", - "net.vi", - "org.vi", - "vn", - "com.vn", - "net.vn", - "org.vn", - "edu.vn", - "gov.vn", - "int.vn", - "ac.vn", - "biz.vn", - "info.vn", - "name.vn", - "pro.vn", - "health.vn", - "vu", - "com.vu", - "edu.vu", - "net.vu", - "org.vu", - "wf", - "ws", - "com.ws", - "net.ws", - "org.ws", - "gov.ws", - "edu.ws", - "yt", - "xn--mgbaam7a8h", - "xn--y9a3aq", - "xn--54b7fta0cc", - "xn--90ae", - "xn--90ais", - "xn--fiqs8s", - "xn--fiqz9s", - "xn--lgbbat1ad8j", - "xn--wgbh1c", - "xn--e1a4c", - "xn--node", - "xn--qxam", - "xn--j6w193g", - "xn--55qx5d.xn--j6w193g", - "xn--wcvs22d.xn--j6w193g", - "xn--mxtq1m.xn--j6w193g", - "xn--gmqw5a.xn--j6w193g", - "xn--od0alg.xn--j6w193g", - "xn--uc0atv.xn--j6w193g", - "xn--2scrj9c", - "xn--3hcrj9c", - "xn--45br5cyl", - "xn--h2breg3eve", - "xn--h2brj9c8c", - "xn--mgbgu82a", - "xn--rvc1e0am3e", - "xn--h2brj9c", - "xn--mgbbh1a", - "xn--mgbbh1a71e", - "xn--fpcrj9c3d", - "xn--gecrj9c", - "xn--s9brj9c", - "xn--45brj9c", - "xn--xkc2dl3a5ee0h", - "xn--mgba3a4f16a", - "xn--mgba3a4fra", - "xn--mgbtx2b", - "xn--mgbayh7gpa", - "xn--3e0b707e", - "xn--80ao21a", - "xn--fzc2c9e2c", - "xn--xkc2al3hye2a", - "xn--mgbc0a9azcg", - "xn--d1alf", - "xn--l1acc", - "xn--mix891f", - "xn--mix082f", - "xn--mgbx4cd0ab", - "xn--mgb9awbf", - "xn--mgbai9azgqp6j", - "xn--mgbai9a5eva00b", - "xn--ygbi2ammx", - "xn--90a3ac", - "xn--o1ac.xn--90a3ac", - "xn--c1avg.xn--90a3ac", - "xn--90azh.xn--90a3ac", - "xn--d1at.xn--90a3ac", - "xn--o1ach.xn--90a3ac", - "xn--80au.xn--90a3ac", - "xn--p1ai", - "xn--wgbl6a", - "xn--mgberp4a5d4ar", - "xn--mgberp4a5d4a87g", - "xn--mgbqly7c0a67fbc", - "xn--mgbqly7cvafr", - "xn--mgbpl2fh", - "xn--yfro4i67o", - "xn--clchc0ea0b2g2a9gcd", - "xn--ogbpf8fl", - "xn--mgbtf8fl", - "xn--o3cw4h", - "xn--12c1fe0br.xn--o3cw4h", - "xn--12co0c3b4eva.xn--o3cw4h", - "xn--h3cuzk1di.xn--o3cw4h", - "xn--o3cyx2a.xn--o3cw4h", - "xn--m3ch0j3a.xn--o3cw4h", - "xn--12cfi8ixb8l.xn--o3cw4h", - "xn--pgbs0dh", - "xn--kpry57d", - "xn--kprw13d", - "xn--nnx388a", - "xn--j1amh", - "xn--mgb2ddes", - "xxx", - "*.ye", - "ac.za", - "agric.za", - "alt.za", - "co.za", - "edu.za", - "gov.za", - "grondar.za", - "law.za", - "mil.za", - "net.za", - "ngo.za", - "nis.za", - "nom.za", - "org.za", - "school.za", - "tm.za", - "web.za", - "zm", - "ac.zm", - "biz.zm", - "co.zm", - "com.zm", - "edu.zm", - "gov.zm", - "info.zm", - "mil.zm", - "net.zm", - "org.zm", - "sch.zm", - "zw", - "ac.zw", - "co.zw", - "gov.zw", - "mil.zw", - "org.zw", - "aaa", - "aarp", - "abarth", - "abb", - "abbott", - "abbvie", - "abc", - "able", - "abogado", - "abudhabi", - "academy", - "accenture", - "accountant", - "accountants", - "aco", - "actor", - "adac", - "ads", - "adult", - "aeg", - "aetna", - "afamilycompany", - "afl", - "africa", - "agakhan", - "agency", - "aig", - "aigo", - "airbus", - "airforce", - "airtel", - "akdn", - "alfaromeo", - "alibaba", - "alipay", - "allfinanz", - "allstate", - "ally", - "alsace", - "alstom", - "americanexpress", - "americanfamily", - "amex", - "amfam", - "amica", - "amsterdam", - "analytics", - "android", - "anquan", - "anz", - "aol", - "apartments", - "app", - "apple", - "aquarelle", - "arab", - "aramco", - "archi", - "army", - "art", - "arte", - "asda", - "associates", - "athleta", - "attorney", - "auction", - "audi", - "audible", - "audio", - "auspost", - "author", - "auto", - "autos", - "avianca", - "aws", - "axa", - "azure", - "baby", - "baidu", - "banamex", - "bananarepublic", - "band", - "bank", - "bar", - "barcelona", - "barclaycard", - "barclays", - "barefoot", - "bargains", - "baseball", - "basketball", - "bauhaus", - "bayern", - "bbc", - "bbt", - "bbva", - "bcg", - "bcn", - "beats", - "beauty", - "beer", - "bentley", - "berlin", - "best", - "bestbuy", - "bet", - "bharti", - "bible", - "bid", - "bike", - "bing", - "bingo", - "bio", - "black", - "blackfriday", - "blockbuster", - "blog", - "bloomberg", - "blue", - "bms", - "bmw", - "bnl", - "bnpparibas", - "boats", - "boehringer", - "bofa", - "bom", - "bond", - "boo", - "book", - "booking", - "bosch", - "bostik", - "boston", - "bot", - "boutique", - "box", - "bradesco", - "bridgestone", - "broadway", - "broker", - "brother", - "brussels", - "budapest", - "bugatti", - "build", - "builders", - "business", - "buy", - "buzz", - "bzh", - "cab", - "cafe", - "cal", - "call", - "calvinklein", - "cam", - "camera", - "camp", - "cancerresearch", - "canon", - "capetown", - "capital", - "capitalone", - "car", - "caravan", - "cards", - "care", - "career", - "careers", - "cars", - "cartier", - "casa", - "case", - "caseih", - "cash", - "casino", - "catering", - "catholic", - "cba", - "cbn", - "cbre", - "cbs", - "ceb", - "center", - "ceo", - "cern", - "cfa", - "cfd", - "chanel", - "channel", - "charity", - "chase", - "chat", - "cheap", - "chintai", - "christmas", - "chrome", - "chrysler", - "church", - "cipriani", - "circle", - "cisco", - "citadel", - "citi", - "citic", - "city", - "cityeats", - "claims", - "cleaning", - "click", - "clinic", - "clinique", - "clothing", - "cloud", - "club", - "clubmed", - "coach", - "codes", - "coffee", - "college", - "cologne", - "comcast", - "commbank", - "community", - "company", - "compare", - "computer", - "comsec", - "condos", - "construction", - "consulting", - "contact", - "contractors", - "cooking", - "cookingchannel", - "cool", - "corsica", - "country", - "coupon", - "coupons", - "courses", - "credit", - "creditcard", - "creditunion", - "cricket", - "crown", - "crs", - "cruise", - "cruises", - "csc", - "cuisinella", - "cymru", - "cyou", - "dabur", - "dad", - "dance", - "data", - "date", - "dating", - "datsun", - "day", - "dclk", - "dds", - "deal", - "dealer", - "deals", - "degree", - "delivery", - "dell", - "deloitte", - "delta", - "democrat", - "dental", - "dentist", - "desi", - "design", - "dev", - "dhl", - "diamonds", - "diet", - "digital", - "direct", - "directory", - "discount", - "discover", - "dish", - "diy", - "dnp", - "docs", - "doctor", - "dodge", - "dog", - "domains", - "dot", - "download", - "drive", - "dtv", - "dubai", - "duck", - "dunlop", - "duns", - "dupont", - "durban", - "dvag", - "dvr", - "earth", - "eat", - "eco", - "edeka", - "education", - "email", - "emerck", - "energy", - "engineer", - "engineering", - "enterprises", - "epson", - "equipment", - "ericsson", - "erni", - "esq", - "estate", - "esurance", - "etisalat", - "eurovision", - "eus", - "events", - "everbank", - "exchange", - "expert", - "exposed", - "express", - "extraspace", - "fage", - "fail", - "fairwinds", - "faith", - "family", - "fan", - "fans", - "farm", - "farmers", - "fashion", - "fast", - "fedex", - "feedback", - "ferrari", - "ferrero", - "fiat", - "fidelity", - "fido", - "film", - "final", - "finance", - "financial", - "fire", - "firestone", - "firmdale", - "fish", - "fishing", - "fit", - "fitness", - "flickr", - "flights", - "flir", - "florist", - "flowers", - "fly", - "foo", - "food", - "foodnetwork", - "football", - "ford", - "forex", - "forsale", - "forum", - "foundation", - "fox", - "free", - "fresenius", - "frl", - "frogans", - "frontdoor", - "frontier", - "ftr", - "fujitsu", - "fujixerox", - "fun", - "fund", - "furniture", - "futbol", - "fyi", - "gal", - "gallery", - "gallo", - "gallup", - "game", - "games", - "gap", - "garden", - "gbiz", - "gdn", - "gea", - "gent", - "genting", - "george", - "ggee", - "gift", - "gifts", - "gives", - "giving", - "glade", - "glass", - "gle", - "global", - "globo", - "gmail", - "gmbh", - "gmo", - "gmx", - "godaddy", - "gold", - "goldpoint", - "golf", - "goo", - "goodyear", - "goog", - "google", - "gop", - "got", - "grainger", - "graphics", - "gratis", - "green", - "gripe", - "grocery", - "group", - "guardian", - "gucci", - "guge", - "guide", - "guitars", - "guru", - "hair", - "hamburg", - "hangout", - "haus", - "hbo", - "hdfc", - "hdfcbank", - "health", - "healthcare", - "help", - "helsinki", - "here", - "hermes", - "hgtv", - "hiphop", - "hisamitsu", - "hitachi", - "hiv", - "hkt", - "hockey", - "holdings", - "holiday", - "homedepot", - "homegoods", - "homes", - "homesense", - "honda", - "honeywell", - "horse", - "hospital", - "host", - "hosting", - "hot", - "hoteles", - "hotels", - "hotmail", - "house", - "how", - "hsbc", - "hughes", - "hyatt", - "hyundai", - "ibm", - "icbc", - "ice", - "icu", - "ieee", - "ifm", - "ikano", - "imamat", - "imdb", - "immo", - "immobilien", - "inc", - "industries", - "infiniti", - "ing", - "ink", - "institute", - "insurance", - "insure", - "intel", - "international", - "intuit", - "investments", - "ipiranga", - "irish", - "iselect", - "ismaili", - "ist", - "istanbul", - "itau", - "itv", - "iveco", - "jaguar", - "java", - "jcb", - "jcp", - "jeep", - "jetzt", - "jewelry", - "jio", - "jll", - "jmp", - "jnj", - "joburg", - "jot", - "joy", - "jpmorgan", - "jprs", - "juegos", - "juniper", - "kaufen", - "kddi", - "kerryhotels", - "kerrylogistics", - "kerryproperties", - "kfh", - "kia", - "kim", - "kinder", - "kindle", - "kitchen", - "kiwi", - "koeln", - "komatsu", - "kosher", - "kpmg", - "kpn", - "krd", - "kred", - "kuokgroup", - "kyoto", - "lacaixa", - "ladbrokes", - "lamborghini", - "lamer", - "lancaster", - "lancia", - "lancome", - "land", - "landrover", - "lanxess", - "lasalle", - "lat", - "latino", - "latrobe", - "law", - "lawyer", - "lds", - "lease", - "leclerc", - "lefrak", - "legal", - "lego", - "lexus", - "lgbt", - "liaison", - "lidl", - "life", - "lifeinsurance", - "lifestyle", - "lighting", - "like", - "lilly", - "limited", - "limo", - "lincoln", - "linde", - "link", - "lipsy", - "live", - "living", - "lixil", - "llc", - "loan", - "loans", - "locker", - "locus", - "loft", - "lol", - "london", - "lotte", - "lotto", - "love", - "lpl", - "lplfinancial", - "ltd", - "ltda", - "lundbeck", - "lupin", - "luxe", - "luxury", - "macys", - "madrid", - "maif", - "maison", - "makeup", - "man", - "management", - "mango", - "map", - "market", - "marketing", - "markets", - "marriott", - "marshalls", - "maserati", - "mattel", - "mba", - "mckinsey", - "med", - "media", - "meet", - "melbourne", - "meme", - "memorial", - "men", - "menu", - "merckmsd", - "metlife", - "miami", - "microsoft", - "mini", - "mint", - "mit", - "mitsubishi", - "mlb", - "mls", - "mma", - "mobile", - "mobily", - "moda", - "moe", - "moi", - "mom", - "monash", - "money", - "monster", - "mopar", - "mormon", - "mortgage", - "moscow", - "moto", - "motorcycles", - "mov", - "movie", - "movistar", - "msd", - "mtn", - "mtr", - "mutual", - "nab", - "nadex", - "nagoya", - "nationwide", - "natura", - "navy", - "nba", - "nec", - "netbank", - "netflix", - "network", - "neustar", - "new", - "newholland", - "news", - "next", - "nextdirect", - "nexus", - "nfl", - "ngo", - "nhk", - "nico", - "nike", - "nikon", - "ninja", - "nissan", - "nissay", - "nokia", - "northwesternmutual", - "norton", - "now", - "nowruz", - "nowtv", - "nra", - "nrw", - "ntt", - "nyc", - "obi", - "observer", - "off", - "office", - "okinawa", - "olayan", - "olayangroup", - "oldnavy", - "ollo", - "omega", - "one", - "ong", - "onl", - "online", - "onyourside", - "ooo", - "open", - "oracle", - "orange", - "organic", - "origins", - "osaka", - "otsuka", - "ott", - "ovh", - "page", - "panasonic", - "paris", - "pars", - "partners", - "parts", - "party", - "passagens", - "pay", - "pccw", - "pet", - "pfizer", - "pharmacy", - "phd", - "philips", - "phone", - "photo", - "photography", - "photos", - "physio", - "piaget", - "pics", - "pictet", - "pictures", - "pid", - "pin", - "ping", - "pink", - "pioneer", - "pizza", - "place", - "play", - "playstation", - "plumbing", - "plus", - "pnc", - "pohl", - "poker", - "politie", - "porn", - "pramerica", - "praxi", - "press", - "prime", - "prod", - "productions", - "prof", - "progressive", - "promo", - "properties", - "property", - "protection", - "pru", - "prudential", - "pub", - "pwc", - "qpon", - "quebec", - "quest", - "qvc", - "racing", - "radio", - "raid", - "read", - "realestate", - "realtor", - "realty", - "recipes", - "red", - "redstone", - "redumbrella", - "rehab", - "reise", - "reisen", - "reit", - "reliance", - "ren", - "rent", - "rentals", - "repair", - "report", - "republican", - "rest", - "restaurant", - "review", - "reviews", - "rexroth", - "rich", - "richardli", - "ricoh", - "rightathome", - "ril", - "rio", - "rip", - "rmit", - "rocher", - "rocks", - "rodeo", - "rogers", - "room", - "rsvp", - "rugby", - "ruhr", - "run", - "rwe", - "ryukyu", - "saarland", - "safe", - "safety", - "sakura", - "sale", - "salon", - "samsclub", - "samsung", - "sandvik", - "sandvikcoromant", - "sanofi", - "sap", - "sarl", - "sas", - "save", - "saxo", - "sbi", - "sbs", - "sca", - "scb", - "schaeffler", - "schmidt", - "scholarships", - "school", - "schule", - "schwarz", - "science", - "scjohnson", - "scor", - "scot", - "search", - "seat", - "secure", - "security", - "seek", - "select", - "sener", - "services", - "ses", - "seven", - "sew", - "sex", - "sexy", - "sfr", - "shangrila", - "sharp", - "shaw", - "shell", - "shia", - "shiksha", - "shoes", - "shop", - "shopping", - "shouji", - "show", - "showtime", - "shriram", - "silk", - "sina", - "singles", - "site", - "ski", - "skin", - "sky", - "skype", - "sling", - "smart", - "smile", - "sncf", - "soccer", - "social", - "softbank", - "software", - "sohu", - "solar", - "solutions", - "song", - "sony", - "soy", - "space", - "sport", - "spot", - "spreadbetting", - "srl", - "srt", - "stada", - "staples", - "star", - "starhub", - "statebank", - "statefarm", - "stc", - "stcgroup", - "stockholm", - "storage", - "store", - "stream", - "studio", - "study", - "style", - "sucks", - "supplies", - "supply", - "support", - "surf", - "surgery", - "suzuki", - "swatch", - "swiftcover", - "swiss", - "sydney", - "symantec", - "systems", - "tab", - "taipei", - "talk", - "taobao", - "target", - "tatamotors", - "tatar", - "tattoo", - "tax", - "taxi", - "tci", - "tdk", - "team", - "tech", - "technology", - "telefonica", - "temasek", - "tennis", - "teva", - "thd", - "theater", - "theatre", - "tiaa", - "tickets", - "tienda", - "tiffany", - "tips", - "tires", - "tirol", - "tjmaxx", - "tjx", - "tkmaxx", - "tmall", - "today", - "tokyo", - "tools", - "top", - "toray", - "toshiba", - "total", - "tours", - "town", - "toyota", - "toys", - "trade", - "trading", - "training", - "travel", - "travelchannel", - "travelers", - "travelersinsurance", - "trust", - "trv", - "tube", - "tui", - "tunes", - "tushu", - "tvs", - "ubank", - "ubs", - "uconnect", - "unicom", - "university", - "uno", - "uol", - "ups", - "vacations", - "vana", - "vanguard", - "vegas", - "ventures", - "verisign", - "versicherung", - "vet", - "viajes", - "video", - "vig", - "viking", - "villas", - "vin", - "vip", - "virgin", - "visa", - "vision", - "vistaprint", - "viva", - "vivo", - "vlaanderen", - "vodka", - "volkswagen", - "volvo", - "vote", - "voting", - "voto", - "voyage", - "vuelos", - "wales", - "walmart", - "walter", - "wang", - "wanggou", - "warman", - "watch", - "watches", - "weather", - "weatherchannel", - "webcam", - "weber", - "website", - "wed", - "wedding", - "weibo", - "weir", - "whoswho", - "wien", - "wiki", - "williamhill", - "win", - "windows", - "wine", - "winners", - "wme", - "wolterskluwer", - "woodside", - "work", - "works", - "world", - "wow", - "wtc", - "wtf", - "xbox", - "xerox", - "xfinity", - "xihuan", - "xin", - "xn--11b4c3d", - "xn--1ck2e1b", - "xn--1qqw23a", - "xn--30rr7y", - "xn--3bst00m", - "xn--3ds443g", - "xn--3oq18vl8pn36a", - "xn--3pxu8k", - "xn--42c2d9a", - "xn--45q11c", - "xn--4gbrim", - "xn--55qw42g", - "xn--55qx5d", - "xn--5su34j936bgsg", - "xn--5tzm5g", - "xn--6frz82g", - "xn--6qq986b3xl", - "xn--80adxhks", - "xn--80aqecdr1a", - "xn--80asehdb", - "xn--80aswg", - "xn--8y0a063a", - "xn--9dbq2a", - "xn--9et52u", - "xn--9krt00a", - "xn--b4w605ferd", - "xn--bck1b9a5dre4c", - "xn--c1avg", - "xn--c2br7g", - "xn--cck2b3b", - "xn--cg4bki", - "xn--czr694b", - "xn--czrs0t", - "xn--czru2d", - "xn--d1acj3b", - "xn--eckvdtc9d", - "xn--efvy88h", - "xn--estv75g", - "xn--fct429k", - "xn--fhbei", - "xn--fiq228c5hs", - "xn--fiq64b", - "xn--fjq720a", - "xn--flw351e", - "xn--fzys8d69uvgm", - "xn--g2xx48c", - "xn--gckr3f0f", - "xn--gk3at1e", - "xn--hxt814e", - "xn--i1b6b1a6a2e", - "xn--imr513n", - "xn--io0a7i", - "xn--j1aef", - "xn--jlq61u9w7b", - "xn--jvr189m", - "xn--kcrx77d1x4a", - "xn--kpu716f", - "xn--kput3i", - "xn--mgba3a3ejt", - "xn--mgba7c0bbn0a", - "xn--mgbaakc7dvf", - "xn--mgbab2bd", - "xn--mgbb9fbpob", - "xn--mgbca7dzdo", - "xn--mgbi4ecexp", - "xn--mgbt3dhd", - "xn--mk1bu44c", - "xn--mxtq1m", - "xn--ngbc5azd", - "xn--ngbe9e0a", - "xn--ngbrx", - "xn--nqv7f", - "xn--nqv7fs00ema", - "xn--nyqy26a", - "xn--otu796d", - "xn--p1acf", - "xn--pbt977c", - "xn--pssy2u", - "xn--q9jyb4c", - "xn--qcka1pmc", - "xn--rhqv96g", - "xn--rovu88b", - "xn--ses554g", - "xn--t60b56a", - "xn--tckwe", - "xn--tiq49xqyj", - "xn--unup4y", - "xn--vermgensberater-ctb", - "xn--vermgensberatung-pwb", - "xn--vhquv", - "xn--vuq861b", - "xn--w4r85el8fhu5dnra", - "xn--w4rs40l", - "xn--xhq521b", - "xn--zfr164b", - "xyz", - "yachts", - "yahoo", - "yamaxun", - "yandex", - "yodobashi", - "yoga", - "yokohama", - "you", - "youtube", - "yun", - "zappos", - "zara", - "zero", - "zip", - "zone", - "zuerich", - "cc.ua", - "inf.ua", - "ltd.ua", - "beep.pl", - "barsy.ca", - "*.compute.estate", - "*.alces.network", - "alwaysdata.net", - "cloudfront.net", - "*.compute.amazonaws.com", - "*.compute-1.amazonaws.com", - "*.compute.amazonaws.com.cn", - "us-east-1.amazonaws.com", - "cn-north-1.eb.amazonaws.com.cn", - "cn-northwest-1.eb.amazonaws.com.cn", - "elasticbeanstalk.com", - "ap-northeast-1.elasticbeanstalk.com", - "ap-northeast-2.elasticbeanstalk.com", - "ap-northeast-3.elasticbeanstalk.com", - "ap-south-1.elasticbeanstalk.com", - "ap-southeast-1.elasticbeanstalk.com", - "ap-southeast-2.elasticbeanstalk.com", - "ca-central-1.elasticbeanstalk.com", - "eu-central-1.elasticbeanstalk.com", - "eu-west-1.elasticbeanstalk.com", - "eu-west-2.elasticbeanstalk.com", - "eu-west-3.elasticbeanstalk.com", - "sa-east-1.elasticbeanstalk.com", - "us-east-1.elasticbeanstalk.com", - "us-east-2.elasticbeanstalk.com", - "us-gov-west-1.elasticbeanstalk.com", - "us-west-1.elasticbeanstalk.com", - "us-west-2.elasticbeanstalk.com", - "*.elb.amazonaws.com", - "*.elb.amazonaws.com.cn", - "s3.amazonaws.com", - "s3-ap-northeast-1.amazonaws.com", - "s3-ap-northeast-2.amazonaws.com", - "s3-ap-south-1.amazonaws.com", - "s3-ap-southeast-1.amazonaws.com", - "s3-ap-southeast-2.amazonaws.com", - "s3-ca-central-1.amazonaws.com", - "s3-eu-central-1.amazonaws.com", - "s3-eu-west-1.amazonaws.com", - "s3-eu-west-2.amazonaws.com", - "s3-eu-west-3.amazonaws.com", - "s3-external-1.amazonaws.com", - "s3-fips-us-gov-west-1.amazonaws.com", - "s3-sa-east-1.amazonaws.com", - "s3-us-gov-west-1.amazonaws.com", - "s3-us-east-2.amazonaws.com", - "s3-us-west-1.amazonaws.com", - "s3-us-west-2.amazonaws.com", - "s3.ap-northeast-2.amazonaws.com", - "s3.ap-south-1.amazonaws.com", - "s3.cn-north-1.amazonaws.com.cn", - "s3.ca-central-1.amazonaws.com", - "s3.eu-central-1.amazonaws.com", - "s3.eu-west-2.amazonaws.com", - "s3.eu-west-3.amazonaws.com", - "s3.us-east-2.amazonaws.com", - "s3.dualstack.ap-northeast-1.amazonaws.com", - "s3.dualstack.ap-northeast-2.amazonaws.com", - "s3.dualstack.ap-south-1.amazonaws.com", - "s3.dualstack.ap-southeast-1.amazonaws.com", - "s3.dualstack.ap-southeast-2.amazonaws.com", - "s3.dualstack.ca-central-1.amazonaws.com", - "s3.dualstack.eu-central-1.amazonaws.com", - "s3.dualstack.eu-west-1.amazonaws.com", - "s3.dualstack.eu-west-2.amazonaws.com", - "s3.dualstack.eu-west-3.amazonaws.com", - "s3.dualstack.sa-east-1.amazonaws.com", - "s3.dualstack.us-east-1.amazonaws.com", - "s3.dualstack.us-east-2.amazonaws.com", - "s3-website-us-east-1.amazonaws.com", - "s3-website-us-west-1.amazonaws.com", - "s3-website-us-west-2.amazonaws.com", - "s3-website-ap-northeast-1.amazonaws.com", - "s3-website-ap-southeast-1.amazonaws.com", - "s3-website-ap-southeast-2.amazonaws.com", - "s3-website-eu-west-1.amazonaws.com", - "s3-website-sa-east-1.amazonaws.com", - "s3-website.ap-northeast-2.amazonaws.com", - "s3-website.ap-south-1.amazonaws.com", - "s3-website.ca-central-1.amazonaws.com", - "s3-website.eu-central-1.amazonaws.com", - "s3-website.eu-west-2.amazonaws.com", - "s3-website.eu-west-3.amazonaws.com", - "s3-website.us-east-2.amazonaws.com", - "t3l3p0rt.net", - "tele.amune.org", - "apigee.io", - "on-aptible.com", - "user.party.eus", - "pimienta.org", - "poivron.org", - "potager.org", - "sweetpepper.org", - "myasustor.com", - "go-vip.co", - "go-vip.net", - "wpcomstaging.com", - "myfritz.net", - "*.awdev.ca", - "*.advisor.ws", - "b-data.io", - "backplaneapp.io", - "balena-devices.com", - "app.banzaicloud.io", - "betainabox.com", - "bnr.la", - "blackbaudcdn.net", - "boomla.net", - "boxfuse.io", - "square7.ch", - "bplaced.com", - "bplaced.de", - "square7.de", - "bplaced.net", - "square7.net", - "browsersafetymark.io", - "uk0.bigv.io", - "dh.bytemark.co.uk", - "vm.bytemark.co.uk", - "mycd.eu", - "carrd.co", - "crd.co", - "uwu.ai", - "ae.org", - "ar.com", - "br.com", - "cn.com", - "com.de", - "com.se", - "de.com", - "eu.com", - "gb.com", - "gb.net", - "hu.com", - "hu.net", - "jp.net", - "jpn.com", - "kr.com", - "mex.com", - "no.com", - "qc.com", - "ru.com", - "sa.com", - "se.net", - "uk.com", - "uk.net", - "us.com", - "uy.com", - "za.bz", - "za.com", - "africa.com", - "gr.com", - "in.net", - "us.org", - "co.com", - "c.la", - "certmgr.org", - "xenapponazure.com", - "discourse.group", - "virtueeldomein.nl", - "cleverapps.io", - "*.lcl.dev", - "*.stg.dev", - "c66.me", - "cloud66.ws", - "cloud66.zone", - "jdevcloud.com", - "wpdevcloud.com", - "cloudaccess.host", - "freesite.host", - "cloudaccess.net", - "cloudcontrolled.com", - "cloudcontrolapp.com", - "cloudera.site", - "workers.dev", - "wnext.app", - "co.ca", - "*.otap.co", - "co.cz", - "c.cdn77.org", - "cdn77-ssl.net", - "r.cdn77.net", - "rsc.cdn77.org", - "ssl.origin.cdn77-secure.org", - "cloudns.asia", - "cloudns.biz", - "cloudns.club", - "cloudns.cc", - "cloudns.eu", - "cloudns.in", - "cloudns.info", - "cloudns.org", - "cloudns.pro", - "cloudns.pw", - "cloudns.us", - "cloudeity.net", - "cnpy.gdn", - "co.nl", - "co.no", - "webhosting.be", - "hosting-cluster.nl", - "dyn.cosidns.de", - "dynamisches-dns.de", - "dnsupdater.de", - "internet-dns.de", - "l-o-g-i-n.de", - "dynamic-dns.info", - "feste-ip.net", - "knx-server.net", - "static-access.net", - "realm.cz", - "*.cryptonomic.net", - "cupcake.is", - "cyon.link", - "cyon.site", - "daplie.me", - "localhost.daplie.me", - "dattolocal.com", - "dattorelay.com", - "dattoweb.com", - "mydatto.com", - "dattolocal.net", - "mydatto.net", - "biz.dk", - "co.dk", - "firm.dk", - "reg.dk", - "store.dk", - "*.dapps.earth", - "*.bzz.dapps.earth", - "debian.net", - "dedyn.io", - "dnshome.de", - "online.th", - "shop.th", - "drayddns.com", - "dreamhosters.com", - "mydrobo.com", - "drud.io", - "drud.us", - "duckdns.org", - "dy.fi", - "tunk.org", - "dyndns-at-home.com", - "dyndns-at-work.com", - "dyndns-blog.com", - "dyndns-free.com", - "dyndns-home.com", - "dyndns-ip.com", - "dyndns-mail.com", - "dyndns-office.com", - "dyndns-pics.com", - "dyndns-remote.com", - "dyndns-server.com", - "dyndns-web.com", - "dyndns-wiki.com", - "dyndns-work.com", - "dyndns.biz", - "dyndns.info", - "dyndns.org", - "dyndns.tv", - "at-band-camp.net", - "ath.cx", - "barrel-of-knowledge.info", - "barrell-of-knowledge.info", - "better-than.tv", - "blogdns.com", - "blogdns.net", - "blogdns.org", - "blogsite.org", - "boldlygoingnowhere.org", - "broke-it.net", - "buyshouses.net", - "cechire.com", - "dnsalias.com", - "dnsalias.net", - "dnsalias.org", - "dnsdojo.com", - "dnsdojo.net", - "dnsdojo.org", - "does-it.net", - "doesntexist.com", - "doesntexist.org", - "dontexist.com", - "dontexist.net", - "dontexist.org", - "doomdns.com", - "doomdns.org", - "dvrdns.org", - "dyn-o-saur.com", - "dynalias.com", - "dynalias.net", - "dynalias.org", - "dynathome.net", - "dyndns.ws", - "endofinternet.net", - "endofinternet.org", - "endoftheinternet.org", - "est-a-la-maison.com", - "est-a-la-masion.com", - "est-le-patron.com", - "est-mon-blogueur.com", - "for-better.biz", - "for-more.biz", - "for-our.info", - "for-some.biz", - "for-the.biz", - "forgot.her.name", - "forgot.his.name", - "from-ak.com", - "from-al.com", - "from-ar.com", - "from-az.net", - "from-ca.com", - "from-co.net", - "from-ct.com", - "from-dc.com", - "from-de.com", - "from-fl.com", - "from-ga.com", - "from-hi.com", - "from-ia.com", - "from-id.com", - "from-il.com", - "from-in.com", - "from-ks.com", - "from-ky.com", - "from-la.net", - "from-ma.com", - "from-md.com", - "from-me.org", - "from-mi.com", - "from-mn.com", - "from-mo.com", - "from-ms.com", - "from-mt.com", - "from-nc.com", - "from-nd.com", - "from-ne.com", - "from-nh.com", - "from-nj.com", - "from-nm.com", - "from-nv.com", - "from-ny.net", - "from-oh.com", - "from-ok.com", - "from-or.com", - "from-pa.com", - "from-pr.com", - "from-ri.com", - "from-sc.com", - "from-sd.com", - "from-tn.com", - "from-tx.com", - "from-ut.com", - "from-va.com", - "from-vt.com", - "from-wa.com", - "from-wi.com", - "from-wv.com", - "from-wy.com", - "ftpaccess.cc", - "fuettertdasnetz.de", - "game-host.org", - "game-server.cc", - "getmyip.com", - "gets-it.net", - "go.dyndns.org", - "gotdns.com", - "gotdns.org", - "groks-the.info", - "groks-this.info", - "ham-radio-op.net", - "here-for-more.info", - "hobby-site.com", - "hobby-site.org", - "home.dyndns.org", - "homedns.org", - "homeftp.net", - "homeftp.org", - "homeip.net", - "homelinux.com", - "homelinux.net", - "homelinux.org", - "homeunix.com", - "homeunix.net", - "homeunix.org", - "iamallama.com", - "in-the-band.net", - "is-a-anarchist.com", - "is-a-blogger.com", - "is-a-bookkeeper.com", - "is-a-bruinsfan.org", - "is-a-bulls-fan.com", - "is-a-candidate.org", - "is-a-caterer.com", - "is-a-celticsfan.org", - "is-a-chef.com", - "is-a-chef.net", - "is-a-chef.org", - "is-a-conservative.com", - "is-a-cpa.com", - "is-a-cubicle-slave.com", - "is-a-democrat.com", - "is-a-designer.com", - "is-a-doctor.com", - "is-a-financialadvisor.com", - "is-a-geek.com", - "is-a-geek.net", - "is-a-geek.org", - "is-a-green.com", - "is-a-guru.com", - "is-a-hard-worker.com", - "is-a-hunter.com", - "is-a-knight.org", - "is-a-landscaper.com", - "is-a-lawyer.com", - "is-a-liberal.com", - "is-a-libertarian.com", - "is-a-linux-user.org", - "is-a-llama.com", - "is-a-musician.com", - "is-a-nascarfan.com", - "is-a-nurse.com", - "is-a-painter.com", - "is-a-patsfan.org", - "is-a-personaltrainer.com", - "is-a-photographer.com", - "is-a-player.com", - "is-a-republican.com", - "is-a-rockstar.com", - "is-a-socialist.com", - "is-a-soxfan.org", - "is-a-student.com", - "is-a-teacher.com", - "is-a-techie.com", - "is-a-therapist.com", - "is-an-accountant.com", - "is-an-actor.com", - "is-an-actress.com", - "is-an-anarchist.com", - "is-an-artist.com", - "is-an-engineer.com", - "is-an-entertainer.com", - "is-by.us", - "is-certified.com", - "is-found.org", - "is-gone.com", - "is-into-anime.com", - "is-into-cars.com", - "is-into-cartoons.com", - "is-into-games.com", - "is-leet.com", - "is-lost.org", - "is-not-certified.com", - "is-saved.org", - "is-slick.com", - "is-uberleet.com", - "is-very-bad.org", - "is-very-evil.org", - "is-very-good.org", - "is-very-nice.org", - "is-very-sweet.org", - "is-with-theband.com", - "isa-geek.com", - "isa-geek.net", - "isa-geek.org", - "isa-hockeynut.com", - "issmarterthanyou.com", - "isteingeek.de", - "istmein.de", - "kicks-ass.net", - "kicks-ass.org", - "knowsitall.info", - "land-4-sale.us", - "lebtimnetz.de", - "leitungsen.de", - "likes-pie.com", - "likescandy.com", - "merseine.nu", - "mine.nu", - "misconfused.org", - "mypets.ws", - "myphotos.cc", - "neat-url.com", - "office-on-the.net", - "on-the-web.tv", - "podzone.net", - "podzone.org", - "readmyblog.org", - "saves-the-whales.com", - "scrapper-site.net", - "scrapping.cc", - "selfip.biz", - "selfip.com", - "selfip.info", - "selfip.net", - "selfip.org", - "sells-for-less.com", - "sells-for-u.com", - "sells-it.net", - "sellsyourhome.org", - "servebbs.com", - "servebbs.net", - "servebbs.org", - "serveftp.net", - "serveftp.org", - "servegame.org", - "shacknet.nu", - "simple-url.com", - "space-to-rent.com", - "stuff-4-sale.org", - "stuff-4-sale.us", - "teaches-yoga.com", - "thruhere.net", - "traeumtgerade.de", - "webhop.biz", - "webhop.info", - "webhop.net", - "webhop.org", - "worse-than.tv", - "writesthisblog.com", - "ddnss.de", - "dyn.ddnss.de", - "dyndns.ddnss.de", - "dyndns1.de", - "dyn-ip24.de", - "home-webserver.de", - "dyn.home-webserver.de", - "myhome-server.de", - "ddnss.org", - "definima.net", - "definima.io", - "bci.dnstrace.pro", - "ddnsfree.com", - "ddnsgeek.com", - "giize.com", - "gleeze.com", - "kozow.com", - "loseyourip.com", - "ooguy.com", - "theworkpc.com", - "casacam.net", - "dynu.net", - "accesscam.org", - "camdvr.org", - "freeddns.org", - "mywire.org", - "webredirect.org", - "myddns.rocks", - "blogsite.xyz", - "dynv6.net", - "e4.cz", - "mytuleap.com", - "onred.one", - "staging.onred.one", - "enonic.io", - "customer.enonic.io", - "eu.org", - "al.eu.org", - "asso.eu.org", - "at.eu.org", - "au.eu.org", - "be.eu.org", - "bg.eu.org", - "ca.eu.org", - "cd.eu.org", - "ch.eu.org", - "cn.eu.org", - "cy.eu.org", - "cz.eu.org", - "de.eu.org", - "dk.eu.org", - "edu.eu.org", - "ee.eu.org", - "es.eu.org", - "fi.eu.org", - "fr.eu.org", - "gr.eu.org", - "hr.eu.org", - "hu.eu.org", - "ie.eu.org", - "il.eu.org", - "in.eu.org", - "int.eu.org", - "is.eu.org", - "it.eu.org", - "jp.eu.org", - "kr.eu.org", - "lt.eu.org", - "lu.eu.org", - "lv.eu.org", - "mc.eu.org", - "me.eu.org", - "mk.eu.org", - "mt.eu.org", - "my.eu.org", - "net.eu.org", - "ng.eu.org", - "nl.eu.org", - "no.eu.org", - "nz.eu.org", - "paris.eu.org", - "pl.eu.org", - "pt.eu.org", - "q-a.eu.org", - "ro.eu.org", - "ru.eu.org", - "se.eu.org", - "si.eu.org", - "sk.eu.org", - "tr.eu.org", - "uk.eu.org", - "us.eu.org", - "eu-1.evennode.com", - "eu-2.evennode.com", - "eu-3.evennode.com", - "eu-4.evennode.com", - "us-1.evennode.com", - "us-2.evennode.com", - "us-3.evennode.com", - "us-4.evennode.com", - "twmail.cc", - "twmail.net", - "twmail.org", - "mymailer.com.tw", - "url.tw", - "apps.fbsbx.com", - "ru.net", - "adygeya.ru", - "bashkiria.ru", - "bir.ru", - "cbg.ru", - "com.ru", - "dagestan.ru", - "grozny.ru", - "kalmykia.ru", - "kustanai.ru", - "marine.ru", - "mordovia.ru", - "msk.ru", - "mytis.ru", - "nalchik.ru", - "nov.ru", - "pyatigorsk.ru", - "spb.ru", - "vladikavkaz.ru", - "vladimir.ru", - "abkhazia.su", - "adygeya.su", - "aktyubinsk.su", - "arkhangelsk.su", - "armenia.su", - "ashgabad.su", - "azerbaijan.su", - "balashov.su", - "bashkiria.su", - "bryansk.su", - "bukhara.su", - "chimkent.su", - "dagestan.su", - "east-kazakhstan.su", - "exnet.su", - "georgia.su", - "grozny.su", - "ivanovo.su", - "jambyl.su", - "kalmykia.su", - "kaluga.su", - "karacol.su", - "karaganda.su", - "karelia.su", - "khakassia.su", - "krasnodar.su", - "kurgan.su", - "kustanai.su", - "lenug.su", - "mangyshlak.su", - "mordovia.su", - "msk.su", - "murmansk.su", - "nalchik.su", - "navoi.su", - "north-kazakhstan.su", - "nov.su", - "obninsk.su", - "penza.su", - "pokrovsk.su", - "sochi.su", - "spb.su", - "tashkent.su", - "termez.su", - "togliatti.su", - "troitsk.su", - "tselinograd.su", - "tula.su", - "tuva.su", - "vladikavkaz.su", - "vladimir.su", - "vologda.su", - "channelsdvr.net", - "fastly-terrarium.com", - "fastlylb.net", - "map.fastlylb.net", - "freetls.fastly.net", - "map.fastly.net", - "a.prod.fastly.net", - "global.prod.fastly.net", - "a.ssl.fastly.net", - "b.ssl.fastly.net", - "global.ssl.fastly.net", - "fastpanel.direct", - "fastvps-server.com", - "fhapp.xyz", - "fedorainfracloud.org", - "fedorapeople.org", - "cloud.fedoraproject.org", - "app.os.fedoraproject.org", - "app.os.stg.fedoraproject.org", - "mydobiss.com", - "filegear.me", - "filegear-au.me", - "filegear-de.me", - "filegear-gb.me", - "filegear-ie.me", - "filegear-jp.me", - "filegear-sg.me", - "firebaseapp.com", - "flynnhub.com", - "flynnhosting.net", - "freebox-os.com", - "freeboxos.com", - "fbx-os.fr", - "fbxos.fr", - "freebox-os.fr", - "freeboxos.fr", - "freedesktop.org", - "*.futurecms.at", - "*.ex.futurecms.at", - "*.in.futurecms.at", - "futurehosting.at", - "futuremailing.at", - "*.ex.ortsinfo.at", - "*.kunden.ortsinfo.at", - "*.statics.cloud", - "service.gov.uk", - "gehirn.ne.jp", - "usercontent.jp", - "lab.ms", - "github.io", - "githubusercontent.com", - "gitlab.io", - "glitch.me", - "cloudapps.digital", - "london.cloudapps.digital", - "homeoffice.gov.uk", - "ro.im", - "shop.ro", - "goip.de", - "run.app", - "a.run.app", - "web.app", - "*.0emm.com", - "appspot.com", - "blogspot.ae", - "blogspot.al", - "blogspot.am", - "blogspot.ba", - "blogspot.be", - "blogspot.bg", - "blogspot.bj", - "blogspot.ca", - "blogspot.cf", - "blogspot.ch", - "blogspot.cl", - "blogspot.co.at", - "blogspot.co.id", - "blogspot.co.il", - "blogspot.co.ke", - "blogspot.co.nz", - "blogspot.co.uk", - "blogspot.co.za", - "blogspot.com", - "blogspot.com.ar", - "blogspot.com.au", - "blogspot.com.br", - "blogspot.com.by", - "blogspot.com.co", - "blogspot.com.cy", - "blogspot.com.ee", - "blogspot.com.eg", - "blogspot.com.es", - "blogspot.com.mt", - "blogspot.com.ng", - "blogspot.com.tr", - "blogspot.com.uy", - "blogspot.cv", - "blogspot.cz", - "blogspot.de", - "blogspot.dk", - "blogspot.fi", - "blogspot.fr", - "blogspot.gr", - "blogspot.hk", - "blogspot.hr", - "blogspot.hu", - "blogspot.ie", - "blogspot.in", - "blogspot.is", - "blogspot.it", - "blogspot.jp", - "blogspot.kr", - "blogspot.li", - "blogspot.lt", - "blogspot.lu", - "blogspot.md", - "blogspot.mk", - "blogspot.mr", - "blogspot.mx", - "blogspot.my", - "blogspot.nl", - "blogspot.no", - "blogspot.pe", - "blogspot.pt", - "blogspot.qa", - "blogspot.re", - "blogspot.ro", - "blogspot.rs", - "blogspot.ru", - "blogspot.se", - "blogspot.sg", - "blogspot.si", - "blogspot.sk", - "blogspot.sn", - "blogspot.td", - "blogspot.tw", - "blogspot.ug", - "blogspot.vn", - "cloudfunctions.net", - "cloud.goog", - "codespot.com", - "googleapis.com", - "googlecode.com", - "pagespeedmobilizer.com", - "publishproxy.com", - "withgoogle.com", - "withyoutube.com", - "fin.ci", - "free.hr", - "caa.li", - "ua.rs", - "conf.se", - "hashbang.sh", - "hasura.app", - "hasura-app.io", - "hepforge.org", - "herokuapp.com", - "herokussl.com", - "myravendb.com", - "ravendb.community", - "ravendb.me", - "development.run", - "ravendb.run", - "bpl.biz", - "orx.biz", - "ng.city", - "ng.ink", - "biz.gl", - "col.ng", - "gen.ng", - "ltd.ng", - "sch.so", - "xn--hkkinen-5wa.fi", - "*.moonscale.io", - "moonscale.net", - "iki.fi", - "dyn-berlin.de", - "in-berlin.de", - "in-brb.de", - "in-butter.de", - "in-dsl.de", - "in-dsl.net", - "in-dsl.org", - "in-vpn.de", - "in-vpn.net", - "in-vpn.org", - "biz.at", - "info.at", - "info.cx", - "ac.leg.br", - "al.leg.br", - "am.leg.br", - "ap.leg.br", - "ba.leg.br", - "ce.leg.br", - "df.leg.br", - "es.leg.br", - "go.leg.br", - "ma.leg.br", - "mg.leg.br", - "ms.leg.br", - "mt.leg.br", - "pa.leg.br", - "pb.leg.br", - "pe.leg.br", - "pi.leg.br", - "pr.leg.br", - "rj.leg.br", - "rn.leg.br", - "ro.leg.br", - "rr.leg.br", - "rs.leg.br", - "sc.leg.br", - "se.leg.br", - "sp.leg.br", - "to.leg.br", - "pixolino.com", - "ipifony.net", - "mein-iserv.de", - "test-iserv.de", - "iobb.net", - "myjino.ru", - "*.hosting.myjino.ru", - "*.landing.myjino.ru", - "*.spectrum.myjino.ru", - "*.vps.myjino.ru", - "*.triton.zone", - "*.cns.joyent.com", - "js.org", - "kaas.gg", - "khplay.nl", - "keymachine.de", - "kinghost.net", - "uni5.net", - "knightpoint.systems", - "co.krd", - "edu.krd", - "git-repos.de", - "lcube-server.de", - "svn-repos.de", - "leadpages.co", - "lpages.co", - "lpusercontent.com", - "co.business", - "co.education", - "co.events", - "co.financial", - "co.network", - "co.place", - "co.technology", - "app.lmpm.com", - "linkitools.space", - "linkyard.cloud", - "linkyard-cloud.ch", - "members.linode.com", - "nodebalancer.linode.com", - "we.bs", - "loginline.app", - "loginline.dev", - "loginline.io", - "loginline.services", - "loginline.site", - "krasnik.pl", - "leczna.pl", - "lubartow.pl", - "lublin.pl", - "poniatowa.pl", - "swidnik.pl", - "uklugs.org", - "glug.org.uk", - "lug.org.uk", - "lugs.org.uk", - "barsy.bg", - "barsy.co.uk", - "barsyonline.co.uk", - "barsycenter.com", - "barsyonline.com", - "barsy.club", - "barsy.de", - "barsy.eu", - "barsy.in", - "barsy.info", - "barsy.io", - "barsy.me", - "barsy.menu", - "barsy.mobi", - "barsy.net", - "barsy.online", - "barsy.org", - "barsy.pro", - "barsy.pub", - "barsy.shop", - "barsy.site", - "barsy.support", - "barsy.uk", - "*.magentosite.cloud", - "mayfirst.info", - "mayfirst.org", - "hb.cldmail.ru", - "miniserver.com", - "memset.net", - "cloud.metacentrum.cz", - "custom.metacentrum.cz", - "flt.cloud.muni.cz", - "usr.cloud.muni.cz", - "meteorapp.com", - "eu.meteorapp.com", - "co.pl", - "azurecontainer.io", - "azurewebsites.net", - "azure-mobile.net", - "cloudapp.net", - "mozilla-iot.org", - "bmoattachments.org", - "net.ru", - "org.ru", - "pp.ru", - "ui.nabu.casa", - "pony.club", - "of.fashion", - "on.fashion", - "of.football", - "in.london", - "of.london", - "for.men", - "and.mom", - "for.mom", - "for.one", - "for.sale", - "of.work", - "to.work", - "nctu.me", - "bitballoon.com", - "netlify.com", - "4u.com", - "ngrok.io", - "nh-serv.co.uk", - "nfshost.com", - "dnsking.ch", - "mypi.co", - "n4t.co", - "001www.com", - "ddnslive.com", - "myiphost.com", - "forumz.info", - "16-b.it", - "32-b.it", - "64-b.it", - "soundcast.me", - "tcp4.me", - "dnsup.net", - "hicam.net", - "now-dns.net", - "ownip.net", - "vpndns.net", - "dynserv.org", - "now-dns.org", - "x443.pw", - "now-dns.top", - "ntdll.top", - "freeddns.us", - "crafting.xyz", - "zapto.xyz", - "nsupdate.info", - "nerdpol.ovh", - "blogsyte.com", - "brasilia.me", - "cable-modem.org", - "ciscofreak.com", - "collegefan.org", - "couchpotatofries.org", - "damnserver.com", - "ddns.me", - "ditchyourip.com", - "dnsfor.me", - "dnsiskinky.com", - "dvrcam.info", - "dynns.com", - "eating-organic.net", - "fantasyleague.cc", - "geekgalaxy.com", - "golffan.us", - "health-carereform.com", - "homesecuritymac.com", - "homesecuritypc.com", - "hopto.me", - "ilovecollege.info", - "loginto.me", - "mlbfan.org", - "mmafan.biz", - "myactivedirectory.com", - "mydissent.net", - "myeffect.net", - "mymediapc.net", - "mypsx.net", - "mysecuritycamera.com", - "mysecuritycamera.net", - "mysecuritycamera.org", - "net-freaks.com", - "nflfan.org", - "nhlfan.net", - "no-ip.ca", - "no-ip.co.uk", - "no-ip.net", - "noip.us", - "onthewifi.com", - "pgafan.net", - "point2this.com", - "pointto.us", - "privatizehealthinsurance.net", - "quicksytes.com", - "read-books.org", - "securitytactics.com", - "serveexchange.com", - "servehumour.com", - "servep2p.com", - "servesarcasm.com", - "stufftoread.com", - "ufcfan.org", - "unusualperson.com", - "workisboring.com", - "3utilities.com", - "bounceme.net", - "ddns.net", - "ddnsking.com", - "gotdns.ch", - "hopto.org", - "myftp.biz", - "myftp.org", - "myvnc.com", - "no-ip.biz", - "no-ip.info", - "no-ip.org", - "noip.me", - "redirectme.net", - "servebeer.com", - "serveblog.net", - "servecounterstrike.com", - "serveftp.com", - "servegame.com", - "servehalflife.com", - "servehttp.com", - "serveirc.com", - "serveminecraft.net", - "servemp3.com", - "servepics.com", - "servequake.com", - "sytes.net", - "webhop.me", - "zapto.org", - "stage.nodeart.io", - "nodum.co", - "nodum.io", - "pcloud.host", - "nyc.mn", - "nom.ae", - "nom.af", - "nom.ai", - "nom.al", - "nym.by", - "nym.bz", - "nom.cl", - "nom.gd", - "nom.ge", - "nom.gl", - "nym.gr", - "nom.gt", - "nym.gy", - "nom.hn", - "nym.ie", - "nom.im", - "nom.ke", - "nym.kz", - "nym.la", - "nym.lc", - "nom.li", - "nym.li", - "nym.lt", - "nym.lu", - "nym.me", - "nom.mk", - "nym.mn", - "nym.mx", - "nom.nu", - "nym.nz", - "nym.pe", - "nym.pt", - "nom.pw", - "nom.qa", - "nym.ro", - "nom.rs", - "nom.si", - "nym.sk", - "nom.st", - "nym.su", - "nym.sx", - "nom.tj", - "nym.tw", - "nom.ug", - "nom.uy", - "nom.vc", - "nom.vg", - "cya.gg", - "cloudycluster.net", - "nid.io", - "opencraft.hosting", - "operaunite.com", - "outsystemscloud.com", - "ownprovider.com", - "own.pm", - "ox.rs", - "oy.lc", - "pgfog.com", - "pagefrontapp.com", - "art.pl", - "gliwice.pl", - "krakow.pl", - "poznan.pl", - "wroc.pl", - "zakopane.pl", - "pantheonsite.io", - "gotpantheon.com", - "mypep.link", - "on-web.fr", - "*.platform.sh", - "*.platformsh.site", - "dyn53.io", - "co.bn", - "xen.prgmr.com", - "priv.at", - "prvcy.page", - "*.dweb.link", - "protonet.io", - "chirurgiens-dentistes-en-france.fr", - "byen.site", - "instantcloud.cn", - "ras.ru", - "qa2.com", - "dev-myqnapcloud.com", - "alpha-myqnapcloud.com", - "myqnapcloud.com", - "*.quipelements.com", - "vapor.cloud", - "vaporcloud.io", - "rackmaze.com", - "rackmaze.net", - "*.on-rancher.cloud", - "*.on-rio.io", - "readthedocs.io", - "rhcloud.com", - "app.render.com", - "onrender.com", - "repl.co", - "repl.run", - "resindevice.io", - "devices.resinstaging.io", - "hzc.io", - "wellbeingzone.eu", - "ptplus.fit", - "wellbeingzone.co.uk", - "git-pages.rit.edu", - "sandcats.io", - "logoip.de", - "logoip.com", - "schokokeks.net", - "scrysec.com", - "firewall-gateway.com", - "firewall-gateway.de", - "my-gateway.de", - "my-router.de", - "spdns.de", - "spdns.eu", - "firewall-gateway.net", - "my-firewall.org", - "myfirewall.org", - "spdns.org", - "*.s5y.io", - "*.sensiosite.cloud", - "biz.ua", - "co.ua", - "pp.ua", - "shiftedit.io", - "myshopblocks.com", - "mo-siemens.io", - "1kapp.com", - "appchizi.com", - "applinzi.com", - "sinaapp.com", - "vipsinaapp.com", - "siteleaf.net", - "bounty-full.com", - "alpha.bounty-full.com", - "beta.bounty-full.com", - "stackhero-network.com", - "static.land", - "dev.static.land", - "sites.static.land", - "apps.lair.io", - "*.stolos.io", - "spacekit.io", - "customer.speedpartner.de", - "api.stdlib.com", - "storj.farm", - "utwente.io", - "soc.srcf.net", - "user.srcf.net", - "temp-dns.com", - "applicationcloud.io", - "scapp.io", - "syncloud.it", - "diskstation.me", - "dscloud.biz", - "dscloud.me", - "dscloud.mobi", - "dsmynas.com", - "dsmynas.net", - "dsmynas.org", - "familyds.com", - "familyds.net", - "familyds.org", - "i234.me", - "myds.me", - "synology.me", - "vpnplus.to", - "taifun-dns.de", - "gda.pl", - "gdansk.pl", - "gdynia.pl", - "med.pl", - "sopot.pl", - "edugit.org", - "telebit.app", - "telebit.io", - "*.telebit.xyz", - "gwiddle.co.uk", - "thingdustdata.com", - "cust.dev.thingdust.io", - "cust.disrec.thingdust.io", - "cust.prod.thingdust.io", - "cust.testing.thingdust.io", - "arvo.network", - "azimuth.network", - "bloxcms.com", - "townnews-staging.com", - "12hp.at", - "2ix.at", - "4lima.at", - "lima-city.at", - "12hp.ch", - "2ix.ch", - "4lima.ch", - "lima-city.ch", - "trafficplex.cloud", - "de.cool", - "12hp.de", - "2ix.de", - "4lima.de", - "lima-city.de", - "1337.pictures", - "clan.rip", - "lima-city.rocks", - "webspace.rocks", - "lima.zone", - "*.transurl.be", - "*.transurl.eu", - "*.transurl.nl", - "tuxfamily.org", - "dd-dns.de", - "diskstation.eu", - "diskstation.org", - "dray-dns.de", - "draydns.de", - "dyn-vpn.de", - "dynvpn.de", - "mein-vigor.de", - "my-vigor.de", - "my-wan.de", - "syno-ds.de", - "synology-diskstation.de", - "synology-ds.de", - "uber.space", - "*.uberspace.de", - "hk.com", - "hk.org", - "ltd.hk", - "inc.hk", - "virtualuser.de", - "virtual-user.de", - "lib.de.us", - "2038.io", - "router.management", - "v-info.info", - "voorloper.cloud", - "wafflecell.com", - "wedeploy.io", - "wedeploy.me", - "wedeploy.sh", - "remotewd.com", - "wmflabs.org", - "half.host", - "xnbay.com", - "u2.xnbay.com", - "u2-local.xnbay.com", - "cistron.nl", - "demon.nl", - "xs4all.space", - "official.academy", - "yolasite.com", - "ybo.faith", - "yombo.me", - "homelink.one", - "ybo.party", - "ybo.review", - "ybo.science", - "ybo.trade", - "nohost.me", - "noho.st", - "za.net", - "za.org", - "now.sh", - "bss.design", - "basicserver.io", - "virtualserver.io", - "site.builder.nu", - "enterprisecloud.nu", - "zone.id", -} - -var nodeLabels = [...]string{ - "aaa", - "aarp", - "abarth", - "abb", - "abbott", - "abbvie", - "abc", - "able", - "abogado", - "abudhabi", - "ac", - "academy", - "accenture", - "accountant", - "accountants", - "aco", - "actor", - "ad", - "adac", - "ads", - "adult", - "ae", - "aeg", - "aero", - "aetna", - "af", - "afamilycompany", - "afl", - "africa", - "ag", - "agakhan", - "agency", - "ai", - "aig", - "aigo", - "airbus", - "airforce", - "airtel", - "akdn", - "al", - "alfaromeo", - "alibaba", - "alipay", - "allfinanz", - "allstate", - "ally", - "alsace", - "alstom", - "am", - "americanexpress", - "americanfamily", - "amex", - "amfam", - "amica", - "amsterdam", - "analytics", - "android", - "anquan", - "anz", - "ao", - "aol", - "apartments", - "app", - "apple", - "aq", - "aquarelle", - "ar", - "arab", - "aramco", - "archi", - "army", - "arpa", - "art", - "arte", - "as", - "asda", - "asia", - "associates", - "at", - "athleta", - "attorney", - "au", - "auction", - "audi", - "audible", - "audio", - "auspost", - "author", - "auto", - "autos", - "avianca", - "aw", - "aws", - "ax", - "axa", - "az", - "azure", - "ba", - "baby", - "baidu", - "banamex", - "bananarepublic", - "band", - "bank", - "bar", - "barcelona", - "barclaycard", - "barclays", - "barefoot", - "bargains", - "baseball", - "basketball", - "bauhaus", - "bayern", - "bb", - "bbc", - "bbt", - "bbva", - "bcg", - "bcn", - "bd", - "be", - "beats", - "beauty", - "beer", - "bentley", - "berlin", - "best", - "bestbuy", - "bet", - "bf", - "bg", - "bh", - "bharti", - "bi", - "bible", - "bid", - "bike", - "bing", - "bingo", - "bio", - "biz", - "bj", - "black", - "blackfriday", - "blockbuster", - "blog", - "bloomberg", - "blue", - "bm", - "bms", - "bmw", - "bn", - "bnl", - "bnpparibas", - "bo", - "boats", - "boehringer", - "bofa", - "bom", - "bond", - "boo", - "book", - "booking", - "bosch", - "bostik", - "boston", - "bot", - "boutique", - "box", - "br", - "bradesco", - "bridgestone", - "broadway", - "broker", - "brother", - "brussels", - "bs", - "bt", - "budapest", - "bugatti", - "build", - "builders", - "business", - "buy", - "buzz", - "bv", - "bw", - "by", - "bz", - "bzh", - "ca", - "cab", - "cafe", - "cal", - "call", - "calvinklein", - "cam", - "camera", - "camp", - "cancerresearch", - "canon", - "capetown", - "capital", - "capitalone", - "car", - "caravan", - "cards", - "care", - "career", - "careers", - "cars", - "cartier", - "casa", - "case", - "caseih", - "cash", - "casino", - "cat", - "catering", - "catholic", - "cba", - "cbn", - "cbre", - "cbs", - "cc", - "cd", - "ceb", - "center", - "ceo", - "cern", - "cf", - "cfa", - "cfd", - "cg", - "ch", - "chanel", - "channel", - "charity", - "chase", - "chat", - "cheap", - "chintai", - "christmas", - "chrome", - "chrysler", - "church", - "ci", - "cipriani", - "circle", - "cisco", - "citadel", - "citi", - "citic", - "city", - "cityeats", - "ck", - "cl", - "claims", - "cleaning", - "click", - "clinic", - "clinique", - "clothing", - "cloud", - "club", - "clubmed", - "cm", - "cn", - "co", - "coach", - "codes", - "coffee", - "college", - "cologne", - "com", - "comcast", - "commbank", - "community", - "company", - "compare", - "computer", - "comsec", - "condos", - "construction", - "consulting", - "contact", - "contractors", - "cooking", - "cookingchannel", - "cool", - "coop", - "corsica", - "country", - "coupon", - "coupons", - "courses", - "cr", - "credit", - "creditcard", - "creditunion", - "cricket", - "crown", - "crs", - "cruise", - "cruises", - "csc", - "cu", - "cuisinella", - "cv", - "cw", - "cx", - "cy", - "cymru", - "cyou", - "cz", - "dabur", - "dad", - "dance", - "data", - "date", - "dating", - "datsun", - "day", - "dclk", - "dds", - "de", - "deal", - "dealer", - "deals", - "degree", - "delivery", - "dell", - "deloitte", - "delta", - "democrat", - "dental", - "dentist", - "desi", - "design", - "dev", - "dhl", - "diamonds", - "diet", - "digital", - "direct", - "directory", - "discount", - "discover", - "dish", - "diy", - "dj", - "dk", - "dm", - "dnp", - "do", - "docs", - "doctor", - "dodge", - "dog", - "domains", - "dot", - "download", - "drive", - "dtv", - "dubai", - "duck", - "dunlop", - "duns", - "dupont", - "durban", - "dvag", - "dvr", - "dz", - "earth", - "eat", - "ec", - "eco", - "edeka", - "edu", - "education", - "ee", - "eg", - "email", - "emerck", - "energy", - "engineer", - "engineering", - "enterprises", - "epson", - "equipment", - "er", - "ericsson", - "erni", - "es", - "esq", - "estate", - "esurance", - "et", - "etisalat", - "eu", - "eurovision", - "eus", - "events", - "everbank", - "exchange", - "expert", - "exposed", - "express", - "extraspace", - "fage", - "fail", - "fairwinds", - "faith", - "family", - "fan", - "fans", - "farm", - "farmers", - "fashion", - "fast", - "fedex", - "feedback", - "ferrari", - "ferrero", - "fi", - "fiat", - "fidelity", - "fido", - "film", - "final", - "finance", - "financial", - "fire", - "firestone", - "firmdale", - "fish", - "fishing", - "fit", - "fitness", - "fj", - "fk", - "flickr", - "flights", - "flir", - "florist", - "flowers", - "fly", - "fm", - "fo", - "foo", - "food", - "foodnetwork", - "football", - "ford", - "forex", - "forsale", - "forum", - "foundation", - "fox", - "fr", - "free", - "fresenius", - "frl", - "frogans", - "frontdoor", - "frontier", - "ftr", - "fujitsu", - "fujixerox", - "fun", - "fund", - "furniture", - "futbol", - "fyi", - "ga", - "gal", - "gallery", - "gallo", - "gallup", - "game", - "games", - "gap", - "garden", - "gb", - "gbiz", - "gd", - "gdn", - "ge", - "gea", - "gent", - "genting", - "george", - "gf", - "gg", - "ggee", - "gh", - "gi", - "gift", - "gifts", - "gives", - "giving", - "gl", - "glade", - "glass", - "gle", - "global", - "globo", - "gm", - "gmail", - "gmbh", - "gmo", - "gmx", - "gn", - "godaddy", - "gold", - "goldpoint", - "golf", - "goo", - "goodyear", - "goog", - "google", - "gop", - "got", - "gov", - "gp", - "gq", - "gr", - "grainger", - "graphics", - "gratis", - "green", - "gripe", - "grocery", - "group", - "gs", - "gt", - "gu", - "guardian", - "gucci", - "guge", - "guide", - "guitars", - "guru", - "gw", - "gy", - "hair", - "hamburg", - "hangout", - "haus", - "hbo", - "hdfc", - "hdfcbank", - "health", - "healthcare", - "help", - "helsinki", - "here", - "hermes", - "hgtv", - "hiphop", - "hisamitsu", - "hitachi", - "hiv", - "hk", - "hkt", - "hm", - "hn", - "hockey", - "holdings", - "holiday", - "homedepot", - "homegoods", - "homes", - "homesense", - "honda", - "honeywell", - "horse", - "hospital", - "host", - "hosting", - "hot", - "hoteles", - "hotels", - "hotmail", - "house", - "how", - "hr", - "hsbc", - "ht", - "hu", - "hughes", - "hyatt", - "hyundai", - "ibm", - "icbc", - "ice", - "icu", - "id", - "ie", - "ieee", - "ifm", - "ikano", - "il", - "im", - "imamat", - "imdb", - "immo", - "immobilien", - "in", - "inc", - "industries", - "infiniti", - "info", - "ing", - "ink", - "institute", - "insurance", - "insure", - "int", - "intel", - "international", - "intuit", - "investments", - "io", - "ipiranga", - "iq", - "ir", - "irish", - "is", - "iselect", - "ismaili", - "ist", - "istanbul", - "it", - "itau", - "itv", - "iveco", - "jaguar", - "java", - "jcb", - "jcp", - "je", - "jeep", - "jetzt", - "jewelry", - "jio", - "jll", - "jm", - "jmp", - "jnj", - "jo", - "jobs", - "joburg", - "jot", - "joy", - "jp", - "jpmorgan", - "jprs", - "juegos", - "juniper", - "kaufen", - "kddi", - "ke", - "kerryhotels", - "kerrylogistics", - "kerryproperties", - "kfh", - "kg", - "kh", - "ki", - "kia", - "kim", - "kinder", - "kindle", - "kitchen", - "kiwi", - "km", - "kn", - "koeln", - "komatsu", - "kosher", - "kp", - "kpmg", - "kpn", - "kr", - "krd", - "kred", - "kuokgroup", - "kw", - "ky", - "kyoto", - "kz", - "la", - "lacaixa", - "ladbrokes", - "lamborghini", - "lamer", - "lancaster", - "lancia", - "lancome", - "land", - "landrover", - "lanxess", - "lasalle", - "lat", - "latino", - "latrobe", - "law", - "lawyer", - "lb", - "lc", - "lds", - "lease", - "leclerc", - "lefrak", - "legal", - "lego", - "lexus", - "lgbt", - "li", - "liaison", - "lidl", - "life", - "lifeinsurance", - "lifestyle", - "lighting", - "like", - "lilly", - "limited", - "limo", - "lincoln", - "linde", - "link", - "lipsy", - "live", - "living", - "lixil", - "lk", - "llc", - "loan", - "loans", - "locker", - "locus", - "loft", - "lol", - "london", - "lotte", - "lotto", - "love", - "lpl", - "lplfinancial", - "lr", - "ls", - "lt", - "ltd", - "ltda", - "lu", - "lundbeck", - "lupin", - "luxe", - "luxury", - "lv", - "ly", - "ma", - "macys", - "madrid", - "maif", - "maison", - "makeup", - "man", - "management", - "mango", - "map", - "market", - "marketing", - "markets", - "marriott", - "marshalls", - "maserati", - "mattel", - "mba", - "mc", - "mckinsey", - "md", - "me", - "med", - "media", - "meet", - "melbourne", - "meme", - "memorial", - "men", - "menu", - "merckmsd", - "metlife", - "mg", - "mh", - "miami", - "microsoft", - "mil", - "mini", - "mint", - "mit", - "mitsubishi", - "mk", - "ml", - "mlb", - "mls", - "mm", - "mma", - "mn", - "mo", - "mobi", - "mobile", - "mobily", - "moda", - "moe", - "moi", - "mom", - "monash", - "money", - "monster", - "mopar", - "mormon", - "mortgage", - "moscow", - "moto", - "motorcycles", - "mov", - "movie", - "movistar", - "mp", - "mq", - "mr", - "ms", - "msd", - "mt", - "mtn", - "mtr", - "mu", - "museum", - "mutual", - "mv", - "mw", - "mx", - "my", - "mz", - "na", - "nab", - "nadex", - "nagoya", - "name", - "nationwide", - "natura", - "navy", - "nba", - "nc", - "ne", - "nec", - "net", - "netbank", - "netflix", - "network", - "neustar", - "new", - "newholland", - "news", - "next", - "nextdirect", - "nexus", - "nf", - "nfl", - "ng", - "ngo", - "nhk", - "ni", - "nico", - "nike", - "nikon", - "ninja", - "nissan", - "nissay", - "nl", - "no", - "nokia", - "northwesternmutual", - "norton", - "now", - "nowruz", - "nowtv", - "np", - "nr", - "nra", - "nrw", - "ntt", - "nu", - "nyc", - "nz", - "obi", - "observer", - "off", - "office", - "okinawa", - "olayan", - "olayangroup", - "oldnavy", - "ollo", - "om", - "omega", - "one", - "ong", - "onion", - "onl", - "online", - "onyourside", - "ooo", - "open", - "oracle", - "orange", - "org", - "organic", - "origins", - "osaka", - "otsuka", - "ott", - "ovh", - "pa", - "page", - "panasonic", - "paris", - "pars", - "partners", - "parts", - "party", - "passagens", - "pay", - "pccw", - "pe", - "pet", - "pf", - "pfizer", - "pg", - "ph", - "pharmacy", - "phd", - "philips", - "phone", - "photo", - "photography", - "photos", - "physio", - "piaget", - "pics", - "pictet", - "pictures", - "pid", - "pin", - "ping", - "pink", - "pioneer", - "pizza", - "pk", - "pl", - "place", - "play", - "playstation", - "plumbing", - "plus", - "pm", - "pn", - "pnc", - "pohl", - "poker", - "politie", - "porn", - "post", - "pr", - "pramerica", - "praxi", - "press", - "prime", - "pro", - "prod", - "productions", - "prof", - "progressive", - "promo", - "properties", - "property", - "protection", - "pru", - "prudential", - "ps", - "pt", - "pub", - "pw", - "pwc", - "py", - "qa", - "qpon", - "quebec", - "quest", - "qvc", - "racing", - "radio", - "raid", - "re", - "read", - "realestate", - "realtor", - "realty", - "recipes", - "red", - "redstone", - "redumbrella", - "rehab", - "reise", - "reisen", - "reit", - "reliance", - "ren", - "rent", - "rentals", - "repair", - "report", - "republican", - "rest", - "restaurant", - "review", - "reviews", - "rexroth", - "rich", - "richardli", - "ricoh", - "rightathome", - "ril", - "rio", - "rip", - "rmit", - "ro", - "rocher", - "rocks", - "rodeo", - "rogers", - "room", - "rs", - "rsvp", - "ru", - "rugby", - "ruhr", - "run", - "rw", - "rwe", - "ryukyu", - "sa", - "saarland", - "safe", - "safety", - "sakura", - "sale", - "salon", - "samsclub", - "samsung", - "sandvik", - "sandvikcoromant", - "sanofi", - "sap", - "sarl", - "sas", - "save", - "saxo", - "sb", - "sbi", - "sbs", - "sc", - "sca", - "scb", - "schaeffler", - "schmidt", - "scholarships", - "school", - "schule", - "schwarz", - "science", - "scjohnson", - "scor", - "scot", - "sd", - "se", - "search", - "seat", - "secure", - "security", - "seek", - "select", - "sener", - "services", - "ses", - "seven", - "sew", - "sex", - "sexy", - "sfr", - "sg", - "sh", - "shangrila", - "sharp", - "shaw", - "shell", - "shia", - "shiksha", - "shoes", - "shop", - "shopping", - "shouji", - "show", - "showtime", - "shriram", - "si", - "silk", - "sina", - "singles", - "site", - "sj", - "sk", - "ski", - "skin", - "sky", - "skype", - "sl", - "sling", - "sm", - "smart", - "smile", - "sn", - "sncf", - "so", - "soccer", - "social", - "softbank", - "software", - "sohu", - "solar", - "solutions", - "song", - "sony", - "soy", - "space", - "sport", - "spot", - "spreadbetting", - "sr", - "srl", - "srt", - "st", - "stada", - "staples", - "star", - "starhub", - "statebank", - "statefarm", - "stc", - "stcgroup", - "stockholm", - "storage", - "store", - "stream", - "studio", - "study", - "style", - "su", - "sucks", - "supplies", - "supply", - "support", - "surf", - "surgery", - "suzuki", - "sv", - "swatch", - "swiftcover", - "swiss", - "sx", - "sy", - "sydney", - "symantec", - "systems", - "sz", - "tab", - "taipei", - "talk", - "taobao", - "target", - "tatamotors", - "tatar", - "tattoo", - "tax", - "taxi", - "tc", - "tci", - "td", - "tdk", - "team", - "tech", - "technology", - "tel", - "telefonica", - "temasek", - "tennis", - "teva", - "tf", - "tg", - "th", - "thd", - "theater", - "theatre", - "tiaa", - "tickets", - "tienda", - "tiffany", - "tips", - "tires", - "tirol", - "tj", - "tjmaxx", - "tjx", - "tk", - "tkmaxx", - "tl", - "tm", - "tmall", - "tn", - "to", - "today", - "tokyo", - "tools", - "top", - "toray", - "toshiba", - "total", - "tours", - "town", - "toyota", - "toys", - "tr", - "trade", - "trading", - "training", - "travel", - "travelchannel", - "travelers", - "travelersinsurance", - "trust", - "trv", - "tt", - "tube", - "tui", - "tunes", - "tushu", - "tv", - "tvs", - "tw", - "tz", - "ua", - "ubank", - "ubs", - "uconnect", - "ug", - "uk", - "unicom", - "university", - "uno", - "uol", - "ups", - "us", - "uy", - "uz", - "va", - "vacations", - "vana", - "vanguard", - "vc", - "ve", - "vegas", - "ventures", - "verisign", - "versicherung", - "vet", - "vg", - "vi", - "viajes", - "video", - "vig", - "viking", - "villas", - "vin", - "vip", - "virgin", - "visa", - "vision", - "vistaprint", - "viva", - "vivo", - "vlaanderen", - "vn", - "vodka", - "volkswagen", - "volvo", - "vote", - "voting", - "voto", - "voyage", - "vu", - "vuelos", - "wales", - "walmart", - "walter", - "wang", - "wanggou", - "warman", - "watch", - "watches", - "weather", - "weatherchannel", - "webcam", - "weber", - "website", - "wed", - "wedding", - "weibo", - "weir", - "wf", - "whoswho", - "wien", - "wiki", - "williamhill", - "win", - "windows", - "wine", - "winners", - "wme", - "wolterskluwer", - "woodside", - "work", - "works", - "world", - "wow", - "ws", - "wtc", - "wtf", - "xbox", - "xerox", - "xfinity", - "xihuan", - "xin", - "xn--11b4c3d", - "xn--1ck2e1b", - "xn--1qqw23a", - "xn--2scrj9c", - "xn--30rr7y", - "xn--3bst00m", - "xn--3ds443g", - "xn--3e0b707e", - "xn--3hcrj9c", - "xn--3oq18vl8pn36a", - "xn--3pxu8k", - "xn--42c2d9a", - "xn--45br5cyl", - "xn--45brj9c", - "xn--45q11c", - "xn--4gbrim", - "xn--54b7fta0cc", - "xn--55qw42g", - "xn--55qx5d", - "xn--5su34j936bgsg", - "xn--5tzm5g", - "xn--6frz82g", - "xn--6qq986b3xl", - "xn--80adxhks", - "xn--80ao21a", - "xn--80aqecdr1a", - "xn--80asehdb", - "xn--80aswg", - "xn--8y0a063a", - "xn--90a3ac", - "xn--90ae", - "xn--90ais", - "xn--9dbq2a", - "xn--9et52u", - "xn--9krt00a", - "xn--b4w605ferd", - "xn--bck1b9a5dre4c", - "xn--c1avg", - "xn--c2br7g", - "xn--cck2b3b", - "xn--cg4bki", - "xn--clchc0ea0b2g2a9gcd", - "xn--czr694b", - "xn--czrs0t", - "xn--czru2d", - "xn--d1acj3b", - "xn--d1alf", - "xn--e1a4c", - "xn--eckvdtc9d", - "xn--efvy88h", - "xn--estv75g", - "xn--fct429k", - "xn--fhbei", - "xn--fiq228c5hs", - "xn--fiq64b", - "xn--fiqs8s", - "xn--fiqz9s", - "xn--fjq720a", - "xn--flw351e", - "xn--fpcrj9c3d", - "xn--fzc2c9e2c", - "xn--fzys8d69uvgm", - "xn--g2xx48c", - "xn--gckr3f0f", - "xn--gecrj9c", - "xn--gk3at1e", - "xn--h2breg3eve", - "xn--h2brj9c", - "xn--h2brj9c8c", - "xn--hxt814e", - "xn--i1b6b1a6a2e", - "xn--imr513n", - "xn--io0a7i", - "xn--j1aef", - "xn--j1amh", - "xn--j6w193g", - "xn--jlq61u9w7b", - "xn--jvr189m", - "xn--kcrx77d1x4a", - "xn--kprw13d", - "xn--kpry57d", - "xn--kpu716f", - "xn--kput3i", - "xn--l1acc", - "xn--lgbbat1ad8j", - "xn--mgb2ddes", - "xn--mgb9awbf", - "xn--mgba3a3ejt", - "xn--mgba3a4f16a", - "xn--mgba3a4fra", - "xn--mgba7c0bbn0a", - "xn--mgbaakc7dvf", - "xn--mgbaam7a8h", - "xn--mgbab2bd", - "xn--mgbai9a5eva00b", - "xn--mgbai9azgqp6j", - "xn--mgbayh7gpa", - "xn--mgbb9fbpob", - "xn--mgbbh1a", - "xn--mgbbh1a71e", - "xn--mgbc0a9azcg", - "xn--mgbca7dzdo", - "xn--mgberp4a5d4a87g", - "xn--mgberp4a5d4ar", - "xn--mgbgu82a", - "xn--mgbi4ecexp", - "xn--mgbpl2fh", - "xn--mgbqly7c0a67fbc", - "xn--mgbqly7cvafr", - "xn--mgbt3dhd", - "xn--mgbtf8fl", - "xn--mgbtx2b", - "xn--mgbx4cd0ab", - "xn--mix082f", - "xn--mix891f", - "xn--mk1bu44c", - "xn--mxtq1m", - "xn--ngbc5azd", - "xn--ngbe9e0a", - "xn--ngbrx", - "xn--nnx388a", - "xn--node", - "xn--nqv7f", - "xn--nqv7fs00ema", - "xn--nyqy26a", - "xn--o3cw4h", - "xn--ogbpf8fl", - "xn--otu796d", - "xn--p1acf", - "xn--p1ai", - "xn--pbt977c", - "xn--pgbs0dh", - "xn--pssy2u", - "xn--q9jyb4c", - "xn--qcka1pmc", - "xn--qxam", - "xn--rhqv96g", - "xn--rovu88b", - "xn--rvc1e0am3e", - "xn--s9brj9c", - "xn--ses554g", - "xn--t60b56a", - "xn--tckwe", - "xn--tiq49xqyj", - "xn--unup4y", - "xn--vermgensberater-ctb", - "xn--vermgensberatung-pwb", - "xn--vhquv", - "xn--vuq861b", - "xn--w4r85el8fhu5dnra", - "xn--w4rs40l", - "xn--wgbh1c", - "xn--wgbl6a", - "xn--xhq521b", - "xn--xkc2al3hye2a", - "xn--xkc2dl3a5ee0h", - "xn--y9a3aq", - "xn--yfro4i67o", - "xn--ygbi2ammx", - "xn--zfr164b", - "xxx", - "xyz", - "yachts", - "yahoo", - "yamaxun", - "yandex", - "ye", - "yodobashi", - "yoga", - "yokohama", - "you", - "youtube", - "yt", - "yun", - "za", - "zappos", - "zara", - "zero", - "zip", - "zm", - "zone", - "zuerich", - "zw", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "official", - "nom", - "ac", - "blogspot", - "co", - "gov", - "mil", - "net", - "nom", - "org", - "sch", - "accident-investigation", - "accident-prevention", - "aerobatic", - "aeroclub", - "aerodrome", - "agents", - "air-surveillance", - "air-traffic-control", - "aircraft", - "airline", - "airport", - "airtraffic", - "ambulance", - "amusement", - "association", - "author", - "ballooning", - "broker", - "caa", - "cargo", - "catering", - "certification", - "championship", - "charter", - "civilaviation", - "club", - "conference", - "consultant", - "consulting", - "control", - "council", - "crew", - "design", - "dgca", - "educator", - "emergency", - "engine", - "engineer", - "entertainment", - "equipment", - "exchange", - "express", - "federation", - "flight", - "freight", - "fuel", - "gliding", - "government", - "groundhandling", - "group", - "hanggliding", - "homebuilt", - "insurance", - "journal", - "journalist", - "leasing", - "logistics", - "magazine", - "maintenance", - "media", - "microlight", - "modelling", - "navigation", - "parachuting", - "paragliding", - "passenger-association", - "pilot", - "press", - "production", - "recreation", - "repbody", - "res", - "research", - "rotorcraft", - "safety", - "scientist", - "services", - "show", - "skydiving", - "software", - "student", - "trader", - "trading", - "trainer", - "union", - "workinggroup", - "works", - "com", - "edu", - "gov", - "net", - "nom", - "org", - "co", - "com", - "net", - "nom", - "org", - "com", - "net", - "nom", - "off", - "org", - "uwu", - "blogspot", - "com", - "edu", - "gov", - "mil", - "net", - "nom", - "org", - "blogspot", - "co", - "com", - "commune", - "net", - "org", - "co", - "ed", - "gv", - "it", - "og", - "pb", - "hasura", - "loginline", - "run", - "telebit", - "web", - "wnext", - "a", - "com", - "edu", - "gob", - "gov", - "int", - "mil", - "musica", - "net", - "org", - "tur", - "blogspot", - "e164", - "in-addr", - "ip6", - "iris", - "uri", - "urn", - "gov", - "cloudns", - "12hp", - "2ix", - "4lima", - "ac", - "biz", - "co", - "futurecms", - "futurehosting", - "futuremailing", - "gv", - "info", - "lima-city", - "or", - "ortsinfo", - "priv", - "blogspot", - "ex", - "in", - "ex", - "kunden", - "act", - "asn", - "com", - "conf", - "edu", - "gov", - "id", - "info", - "net", - "nsw", - "nt", - "org", - "oz", - "qld", - "sa", - "tas", - "vic", - "wa", - "blogspot", - "act", - "nsw", - "nt", - "qld", - "sa", - "tas", - "vic", - "wa", - "qld", - "sa", - "tas", - "vic", - "wa", - "com", - "biz", - "com", - "edu", - "gov", - "info", - "int", - "mil", - "name", - "net", - "org", - "pp", - "pro", - "blogspot", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "biz", - "co", - "com", - "edu", - "gov", - "info", - "net", - "org", - "store", - "tv", - "ac", - "blogspot", - "transurl", - "webhosting", - "gov", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "a", - "b", - "barsy", - "blogspot", - "c", - "d", - "e", - "f", - "g", - "h", - "i", - "j", - "k", - "l", - "m", - "n", - "o", - "p", - "q", - "r", - "s", - "t", - "u", - "v", - "w", - "x", - "y", - "z", - "com", - "edu", - "gov", - "net", - "org", - "co", - "com", - "edu", - "or", - "org", - "bpl", - "cloudns", - "dscloud", - "dyndns", - "for-better", - "for-more", - "for-some", - "for-the", - "mmafan", - "myftp", - "no-ip", - "orx", - "selfip", - "webhop", - "asso", - "barreau", - "blogspot", - "gouv", - "com", - "edu", - "gov", - "net", - "org", - "co", - "com", - "edu", - "gov", - "net", - "org", - "academia", - "agro", - "arte", - "blog", - "bolivia", - "ciencia", - "com", - "cooperativa", - "democracia", - "deporte", - "ecologia", - "economia", - "edu", - "empresa", - "gob", - "indigena", - "industria", - "info", - "int", - "medicina", - "mil", - "movimiento", - "musica", - "natural", - "net", - "nombre", - "noticias", - "org", - "patria", - "plurinacional", - "politica", - "profesional", - "pueblo", - "revista", - "salud", - "tecnologia", - "tksat", - "transporte", - "tv", - "web", - "wiki", - "9guacu", - "abc", - "adm", - "adv", - "agr", - "aju", - "am", - "anani", - "aparecida", - "arq", - "art", - "ato", - "b", - "barueri", - "belem", - "bhz", - "bio", - "blog", - "bmd", - "boavista", - "bsb", - "campinagrande", - "campinas", - "caxias", - "cim", - "cng", - "cnt", - "com", - "contagem", - "coop", - "cri", - "cuiaba", - "curitiba", - "def", - "ecn", - "eco", - "edu", - "emp", - "eng", - "esp", - "etc", - "eti", - "far", - "feira", - "flog", - "floripa", - "fm", - "fnd", - "fortal", - "fot", - "foz", - "fst", - "g12", - "ggf", - "goiania", - "gov", - "gru", - "imb", - "ind", - "inf", - "jab", - "jampa", - "jdf", - "joinville", - "jor", - "jus", - "leg", - "lel", - "londrina", - "macapa", - "maceio", - "manaus", - "maringa", - "mat", - "med", - "mil", - "morena", - "mp", - "mus", - "natal", - "net", - "niteroi", - "nom", - "not", - "ntr", - "odo", - "ong", - "org", - "osasco", - "palmas", - "poa", - "ppg", - "pro", - "psc", - "psi", - "pvh", - "qsl", - "radio", - "rec", - "recife", - "ribeirao", - "rio", - "riobranco", - "riopreto", - "salvador", - "sampa", - "santamaria", - "santoandre", - "saobernardo", - "saogonca", - "sjc", - "slg", - "slz", - "sorocaba", - "srv", - "taxi", - "tc", - "teo", - "the", - "tmp", - "trd", - "tur", - "tv", - "udi", - "vet", - "vix", - "vlog", - "wiki", - "zlg", - "blogspot", - "ac", - "al", - "am", - "ap", - "ba", - "ce", - "df", - "es", - "go", - "ma", - "mg", - "ms", - "mt", - "pa", - "pb", - "pe", - "pi", - "pr", - "rj", - "rn", - "ro", - "rr", - "rs", - "sc", - "se", - "sp", - "to", - "ac", - "al", - "am", - "ap", - "ba", - "ce", - "df", - "es", - "go", - "ma", - "mg", - "ms", - "mt", - "pa", - "pb", - "pe", - "pi", - "pr", - "rj", - "rn", - "ro", - "rr", - "rs", - "sc", - "se", - "sp", - "to", - "com", - "edu", - "gov", - "net", - "org", - "we", - "com", - "edu", - "gov", - "net", - "org", - "co", - "co", - "org", - "com", - "gov", - "mil", - "nym", - "of", - "blogspot", - "com", - "edu", - "gov", - "net", - "nym", - "org", - "za", - "ab", - "awdev", - "barsy", - "bc", - "blogspot", - "co", - "gc", - "mb", - "nb", - "nf", - "nl", - "no-ip", - "ns", - "nt", - "nu", - "on", - "pe", - "qc", - "sk", - "yk", - "nabu", - "ui", - "cloudns", - "fantasyleague", - "ftpaccess", - "game-server", - "myphotos", - "scrapping", - "twmail", - "gov", - "blogspot", - "12hp", - "2ix", - "4lima", - "blogspot", - "dnsking", - "gotdns", - "lima-city", - "linkyard-cloud", - "square7", - "ac", - "asso", - "co", - "com", - "ed", - "edu", - "fin", - "go", - "gouv", - "int", - "md", - "net", - "or", - "org", - "presse", - "xn--aroport-bya", - "ng", - "www", - "blogspot", - "co", - "gob", - "gov", - "mil", - "nom", - "linkyard", - "magentosite", - "on-rancher", - "sensiosite", - "statics", - "trafficplex", - "vapor", - "voorloper", - "barsy", - "cloudns", - "pony", - "co", - "com", - "gov", - "net", - "ac", - "ah", - "bj", - "com", - "cq", - "edu", - "fj", - "gd", - "gov", - "gs", - "gx", - "gz", - "ha", - "hb", - "he", - "hi", - "hk", - "hl", - "hn", - "instantcloud", - "jl", - "js", - "jx", - "ln", - "mil", - "mo", - "net", - "nm", - "nx", - "org", - "qh", - "sc", - "sd", - "sh", - "sn", - "sx", - "tj", - "tw", - "xj", - "xn--55qx5d", - "xn--io0a7i", - "xn--od0alg", - "xz", - "yn", - "zj", - "amazonaws", - "cn-north-1", - "compute", - "eb", - "elb", - "s3", - "cn-north-1", - "cn-northwest-1", - "arts", - "carrd", - "com", - "crd", - "edu", - "firm", - "go-vip", - "gov", - "info", - "int", - "leadpages", - "lpages", - "mil", - "mypi", - "n4t", - "net", - "nodum", - "nom", - "org", - "otap", - "rec", - "repl", - "web", - "blogspot", - "001www", - "0emm", - "1kapp", - "3utilities", - "4u", - "africa", - "alpha-myqnapcloud", - "amazonaws", - "appchizi", - "applinzi", - "appspot", - "ar", - "balena-devices", - "barsycenter", - "barsyonline", - "betainabox", - "bitballoon", - "blogdns", - "blogspot", - "blogsyte", - "bloxcms", - "bounty-full", - "bplaced", - "br", - "cechire", - "ciscofreak", - "cloudcontrolapp", - "cloudcontrolled", - "cn", - "co", - "codespot", - "damnserver", - "dattolocal", - "dattorelay", - "dattoweb", - "ddnsfree", - "ddnsgeek", - "ddnsking", - "ddnslive", - "de", - "dev-myqnapcloud", - "ditchyourip", - "dnsalias", - "dnsdojo", - "dnsiskinky", - "doesntexist", - "dontexist", - "doomdns", - "drayddns", - "dreamhosters", - "dsmynas", - "dyn-o-saur", - "dynalias", - "dyndns-at-home", - "dyndns-at-work", - "dyndns-blog", - "dyndns-free", - "dyndns-home", - "dyndns-ip", - "dyndns-mail", - "dyndns-office", - "dyndns-pics", - "dyndns-remote", - "dyndns-server", - "dyndns-web", - "dyndns-wiki", - "dyndns-work", - "dynns", - "elasticbeanstalk", - "est-a-la-maison", - "est-a-la-masion", - "est-le-patron", - "est-mon-blogueur", - "eu", - "evennode", - "familyds", - "fastly-terrarium", - "fastvps-server", - "fbsbx", - "firebaseapp", - "firewall-gateway", - "flynnhub", - "freebox-os", - "freeboxos", - "from-ak", - "from-al", - "from-ar", - "from-ca", - "from-ct", - "from-dc", - "from-de", - "from-fl", - "from-ga", - "from-hi", - "from-ia", - "from-id", - "from-il", - "from-in", - "from-ks", - "from-ky", - "from-ma", - "from-md", - "from-mi", - "from-mn", - "from-mo", - "from-ms", - "from-mt", - "from-nc", - "from-nd", - "from-ne", - "from-nh", - "from-nj", - "from-nm", - "from-nv", - "from-oh", - "from-ok", - "from-or", - "from-pa", - "from-pr", - "from-ri", - "from-sc", - "from-sd", - "from-tn", - "from-tx", - "from-ut", - "from-va", - "from-vt", - "from-wa", - "from-wi", - "from-wv", - "from-wy", - "gb", - "geekgalaxy", - "getmyip", - "giize", - "githubusercontent", - "gleeze", - "googleapis", - "googlecode", - "gotdns", - "gotpantheon", - "gr", - "health-carereform", - "herokuapp", - "herokussl", - "hk", - "hobby-site", - "homelinux", - "homesecuritymac", - "homesecuritypc", - "homeunix", - "hu", - "iamallama", - "is-a-anarchist", - "is-a-blogger", - "is-a-bookkeeper", - "is-a-bulls-fan", - "is-a-caterer", - "is-a-chef", - "is-a-conservative", - "is-a-cpa", - "is-a-cubicle-slave", - "is-a-democrat", - "is-a-designer", - "is-a-doctor", - "is-a-financialadvisor", - "is-a-geek", - "is-a-green", - "is-a-guru", - "is-a-hard-worker", - "is-a-hunter", - "is-a-landscaper", - "is-a-lawyer", - "is-a-liberal", - "is-a-libertarian", - "is-a-llama", - "is-a-musician", - "is-a-nascarfan", - "is-a-nurse", - "is-a-painter", - "is-a-personaltrainer", - "is-a-photographer", - "is-a-player", - "is-a-republican", - "is-a-rockstar", - "is-a-socialist", - "is-a-student", - "is-a-teacher", - "is-a-techie", - "is-a-therapist", - "is-an-accountant", - "is-an-actor", - "is-an-actress", - "is-an-anarchist", - "is-an-artist", - "is-an-engineer", - "is-an-entertainer", - "is-certified", - "is-gone", - "is-into-anime", - "is-into-cars", - "is-into-cartoons", - "is-into-games", - "is-leet", - "is-not-certified", - "is-slick", - "is-uberleet", - "is-with-theband", - "isa-geek", - "isa-hockeynut", - "issmarterthanyou", - "jdevcloud", - "joyent", - "jpn", - "kozow", - "kr", - "likes-pie", - "likescandy", - "linode", - "lmpm", - "logoip", - "loseyourip", - "lpusercontent", - "meteorapp", - "mex", - "miniserver", - "myactivedirectory", - "myasustor", - "mydatto", - "mydobiss", - "mydrobo", - "myiphost", - "myqnapcloud", - "myravendb", - "mysecuritycamera", - "myshopblocks", - "mytuleap", - "myvnc", - "neat-url", - "net-freaks", - "netlify", - "nfshost", - "no", - "on-aptible", - "onrender", - "onthewifi", - "ooguy", - "operaunite", - "outsystemscloud", - "ownprovider", - "pagefrontapp", - "pagespeedmobilizer", - "pgfog", - "pixolino", - "point2this", - "prgmr", - "publishproxy", - "qa2", - "qc", - "quicksytes", - "quipelements", - "rackmaze", - "remotewd", - "render", - "rhcloud", - "ru", - "sa", - "saves-the-whales", - "scrysec", - "securitytactics", - "selfip", - "sells-for-less", - "sells-for-u", - "servebbs", - "servebeer", - "servecounterstrike", - "serveexchange", - "serveftp", - "servegame", - "servehalflife", - "servehttp", - "servehumour", - "serveirc", - "servemp3", - "servep2p", - "servepics", - "servequake", - "servesarcasm", - "simple-url", - "sinaapp", - "space-to-rent", - "stackhero-network", - "stdlib", - "stufftoread", - "teaches-yoga", - "temp-dns", - "theworkpc", - "thingdustdata", - "townnews-staging", - "uk", - "unusualperson", - "us", - "uy", - "vipsinaapp", - "wafflecell", - "withgoogle", - "withyoutube", - "workisboring", - "wpcomstaging", - "wpdevcloud", - "writesthisblog", - "xenapponazure", - "xnbay", - "yolasite", - "za", - "ap-northeast-1", - "ap-northeast-2", - "ap-south-1", - "ap-southeast-1", - "ap-southeast-2", - "ca-central-1", - "compute", - "compute-1", - "elb", - "eu-central-1", - "eu-west-1", - "eu-west-2", - "eu-west-3", - "s3", - "s3-ap-northeast-1", - "s3-ap-northeast-2", - "s3-ap-south-1", - "s3-ap-southeast-1", - "s3-ap-southeast-2", - "s3-ca-central-1", - "s3-eu-central-1", - "s3-eu-west-1", - "s3-eu-west-2", - "s3-eu-west-3", - "s3-external-1", - "s3-fips-us-gov-west-1", - "s3-sa-east-1", - "s3-us-east-2", - "s3-us-gov-west-1", - "s3-us-west-1", - "s3-us-west-2", - "s3-website-ap-northeast-1", - "s3-website-ap-southeast-1", - "s3-website-ap-southeast-2", - "s3-website-eu-west-1", - "s3-website-sa-east-1", - "s3-website-us-east-1", - "s3-website-us-west-1", - "s3-website-us-west-2", - "sa-east-1", - "us-east-1", - "us-east-2", - "dualstack", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "dualstack", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "dualstack", - "s3", - "dualstack", - "s3", - "dualstack", - "s3", - "s3-website", - "s3", - "alpha", - "beta", - "ap-northeast-1", - "ap-northeast-2", - "ap-northeast-3", - "ap-south-1", - "ap-southeast-1", - "ap-southeast-2", - "ca-central-1", - "eu-central-1", - "eu-west-1", - "eu-west-2", - "eu-west-3", - "sa-east-1", - "us-east-1", - "us-east-2", - "us-gov-west-1", - "us-west-1", - "us-west-2", - "eu-1", - "eu-2", - "eu-3", - "eu-4", - "us-1", - "us-2", - "us-3", - "us-4", - "apps", - "cns", - "members", - "nodebalancer", - "app", - "eu", - "xen", - "app", - "api", - "u2", - "u2-local", - "ravendb", - "de", - "ac", - "co", - "ed", - "fi", - "go", - "or", - "sa", - "com", - "edu", - "gov", - "inf", - "net", - "org", - "blogspot", - "com", - "edu", - "net", - "org", - "ath", - "gov", - "info", - "ac", - "biz", - "com", - "ekloges", - "gov", - "ltd", - "name", - "net", - "org", - "parliament", - "press", - "pro", - "tm", - "blogspot", - "blogspot", - "co", - "e4", - "metacentrum", - "muni", - "realm", - "cloud", - "custom", - "cloud", - "flt", - "usr", - "12hp", - "2ix", - "4lima", - "barsy", - "blogspot", - "bplaced", - "com", - "cosidns", - "dd-dns", - "ddnss", - "dnshome", - "dnsupdater", - "dray-dns", - "draydns", - "dyn-berlin", - "dyn-ip24", - "dyn-vpn", - "dynamisches-dns", - "dyndns1", - "dynvpn", - "firewall-gateway", - "fuettertdasnetz", - "git-repos", - "goip", - "home-webserver", - "in-berlin", - "in-brb", - "in-butter", - "in-dsl", - "in-vpn", - "internet-dns", - "isteingeek", - "istmein", - "keymachine", - "l-o-g-i-n", - "lcube-server", - "lebtimnetz", - "leitungsen", - "lima-city", - "logoip", - "mein-iserv", - "mein-vigor", - "my-gateway", - "my-router", - "my-vigor", - "my-wan", - "myhome-server", - "spdns", - "speedpartner", - "square7", - "svn-repos", - "syno-ds", - "synology-diskstation", - "synology-ds", - "taifun-dns", - "test-iserv", - "traeumtgerade", - "uberspace", - "virtual-user", - "virtualuser", - "dyn", - "dyn", - "dyndns", - "dyn", - "customer", - "bss", - "lcl", - "loginline", - "stg", - "workers", - "cloudapps", - "london", - "fastpanel", - "biz", - "blogspot", - "co", - "firm", - "reg", - "store", - "com", - "edu", - "gov", - "net", - "org", - "art", - "com", - "edu", - "gob", - "gov", - "mil", - "net", - "org", - "sld", - "web", - "art", - "asso", - "com", - "edu", - "gov", - "net", - "org", - "pol", - "dapps", - "bzz", - "com", - "edu", - "fin", - "gob", - "gov", - "info", - "k12", - "med", - "mil", - "net", - "org", - "pro", - "rit", - "git-pages", - "co", - "aip", - "com", - "edu", - "fie", - "gov", - "lib", - "med", - "org", - "pri", - "riik", - "blogspot", - "com", - "edu", - "eun", - "gov", - "mil", - "name", - "net", - "org", - "sci", - "blogspot", - "com", - "edu", - "gob", - "nom", - "org", - "blogspot", - "compute", - "biz", - "com", - "edu", - "gov", - "info", - "name", - "net", - "org", - "barsy", - "cloudns", - "diskstation", - "mycd", - "spdns", - "transurl", - "wellbeingzone", - "party", - "user", - "co", - "ybo", - "storj", - "of", - "on", - "aland", - "blogspot", - "dy", - "iki", - "xn--hkkinen-5wa", - "co", - "ptplus", - "of", - "aeroport", - "asso", - "avocat", - "avoues", - "blogspot", - "cci", - "chambagri", - "chirurgiens-dentistes", - "chirurgiens-dentistes-en-france", - "com", - "experts-comptables", - "fbx-os", - "fbxos", - "freebox-os", - "freeboxos", - "geometre-expert", - "gouv", - "greta", - "huissier-justice", - "medecin", - "nom", - "notaires", - "on-web", - "pharmacien", - "port", - "prd", - "tm", - "veterinaire", - "nom", - "cnpy", - "com", - "edu", - "gov", - "mil", - "net", - "nom", - "org", - "pvt", - "co", - "cya", - "kaas", - "net", - "org", - "com", - "edu", - "gov", - "mil", - "org", - "com", - "edu", - "gov", - "ltd", - "mod", - "org", - "biz", - "co", - "com", - "edu", - "net", - "nom", - "org", - "ac", - "com", - "edu", - "gov", - "net", - "org", - "cloud", - "asso", - "com", - "edu", - "mobi", - "net", - "org", - "blogspot", - "com", - "edu", - "gov", - "net", - "nym", - "org", - "discourse", - "com", - "edu", - "gob", - "ind", - "mil", - "net", - "nom", - "org", - "com", - "edu", - "gov", - "guam", - "info", - "net", - "org", - "web", - "co", - "com", - "edu", - "gov", - "net", - "nym", - "org", - "blogspot", - "com", - "edu", - "gov", - "idv", - "inc", - "ltd", - "net", - "org", - "xn--55qx5d", - "xn--ciqpn", - "xn--gmq050i", - "xn--gmqw5a", - "xn--io0a7i", - "xn--lcvr32d", - "xn--mk0axi", - "xn--mxtq1m", - "xn--od0alg", - "xn--od0aq3b", - "xn--tn0ag", - "xn--uc0atv", - "xn--uc0ay4a", - "xn--wcvs22d", - "xn--zf0avx", - "com", - "edu", - "gob", - "mil", - "net", - "nom", - "org", - "cloudaccess", - "freesite", - "half", - "pcloud", - "opencraft", - "blogspot", - "com", - "free", - "from", - "iz", - "name", - "adult", - "art", - "asso", - "com", - "coop", - "edu", - "firm", - "gouv", - "info", - "med", - "net", - "org", - "perso", - "pol", - "pro", - "rel", - "shop", - "2000", - "agrar", - "blogspot", - "bolt", - "casino", - "city", - "co", - "erotica", - "erotika", - "film", - "forum", - "games", - "hotel", - "info", - "ingatlan", - "jogasz", - "konyvelo", - "lakas", - "media", - "news", - "org", - "priv", - "reklam", - "sex", - "shop", - "sport", - "suli", - "szex", - "tm", - "tozsde", - "utazas", - "video", - "ac", - "biz", - "co", - "desa", - "go", - "mil", - "my", - "net", - "or", - "ponpes", - "sch", - "web", - "zone", - "blogspot", - "blogspot", - "gov", - "nym", - "ac", - "co", - "gov", - "idf", - "k12", - "muni", - "net", - "org", - "blogspot", - "ac", - "co", - "com", - "net", - "nom", - "org", - "ro", - "tt", - "tv", - "ltd", - "plc", - "ac", - "barsy", - "blogspot", - "cloudns", - "co", - "edu", - "firm", - "gen", - "gov", - "ind", - "mil", - "net", - "nic", - "org", - "res", - "barrel-of-knowledge", - "barrell-of-knowledge", - "barsy", - "cloudns", - "dvrcam", - "dynamic-dns", - "dyndns", - "for-our", - "forumz", - "groks-the", - "groks-this", - "here-for-more", - "ilovecollege", - "knowsitall", - "mayfirst", - "no-ip", - "nsupdate", - "selfip", - "v-info", - "webhop", - "ng", - "eu", - "2038", - "apigee", - "applicationcloud", - "azurecontainer", - "b-data", - "backplaneapp", - "banzaicloud", - "barsy", - "basicserver", - "bigv", - "boxfuse", - "browsersafetymark", - "cleverapps", - "com", - "dedyn", - "definima", - "drud", - "dyn53", - "enonic", - "github", - "gitlab", - "hasura-app", - "hzc", - "lair", - "loginline", - "mo-siemens", - "moonscale", - "ngrok", - "nid", - "nodeart", - "nodum", - "on-rio", - "pantheonsite", - "protonet", - "readthedocs", - "resindevice", - "resinstaging", - "s5y", - "sandcats", - "scapp", - "shiftedit", - "spacekit", - "stolos", - "telebit", - "thingdust", - "utwente", - "vaporcloud", - "virtualserver", - "wedeploy", - "app", - "uk0", - "customer", - "apps", - "stage", - "devices", - "dev", - "disrec", - "prod", - "testing", - "cust", - "cust", - "cust", - "cust", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "ac", - "co", - "gov", - "id", - "net", - "org", - "sch", - "xn--mgba3a4f16a", - "xn--mgba3a4fra", - "blogspot", - "com", - "cupcake", - "edu", - "gov", - "int", - "net", - "org", - "16-b", - "32-b", - "64-b", - "abr", - "abruzzo", - "ag", - "agrigento", - "al", - "alessandria", - "alto-adige", - "altoadige", - "an", - "ancona", - "andria-barletta-trani", - "andria-trani-barletta", - "andriabarlettatrani", - "andriatranibarletta", - "ao", - "aosta", - "aosta-valley", - "aostavalley", - "aoste", - "ap", - "aq", - "aquila", - "ar", - "arezzo", - "ascoli-piceno", - "ascolipiceno", - "asti", - "at", - "av", - "avellino", - "ba", - "balsan", - "balsan-sudtirol", - "balsan-suedtirol", - "bari", - "barletta-trani-andria", - "barlettatraniandria", - "bas", - "basilicata", - "belluno", - "benevento", - "bergamo", - "bg", - "bi", - "biella", - "bl", - "blogspot", - "bn", - "bo", - "bologna", - "bolzano", - "bolzano-altoadige", - "bozen", - "bozen-sudtirol", - "bozen-suedtirol", - "br", - "brescia", - "brindisi", - "bs", - "bt", - "bulsan", - "bulsan-sudtirol", - "bulsan-suedtirol", - "bz", - "ca", - "cagliari", - "cal", - "calabria", - "caltanissetta", - "cam", - "campania", - "campidano-medio", - "campidanomedio", - "campobasso", - "carbonia-iglesias", - "carboniaiglesias", - "carrara-massa", - "carraramassa", - "caserta", - "catania", - "catanzaro", - "cb", - "ce", - "cesena-forli", - "cesenaforli", - "ch", - "chieti", - "ci", - "cl", - "cn", - "co", - "como", - "cosenza", - "cr", - "cremona", - "crotone", - "cs", - "ct", - "cuneo", - "cz", - "dell-ogliastra", - "dellogliastra", - "edu", - "emilia-romagna", - "emiliaromagna", - "emr", - "en", - "enna", - "fc", - "fe", - "fermo", - "ferrara", - "fg", - "fi", - "firenze", - "florence", - "fm", - "foggia", - "forli-cesena", - "forlicesena", - "fr", - "friuli-v-giulia", - "friuli-ve-giulia", - "friuli-vegiulia", - "friuli-venezia-giulia", - "friuli-veneziagiulia", - "friuli-vgiulia", - "friuliv-giulia", - "friulive-giulia", - "friulivegiulia", - "friulivenezia-giulia", - "friuliveneziagiulia", - "friulivgiulia", - "frosinone", - "fvg", - "ge", - "genoa", - "genova", - "go", - "gorizia", - "gov", - "gr", - "grosseto", - "iglesias-carbonia", - "iglesiascarbonia", - "im", - "imperia", - "is", - "isernia", - "kr", - "la-spezia", - "laquila", - "laspezia", - "latina", - "laz", - "lazio", - "lc", - "le", - "lecce", - "lecco", - "li", - "lig", - "liguria", - "livorno", - "lo", - "lodi", - "lom", - "lombardia", - "lombardy", - "lt", - "lu", - "lucania", - "lucca", - "macerata", - "mantova", - "mar", - "marche", - "massa-carrara", - "massacarrara", - "matera", - "mb", - "mc", - "me", - "medio-campidano", - "mediocampidano", - "messina", - "mi", - "milan", - "milano", - "mn", - "mo", - "modena", - "mol", - "molise", - "monza", - "monza-brianza", - "monza-e-della-brianza", - "monzabrianza", - "monzaebrianza", - "monzaedellabrianza", - "ms", - "mt", - "na", - "naples", - "napoli", - "no", - "novara", - "nu", - "nuoro", - "og", - "ogliastra", - "olbia-tempio", - "olbiatempio", - "or", - "oristano", - "ot", - "pa", - "padova", - "padua", - "palermo", - "parma", - "pavia", - "pc", - "pd", - "pe", - "perugia", - "pesaro-urbino", - "pesarourbino", - "pescara", - "pg", - "pi", - "piacenza", - "piedmont", - "piemonte", - "pisa", - "pistoia", - "pmn", - "pn", - "po", - "pordenone", - "potenza", - "pr", - "prato", - "pt", - "pu", - "pug", - "puglia", - "pv", - "pz", - "ra", - "ragusa", - "ravenna", - "rc", - "re", - "reggio-calabria", - "reggio-emilia", - "reggiocalabria", - "reggioemilia", - "rg", - "ri", - "rieti", - "rimini", - "rm", - "rn", - "ro", - "roma", - "rome", - "rovigo", - "sa", - "salerno", - "sar", - "sardegna", - "sardinia", - "sassari", - "savona", - "si", - "sic", - "sicilia", - "sicily", - "siena", - "siracusa", - "so", - "sondrio", - "sp", - "sr", - "ss", - "suedtirol", - "sv", - "syncloud", - "ta", - "taa", - "taranto", - "te", - "tempio-olbia", - "tempioolbia", - "teramo", - "terni", - "tn", - "to", - "torino", - "tos", - "toscana", - "tp", - "tr", - "trani-andria-barletta", - "trani-barletta-andria", - "traniandriabarletta", - "tranibarlettaandria", - "trapani", - "trentin-sud-tirol", - "trentin-sudtirol", - "trentin-sued-tirol", - "trentin-suedtirol", - "trentino", - "trentino-a-adige", - "trentino-aadige", - "trentino-alto-adige", - "trentino-altoadige", - "trentino-s-tirol", - "trentino-stirol", - "trentino-sud-tirol", - "trentino-sudtirol", - "trentino-sued-tirol", - "trentino-suedtirol", - "trentinoa-adige", - "trentinoaadige", - "trentinoalto-adige", - "trentinoaltoadige", - "trentinos-tirol", - "trentinostirol", - "trentinosud-tirol", - "trentinosudtirol", - "trentinosued-tirol", - "trentinosuedtirol", - "trentinsud-tirol", - "trentinsudtirol", - "trentinsued-tirol", - "trentinsuedtirol", - "trento", - "treviso", - "trieste", - "ts", - "turin", - "tuscany", - "tv", - "ud", - "udine", - "umb", - "umbria", - "urbino-pesaro", - "urbinopesaro", - "va", - "val-d-aosta", - "val-daosta", - "vald-aosta", - "valdaosta", - "valle-aosta", - "valle-d-aosta", - "valle-daosta", - "valleaosta", - "valled-aosta", - "valledaosta", - "vallee-aoste", - "vallee-d-aoste", - "valleeaoste", - "valleedaoste", - "vao", - "varese", - "vb", - "vc", - "vda", - "ve", - "ven", - "veneto", - "venezia", - "venice", - "verbania", - "vercelli", - "verona", - "vi", - "vibo-valentia", - "vibovalentia", - "vicenza", - "viterbo", - "vr", - "vs", - "vt", - "vv", - "xn--balsan-sdtirol-nsb", - "xn--bozen-sdtirol-2ob", - "xn--bulsan-sdtirol-nsb", - "xn--cesena-forl-mcb", - "xn--cesenaforl-i8a", - "xn--forl-cesena-fcb", - "xn--forlcesena-c8a", - "xn--sdtirol-n2a", - "xn--trentin-sd-tirol-rzb", - "xn--trentin-sdtirol-7vb", - "xn--trentino-sd-tirol-c3b", - "xn--trentino-sdtirol-szb", - "xn--trentinosd-tirol-rzb", - "xn--trentinosdtirol-7vb", - "xn--trentinsd-tirol-6vb", - "xn--trentinsdtirol-nsb", - "xn--valle-aoste-ebb", - "xn--valle-d-aoste-ehb", - "xn--valleaoste-e7a", - "xn--valledaoste-ebb", - "co", - "net", - "org", - "com", - "edu", - "gov", - "mil", - "name", - "net", - "org", - "sch", - "ac", - "ad", - "aichi", - "akita", - "aomori", - "blogspot", - "chiba", - "co", - "ed", - "ehime", - "fukui", - "fukuoka", - "fukushima", - "gifu", - "go", - "gr", - "gunma", - "hiroshima", - "hokkaido", - "hyogo", - "ibaraki", - "ishikawa", - "iwate", - "kagawa", - "kagoshima", - "kanagawa", - "kawasaki", - "kitakyushu", - "kobe", - "kochi", - "kumamoto", - "kyoto", - "lg", - "mie", - "miyagi", - "miyazaki", - "nagano", - "nagasaki", - "nagoya", - "nara", - "ne", - "niigata", - "oita", - "okayama", - "okinawa", - "or", - "osaka", - "saga", - "saitama", - "sapporo", - "sendai", - "shiga", - "shimane", - "shizuoka", - "tochigi", - "tokushima", - "tokyo", - "tottori", - "toyama", - "usercontent", - "wakayama", - "xn--0trq7p7nn", - "xn--1ctwo", - "xn--1lqs03n", - "xn--1lqs71d", - "xn--2m4a15e", - "xn--32vp30h", - "xn--4it168d", - "xn--4it797k", - "xn--4pvxs", - "xn--5js045d", - "xn--5rtp49c", - "xn--5rtq34k", - "xn--6btw5a", - "xn--6orx2r", - "xn--7t0a264c", - "xn--8ltr62k", - "xn--8pvr4u", - "xn--c3s14m", - "xn--d5qv7z876c", - "xn--djrs72d6uy", - "xn--djty4k", - "xn--efvn9s", - "xn--ehqz56n", - "xn--elqq16h", - "xn--f6qx53a", - "xn--k7yn95e", - "xn--kbrq7o", - "xn--klt787d", - "xn--kltp7d", - "xn--kltx9a", - "xn--klty5x", - "xn--mkru45i", - "xn--nit225k", - "xn--ntso0iqx3a", - "xn--ntsq17g", - "xn--pssu33l", - "xn--qqqt11m", - "xn--rht27z", - "xn--rht3d", - "xn--rht61e", - "xn--rny31h", - "xn--tor131o", - "xn--uist22h", - "xn--uisz3g", - "xn--uuwu58a", - "xn--vgu402c", - "xn--zbx025d", - "yamagata", - "yamaguchi", - "yamanashi", - "yokohama", - "aisai", - "ama", - "anjo", - "asuke", - "chiryu", - "chita", - "fuso", - "gamagori", - "handa", - "hazu", - "hekinan", - "higashiura", - "ichinomiya", - "inazawa", - "inuyama", - "isshiki", - "iwakura", - "kanie", - "kariya", - "kasugai", - "kira", - "kiyosu", - "komaki", - "konan", - "kota", - "mihama", - "miyoshi", - "nishio", - "nisshin", - "obu", - "oguchi", - "oharu", - "okazaki", - "owariasahi", - "seto", - "shikatsu", - "shinshiro", - "shitara", - "tahara", - "takahama", - "tobishima", - "toei", - "togo", - "tokai", - "tokoname", - "toyoake", - "toyohashi", - "toyokawa", - "toyone", - "toyota", - "tsushima", - "yatomi", - "akita", - "daisen", - "fujisato", - "gojome", - "hachirogata", - "happou", - "higashinaruse", - "honjo", - "honjyo", - "ikawa", - "kamikoani", - "kamioka", - "katagami", - "kazuno", - "kitaakita", - "kosaka", - "kyowa", - "misato", - "mitane", - "moriyoshi", - "nikaho", - "noshiro", - "odate", - "oga", - "ogata", - "semboku", - "yokote", - "yurihonjo", - "aomori", - "gonohe", - "hachinohe", - "hashikami", - "hiranai", - "hirosaki", - "itayanagi", - "kuroishi", - "misawa", - "mutsu", - "nakadomari", - "noheji", - "oirase", - "owani", - "rokunohe", - "sannohe", - "shichinohe", - "shingo", - "takko", - "towada", - "tsugaru", - "tsuruta", - "abiko", - "asahi", - "chonan", - "chosei", - "choshi", - "chuo", - "funabashi", - "futtsu", - "hanamigawa", - "ichihara", - "ichikawa", - "ichinomiya", - "inzai", - "isumi", - "kamagaya", - "kamogawa", - "kashiwa", - "katori", - "katsuura", - "kimitsu", - "kisarazu", - "kozaki", - "kujukuri", - "kyonan", - "matsudo", - "midori", - "mihama", - "minamiboso", - "mobara", - "mutsuzawa", - "nagara", - "nagareyama", - "narashino", - "narita", - "noda", - "oamishirasato", - "omigawa", - "onjuku", - "otaki", - "sakae", - "sakura", - "shimofusa", - "shirako", - "shiroi", - "shisui", - "sodegaura", - "sosa", - "tako", - "tateyama", - "togane", - "tohnosho", - "tomisato", - "urayasu", - "yachimata", - "yachiyo", - "yokaichiba", - "yokoshibahikari", - "yotsukaido", - "ainan", - "honai", - "ikata", - "imabari", - "iyo", - "kamijima", - "kihoku", - "kumakogen", - "masaki", - "matsuno", - "matsuyama", - "namikata", - "niihama", - "ozu", - "saijo", - "seiyo", - "shikokuchuo", - "tobe", - "toon", - "uchiko", - "uwajima", - "yawatahama", - "echizen", - "eiheiji", - "fukui", - "ikeda", - "katsuyama", - "mihama", - "minamiechizen", - "obama", - "ohi", - "ono", - "sabae", - "sakai", - "takahama", - "tsuruga", - "wakasa", - "ashiya", - "buzen", - "chikugo", - "chikuho", - "chikujo", - "chikushino", - "chikuzen", - "chuo", - "dazaifu", - "fukuchi", - "hakata", - "higashi", - "hirokawa", - "hisayama", - "iizuka", - "inatsuki", - "kaho", - "kasuga", - "kasuya", - "kawara", - "keisen", - "koga", - "kurate", - "kurogi", - "kurume", - "minami", - "miyako", - "miyama", - "miyawaka", - "mizumaki", - "munakata", - "nakagawa", - "nakama", - "nishi", - "nogata", - "ogori", - "okagaki", - "okawa", - "oki", - "omuta", - "onga", - "onojo", - "oto", - "saigawa", - "sasaguri", - "shingu", - "shinyoshitomi", - "shonai", - "soeda", - "sue", - "tachiarai", - "tagawa", - "takata", - "toho", - "toyotsu", - "tsuiki", - "ukiha", - "umi", - "usui", - "yamada", - "yame", - "yanagawa", - "yukuhashi", - "aizubange", - "aizumisato", - "aizuwakamatsu", - "asakawa", - "bandai", - "date", - "fukushima", - "furudono", - "futaba", - "hanawa", - "higashi", - "hirata", - "hirono", - "iitate", - "inawashiro", - "ishikawa", - "iwaki", - "izumizaki", - "kagamiishi", - "kaneyama", - "kawamata", - "kitakata", - "kitashiobara", - "koori", - "koriyama", - "kunimi", - "miharu", - "mishima", - "namie", - "nango", - "nishiaizu", - "nishigo", - "okuma", - "omotego", - "ono", - "otama", - "samegawa", - "shimogo", - "shirakawa", - "showa", - "soma", - "sukagawa", - "taishin", - "tamakawa", - "tanagura", - "tenei", - "yabuki", - "yamato", - "yamatsuri", - "yanaizu", - "yugawa", - "anpachi", - "ena", - "gifu", - "ginan", - "godo", - "gujo", - "hashima", - "hichiso", - "hida", - "higashishirakawa", - "ibigawa", - "ikeda", - "kakamigahara", - "kani", - "kasahara", - "kasamatsu", - "kawaue", - "kitagata", - "mino", - "minokamo", - "mitake", - "mizunami", - "motosu", - "nakatsugawa", - "ogaki", - "sakahogi", - "seki", - "sekigahara", - "shirakawa", - "tajimi", - "takayama", - "tarui", - "toki", - "tomika", - "wanouchi", - "yamagata", - "yaotsu", - "yoro", - "annaka", - "chiyoda", - "fujioka", - "higashiagatsuma", - "isesaki", - "itakura", - "kanna", - "kanra", - "katashina", - "kawaba", - "kiryu", - "kusatsu", - "maebashi", - "meiwa", - "midori", - "minakami", - "naganohara", - "nakanojo", - "nanmoku", - "numata", - "oizumi", - "ora", - "ota", - "shibukawa", - "shimonita", - "shinto", - "showa", - "takasaki", - "takayama", - "tamamura", - "tatebayashi", - "tomioka", - "tsukiyono", - "tsumagoi", - "ueno", - "yoshioka", - "asaminami", - "daiwa", - "etajima", - "fuchu", - "fukuyama", - "hatsukaichi", - "higashihiroshima", - "hongo", - "jinsekikogen", - "kaita", - "kui", - "kumano", - "kure", - "mihara", - "miyoshi", - "naka", - "onomichi", - "osakikamijima", - "otake", - "saka", - "sera", - "seranishi", - "shinichi", - "shobara", - "takehara", - "abashiri", - "abira", - "aibetsu", - "akabira", - "akkeshi", - "asahikawa", - "ashibetsu", - "ashoro", - "assabu", - "atsuma", - "bibai", - "biei", - "bifuka", - "bihoro", - "biratori", - "chippubetsu", - "chitose", - "date", - "ebetsu", - "embetsu", - "eniwa", - "erimo", - "esan", - "esashi", - "fukagawa", - "fukushima", - "furano", - "furubira", - "haboro", - "hakodate", - "hamatonbetsu", - "hidaka", - "higashikagura", - "higashikawa", - "hiroo", - "hokuryu", - "hokuto", - "honbetsu", - "horokanai", - "horonobe", - "ikeda", - "imakane", - "ishikari", - "iwamizawa", - "iwanai", - "kamifurano", - "kamikawa", - "kamishihoro", - "kamisunagawa", - "kamoenai", - "kayabe", - "kembuchi", - "kikonai", - "kimobetsu", - "kitahiroshima", - "kitami", - "kiyosato", - "koshimizu", - "kunneppu", - "kuriyama", - "kuromatsunai", - "kushiro", - "kutchan", - "kyowa", - "mashike", - "matsumae", - "mikasa", - "minamifurano", - "mombetsu", - "moseushi", - "mukawa", - "muroran", - "naie", - "nakagawa", - "nakasatsunai", - "nakatombetsu", - "nanae", - "nanporo", - "nayoro", - "nemuro", - "niikappu", - "niki", - "nishiokoppe", - "noboribetsu", - "numata", - "obihiro", - "obira", - "oketo", - "okoppe", - "otaru", - "otobe", - "otofuke", - "otoineppu", - "oumu", - "ozora", - "pippu", - "rankoshi", - "rebun", - "rikubetsu", - "rishiri", - "rishirifuji", - "saroma", - "sarufutsu", - "shakotan", - "shari", - "shibecha", - "shibetsu", - "shikabe", - "shikaoi", - "shimamaki", - "shimizu", - "shimokawa", - "shinshinotsu", - "shintoku", - "shiranuka", - "shiraoi", - "shiriuchi", - "sobetsu", - "sunagawa", - "taiki", - "takasu", - "takikawa", - "takinoue", - "teshikaga", - "tobetsu", - "tohma", - "tomakomai", - "tomari", - "toya", - "toyako", - "toyotomi", - "toyoura", - "tsubetsu", - "tsukigata", - "urakawa", - "urausu", - "uryu", - "utashinai", - "wakkanai", - "wassamu", - "yakumo", - "yoichi", - "aioi", - "akashi", - "ako", - "amagasaki", - "aogaki", - "asago", - "ashiya", - "awaji", - "fukusaki", - "goshiki", - "harima", - "himeji", - "ichikawa", - "inagawa", - "itami", - "kakogawa", - "kamigori", - "kamikawa", - "kasai", - "kasuga", - "kawanishi", - "miki", - "minamiawaji", - "nishinomiya", - "nishiwaki", - "ono", - "sanda", - "sannan", - "sasayama", - "sayo", - "shingu", - "shinonsen", - "shiso", - "sumoto", - "taishi", - "taka", - "takarazuka", - "takasago", - "takino", - "tamba", - "tatsuno", - "toyooka", - "yabu", - "yashiro", - "yoka", - "yokawa", - "ami", - "asahi", - "bando", - "chikusei", - "daigo", - "fujishiro", - "hitachi", - "hitachinaka", - "hitachiomiya", - "hitachiota", - "ibaraki", - "ina", - "inashiki", - "itako", - "iwama", - "joso", - "kamisu", - "kasama", - "kashima", - "kasumigaura", - "koga", - "miho", - "mito", - "moriya", - "naka", - "namegata", - "oarai", - "ogawa", - "omitama", - "ryugasaki", - "sakai", - "sakuragawa", - "shimodate", - "shimotsuma", - "shirosato", - "sowa", - "suifu", - "takahagi", - "tamatsukuri", - "tokai", - "tomobe", - "tone", - "toride", - "tsuchiura", - "tsukuba", - "uchihara", - "ushiku", - "yachiyo", - "yamagata", - "yawara", - "yuki", - "anamizu", - "hakui", - "hakusan", - "kaga", - "kahoku", - "kanazawa", - "kawakita", - "komatsu", - "nakanoto", - "nanao", - "nomi", - "nonoichi", - "noto", - "shika", - "suzu", - "tsubata", - "tsurugi", - "uchinada", - "wajima", - "fudai", - "fujisawa", - "hanamaki", - "hiraizumi", - "hirono", - "ichinohe", - "ichinoseki", - "iwaizumi", - "iwate", - "joboji", - "kamaishi", - "kanegasaki", - "karumai", - "kawai", - "kitakami", - "kuji", - "kunohe", - "kuzumaki", - "miyako", - "mizusawa", - "morioka", - "ninohe", - "noda", - "ofunato", - "oshu", - "otsuchi", - "rikuzentakata", - "shiwa", - "shizukuishi", - "sumita", - "tanohata", - "tono", - "yahaba", - "yamada", - "ayagawa", - "higashikagawa", - "kanonji", - "kotohira", - "manno", - "marugame", - "mitoyo", - "naoshima", - "sanuki", - "tadotsu", - "takamatsu", - "tonosho", - "uchinomi", - "utazu", - "zentsuji", - "akune", - "amami", - "hioki", - "isa", - "isen", - "izumi", - "kagoshima", - "kanoya", - "kawanabe", - "kinko", - "kouyama", - "makurazaki", - "matsumoto", - "minamitane", - "nakatane", - "nishinoomote", - "satsumasendai", - "soo", - "tarumizu", - "yusui", - "aikawa", - "atsugi", - "ayase", - "chigasaki", - "ebina", - "fujisawa", - "hadano", - "hakone", - "hiratsuka", - "isehara", - "kaisei", - "kamakura", - "kiyokawa", - "matsuda", - "minamiashigara", - "miura", - "nakai", - "ninomiya", - "odawara", - "oi", - "oiso", - "sagamihara", - "samukawa", - "tsukui", - "yamakita", - "yamato", - "yokosuka", - "yugawara", - "zama", - "zushi", - "city", - "city", - "city", - "aki", - "geisei", - "hidaka", - "higashitsuno", - "ino", - "kagami", - "kami", - "kitagawa", - "kochi", - "mihara", - "motoyama", - "muroto", - "nahari", - "nakamura", - "nankoku", - "nishitosa", - "niyodogawa", - "ochi", - "okawa", - "otoyo", - "otsuki", - "sakawa", - "sukumo", - "susaki", - "tosa", - "tosashimizu", - "toyo", - "tsuno", - "umaji", - "yasuda", - "yusuhara", - "amakusa", - "arao", - "aso", - "choyo", - "gyokuto", - "kamiamakusa", - "kikuchi", - "kumamoto", - "mashiki", - "mifune", - "minamata", - "minamioguni", - "nagasu", - "nishihara", - "oguni", - "ozu", - "sumoto", - "takamori", - "uki", - "uto", - "yamaga", - "yamato", - "yatsushiro", - "ayabe", - "fukuchiyama", - "higashiyama", - "ide", - "ine", - "joyo", - "kameoka", - "kamo", - "kita", - "kizu", - "kumiyama", - "kyotamba", - "kyotanabe", - "kyotango", - "maizuru", - "minami", - "minamiyamashiro", - "miyazu", - "muko", - "nagaokakyo", - "nakagyo", - "nantan", - "oyamazaki", - "sakyo", - "seika", - "tanabe", - "uji", - "ujitawara", - "wazuka", - "yamashina", - "yawata", - "asahi", - "inabe", - "ise", - "kameyama", - "kawagoe", - "kiho", - "kisosaki", - "kiwa", - "komono", - "kumano", - "kuwana", - "matsusaka", - "meiwa", - "mihama", - "minamiise", - "misugi", - "miyama", - "nabari", - "shima", - "suzuka", - "tado", - "taiki", - "taki", - "tamaki", - "toba", - "tsu", - "udono", - "ureshino", - "watarai", - "yokkaichi", - "furukawa", - "higashimatsushima", - "ishinomaki", - "iwanuma", - "kakuda", - "kami", - "kawasaki", - "marumori", - "matsushima", - "minamisanriku", - "misato", - "murata", - "natori", - "ogawara", - "ohira", - "onagawa", - "osaki", - "rifu", - "semine", - "shibata", - "shichikashuku", - "shikama", - "shiogama", - "shiroishi", - "tagajo", - "taiwa", - "tome", - "tomiya", - "wakuya", - "watari", - "yamamoto", - "zao", - "aya", - "ebino", - "gokase", - "hyuga", - "kadogawa", - "kawaminami", - "kijo", - "kitagawa", - "kitakata", - "kitaura", - "kobayashi", - "kunitomi", - "kushima", - "mimata", - "miyakonojo", - "miyazaki", - "morotsuka", - "nichinan", - "nishimera", - "nobeoka", - "saito", - "shiiba", - "shintomi", - "takaharu", - "takanabe", - "takazaki", - "tsuno", - "achi", - "agematsu", - "anan", - "aoki", - "asahi", - "azumino", - "chikuhoku", - "chikuma", - "chino", - "fujimi", - "hakuba", - "hara", - "hiraya", - "iida", - "iijima", - "iiyama", - "iizuna", - "ikeda", - "ikusaka", - "ina", - "karuizawa", - "kawakami", - "kiso", - "kisofukushima", - "kitaaiki", - "komagane", - "komoro", - "matsukawa", - "matsumoto", - "miasa", - "minamiaiki", - "minamimaki", - "minamiminowa", - "minowa", - "miyada", - "miyota", - "mochizuki", - "nagano", - "nagawa", - "nagiso", - "nakagawa", - "nakano", - "nozawaonsen", - "obuse", - "ogawa", - "okaya", - "omachi", - "omi", - "ookuwa", - "ooshika", - "otaki", - "otari", - "sakae", - "sakaki", - "saku", - "sakuho", - "shimosuwa", - "shinanomachi", - "shiojiri", - "suwa", - "suzaka", - "takagi", - "takamori", - "takayama", - "tateshina", - "tatsuno", - "togakushi", - "togura", - "tomi", - "ueda", - "wada", - "yamagata", - "yamanouchi", - "yasaka", - "yasuoka", - "chijiwa", - "futsu", - "goto", - "hasami", - "hirado", - "iki", - "isahaya", - "kawatana", - "kuchinotsu", - "matsuura", - "nagasaki", - "obama", - "omura", - "oseto", - "saikai", - "sasebo", - "seihi", - "shimabara", - "shinkamigoto", - "togitsu", - "tsushima", - "unzen", - "city", - "ando", - "gose", - "heguri", - "higashiyoshino", - "ikaruga", - "ikoma", - "kamikitayama", - "kanmaki", - "kashiba", - "kashihara", - "katsuragi", - "kawai", - "kawakami", - "kawanishi", - "koryo", - "kurotaki", - "mitsue", - "miyake", - "nara", - "nosegawa", - "oji", - "ouda", - "oyodo", - "sakurai", - "sango", - "shimoichi", - "shimokitayama", - "shinjo", - "soni", - "takatori", - "tawaramoto", - "tenkawa", - "tenri", - "uda", - "yamatokoriyama", - "yamatotakada", - "yamazoe", - "yoshino", - "gehirn", - "aga", - "agano", - "gosen", - "itoigawa", - "izumozaki", - "joetsu", - "kamo", - "kariwa", - "kashiwazaki", - "minamiuonuma", - "mitsuke", - "muika", - "murakami", - "myoko", - "nagaoka", - "niigata", - "ojiya", - "omi", - "sado", - "sanjo", - "seiro", - "seirou", - "sekikawa", - "shibata", - "tagami", - "tainai", - "tochio", - "tokamachi", - "tsubame", - "tsunan", - "uonuma", - "yahiko", - "yoita", - "yuzawa", - "beppu", - "bungoono", - "bungotakada", - "hasama", - "hiji", - "himeshima", - "hita", - "kamitsue", - "kokonoe", - "kuju", - "kunisaki", - "kusu", - "oita", - "saiki", - "taketa", - "tsukumi", - "usa", - "usuki", - "yufu", - "akaiwa", - "asakuchi", - "bizen", - "hayashima", - "ibara", - "kagamino", - "kasaoka", - "kibichuo", - "kumenan", - "kurashiki", - "maniwa", - "misaki", - "nagi", - "niimi", - "nishiawakura", - "okayama", - "satosho", - "setouchi", - "shinjo", - "shoo", - "soja", - "takahashi", - "tamano", - "tsuyama", - "wake", - "yakage", - "aguni", - "ginowan", - "ginoza", - "gushikami", - "haebaru", - "higashi", - "hirara", - "iheya", - "ishigaki", - "ishikawa", - "itoman", - "izena", - "kadena", - "kin", - "kitadaito", - "kitanakagusuku", - "kumejima", - "kunigami", - "minamidaito", - "motobu", - "nago", - "naha", - "nakagusuku", - "nakijin", - "nanjo", - "nishihara", - "ogimi", - "okinawa", - "onna", - "shimoji", - "taketomi", - "tarama", - "tokashiki", - "tomigusuku", - "tonaki", - "urasoe", - "uruma", - "yaese", - "yomitan", - "yonabaru", - "yonaguni", - "zamami", - "abeno", - "chihayaakasaka", - "chuo", - "daito", - "fujiidera", - "habikino", - "hannan", - "higashiosaka", - "higashisumiyoshi", - "higashiyodogawa", - "hirakata", - "ibaraki", - "ikeda", - "izumi", - "izumiotsu", - "izumisano", - "kadoma", - "kaizuka", - "kanan", - "kashiwara", - "katano", - "kawachinagano", - "kishiwada", - "kita", - "kumatori", - "matsubara", - "minato", - "minoh", - "misaki", - "moriguchi", - "neyagawa", - "nishi", - "nose", - "osakasayama", - "sakai", - "sayama", - "sennan", - "settsu", - "shijonawate", - "shimamoto", - "suita", - "tadaoka", - "taishi", - "tajiri", - "takaishi", - "takatsuki", - "tondabayashi", - "toyonaka", - "toyono", - "yao", - "ariake", - "arita", - "fukudomi", - "genkai", - "hamatama", - "hizen", - "imari", - "kamimine", - "kanzaki", - "karatsu", - "kashima", - "kitagata", - "kitahata", - "kiyama", - "kouhoku", - "kyuragi", - "nishiarita", - "ogi", - "omachi", - "ouchi", - "saga", - "shiroishi", - "taku", - "tara", - "tosu", - "yoshinogari", - "arakawa", - "asaka", - "chichibu", - "fujimi", - "fujimino", - "fukaya", - "hanno", - "hanyu", - "hasuda", - "hatogaya", - "hatoyama", - "hidaka", - "higashichichibu", - "higashimatsuyama", - "honjo", - "ina", - "iruma", - "iwatsuki", - "kamiizumi", - "kamikawa", - "kamisato", - "kasukabe", - "kawagoe", - "kawaguchi", - "kawajima", - "kazo", - "kitamoto", - "koshigaya", - "kounosu", - "kuki", - "kumagaya", - "matsubushi", - "minano", - "misato", - "miyashiro", - "miyoshi", - "moroyama", - "nagatoro", - "namegawa", - "niiza", - "ogano", - "ogawa", - "ogose", - "okegawa", - "omiya", - "otaki", - "ranzan", - "ryokami", - "saitama", - "sakado", - "satte", - "sayama", - "shiki", - "shiraoka", - "soka", - "sugito", - "toda", - "tokigawa", - "tokorozawa", - "tsurugashima", - "urawa", - "warabi", - "yashio", - "yokoze", - "yono", - "yorii", - "yoshida", - "yoshikawa", - "yoshimi", - "city", - "city", - "aisho", - "gamo", - "higashiomi", - "hikone", - "koka", - "konan", - "kosei", - "koto", - "kusatsu", - "maibara", - "moriyama", - "nagahama", - "nishiazai", - "notogawa", - "omihachiman", - "otsu", - "ritto", - "ryuoh", - "takashima", - "takatsuki", - "torahime", - "toyosato", - "yasu", - "akagi", - "ama", - "gotsu", - "hamada", - "higashiizumo", - "hikawa", - "hikimi", - "izumo", - "kakinoki", - "masuda", - "matsue", - "misato", - "nishinoshima", - "ohda", - "okinoshima", - "okuizumo", - "shimane", - "tamayu", - "tsuwano", - "unnan", - "yakumo", - "yasugi", - "yatsuka", - "arai", - "atami", - "fuji", - "fujieda", - "fujikawa", - "fujinomiya", - "fukuroi", - "gotemba", - "haibara", - "hamamatsu", - "higashiizu", - "ito", - "iwata", - "izu", - "izunokuni", - "kakegawa", - "kannami", - "kawanehon", - "kawazu", - "kikugawa", - "kosai", - "makinohara", - "matsuzaki", - "minamiizu", - "mishima", - "morimachi", - "nishiizu", - "numazu", - "omaezaki", - "shimada", - "shimizu", - "shimoda", - "shizuoka", - "susono", - "yaizu", - "yoshida", - "ashikaga", - "bato", - "haga", - "ichikai", - "iwafune", - "kaminokawa", - "kanuma", - "karasuyama", - "kuroiso", - "mashiko", - "mibu", - "moka", - "motegi", - "nasu", - "nasushiobara", - "nikko", - "nishikata", - "nogi", - "ohira", - "ohtawara", - "oyama", - "sakura", - "sano", - "shimotsuke", - "shioya", - "takanezawa", - "tochigi", - "tsuga", - "ujiie", - "utsunomiya", - "yaita", - "aizumi", - "anan", - "ichiba", - "itano", - "kainan", - "komatsushima", - "matsushige", - "mima", - "minami", - "miyoshi", - "mugi", - "nakagawa", - "naruto", - "sanagochi", - "shishikui", - "tokushima", - "wajiki", - "adachi", - "akiruno", - "akishima", - "aogashima", - "arakawa", - "bunkyo", - "chiyoda", - "chofu", - "chuo", - "edogawa", - "fuchu", - "fussa", - "hachijo", - "hachioji", - "hamura", - "higashikurume", - "higashimurayama", - "higashiyamato", - "hino", - "hinode", - "hinohara", - "inagi", - "itabashi", - "katsushika", - "kita", - "kiyose", - "kodaira", - "koganei", - "kokubunji", - "komae", - "koto", - "kouzushima", - "kunitachi", - "machida", - "meguro", - "minato", - "mitaka", - "mizuho", - "musashimurayama", - "musashino", - "nakano", - "nerima", - "ogasawara", - "okutama", - "ome", - "oshima", - "ota", - "setagaya", - "shibuya", - "shinagawa", - "shinjuku", - "suginami", - "sumida", - "tachikawa", - "taito", - "tama", - "toshima", - "chizu", - "hino", - "kawahara", - "koge", - "kotoura", - "misasa", - "nanbu", - "nichinan", - "sakaiminato", - "tottori", - "wakasa", - "yazu", - "yonago", - "asahi", - "fuchu", - "fukumitsu", - "funahashi", - "himi", - "imizu", - "inami", - "johana", - "kamiichi", - "kurobe", - "nakaniikawa", - "namerikawa", - "nanto", - "nyuzen", - "oyabe", - "taira", - "takaoka", - "tateyama", - "toga", - "tonami", - "toyama", - "unazuki", - "uozu", - "yamada", - "arida", - "aridagawa", - "gobo", - "hashimoto", - "hidaka", - "hirogawa", - "inami", - "iwade", - "kainan", - "kamitonda", - "katsuragi", - "kimino", - "kinokawa", - "kitayama", - "koya", - "koza", - "kozagawa", - "kudoyama", - "kushimoto", - "mihama", - "misato", - "nachikatsuura", - "shingu", - "shirahama", - "taiji", - "tanabe", - "wakayama", - "yuasa", - "yura", - "asahi", - "funagata", - "higashine", - "iide", - "kahoku", - "kaminoyama", - "kaneyama", - "kawanishi", - "mamurogawa", - "mikawa", - "murayama", - "nagai", - "nakayama", - "nanyo", - "nishikawa", - "obanazawa", - "oe", - "oguni", - "ohkura", - "oishida", - "sagae", - "sakata", - "sakegawa", - "shinjo", - "shirataka", - "shonai", - "takahata", - "tendo", - "tozawa", - "tsuruoka", - "yamagata", - "yamanobe", - "yonezawa", - "yuza", - "abu", - "hagi", - "hikari", - "hofu", - "iwakuni", - "kudamatsu", - "mitou", - "nagato", - "oshima", - "shimonoseki", - "shunan", - "tabuse", - "tokuyama", - "toyota", - "ube", - "yuu", - "chuo", - "doshi", - "fuefuki", - "fujikawa", - "fujikawaguchiko", - "fujiyoshida", - "hayakawa", - "hokuto", - "ichikawamisato", - "kai", - "kofu", - "koshu", - "kosuge", - "minami-alps", - "minobu", - "nakamichi", - "nanbu", - "narusawa", - "nirasaki", - "nishikatsura", - "oshino", - "otsuki", - "showa", - "tabayama", - "tsuru", - "uenohara", - "yamanakako", - "yamanashi", - "city", - "ac", - "co", - "go", - "info", - "me", - "mobi", - "ne", - "nom", - "or", - "sc", - "blogspot", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "biz", - "com", - "edu", - "gov", - "info", - "net", - "org", - "ass", - "asso", - "com", - "coop", - "edu", - "gouv", - "gov", - "medecin", - "mil", - "nom", - "notaires", - "org", - "pharmaciens", - "prd", - "presse", - "tm", - "veterinaire", - "edu", - "gov", - "net", - "org", - "com", - "edu", - "gov", - "org", - "rep", - "tra", - "ac", - "blogspot", - "busan", - "chungbuk", - "chungnam", - "co", - "daegu", - "daejeon", - "es", - "gangwon", - "go", - "gwangju", - "gyeongbuk", - "gyeonggi", - "gyeongnam", - "hs", - "incheon", - "jeju", - "jeonbuk", - "jeonnam", - "kg", - "mil", - "ms", - "ne", - "or", - "pe", - "re", - "sc", - "seoul", - "ulsan", - "co", - "edu", - "com", - "edu", - "emb", - "gov", - "ind", - "net", - "org", - "com", - "edu", - "gov", - "net", - "org", - "com", - "edu", - "gov", - "mil", - "net", - "nym", - "org", - "bnr", - "c", - "com", - "edu", - "gov", - "info", - "int", - "net", - "nym", - "org", - "per", - "static", - "dev", - "sites", - "com", - "edu", - "gov", - "net", - "org", - "co", - "com", - "edu", - "gov", - "net", - "nym", - "org", - "oy", - "blogspot", - "caa", - "nom", - "nym", - "cyon", - "dweb", - "mypep", - "ac", - "assn", - "com", - "edu", - "gov", - "grp", - "hotel", - "int", - "ltd", - "net", - "ngo", - "org", - "sch", - "soc", - "web", - "in", - "of", - "com", - "edu", - "gov", - "net", - "org", - "ac", - "biz", - "co", - "edu", - "gov", - "info", - "net", - "org", - "sc", - "blogspot", - "gov", - "nym", - "blogspot", - "nym", - "asn", - "com", - "conf", - "edu", - "gov", - "id", - "mil", - "net", - "org", - "com", - "edu", - "gov", - "id", - "med", - "net", - "org", - "plc", - "sch", - "ac", - "co", - "gov", - "net", - "org", - "press", - "router", - "asso", - "tm", - "blogspot", - "ac", - "barsy", - "brasilia", - "c66", - "co", - "daplie", - "ddns", - "diskstation", - "dnsfor", - "dscloud", - "edu", - "filegear", - "filegear-au", - "filegear-de", - "filegear-gb", - "filegear-ie", - "filegear-jp", - "filegear-sg", - "glitch", - "gov", - "hopto", - "i234", - "its", - "loginto", - "myds", - "nctu", - "net", - "nohost", - "noip", - "nym", - "org", - "priv", - "ravendb", - "soundcast", - "synology", - "tcp4", - "webhop", - "wedeploy", - "yombo", - "localhost", - "for", - "barsy", - "co", - "com", - "edu", - "gov", - "mil", - "nom", - "org", - "prd", - "tm", - "blogspot", - "com", - "edu", - "gov", - "inf", - "name", - "net", - "nom", - "org", - "com", - "edu", - "gouv", - "gov", - "net", - "org", - "presse", - "edu", - "gov", - "nyc", - "nym", - "org", - "com", - "edu", - "gov", - "net", - "org", - "barsy", - "dscloud", - "and", - "for", - "blogspot", - "gov", - "com", - "edu", - "gov", - "lab", - "net", - "org", - "com", - "edu", - "net", - "org", - "blogspot", - "ac", - "co", - "com", - "gov", - "net", - "or", - "org", - "academy", - "agriculture", - "air", - "airguard", - "alabama", - "alaska", - "amber", - "ambulance", - "american", - "americana", - "americanantiques", - "americanart", - "amsterdam", - "and", - "annefrank", - "anthro", - "anthropology", - "antiques", - "aquarium", - "arboretum", - "archaeological", - "archaeology", - "architecture", - "art", - "artanddesign", - "artcenter", - "artdeco", - "arteducation", - "artgallery", - "arts", - "artsandcrafts", - "asmatart", - "assassination", - "assisi", - "association", - "astronomy", - "atlanta", - "austin", - "australia", - "automotive", - "aviation", - "axis", - "badajoz", - "baghdad", - "bahn", - "bale", - "baltimore", - "barcelona", - "baseball", - "basel", - "baths", - "bauern", - "beauxarts", - "beeldengeluid", - "bellevue", - "bergbau", - "berkeley", - "berlin", - "bern", - "bible", - "bilbao", - "bill", - "birdart", - "birthplace", - "bonn", - "boston", - "botanical", - "botanicalgarden", - "botanicgarden", - "botany", - "brandywinevalley", - "brasil", - "bristol", - "british", - "britishcolumbia", - "broadcast", - "brunel", - "brussel", - "brussels", - "bruxelles", - "building", - "burghof", - "bus", - "bushey", - "cadaques", - "california", - "cambridge", - "can", - "canada", - "capebreton", - "carrier", - "cartoonart", - "casadelamoneda", - "castle", - "castres", - "celtic", - "center", - "chattanooga", - "cheltenham", - "chesapeakebay", - "chicago", - "children", - "childrens", - "childrensgarden", - "chiropractic", - "chocolate", - "christiansburg", - "cincinnati", - "cinema", - "circus", - "civilisation", - "civilization", - "civilwar", - "clinton", - "clock", - "coal", - "coastaldefence", - "cody", - "coldwar", - "collection", - "colonialwilliamsburg", - "coloradoplateau", - "columbia", - "columbus", - "communication", - "communications", - "community", - "computer", - "computerhistory", - "contemporary", - "contemporaryart", - "convent", - "copenhagen", - "corporation", - "corvette", - "costume", - "countryestate", - "county", - "crafts", - "cranbrook", - "creation", - "cultural", - "culturalcenter", - "culture", - "cyber", - "cymru", - "dali", - "dallas", - "database", - "ddr", - "decorativearts", - "delaware", - "delmenhorst", - "denmark", - "depot", - "design", - "detroit", - "dinosaur", - "discovery", - "dolls", - "donostia", - "durham", - "eastafrica", - "eastcoast", - "education", - "educational", - "egyptian", - "eisenbahn", - "elburg", - "elvendrell", - "embroidery", - "encyclopedic", - "england", - "entomology", - "environment", - "environmentalconservation", - "epilepsy", - "essex", - "estate", - "ethnology", - "exeter", - "exhibition", - "family", - "farm", - "farmequipment", - "farmers", - "farmstead", - "field", - "figueres", - "filatelia", - "film", - "fineart", - "finearts", - "finland", - "flanders", - "florida", - "force", - "fortmissoula", - "fortworth", - "foundation", - "francaise", - "frankfurt", - "franziskaner", - "freemasonry", - "freiburg", - "fribourg", - "frog", - "fundacio", - "furniture", - "gallery", - "garden", - "gateway", - "geelvinck", - "gemological", - "geology", - "georgia", - "giessen", - "glas", - "glass", - "gorge", - "grandrapids", - "graz", - "guernsey", - "halloffame", - "hamburg", - "handson", - "harvestcelebration", - "hawaii", - "health", - "heimatunduhren", - "hellas", - "helsinki", - "hembygdsforbund", - "heritage", - "histoire", - "historical", - "historicalsociety", - "historichouses", - "historisch", - "historisches", - "history", - "historyofscience", - "horology", - "house", - "humanities", - "illustration", - "imageandsound", - "indian", - "indiana", - "indianapolis", - "indianmarket", - "intelligence", - "interactive", - "iraq", - "iron", - "isleofman", - "jamison", - "jefferson", - "jerusalem", - "jewelry", - "jewish", - "jewishart", - "jfk", - "journalism", - "judaica", - "judygarland", - "juedisches", - "juif", - "karate", - "karikatur", - "kids", - "koebenhavn", - "koeln", - "kunst", - "kunstsammlung", - "kunstunddesign", - "labor", - "labour", - "lajolla", - "lancashire", - "landes", - "lans", - "larsson", - "lewismiller", - "lincoln", - "linz", - "living", - "livinghistory", - "localhistory", - "london", - "losangeles", - "louvre", - "loyalist", - "lucerne", - "luxembourg", - "luzern", - "mad", - "madrid", - "mallorca", - "manchester", - "mansion", - "mansions", - "manx", - "marburg", - "maritime", - "maritimo", - "maryland", - "marylhurst", - "media", - "medical", - "medizinhistorisches", - "meeres", - "memorial", - "mesaverde", - "michigan", - "midatlantic", - "military", - "mill", - "miners", - "mining", - "minnesota", - "missile", - "missoula", - "modern", - "moma", - "money", - "monmouth", - "monticello", - "montreal", - "moscow", - "motorcycle", - "muenchen", - "muenster", - "mulhouse", - "muncie", - "museet", - "museumcenter", - "museumvereniging", - "music", - "national", - "nationalfirearms", - "nationalheritage", - "nativeamerican", - "naturalhistory", - "naturalhistorymuseum", - "naturalsciences", - "nature", - "naturhistorisches", - "natuurwetenschappen", - "naumburg", - "naval", - "nebraska", - "neues", - "newhampshire", - "newjersey", - "newmexico", - "newport", - "newspaper", - "newyork", - "niepce", - "norfolk", - "north", - "nrw", - "nuernberg", - "nuremberg", - "nyc", - "nyny", - "oceanographic", - "oceanographique", - "omaha", - "online", - "ontario", - "openair", - "oregon", - "oregontrail", - "otago", - "oxford", - "pacific", - "paderborn", - "palace", - "paleo", - "palmsprings", - "panama", - "paris", - "pasadena", - "pharmacy", - "philadelphia", - "philadelphiaarea", - "philately", - "phoenix", - "photography", - "pilots", - "pittsburgh", - "planetarium", - "plantation", - "plants", - "plaza", - "portal", - "portland", - "portlligat", - "posts-and-telecommunications", - "preservation", - "presidio", - "press", - "project", - "public", - "pubol", - "quebec", - "railroad", - "railway", - "research", - "resistance", - "riodejaneiro", - "rochester", - "rockart", - "roma", - "russia", - "saintlouis", - "salem", - "salvadordali", - "salzburg", - "sandiego", - "sanfrancisco", - "santabarbara", - "santacruz", - "santafe", - "saskatchewan", - "satx", - "savannahga", - "schlesisches", - "schoenbrunn", - "schokoladen", - "school", - "schweiz", - "science", - "science-fiction", - "scienceandhistory", - "scienceandindustry", - "sciencecenter", - "sciencecenters", - "sciencehistory", - "sciences", - "sciencesnaturelles", - "scotland", - "seaport", - "settlement", - "settlers", - "shell", - "sherbrooke", - "sibenik", - "silk", - "ski", - "skole", - "society", - "sologne", - "soundandvision", - "southcarolina", - "southwest", - "space", - "spy", - "square", - "stadt", - "stalbans", - "starnberg", - "state", - "stateofdelaware", - "station", - "steam", - "steiermark", - "stjohn", - "stockholm", - "stpetersburg", - "stuttgart", - "suisse", - "surgeonshall", - "surrey", - "svizzera", - "sweden", - "sydney", - "tank", - "tcm", - "technology", - "telekommunikation", - "television", - "texas", - "textile", - "theater", - "time", - "timekeeping", - "topology", - "torino", - "touch", - "town", - "transport", - "tree", - "trolley", - "trust", - "trustee", - "uhren", - "ulm", - "undersea", - "university", - "usa", - "usantiques", - "usarts", - "uscountryestate", - "usculture", - "usdecorativearts", - "usgarden", - "ushistory", - "ushuaia", - "uslivinghistory", - "utah", - "uvic", - "valley", - "vantaa", - "versailles", - "viking", - "village", - "virginia", - "virtual", - "virtuel", - "vlaanderen", - "volkenkunde", - "wales", - "wallonie", - "war", - "washingtondc", - "watch-and-clock", - "watchandclock", - "western", - "westfalen", - "whaling", - "wildlife", - "williamsburg", - "windmill", - "workshop", - "xn--9dbhblg6di", - "xn--comunicaes-v6a2o", - "xn--correios-e-telecomunicaes-ghc29a", - "xn--h1aegh", - "xn--lns-qla", - "york", - "yorkshire", - "yosemite", - "youth", - "zoological", - "zoology", - "aero", - "biz", - "com", - "coop", - "edu", - "gov", - "info", - "int", - "mil", - "museum", - "name", - "net", - "org", - "pro", - "ac", - "biz", - "co", - "com", - "coop", - "edu", - "gov", - "int", - "museum", - "net", - "org", - "blogspot", - "com", - "edu", - "gob", - "net", - "nym", - "org", - "blogspot", - "com", - "edu", - "gov", - "mil", - "name", - "net", - "org", - "ac", - "adv", - "co", - "edu", - "gov", - "mil", - "net", - "org", - "ca", - "cc", - "co", - "com", - "dr", - "in", - "info", - "mobi", - "mx", - "name", - "or", - "org", - "pro", - "school", - "tv", - "us", - "ws", - "her", - "his", - "forgot", - "forgot", - "asso", - "nom", - "alwaysdata", - "at-band-camp", - "azure-mobile", - "azurewebsites", - "barsy", - "blackbaudcdn", - "blogdns", - "boomla", - "bounceme", - "bplaced", - "broke-it", - "buyshouses", - "casacam", - "cdn77", - "cdn77-ssl", - "channelsdvr", - "cloudaccess", - "cloudapp", - "cloudeity", - "cloudfront", - "cloudfunctions", - "cloudycluster", - "cryptonomic", - "dattolocal", - "ddns", - "debian", - "definima", - "dnsalias", - "dnsdojo", - "dnsup", - "does-it", - "dontexist", - "dsmynas", - "dynalias", - "dynathome", - "dynu", - "dynv6", - "eating-organic", - "endofinternet", - "familyds", - "fastly", - "fastlylb", - "feste-ip", - "firewall-gateway", - "flynnhosting", - "from-az", - "from-co", - "from-la", - "from-ny", - "gb", - "gets-it", - "go-vip", - "ham-radio-op", - "hicam", - "homeftp", - "homeip", - "homelinux", - "homeunix", - "hu", - "in", - "in-dsl", - "in-the-band", - "in-vpn", - "iobb", - "ipifony", - "is-a-chef", - "is-a-geek", - "isa-geek", - "jp", - "kicks-ass", - "kinghost", - "knx-server", - "memset", - "moonscale", - "mydatto", - "mydissent", - "myeffect", - "myfritz", - "mymediapc", - "mypsx", - "mysecuritycamera", - "nhlfan", - "no-ip", - "now-dns", - "office-on-the", - "ownip", - "pgafan", - "podzone", - "privatizehealthinsurance", - "rackmaze", - "redirectme", - "ru", - "schokokeks", - "scrapper-site", - "se", - "selfip", - "sells-it", - "servebbs", - "serveblog", - "serveftp", - "serveminecraft", - "siteleaf", - "square7", - "srcf", - "static-access", - "sytes", - "t3l3p0rt", - "thruhere", - "twmail", - "uk", - "uni5", - "vpndns", - "webhop", - "za", - "r", - "freetls", - "map", - "prod", - "ssl", - "a", - "global", - "a", - "b", - "global", - "map", - "soc", - "user", - "alces", - "arvo", - "azimuth", - "co", - "arts", - "com", - "firm", - "info", - "net", - "other", - "per", - "rec", - "store", - "web", - "col", - "com", - "edu", - "gen", - "gov", - "i", - "ltd", - "mil", - "mobi", - "name", - "net", - "org", - "sch", - "blogspot", - "ac", - "biz", - "co", - "com", - "edu", - "gob", - "in", - "info", - "int", - "mil", - "net", - "nom", - "org", - "web", - "blogspot", - "cistron", - "co", - "demon", - "hosting-cluster", - "khplay", - "transurl", - "virtueeldomein", - "aa", - "aarborte", - "aejrie", - "afjord", - "agdenes", - "ah", - "akershus", - "aknoluokta", - "akrehamn", - "al", - "alaheadju", - "alesund", - "algard", - "alstahaug", - "alta", - "alvdal", - "amli", - "amot", - "andasuolo", - "andebu", - "andoy", - "ardal", - "aremark", - "arendal", - "arna", - "aseral", - "asker", - "askim", - "askoy", - "askvoll", - "asnes", - "audnedaln", - "aukra", - "aure", - "aurland", - "aurskog-holand", - "austevoll", - "austrheim", - "averoy", - "badaddja", - "bahcavuotna", - "bahccavuotna", - "baidar", - "bajddar", - "balat", - "balestrand", - "ballangen", - "balsfjord", - "bamble", - "bardu", - "barum", - "batsfjord", - "bearalvahki", - "beardu", - "beiarn", - "berg", - "bergen", - "berlevag", - "bievat", - "bindal", - "birkenes", - "bjarkoy", - "bjerkreim", - "bjugn", - "blogspot", - "bodo", - "bokn", - "bomlo", - "bremanger", - "bronnoy", - "bronnoysund", - "brumunddal", - "bryne", - "bu", - "budejju", - "buskerud", - "bygland", - "bykle", - "cahcesuolo", - "co", - "davvenjarga", - "davvesiida", - "deatnu", - "dep", - "dielddanuorri", - "divtasvuodna", - "divttasvuotna", - "donna", - "dovre", - "drammen", - "drangedal", - "drobak", - "dyroy", - "egersund", - "eid", - "eidfjord", - "eidsberg", - "eidskog", - "eidsvoll", - "eigersund", - "elverum", - "enebakk", - "engerdal", - "etne", - "etnedal", - "evenassi", - "evenes", - "evje-og-hornnes", - "farsund", - "fauske", - "fedje", - "fet", - "fetsund", - "fhs", - "finnoy", - "fitjar", - "fjaler", - "fjell", - "fla", - "flakstad", - "flatanger", - "flekkefjord", - "flesberg", - "flora", - "floro", - "fm", - "folkebibl", - "folldal", - "forde", - "forsand", - "fosnes", - "frana", - "fredrikstad", - "frei", - "frogn", - "froland", - "frosta", - "froya", - "fuoisku", - "fuossko", - "fusa", - "fylkesbibl", - "fyresdal", - "gaivuotna", - "galsa", - "gamvik", - "gangaviika", - "gaular", - "gausdal", - "giehtavuoatna", - "gildeskal", - "giske", - "gjemnes", - "gjerdrum", - "gjerstad", - "gjesdal", - "gjovik", - "gloppen", - "gol", - "gran", - "grane", - "granvin", - "gratangen", - "grimstad", - "grong", - "grue", - "gulen", - "guovdageaidnu", - "ha", - "habmer", - "hadsel", - "hagebostad", - "halden", - "halsa", - "hamar", - "hamaroy", - "hammarfeasta", - "hammerfest", - "hapmir", - "haram", - "hareid", - "harstad", - "hasvik", - "hattfjelldal", - "haugesund", - "hedmark", - "hemne", - "hemnes", - "hemsedal", - "herad", - "hitra", - "hjartdal", - "hjelmeland", - "hl", - "hm", - "hobol", - "hof", - "hokksund", - "hol", - "hole", - "holmestrand", - "holtalen", - "honefoss", - "hordaland", - "hornindal", - "horten", - "hoyanger", - "hoylandet", - "hurdal", - "hurum", - "hvaler", - "hyllestad", - "ibestad", - "idrett", - "inderoy", - "iveland", - "ivgu", - "jan-mayen", - "jessheim", - "jevnaker", - "jolster", - "jondal", - "jorpeland", - "kafjord", - "karasjohka", - "karasjok", - "karlsoy", - "karmoy", - "kautokeino", - "kirkenes", - "klabu", - "klepp", - "kommune", - "kongsberg", - "kongsvinger", - "kopervik", - "kraanghke", - "kragero", - "kristiansand", - "kristiansund", - "krodsherad", - "krokstadelva", - "kvafjord", - "kvalsund", - "kvam", - "kvanangen", - "kvinesdal", - "kvinnherad", - "kviteseid", - "kvitsoy", - "laakesvuemie", - "lahppi", - "langevag", - "lardal", - "larvik", - "lavagis", - "lavangen", - "leangaviika", - "lebesby", - "leikanger", - "leirfjord", - "leirvik", - "leka", - "leksvik", - "lenvik", - "lerdal", - "lesja", - "levanger", - "lier", - "lierne", - "lillehammer", - "lillesand", - "lindas", - "lindesnes", - "loabat", - "lodingen", - "lom", - "loppa", - "lorenskog", - "loten", - "lund", - "lunner", - "luroy", - "luster", - "lyngdal", - "lyngen", - "malatvuopmi", - "malselv", - "malvik", - "mandal", - "marker", - "marnardal", - "masfjorden", - "masoy", - "matta-varjjat", - "meland", - "meldal", - "melhus", - "meloy", - "meraker", - "midsund", - "midtre-gauldal", - "mil", - "mjondalen", - "mo-i-rana", - "moareke", - "modalen", - "modum", - "molde", - "more-og-romsdal", - "mosjoen", - "moskenes", - "moss", - "mosvik", - "mr", - "muosat", - "museum", - "naamesjevuemie", - "namdalseid", - "namsos", - "namsskogan", - "nannestad", - "naroy", - "narviika", - "narvik", - "naustdal", - "navuotna", - "nedre-eiker", - "nesna", - "nesodden", - "nesoddtangen", - "nesseby", - "nesset", - "nissedal", - "nittedal", - "nl", - "nord-aurdal", - "nord-fron", - "nord-odal", - "norddal", - "nordkapp", - "nordland", - "nordre-land", - "nordreisa", - "nore-og-uvdal", - "notodden", - "notteroy", - "nt", - "odda", - "of", - "oksnes", - "ol", - "omasvuotna", - "oppdal", - "oppegard", - "orkanger", - "orkdal", - "orland", - "orskog", - "orsta", - "osen", - "oslo", - "osoyro", - "osteroy", - "ostfold", - "ostre-toten", - "overhalla", - "ovre-eiker", - "oyer", - "oygarden", - "oystre-slidre", - "porsanger", - "porsangu", - "porsgrunn", - "priv", - "rade", - "radoy", - "rahkkeravju", - "raholt", - "raisa", - "rakkestad", - "ralingen", - "rana", - "randaberg", - "rauma", - "rendalen", - "rennebu", - "rennesoy", - "rindal", - "ringebu", - "ringerike", - "ringsaker", - "risor", - "rissa", - "rl", - "roan", - "rodoy", - "rollag", - "romsa", - "romskog", - "roros", - "rost", - "royken", - "royrvik", - "ruovat", - "rygge", - "salangen", - "salat", - "saltdal", - "samnanger", - "sandefjord", - "sandnes", - "sandnessjoen", - "sandoy", - "sarpsborg", - "sauda", - "sauherad", - "sel", - "selbu", - "selje", - "seljord", - "sf", - "siellak", - "sigdal", - "siljan", - "sirdal", - "skanit", - "skanland", - "skaun", - "skedsmo", - "skedsmokorset", - "ski", - "skien", - "skierva", - "skiptvet", - "skjak", - "skjervoy", - "skodje", - "slattum", - "smola", - "snaase", - "snasa", - "snillfjord", - "snoasa", - "sogndal", - "sogne", - "sokndal", - "sola", - "solund", - "somna", - "sondre-land", - "songdalen", - "sor-aurdal", - "sor-fron", - "sor-odal", - "sor-varanger", - "sorfold", - "sorreisa", - "sortland", - "sorum", - "spjelkavik", - "spydeberg", - "st", - "stange", - "stat", - "stathelle", - "stavanger", - "stavern", - "steigen", - "steinkjer", - "stjordal", - "stjordalshalsen", - "stokke", - "stor-elvdal", - "stord", - "stordal", - "storfjord", - "strand", - "stranda", - "stryn", - "sula", - "suldal", - "sund", - "sunndal", - "surnadal", - "svalbard", - "sveio", - "svelvik", - "sykkylven", - "tana", - "tananger", - "telemark", - "time", - "tingvoll", - "tinn", - "tjeldsund", - "tjome", - "tm", - "tokke", - "tolga", - "tonsberg", - "torsken", - "tr", - "trana", - "tranby", - "tranoy", - "troandin", - "trogstad", - "tromsa", - "tromso", - "trondheim", - "trysil", - "tvedestrand", - "tydal", - "tynset", - "tysfjord", - "tysnes", - "tysvar", - "ullensaker", - "ullensvang", - "ulvik", - "unjarga", - "utsira", - "va", - "vaapste", - "vadso", - "vaga", - "vagan", - "vagsoy", - "vaksdal", - "valle", - "vang", - "vanylven", - "vardo", - "varggat", - "varoy", - "vefsn", - "vega", - "vegarshei", - "vennesla", - "verdal", - "verran", - "vestby", - "vestfold", - "vestnes", - "vestre-slidre", - "vestre-toten", - "vestvagoy", - "vevelstad", - "vf", - "vgs", - "vik", - "vikna", - "vindafjord", - "voagat", - "volda", - "voss", - "vossevangen", - "xn--andy-ira", - "xn--asky-ira", - "xn--aurskog-hland-jnb", - "xn--avery-yua", - "xn--bdddj-mrabd", - "xn--bearalvhki-y4a", - "xn--berlevg-jxa", - "xn--bhcavuotna-s4a", - "xn--bhccavuotna-k7a", - "xn--bidr-5nac", - "xn--bievt-0qa", - "xn--bjarky-fya", - "xn--bjddar-pta", - "xn--blt-elab", - "xn--bmlo-gra", - "xn--bod-2na", - "xn--brnny-wuac", - "xn--brnnysund-m8ac", - "xn--brum-voa", - "xn--btsfjord-9za", - "xn--davvenjrga-y4a", - "xn--dnna-gra", - "xn--drbak-wua", - "xn--dyry-ira", - "xn--eveni-0qa01ga", - "xn--finny-yua", - "xn--fjord-lra", - "xn--fl-zia", - "xn--flor-jra", - "xn--frde-gra", - "xn--frna-woa", - "xn--frya-hra", - "xn--ggaviika-8ya47h", - "xn--gildeskl-g0a", - "xn--givuotna-8ya", - "xn--gjvik-wua", - "xn--gls-elac", - "xn--h-2fa", - "xn--hbmer-xqa", - "xn--hcesuolo-7ya35b", - "xn--hgebostad-g3a", - "xn--hmmrfeasta-s4ac", - "xn--hnefoss-q1a", - "xn--hobl-ira", - "xn--holtlen-hxa", - "xn--hpmir-xqa", - "xn--hyanger-q1a", - "xn--hylandet-54a", - "xn--indery-fya", - "xn--jlster-bya", - "xn--jrpeland-54a", - "xn--karmy-yua", - "xn--kfjord-iua", - "xn--klbu-woa", - "xn--koluokta-7ya57h", - "xn--krager-gya", - "xn--kranghke-b0a", - "xn--krdsherad-m8a", - "xn--krehamn-dxa", - "xn--krjohka-hwab49j", - "xn--ksnes-uua", - "xn--kvfjord-nxa", - "xn--kvitsy-fya", - "xn--kvnangen-k0a", - "xn--l-1fa", - "xn--laheadju-7ya", - "xn--langevg-jxa", - "xn--ldingen-q1a", - "xn--leagaviika-52b", - "xn--lesund-hua", - "xn--lgrd-poac", - "xn--lhppi-xqa", - "xn--linds-pra", - "xn--loabt-0qa", - "xn--lrdal-sra", - "xn--lrenskog-54a", - "xn--lt-liac", - "xn--lten-gra", - "xn--lury-ira", - "xn--mely-ira", - "xn--merker-kua", - "xn--mjndalen-64a", - "xn--mlatvuopmi-s4a", - "xn--mli-tla", - "xn--mlselv-iua", - "xn--moreke-jua", - "xn--mosjen-eya", - "xn--mot-tla", - "xn--mre-og-romsdal-qqb", - "xn--msy-ula0h", - "xn--mtta-vrjjat-k7af", - "xn--muost-0qa", - "xn--nmesjevuemie-tcba", - "xn--nry-yla5g", - "xn--nttery-byae", - "xn--nvuotna-hwa", - "xn--oppegrd-ixa", - "xn--ostery-fya", - "xn--osyro-wua", - "xn--porsgu-sta26f", - "xn--rady-ira", - "xn--rdal-poa", - "xn--rde-ula", - "xn--rdy-0nab", - "xn--rennesy-v1a", - "xn--rhkkervju-01af", - "xn--rholt-mra", - "xn--risa-5na", - "xn--risr-ira", - "xn--rland-uua", - "xn--rlingen-mxa", - "xn--rmskog-bya", - "xn--rros-gra", - "xn--rskog-uua", - "xn--rst-0na", - "xn--rsta-fra", - "xn--ryken-vua", - "xn--ryrvik-bya", - "xn--s-1fa", - "xn--sandnessjen-ogb", - "xn--sandy-yua", - "xn--seral-lra", - "xn--sgne-gra", - "xn--skierv-uta", - "xn--skjervy-v1a", - "xn--skjk-soa", - "xn--sknit-yqa", - "xn--sknland-fxa", - "xn--slat-5na", - "xn--slt-elab", - "xn--smla-hra", - "xn--smna-gra", - "xn--snase-nra", - "xn--sndre-land-0cb", - "xn--snes-poa", - "xn--snsa-roa", - "xn--sr-aurdal-l8a", - "xn--sr-fron-q1a", - "xn--sr-odal-q1a", - "xn--sr-varanger-ggb", - "xn--srfold-bya", - "xn--srreisa-q1a", - "xn--srum-gra", - "xn--stfold-9xa", - "xn--stjrdal-s1a", - "xn--stjrdalshalsen-sqb", - "xn--stre-toten-zcb", - "xn--tjme-hra", - "xn--tnsberg-q1a", - "xn--trany-yua", - "xn--trgstad-r1a", - "xn--trna-woa", - "xn--troms-zua", - "xn--tysvr-vra", - "xn--unjrga-rta", - "xn--vads-jra", - "xn--vard-jra", - "xn--vegrshei-c0a", - "xn--vestvgy-ixa6o", - "xn--vg-yiab", - "xn--vgan-qoa", - "xn--vgsy-qoa0j", - "xn--vre-eiker-k8a", - "xn--vrggt-xqad", - "xn--vry-yla5g", - "xn--yer-zna", - "xn--ygarden-p1a", - "xn--ystre-slidre-ujb", - "gs", - "gs", - "nes", - "gs", - "nes", - "gs", - "os", - "valer", - "xn--vler-qoa", - "gs", - "gs", - "os", - "gs", - "heroy", - "sande", - "gs", - "gs", - "bo", - "heroy", - "xn--b-5ga", - "xn--hery-ira", - "gs", - "gs", - "gs", - "gs", - "valer", - "gs", - "gs", - "gs", - "gs", - "bo", - "xn--b-5ga", - "gs", - "gs", - "gs", - "sande", - "gs", - "sande", - "xn--hery-ira", - "xn--vler-qoa", - "biz", - "com", - "edu", - "gov", - "info", - "net", - "org", - "builder", - "enterprisecloud", - "merseine", - "mine", - "nom", - "shacknet", - "site", - "ac", - "co", - "cri", - "geek", - "gen", - "govt", - "health", - "iwi", - "kiwi", - "maori", - "mil", - "net", - "nym", - "org", - "parliament", - "school", - "xn--mori-qsa", - "blogspot", - "co", - "com", - "edu", - "gov", - "med", - "museum", - "net", - "org", - "pro", - "for", - "homelink", - "onred", - "staging", - "barsy", - "accesscam", - "ae", - "amune", - "barsy", - "blogdns", - "blogsite", - "bmoattachments", - "boldlygoingnowhere", - "cable-modem", - "camdvr", - "cdn77", - "cdn77-secure", - "certmgr", - "cloudns", - "collegefan", - "couchpotatofries", - "ddnss", - "diskstation", - "dnsalias", - "dnsdojo", - "doesntexist", - "dontexist", - "doomdns", - "dsmynas", - "duckdns", - "dvrdns", - "dynalias", - "dyndns", - "dynserv", - "edugit", - "endofinternet", - "endoftheinternet", - "eu", - "familyds", - "fedorainfracloud", - "fedorapeople", - "fedoraproject", - "freeddns", - "freedesktop", - "from-me", - "game-host", - "gotdns", - "hepforge", - "hk", - "hobby-site", - "homedns", - "homeftp", - "homelinux", - "homeunix", - "hopto", - "in-dsl", - "in-vpn", - "is-a-bruinsfan", - "is-a-candidate", - "is-a-celticsfan", - "is-a-chef", - "is-a-geek", - "is-a-knight", - "is-a-linux-user", - "is-a-patsfan", - "is-a-soxfan", - "is-found", - "is-lost", - "is-saved", - "is-very-bad", - "is-very-evil", - "is-very-good", - "is-very-nice", - "is-very-sweet", - "isa-geek", - "js", - "kicks-ass", - "mayfirst", - "misconfused", - "mlbfan", - "mozilla-iot", - "my-firewall", - "myfirewall", - "myftp", - "mysecuritycamera", - "mywire", - "nflfan", - "no-ip", - "now-dns", - "pimienta", - "podzone", - "poivron", - "potager", - "read-books", - "readmyblog", - "selfip", - "sellsyourhome", - "servebbs", - "serveftp", - "servegame", - "spdns", - "stuff-4-sale", - "sweetpepper", - "tunk", - "tuxfamily", - "twmail", - "ufcfan", - "uklugs", - "us", - "webhop", - "webredirect", - "wmflabs", - "za", - "zapto", - "tele", - "c", - "rsc", - "origin", - "ssl", - "go", - "home", - "al", - "asso", - "at", - "au", - "be", - "bg", - "ca", - "cd", - "ch", - "cn", - "cy", - "cz", - "de", - "dk", - "edu", - "ee", - "es", - "fi", - "fr", - "gr", - "hr", - "hu", - "ie", - "il", - "in", - "int", - "is", - "it", - "jp", - "kr", - "lt", - "lu", - "lv", - "mc", - "me", - "mk", - "mt", - "my", - "net", - "ng", - "nl", - "no", - "nz", - "paris", - "pl", - "pt", - "q-a", - "ro", - "ru", - "se", - "si", - "sk", - "tr", - "uk", - "us", - "cloud", - "os", - "stg", - "app", - "os", - "app", - "nerdpol", - "abo", - "ac", - "com", - "edu", - "gob", - "ing", - "med", - "net", - "nom", - "org", - "sld", - "prvcy", - "ybo", - "blogspot", - "com", - "edu", - "gob", - "mil", - "net", - "nom", - "nym", - "org", - "com", - "edu", - "org", - "com", - "edu", - "gov", - "i", - "mil", - "net", - "ngo", - "org", - "1337", - "biz", - "com", - "edu", - "fam", - "gob", - "gok", - "gon", - "gop", - "gos", - "gov", - "info", - "net", - "org", - "web", - "agro", - "aid", - "art", - "atm", - "augustow", - "auto", - "babia-gora", - "bedzin", - "beep", - "beskidy", - "bialowieza", - "bialystok", - "bielawa", - "bieszczady", - "biz", - "boleslawiec", - "bydgoszcz", - "bytom", - "cieszyn", - "co", - "com", - "czeladz", - "czest", - "dlugoleka", - "edu", - "elblag", - "elk", - "gda", - "gdansk", - "gdynia", - "gliwice", - "glogow", - "gmina", - "gniezno", - "gorlice", - "gov", - "grajewo", - "gsm", - "ilawa", - "info", - "jaworzno", - "jelenia-gora", - "jgora", - "kalisz", - "karpacz", - "kartuzy", - "kaszuby", - "katowice", - "kazimierz-dolny", - "kepno", - "ketrzyn", - "klodzko", - "kobierzyce", - "kolobrzeg", - "konin", - "konskowola", - "krakow", - "krasnik", - "kutno", - "lapy", - "lebork", - "leczna", - "legnica", - "lezajsk", - "limanowa", - "lomza", - "lowicz", - "lubartow", - "lubin", - "lublin", - "lukow", - "mail", - "malbork", - "malopolska", - "mazowsze", - "mazury", - "med", - "media", - "miasta", - "mielec", - "mielno", - "mil", - "mragowo", - "naklo", - "net", - "nieruchomosci", - "nom", - "nowaruda", - "nysa", - "olawa", - "olecko", - "olkusz", - "olsztyn", - "opoczno", - "opole", - "org", - "ostroda", - "ostroleka", - "ostrowiec", - "ostrowwlkp", - "pc", - "pila", - "pisz", - "podhale", - "podlasie", - "polkowice", - "pomorskie", - "pomorze", - "poniatowa", - "powiat", - "poznan", - "priv", - "prochowice", - "pruszkow", - "przeworsk", - "pulawy", - "radom", - "rawa-maz", - "realestate", - "rel", - "rybnik", - "rzeszow", - "sanok", - "sejny", - "sex", - "shop", - "sklep", - "skoczow", - "slask", - "slupsk", - "sopot", - "sos", - "sosnowiec", - "stalowa-wola", - "starachowice", - "stargard", - "suwalki", - "swidnica", - "swidnik", - "swiebodzin", - "swinoujscie", - "szczecin", - "szczytno", - "szkola", - "targi", - "tarnobrzeg", - "tgory", - "tm", - "tourism", - "travel", - "turek", - "turystyka", - "tychy", - "ustka", - "walbrzych", - "warmia", - "warszawa", - "waw", - "wegrow", - "wielun", - "wlocl", - "wloclawek", - "wodzislaw", - "wolomin", - "wroc", - "wroclaw", - "zachpomor", - "zagan", - "zakopane", - "zarow", - "zgora", - "zgorzelec", - "ap", - "griw", - "ic", - "is", - "kmpsp", - "konsulat", - "kppsp", - "kwp", - "kwpsp", - "mup", - "mw", - "oirm", - "oum", - "pa", - "pinb", - "piw", - "po", - "psp", - "psse", - "pup", - "rzgw", - "sa", - "sdn", - "sko", - "so", - "sr", - "starostwo", - "ug", - "ugim", - "um", - "umig", - "upow", - "uppo", - "us", - "uw", - "uzs", - "wif", - "wiih", - "winb", - "wios", - "witd", - "wiw", - "wsa", - "wskr", - "wuoz", - "wzmiuw", - "zp", - "co", - "own", - "co", - "edu", - "gov", - "net", - "org", - "ac", - "biz", - "com", - "edu", - "est", - "gov", - "info", - "isla", - "name", - "net", - "org", - "pro", - "prof", - "aaa", - "aca", - "acct", - "avocat", - "bar", - "barsy", - "cloudns", - "cpa", - "dnstrace", - "eng", - "jur", - "law", - "med", - "recht", - "bci", - "com", - "edu", - "gov", - "net", - "org", - "plo", - "sec", - "blogspot", - "com", - "edu", - "gov", - "int", - "net", - "nome", - "nym", - "org", - "publ", - "barsy", - "belau", - "cloudns", - "co", - "ed", - "go", - "ne", - "nom", - "or", - "x443", - "com", - "coop", - "edu", - "gov", - "mil", - "net", - "org", - "blogspot", - "com", - "edu", - "gov", - "mil", - "name", - "net", - "nom", - "org", - "sch", - "asso", - "blogspot", - "com", - "nom", - "ybo", - "clan", - "arts", - "blogspot", - "com", - "firm", - "info", - "nom", - "nt", - "nym", - "org", - "rec", - "shop", - "store", - "tm", - "www", - "lima-city", - "myddns", - "webspace", - "ac", - "blogspot", - "co", - "edu", - "gov", - "in", - "nom", - "org", - "ox", - "ua", - "ac", - "adygeya", - "bashkiria", - "bir", - "blogspot", - "cbg", - "cldmail", - "com", - "dagestan", - "edu", - "gov", - "grozny", - "int", - "kalmykia", - "kustanai", - "marine", - "mil", - "mordovia", - "msk", - "myjino", - "mytis", - "nalchik", - "net", - "nov", - "org", - "pp", - "pyatigorsk", - "ras", - "spb", - "test", - "vladikavkaz", - "vladimir", - "hb", - "hosting", - "landing", - "spectrum", - "vps", - "development", - "ravendb", - "repl", - "ac", - "co", - "coop", - "gov", - "mil", - "net", - "org", - "com", - "edu", - "gov", - "med", - "net", - "org", - "pub", - "sch", - "for", - "com", - "edu", - "gov", - "net", - "org", - "com", - "edu", - "gov", - "net", - "org", - "ybo", - "com", - "edu", - "gov", - "info", - "med", - "net", - "org", - "tv", - "a", - "ac", - "b", - "bd", - "blogspot", - "brand", - "c", - "com", - "conf", - "d", - "e", - "f", - "fh", - "fhsk", - "fhv", - "g", - "h", - "i", - "k", - "komforb", - "kommunalforbund", - "komvux", - "l", - "lanbib", - "m", - "n", - "naturbruksgymn", - "o", - "org", - "p", - "parti", - "pp", - "press", - "r", - "s", - "t", - "tm", - "u", - "w", - "x", - "y", - "z", - "loginline", - "blogspot", - "com", - "edu", - "gov", - "net", - "org", - "per", - "com", - "gov", - "hashbang", - "mil", - "net", - "now", - "org", - "platform", - "wedeploy", - "barsy", - "blogspot", - "nom", - "barsy", - "byen", - "cloudera", - "cyon", - "loginline", - "platformsh", - "blogspot", - "nym", - "com", - "edu", - "gov", - "net", - "org", - "art", - "blogspot", - "com", - "edu", - "gouv", - "org", - "perso", - "univ", - "com", - "net", - "org", - "sch", - "linkitools", - "uber", - "xs4all", - "co", - "com", - "consulado", - "edu", - "embaixada", - "gov", - "mil", - "net", - "noho", - "nom", - "org", - "principe", - "saotome", - "store", - "abkhazia", - "adygeya", - "aktyubinsk", - "arkhangelsk", - "armenia", - "ashgabad", - "azerbaijan", - "balashov", - "bashkiria", - "bryansk", - "bukhara", - "chimkent", - "dagestan", - "east-kazakhstan", - "exnet", - "georgia", - "grozny", - "ivanovo", - "jambyl", - "kalmykia", - "kaluga", - "karacol", - "karaganda", - "karelia", - "khakassia", - "krasnodar", - "kurgan", - "kustanai", - "lenug", - "mangyshlak", - "mordovia", - "msk", - "murmansk", - "nalchik", - "navoi", - "north-kazakhstan", - "nov", - "nym", - "obninsk", - "penza", - "pokrovsk", - "sochi", - "spb", - "tashkent", - "termez", - "togliatti", - "troitsk", - "tselinograd", - "tula", - "tuva", - "vladikavkaz", - "vladimir", - "vologda", - "barsy", - "com", - "edu", - "gob", - "org", - "red", - "gov", - "nym", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "knightpoint", - "ac", - "co", - "org", - "blogspot", - "co", - "ac", - "co", - "go", - "in", - "mi", - "net", - "online", - "or", - "shop", - "ac", - "biz", - "co", - "com", - "edu", - "go", - "gov", - "int", - "mil", - "name", - "net", - "nic", - "nom", - "org", - "test", - "web", - "gov", - "co", - "com", - "edu", - "gov", - "mil", - "net", - "nom", - "org", - "agrinet", - "com", - "defense", - "edunet", - "ens", - "fin", - "gov", - "ind", - "info", - "intl", - "mincom", - "nat", - "net", - "org", - "perso", - "rnrt", - "rns", - "rnu", - "tourism", - "turen", - "com", - "edu", - "gov", - "mil", - "net", - "org", - "vpnplus", - "now-dns", - "ntdll", - "av", - "bbs", - "bel", - "biz", - "com", - "dr", - "edu", - "gen", - "gov", - "info", - "k12", - "kep", - "mil", - "name", - "nc", - "net", - "org", - "pol", - "tel", - "tsk", - "tv", - "web", - "blogspot", - "gov", - "ybo", - "aero", - "biz", - "co", - "com", - "coop", - "edu", - "gov", - "info", - "int", - "jobs", - "mobi", - "museum", - "name", - "net", - "org", - "pro", - "travel", - "better-than", - "dyndns", - "on-the-web", - "worse-than", - "blogspot", - "club", - "com", - "ebiz", - "edu", - "game", - "gov", - "idv", - "mil", - "net", - "nym", - "org", - "url", - "xn--czrw28b", - "xn--uc0atv", - "xn--zf0ao64a", - "mymailer", - "ac", - "co", - "go", - "hotel", - "info", - "me", - "mil", - "mobi", - "ne", - "or", - "sc", - "tv", - "biz", - "cc", - "cherkassy", - "cherkasy", - "chernigov", - "chernihiv", - "chernivtsi", - "chernovtsy", - "ck", - "cn", - "co", - "com", - "cr", - "crimea", - "cv", - "dn", - "dnepropetrovsk", - "dnipropetrovsk", - "dominic", - "donetsk", - "dp", - "edu", - "gov", - "if", - "in", - "inf", - "ivano-frankivsk", - "kh", - "kharkiv", - "kharkov", - "kherson", - "khmelnitskiy", - "khmelnytskyi", - "kiev", - "kirovograd", - "km", - "kr", - "krym", - "ks", - "kv", - "kyiv", - "lg", - "lt", - "ltd", - "lugansk", - "lutsk", - "lv", - "lviv", - "mk", - "mykolaiv", - "net", - "nikolaev", - "od", - "odesa", - "odessa", - "org", - "pl", - "poltava", - "pp", - "rivne", - "rovno", - "rv", - "sb", - "sebastopol", - "sevastopol", - "sm", - "sumy", - "te", - "ternopil", - "uz", - "uzhgorod", - "vinnica", - "vinnytsia", - "vn", - "volyn", - "yalta", - "zaporizhzhe", - "zaporizhzhia", - "zhitomir", - "zhytomyr", - "zp", - "zt", - "ac", - "blogspot", - "co", - "com", - "go", - "ne", - "nom", - "or", - "org", - "sc", - "ac", - "barsy", - "co", - "gov", - "ltd", - "me", - "net", - "nhs", - "org", - "plc", - "police", - "sch", - "barsy", - "barsyonline", - "blogspot", - "bytemark", - "gwiddle", - "nh-serv", - "no-ip", - "wellbeingzone", - "dh", - "vm", - "homeoffice", - "service", - "glug", - "lug", - "lugs", - "ak", - "al", - "ar", - "as", - "az", - "ca", - "cloudns", - "co", - "ct", - "dc", - "de", - "dni", - "drud", - "fed", - "fl", - "freeddns", - "ga", - "golffan", - "gu", - "hi", - "ia", - "id", - "il", - "in", - "is-by", - "isa", - "kids", - "ks", - "ky", - "la", - "land-4-sale", - "ma", - "md", - "me", - "mi", - "mn", - "mo", - "ms", - "mt", - "nc", - "nd", - "ne", - "nh", - "nj", - "nm", - "noip", - "nsn", - "nv", - "ny", - "oh", - "ok", - "or", - "pa", - "pointto", - "pr", - "ri", - "sc", - "sd", - "stuff-4-sale", - "tn", - "tx", - "ut", - "va", - "vi", - "vt", - "wa", - "wi", - "wv", - "wy", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "chtr", - "paroch", - "pvt", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "ann-arbor", - "cc", - "cog", - "dst", - "eaton", - "gen", - "k12", - "lib", - "mus", - "tec", - "washtenaw", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "k12", - "lib", - "cc", - "cc", - "k12", - "lib", - "com", - "edu", - "gub", - "mil", - "net", - "nom", - "org", - "blogspot", - "co", - "com", - "net", - "org", - "com", - "edu", - "gov", - "mil", - "net", - "nom", - "org", - "arts", - "co", - "com", - "e12", - "edu", - "firm", - "gob", - "gov", - "info", - "int", - "mil", - "net", - "org", - "rec", - "store", - "tec", - "web", - "nom", - "co", - "com", - "k12", - "net", - "org", - "ac", - "biz", - "blogspot", - "com", - "edu", - "gov", - "health", - "info", - "int", - "name", - "net", - "org", - "pro", - "com", - "edu", - "net", - "org", - "of", - "to", - "advisor", - "cloud66", - "com", - "dyndns", - "edu", - "gov", - "mypets", - "net", - "org", - "xn--80au", - "xn--90azh", - "xn--c1avg", - "xn--d1at", - "xn--o1ac", - "xn--o1ach", - "xn--55qx5d", - "xn--gmqw5a", - "xn--mxtq1m", - "xn--od0alg", - "xn--uc0atv", - "xn--wcvs22d", - "xn--12c1fe0br", - "xn--12cfi8ixb8l", - "xn--12co0c3b4eva", - "xn--h3cuzk1di", - "xn--m3ch0j3a", - "xn--o3cyx2a", - "blogsite", - "crafting", - "fhapp", - "telebit", - "zapto", - "ac", - "agric", - "alt", - "co", - "edu", - "gov", - "grondar", - "law", - "mil", - "net", - "ngo", - "nis", - "nom", - "org", - "school", - "tm", - "web", - "blogspot", - "ac", - "biz", - "co", - "com", - "edu", - "gov", - "info", - "mil", - "net", - "org", - "sch", - "cloud66", - "lima", - "triton", - "ac", - "co", - "gov", - "mil", - "org", -} diff --git a/vendor/golang.org/x/net/websocket/websocket.go b/vendor/golang.org/x/net/websocket/websocket.go index 1f4f7be400..6c45c73529 100644 --- a/vendor/golang.org/x/net/websocket/websocket.go +++ b/vendor/golang.org/x/net/websocket/websocket.go @@ -5,11 +5,11 @@ // Package websocket implements a client and server for the WebSocket protocol // as specified in RFC 6455. // -// This package currently lacks some features found in an alternative -// and more actively maintained WebSocket package: +// This package currently lacks some features found in alternative +// and more actively maintained WebSocket packages: // // https://godoc.org/github.com/gorilla/websocket -// +// https://godoc.org/nhooyr.io/websocket package websocket // import "golang.org/x/net/websocket" import ( diff --git a/vendor/golang.org/x/sys/unix/mkasm_darwin.go b/vendor/golang.org/x/sys/unix/mkasm_darwin.go deleted file mode 100644 index 4548b993db..0000000000 --- a/vendor/golang.org/x/sys/unix/mkasm_darwin.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go. -//This program must be run after mksyscall.go. -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "os" - "strings" -) - -func main() { - in1, err := ioutil.ReadFile("syscall_darwin.go") - if err != nil { - log.Fatalf("can't open syscall_darwin.go: %s", err) - } - arch := os.Args[1] - in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) - if err != nil { - log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err) - } - in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) - if err != nil { - log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err) - } - in := string(in1) + string(in2) + string(in3) - - trampolines := map[string]bool{} - - var out bytes.Buffer - - fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " ")) - fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n") - fmt.Fprintf(&out, "\n") - fmt.Fprintf(&out, "// +build go1.12\n") - fmt.Fprintf(&out, "\n") - fmt.Fprintf(&out, "#include \"textflag.h\"\n") - for _, line := range strings.Split(in, "\n") { - if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") { - continue - } - fn := line[5 : len(line)-13] - if !trampolines[fn] { - trampolines[fn] = true - fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn) - fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn) - } - } - err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) - if err != nil { - log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) - } -} diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go deleted file mode 100644 index eb4332059a..0000000000 --- a/vendor/golang.org/x/sys/unix/mkpost.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// mkpost processes the output of cgo -godefs to -// modify the generated types. It is used to clean up -// the sys API in an architecture specific manner. -// -// mkpost is run after cgo -godefs; see README.md. -package main - -import ( - "bytes" - "fmt" - "go/format" - "io/ioutil" - "log" - "os" - "regexp" -) - -func main() { - // Get the OS and architecture (using GOARCH_TARGET if it exists) - goos := os.Getenv("GOOS") - goarch := os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check that we are using the Docker-based build system if we should be. - if goos == "linux" { - if os.Getenv("GOLANG_SYS_BUILD") != "docker" { - os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n") - os.Stderr.WriteString("See README.md\n") - os.Exit(1) - } - } - - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatal(err) - } - - if goos == "aix" { - // Replace type of Atim, Mtim and Ctim by Timespec in Stat_t - // to avoid having both StTimespec and Timespec. - sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`) - b = sttimespec.ReplaceAll(b, []byte("Timespec")) - } - - // Intentionally export __val fields in Fsid and Sigset_t - valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`) - b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}")) - - // Intentionally export __fds_bits field in FdSet - fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`) - b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}")) - - // If we have empty Ptrace structs, we should delete them. Only s390x emits - // nonempty Ptrace structs. - ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`) - b = ptraceRexexp.ReplaceAll(b, nil) - - // Replace the control_regs union with a blank identifier for now. - controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`) - b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64")) - - // Remove fields that are added by glibc - // Note that this is unstable as the identifers are private. - removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`) - b = removeFieldsRegex.ReplaceAll(b, []byte("_")) - - // Convert [65]int8 to [65]byte in Utsname members to simplify - // conversion to string; see golang.org/issue/20753 - convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`) - b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte")) - - // Convert [1024]int8 to [1024]byte in Ptmget members - convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`) - b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte")) - - // Remove spare fields (e.g. in Statx_t) - spareFieldsRegex := regexp.MustCompile(`X__spare\S*`) - b = spareFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove cgo padding fields - removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) - b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove padding, hidden, or unused fields - removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`) - b = removeFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove the first line of warning from cgo - b = b[bytes.IndexByte(b, '\n')+1:] - // Modify the command in the header to include: - // mkpost, our own warning, and a build tag. - replacement := fmt.Sprintf(`$1 | go run mkpost.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s,%s`, goarch, goos) - cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`) - b = cgoCommandRegex.ReplaceAll(b, []byte(replacement)) - - // Rename Stat_t time fields - if goos == "freebsd" && goarch == "386" { - // Hide Stat_t.[AMCB]tim_ext fields - renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`) - b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_")) - } - renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`) - b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}")) - - // gofmt - b, err = format.Source(b) - if err != nil { - log.Fatal(err) - } - - os.Stdout.Write(b) -} diff --git a/vendor/golang.org/x/sys/unix/mksyscall.go b/vendor/golang.org/x/sys/unix/mksyscall.go deleted file mode 100644 index e4af9424e9..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall.go +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_darwin.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named errno. - -A line beginning with //sysnb is like //sys, except that the -goroutine will not be suspended during the execution of the system -call. This must only be used for system calls which can never -block, as otherwise the system call could cause all goroutines to -hang. -*/ -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - plan9 = flag.Bool("plan9", false, "plan9") - openbsd = flag.Bool("openbsd", false, "openbsd") - netbsd = flag.Bool("netbsd", false, "netbsd") - dragonfly = flag.Bool("dragonfly", false, "dragonfly") - arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair - tags = flag.String("tags", "", "build tags") - filename = flag.String("output", "", "output file name (standard output if omitted)") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - // Get the OS and architecture (using GOARCH_TARGET if it exists) - goos := os.Getenv("GOOS") - if goos == "" { - fmt.Fprintln(os.Stderr, "GOOS not defined in environment") - os.Exit(1) - } - goarch := os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - - // Check that we are using the Docker-based build system if we should - if goos == "linux" { - if os.Getenv("GOLANG_SYS_BUILD") != "docker" { - fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n") - fmt.Fprintf(os.Stderr, "See README.md\n") - os.Exit(1) - } - } - - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - libc := false - if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") { - libc = true - } - trampolines := map[string]bool{} - - text := "" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, errno error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, sysname := f[2], f[3], f[4], f[5] - - // ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers. - if goos == "darwin" && !libc && funct == "ClockGettime" { - continue - } - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // Go function header. - outDecl := "" - if len(out) > 0 { - outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", ")) - } - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl) - - // Check if err return available - errvar := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - break - } - } - - // Prepare arguments to Syscall. - var args []string - n := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\tvar _p%d *byte\n", n) - text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name) - text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\tvar _p%d *byte\n", n) - text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass dummy pointer in that case. - // Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). - text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name) - text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n) - args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) - n++ - } else if p.Type == "int64" && (*openbsd || *netbsd) { - args = append(args, "0") - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else if endianness == "little-endian" { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } else if p.Type == "int64" && *dragonfly { - if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil { - args = append(args, "0") - } - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else if endianness == "little-endian" { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" { - if len(args)%2 == 1 && *arm { - // arm abi specifies 64-bit argument uses - // (even, odd) pair - args = append(args, "0") - } - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } - - // Determine which form to use; pad args with zeros. - asm := "Syscall" - if nonblock != nil { - if errvar == "" && goos == "linux" { - asm = "RawSyscallNoError" - } else { - asm = "RawSyscall" - } - } else { - if errvar == "" && goos == "linux" { - asm = "SyscallNoError" - } - } - if len(args) <= 3 { - for len(args) < 3 { - args = append(args, "0") - } - } else if len(args) <= 6 { - asm += "6" - for len(args) < 6 { - args = append(args, "0") - } - } else if len(args) <= 9 { - asm += "9" - for len(args) < 9 { - args = append(args, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct) - } - - // System call number. - if sysname == "" { - sysname = "SYS_" + funct - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToUpper(sysname) - } - - var libcFn string - if libc { - asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call - sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_ - sysname = strings.ToLower(sysname) // lowercase - if sysname == "getdirentries64" { - // Special case - libSystem name and - // raw syscall name don't match. - sysname = "__getdirentries64" - } - libcFn = sysname - sysname = "funcPC(libc_" + sysname + "_trampoline)" - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist) - - // Assign return values. - body := "" - ret := []string{"_", "_", "_"} - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" && !*plan9 { - reg = "e1" - ret[2] = reg - doErrno = true - } else if p.Name == "err" && *plan9 { - ret[0] = "r0" - ret[2] = "e1" - break - } else { - reg = fmt.Sprintf("r%d", i) - ret[i] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%s != 0", reg) - } - if p.Type == "int64" && endianness != "" { - // 64-bit number in r1:r0 or r0:r1. - if i+2 > len(out) { - fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct) - } - if endianness == "big-endian" { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) - } else { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) - } - ret[i] = fmt.Sprintf("r%d", i) - ret[i+1] = fmt.Sprintf("r%d", i+1) - } - if reg != "e1" || *plan9 { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { - text += fmt.Sprintf("\t%s\n", call) - } else { - if errvar == "" && goos == "linux" { - // raw syscall without error on Linux, see golang.org/issue/22924 - text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call) - } else { - text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) - } - } - text += body - - if *plan9 && ret[2] == "e1" { - text += "\tif int32(r0) == -1 {\n" - text += "\t\terr = e1\n" - text += "\t}\n" - } else if doErrno { - text += "\tif e1 != 0 {\n" - text += "\t\terr = errnoErr(e1)\n" - text += "\t}\n" - } - text += "\treturn\n" - text += "}\n\n" - - if libc && !trampolines[libcFn] { - // some system calls share a trampoline, like read and readlen. - trampolines[libcFn] = true - // Declare assembly trampoline. - text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn) - // Assembly trampoline calls the libc_* function, which this magic - // redirects to use the function from libSystem. - text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn) - text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn) - text += "\n" - } - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go deleted file mode 100644 index 3be3cdfc3b..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_aix.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt -*/ -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - aix = flag.Bool("aix", false, "aix") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - text := "" - cExtern := "/*\n#include \n#include \n" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // Check if value return, err return available - errvar := "" - retvar := "" - rettype := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - } else { - retvar = p.Name - rettype = p.Type - } - } - - // System call name. - if sysname == "" { - sysname = funct - } - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - cRettype := "" - if rettype == "unsafe.Pointer" { - cRettype = "uintptr_t" - } else if rettype == "uintptr" { - cRettype = "uintptr_t" - } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { - cRettype = "uintptr_t" - } else if rettype == "int" { - cRettype = "int" - } else if rettype == "int32" { - cRettype = "int" - } else if rettype == "int64" { - cRettype = "long long" - } else if rettype == "uint32" { - cRettype = "unsigned int" - } else if rettype == "uint64" { - cRettype = "unsigned long long" - } else { - cRettype = "int" - } - if sysname == "exit" { - cRettype = "void" - } - - // Change p.Types to c - var cIn []string - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "string" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t", "size_t") - } else if p.Type == "unsafe.Pointer" { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "uintptr" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "int" { - cIn = append(cIn, "int") - } else if p.Type == "int32" { - cIn = append(cIn, "int") - } else if p.Type == "int64" { - cIn = append(cIn, "long long") - } else if p.Type == "uint32" { - cIn = append(cIn, "unsigned int") - } else if p.Type == "uint64" { - cIn = append(cIn, "unsigned long long") - } else { - cIn = append(cIn, "int") - } - } - - if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - cExtern += "#define c_select select\n" - } - // Imports of system calls from libc - cExtern += fmt.Sprintf("%s %s", cRettype, sysname) - cIn := strings.Join(cIn, ", ") - cExtern += fmt.Sprintf("(%s);\n", cIn) - } - - // So file name. - if *aix { - if modname == "" { - modname = "libc.a/shr_64.o" - } else { - fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) - os.Exit(1) - } - } - - strconvfunc := "C.CString" - - // Go function header. - if outps != "" { - outps = fmt.Sprintf(" (%s)", outps) - } - if text != "" { - text += "\n" - } - - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) - - // Prepare arguments to Syscall. - var args []string - n := 0 - argN := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) - n++ - text += fmt.Sprintf("\tvar _p%d int\n", n) - text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) - args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) - n++ - } else if p.Type == "int64" && endianness != "" { - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - n++ - } else if p.Type == "bool" { - text += fmt.Sprintf("\tvar _p%d uint32\n", n) - text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) - args = append(args, fmt.Sprintf("_p%d", n)) - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) - } else if p.Type == "unsafe.Pointer" { - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) - } else if p.Type == "int" { - if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { - args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) - } else if argN == 0 && funct == "fcntl" { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } - } else if p.Type == "int32" { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } else if p.Type == "int64" { - args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) - } else if p.Type == "uint32" { - args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) - } else if p.Type == "uint64" { - args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) - } else if p.Type == "uintptr" { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } - argN++ - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := "" - if sysname == "exit" { - if errvar != "" { - call += "er :=" - } else { - call += "" - } - } else if errvar != "" { - call += "r0,er :=" - } else if retvar != "" { - call += "r0,_ :=" - } else { - call += "" - } - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist) - } else { - call += fmt.Sprintf("C.%s(%s)", sysname, arglist) - } - - // Assign return values. - body := "" - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - } else { - reg = "r0" - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - - // verify return - if sysname != "exit" && errvar != "" { - if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { - body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } else { - body += "\tif (r0 ==-1 && er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } - } else if errvar != "" { - body += "\tif (er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } - - text += fmt.Sprintf("\t%s\n", call) - text += body - - text += "\treturn\n" - text += "}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - - -%s -*/ -import "C" -import ( - "unsafe" -) - - -%s - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go deleted file mode 100644 index c960099517..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_aix.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt - - -This program will generate three files and handle both gc and gccgo implementation: - - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) - - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 - - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. - - The generated code looks like this - -zsyscall_aix_ppc64.go -func asyscall(...) (n int, err error) { - // Pointer Creation - r1, e1 := callasyscall(...) - // Type Conversion - // Error Handler - return -} - -zsyscall_aix_ppc64_gc.go -//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" -//go:linkname libc_asyscall libc_asyscall -var asyscall syscallFunc - -func callasyscall(...) (r1 uintptr, e1 Errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) - return -} - -zsyscall_aix_ppc64_ggcgo.go - -// int asyscall(...) - -import "C" - -func callasyscall(...) (r1 uintptr, e1 Errno) { - r1 = uintptr(C.asyscall(...)) - e1 = syscall.GetErrno() - return -} -*/ - -package main - -import ( - "bufio" - "flag" - "fmt" - "io/ioutil" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - aix = flag.Bool("aix", false, "aix") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - // GCCGO - textgccgo := "" - cExtern := "/*\n#include \n" - // GC - textgc := "" - dynimports := "" - linknames := "" - var vars []string - // COMMON - textcommon := "" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - if sysname == "" { - sysname = funct - } - - onlyCommon := false - if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" { - // This function call another syscall which is already implemented. - // Therefore, the gc and gccgo part must not be generated. - onlyCommon = true - } - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - - textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - if !onlyCommon { - textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - } - - // Check if value return, err return available - errvar := "" - rettype := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - } else { - rettype = p.Type - } - } - - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - // GCCGO Prototype return type - cRettype := "" - if rettype == "unsafe.Pointer" { - cRettype = "uintptr_t" - } else if rettype == "uintptr" { - cRettype = "uintptr_t" - } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { - cRettype = "uintptr_t" - } else if rettype == "int" { - cRettype = "int" - } else if rettype == "int32" { - cRettype = "int" - } else if rettype == "int64" { - cRettype = "long long" - } else if rettype == "uint32" { - cRettype = "unsigned int" - } else if rettype == "uint64" { - cRettype = "unsigned long long" - } else { - cRettype = "int" - } - if sysname == "exit" { - cRettype = "void" - } - - // GCCGO Prototype arguments type - var cIn []string - for i, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "string" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t", "size_t") - } else if p.Type == "unsafe.Pointer" { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "uintptr" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "int" { - if (i == 0 || i == 2) && funct == "fcntl" { - // These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock - cIn = append(cIn, "uintptr_t") - } else { - cIn = append(cIn, "int") - } - - } else if p.Type == "int32" { - cIn = append(cIn, "int") - } else if p.Type == "int64" { - cIn = append(cIn, "long long") - } else if p.Type == "uint32" { - cIn = append(cIn, "unsigned int") - } else if p.Type == "uint64" { - cIn = append(cIn, "unsigned long long") - } else { - cIn = append(cIn, "int") - } - } - - if !onlyCommon { - // GCCGO Prototype Generation - // Imports of system calls from libc - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - cExtern += "#define c_select select\n" - } - cExtern += fmt.Sprintf("%s %s", cRettype, sysname) - cIn := strings.Join(cIn, ", ") - cExtern += fmt.Sprintf("(%s);\n", cIn) - } - // GC Library name - if modname == "" { - modname = "libc.a/shr_64.o" - } else { - fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) - os.Exit(1) - } - sysvarname := fmt.Sprintf("libc_%s", sysname) - - if !onlyCommon { - // GC Runtime import of function to allow cross-platform builds. - dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname) - // GC Link symbol to proc address variable. - linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname) - // GC Library proc address variable. - vars = append(vars, sysvarname) - } - - strconvfunc := "BytePtrFromString" - strconvtype := "*byte" - - // Go function header. - if outps != "" { - outps = fmt.Sprintf(" (%s)", outps) - } - if textcommon != "" { - textcommon += "\n" - } - - textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) - - // Prepare arguments tocall. - var argscommon []string // Arguments in the common part - var argscall []string // Arguments for call prototype - var argsgc []string // Arguments for gc call (with syscall6) - var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall) - n := 0 - argN := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if p.Type == "string" && errvar != "" { - textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) - textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) - n++ - } else if p.Type == "int64" && endianness != "" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") - } else if p.Type == "bool" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { - argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if p.Type == "int" { - if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { - // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock - argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - - } else { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } - } else if p.Type == "int32" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } else if p.Type == "int64" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) - } else if p.Type == "uint32" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) - } else if p.Type == "uint64" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) - } else if p.Type == "uintptr" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } - argN++ - } - nargs := len(argsgc) - - // COMMON function generation - argscommonlist := strings.Join(argscommon, ", ") - callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) - ret := []string{"_", "_"} - body := "" - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - ret[1] = reg - doErrno = true - } else { - reg = "r0" - ret[0] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%s != 0", reg) - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" { - textcommon += fmt.Sprintf("\t%s\n", callcommon) - } else { - textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) - } - textcommon += body - - if doErrno { - textcommon += "\tif e1 != 0 {\n" - textcommon += "\t\terr = errnoErr(e1)\n" - textcommon += "\t}\n" - } - textcommon += "\treturn\n" - textcommon += "}\n" - - if onlyCommon { - continue - } - - // CALL Prototype - callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) - - // GC function generation - asm := "syscall6" - if nonblock != nil { - asm = "rawSyscall6" - } - - if len(argsgc) <= 6 { - for len(argsgc) < 6 { - argsgc = append(argsgc, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) - os.Exit(1) - } - argsgclist := strings.Join(argsgc, ", ") - callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) - - textgc += callProto - textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) - textgc += "\treturn\n}\n" - - // GCCGO function generation - argsgccgolist := strings.Join(argsgccgo, ", ") - var callgccgo string - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist) - } else { - callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) - } - textgccgo += callProto - textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) - textgccgo += "\te1 = syscall.GetErrno()\n" - textgccgo += "\treturn\n}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - - // Print zsyscall_aix_ppc64.go - err := ioutil.WriteFile("zsyscall_aix_ppc64.go", - []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - // Print zsyscall_aix_ppc64_gc.go - vardecls := "\t" + strings.Join(vars, ",\n\t") - vardecls += " syscallFunc" - err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", - []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - // Print zsyscall_aix_ppc64_gccgo.go - err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", - []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } -} - -const srcTemplate1 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - -import ( - "unsafe" -) - - -%s - -%s -` -const srcTemplate2 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s -// +build !gccgo - -package %s - -import ( - "unsafe" -) -%s -%s -%s -type syscallFunc uintptr - -var ( -%s -) - -// Implemented in runtime/syscall_aix.go. -func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - -%s -` -const srcTemplate3 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s -// +build gccgo - -package %s - -%s -*/ -import "C" -import ( - "syscall" -) - - -%s - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go deleted file mode 100644 index 3d864738b6..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* - This program reads a file containing function prototypes - (like syscall_solaris.go) and generates system call bodies. - The prototypes are marked by lines beginning with "//sys" - and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt -*/ - -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - text := "" - dynimports := "" - linknames := "" - var vars []string - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // So file name. - if modname == "" { - modname = "libc" - } - - // System call name. - if sysname == "" { - sysname = funct - } - - // System call pointer variable name. - sysvarname := fmt.Sprintf("proc%s", sysname) - - strconvfunc := "BytePtrFromString" - strconvtype := "*byte" - - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - // Runtime import of function to allow cross-platform builds. - dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname) - // Link symbol to proc address variable. - linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname) - // Library proc address variable. - vars = append(vars, sysvarname) - - // Go function header. - outlist := strings.Join(out, ", ") - if outlist != "" { - outlist = fmt.Sprintf(" (%s)", outlist) - } - if text != "" { - text += "\n" - } - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist) - - // Check if err return available - errvar := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - continue - } - } - - // Prepare arguments to Syscall. - var args []string - n := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1]) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) - n++ - } else if p.Type == "int64" && endianness != "" { - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - } else if p.Type == "bool" { - text += fmt.Sprintf("\tvar _p%d uint32\n", n) - text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) - args = append(args, fmt.Sprintf("uintptr(_p%d)", n)) - n++ - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } - nargs := len(args) - - // Determine which form to use; pad args with zeros. - asm := "sysvicall6" - if nonblock != nil { - asm = "rawSysvicall6" - } - if len(args) <= 6 { - for len(args) < 6 { - args = append(args, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path) - os.Exit(1) - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist) - - // Assign return values. - body := "" - ret := []string{"_", "_", "_"} - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - ret[2] = reg - doErrno = true - } else { - reg = fmt.Sprintf("r%d", i) - ret[i] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%d != 0", reg) - } - if p.Type == "int64" && endianness != "" { - // 64-bit number in r1:r0 or r0:r1. - if i+2 > len(out) { - fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path) - os.Exit(1) - } - if endianness == "big-endian" { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) - } else { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) - } - ret[i] = fmt.Sprintf("r%d", i) - ret[i+1] = fmt.Sprintf("r%d", i+1) - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { - text += fmt.Sprintf("\t%s\n", call) - } else { - text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) - } - text += body - - if doErrno { - text += "\tif e1 != 0 {\n" - text += "\t\terr = e1\n" - text += "\t}\n" - } - text += "\treturn\n" - text += "}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - vardecls := "\t" + strings.Join(vars, ",\n\t") - vardecls += " syscallFunc" - fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - -import ( - "syscall" - "unsafe" -) -%s -%s -%s -var ( -%s -) - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go deleted file mode 100644 index b6b409909c..0000000000 --- a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Parse the header files for OpenBSD and generate a Go usable sysctl MIB. -// -// Build a MIB with each entry being an array containing the level, type and -// a hash that will contain additional entries if the current entry is a node. -// We then walk this MIB and create a flattened sysctl name to OID hash. - -package main - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "regexp" - "sort" - "strings" -) - -var ( - goos, goarch string -) - -// cmdLine returns this programs's commandline arguments. -func cmdLine() string { - return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags. -func buildTags() string { - return fmt.Sprintf("%s,%s", goarch, goos) -} - -// reMatch performs regular expression match and stores the substring slice to value pointed by m. -func reMatch(re *regexp.Regexp, str string, m *[]string) bool { - *m = re.FindStringSubmatch(str) - if *m != nil { - return true - } - return false -} - -type nodeElement struct { - n int - t string - pE *map[string]nodeElement -} - -var ( - debugEnabled bool - mib map[string]nodeElement - node *map[string]nodeElement - nodeMap map[string]string - sysCtl []string -) - -var ( - ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`) - ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`) - ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`) - netInetRE = regexp.MustCompile(`^netinet/`) - netInet6RE = regexp.MustCompile(`^netinet6/`) - netRE = regexp.MustCompile(`^net/`) - bracesRE = regexp.MustCompile(`{.*}`) - ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`) - fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`) -) - -func debug(s string) { - if debugEnabled { - fmt.Fprintln(os.Stderr, s) - } -} - -// Walk the MIB and build a sysctl name to OID mapping. -func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) { - lNode := pNode // local copy of pointer to node - var keys []string - for k := range *lNode { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, key := range keys { - nodename := name - if name != "" { - nodename += "." - } - nodename += key - - nodeoid := append(oid, (*pNode)[key].n) - - if (*pNode)[key].t == `CTLTYPE_NODE` { - if _, ok := nodeMap[nodename]; ok { - lNode = &mib - ctlName := nodeMap[nodename] - for _, part := range strings.Split(ctlName, ".") { - lNode = ((*lNode)[part]).pE - } - } else { - lNode = (*pNode)[key].pE - } - buildSysctl(lNode, nodename, nodeoid) - } else if (*pNode)[key].t != "" { - oidStr := []string{} - for j := range nodeoid { - oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j])) - } - text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n" - sysCtl = append(sysCtl, text) - } - } -} - -func main() { - // Get the OS (using GOOS_TARGET if it exist) - goos = os.Getenv("GOOS_TARGET") - if goos == "" { - goos = os.Getenv("GOOS") - } - // Get the architecture (using GOARCH_TARGET if it exists) - goarch = os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check if GOOS and GOARCH environment variables are defined - if goarch == "" || goos == "" { - fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") - os.Exit(1) - } - - mib = make(map[string]nodeElement) - headers := [...]string{ - `sys/sysctl.h`, - `sys/socket.h`, - `sys/tty.h`, - `sys/malloc.h`, - `sys/mount.h`, - `sys/namei.h`, - `sys/sem.h`, - `sys/shm.h`, - `sys/vmmeter.h`, - `uvm/uvmexp.h`, - `uvm/uvm_param.h`, - `uvm/uvm_swap_encrypt.h`, - `ddb/db_var.h`, - `net/if.h`, - `net/if_pfsync.h`, - `net/pipex.h`, - `netinet/in.h`, - `netinet/icmp_var.h`, - `netinet/igmp_var.h`, - `netinet/ip_ah.h`, - `netinet/ip_carp.h`, - `netinet/ip_divert.h`, - `netinet/ip_esp.h`, - `netinet/ip_ether.h`, - `netinet/ip_gre.h`, - `netinet/ip_ipcomp.h`, - `netinet/ip_ipip.h`, - `netinet/pim_var.h`, - `netinet/tcp_var.h`, - `netinet/udp_var.h`, - `netinet6/in6.h`, - `netinet6/ip6_divert.h`, - `netinet6/pim6_var.h`, - `netinet/icmp6.h`, - `netmpls/mpls.h`, - } - - ctls := [...]string{ - `kern`, - `vm`, - `fs`, - `net`, - //debug /* Special handling required */ - `hw`, - //machdep /* Arch specific */ - `user`, - `ddb`, - //vfs /* Special handling required */ - `fs.posix`, - `kern.forkstat`, - `kern.intrcnt`, - `kern.malloc`, - `kern.nchstats`, - `kern.seminfo`, - `kern.shminfo`, - `kern.timecounter`, - `kern.tty`, - `kern.watchdog`, - `net.bpf`, - `net.ifq`, - `net.inet`, - `net.inet.ah`, - `net.inet.carp`, - `net.inet.divert`, - `net.inet.esp`, - `net.inet.etherip`, - `net.inet.gre`, - `net.inet.icmp`, - `net.inet.igmp`, - `net.inet.ip`, - `net.inet.ip.ifq`, - `net.inet.ipcomp`, - `net.inet.ipip`, - `net.inet.mobileip`, - `net.inet.pfsync`, - `net.inet.pim`, - `net.inet.tcp`, - `net.inet.udp`, - `net.inet6`, - `net.inet6.divert`, - `net.inet6.ip6`, - `net.inet6.icmp6`, - `net.inet6.pim6`, - `net.inet6.tcp6`, - `net.inet6.udp6`, - `net.mpls`, - `net.mpls.ifq`, - `net.key`, - `net.pflow`, - `net.pfsync`, - `net.pipex`, - `net.rt`, - `vm.swapencrypt`, - //vfsgenctl /* Special handling required */ - } - - // Node name "fixups" - ctlMap := map[string]string{ - "ipproto": "net.inet", - "net.inet.ipproto": "net.inet", - "net.inet6.ipv6proto": "net.inet6", - "net.inet6.ipv6": "net.inet6.ip6", - "net.inet.icmpv6": "net.inet6.icmp6", - "net.inet6.divert6": "net.inet6.divert", - "net.inet6.tcp6": "net.inet.tcp", - "net.inet6.udp6": "net.inet.udp", - "mpls": "net.mpls", - "swpenc": "vm.swapencrypt", - } - - // Node mappings - nodeMap = map[string]string{ - "net.inet.ip.ifq": "net.ifq", - "net.inet.pfsync": "net.pfsync", - "net.mpls.ifq": "net.ifq", - } - - mCtls := make(map[string]bool) - for _, ctl := range ctls { - mCtls[ctl] = true - } - - for _, header := range headers { - debug("Processing " + header) - file, err := os.Open(filepath.Join("/usr/include", header)) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - var sub []string - if reMatch(ctlNames1RE, s.Text(), &sub) || - reMatch(ctlNames2RE, s.Text(), &sub) || - reMatch(ctlNames3RE, s.Text(), &sub) { - if sub[1] == `CTL_NAMES` { - // Top level. - node = &mib - } else { - // Node. - nodename := strings.ToLower(sub[2]) - ctlName := "" - if reMatch(netInetRE, header, &sub) { - ctlName = "net.inet." + nodename - } else if reMatch(netInet6RE, header, &sub) { - ctlName = "net.inet6." + nodename - } else if reMatch(netRE, header, &sub) { - ctlName = "net." + nodename - } else { - ctlName = nodename - ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) - } - - if val, ok := ctlMap[ctlName]; ok { - ctlName = val - } - if _, ok := mCtls[ctlName]; !ok { - debug("Ignoring " + ctlName + "...") - continue - } - - // Walk down from the top of the MIB. - node = &mib - for _, part := range strings.Split(ctlName, ".") { - if _, ok := (*node)[part]; !ok { - debug("Missing node " + part) - (*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} - } - node = (*node)[part].pE - } - } - - // Populate current node with entries. - i := -1 - for !strings.HasPrefix(s.Text(), "}") { - s.Scan() - if reMatch(bracesRE, s.Text(), &sub) { - i++ - } - if !reMatch(ctlTypeRE, s.Text(), &sub) { - continue - } - (*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} - } - } - } - err = s.Err() - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - file.Close() - } - buildSysctl(&mib, "", []int{}) - - sort.Strings(sysCtl) - text := strings.Join(sysCtl, "") - - fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) -} - -const srcTemplate = `// %s -// Code generated by the command above; DO NOT EDIT. - -// +build %s - -package unix - -type mibentry struct { - ctlname string - ctloid []_C_int -} - -var sysctlMib = []mibentry { -%s -} -` diff --git a/vendor/golang.org/x/sys/unix/mksysnum.go b/vendor/golang.org/x/sys/unix/mksysnum.go deleted file mode 100644 index baa6ecd850..0000000000 --- a/vendor/golang.org/x/sys/unix/mksysnum.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Generate system call table for DragonFly, NetBSD, -// FreeBSD, OpenBSD or Darwin from master list -// (for example, /usr/src/sys/kern/syscalls.master or -// sys/syscall.h). -package main - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "regexp" - "strings" -) - -var ( - goos, goarch string -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return fmt.Sprintf("%s,%s", goarch, goos) -} - -func checkErr(err error) { - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } -} - -// source string and substring slice for regexp -type re struct { - str string // source string - sub []string // matched sub-string -} - -// Match performs regular expression match -func (r *re) Match(exp string) bool { - r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) - if r.sub != nil { - return true - } - return false -} - -// fetchFile fetches a text file from URL -func fetchFile(URL string) io.Reader { - resp, err := http.Get(URL) - checkErr(err) - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - checkErr(err) - return strings.NewReader(string(body)) -} - -// readFile reads a text file from path -func readFile(path string) io.Reader { - file, err := os.Open(os.Args[1]) - checkErr(err) - return file -} - -func format(name, num, proto string) string { - name = strings.ToUpper(name) - // There are multiple entries for enosys and nosys, so comment them out. - nm := re{str: name} - if nm.Match(`^SYS_E?NOSYS$`) { - name = fmt.Sprintf("// %s", name) - } - if name == `SYS_SYS_EXIT` { - name = `SYS_EXIT` - } - return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) -} - -func main() { - // Get the OS (using GOOS_TARGET if it exist) - goos = os.Getenv("GOOS_TARGET") - if goos == "" { - goos = os.Getenv("GOOS") - } - // Get the architecture (using GOARCH_TARGET if it exists) - goarch = os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check if GOOS and GOARCH environment variables are defined - if goarch == "" || goos == "" { - fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") - os.Exit(1) - } - - file := strings.TrimSpace(os.Args[1]) - var syscalls io.Reader - if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { - // Download syscalls.master file - syscalls = fetchFile(file) - } else { - syscalls = readFile(file) - } - - var text, line string - s := bufio.NewScanner(syscalls) - for s.Scan() { - t := re{str: line} - if t.Match(`^(.*)\\$`) { - // Handle continuation - line = t.sub[1] - line += strings.TrimLeft(s.Text(), " \t") - } else { - // New line - line = s.Text() - } - t = re{str: line} - if t.Match(`\\$`) { - continue - } - t = re{str: line} - - switch goos { - case "dragonfly": - if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { - num, proto := t.sub[1], t.sub[2] - name := fmt.Sprintf("SYS_%s", t.sub[3]) - text += format(name, num, proto) - } - case "freebsd": - if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { - num, proto := t.sub[1], t.sub[2] - name := fmt.Sprintf("SYS_%s", t.sub[3]) - text += format(name, num, proto) - } - case "openbsd": - if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { - num, proto, name := t.sub[1], t.sub[3], t.sub[4] - text += format(name, num, proto) - } - case "netbsd": - if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { - num, proto, compat := t.sub[1], t.sub[6], t.sub[8] - name := t.sub[7] + "_" + t.sub[9] - if t.sub[11] != "" { - name = t.sub[7] + "_" + t.sub[11] - } - name = strings.ToUpper(name) - if compat == "" || compat == "13" || compat == "30" || compat == "50" { - text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) - } - } - case "darwin": - if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) { - name, num := t.sub[1], t.sub[2] - name = strings.ToUpper(name) - text += fmt.Sprintf(" SYS_%s = %s;\n", name, num) - } - default: - fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) - os.Exit(1) - - } - } - err := s.Err() - checkErr(err) - - fmt.Printf(template, cmdLine(), buildTags(), text) -} - -const template = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package unix - -const( -%s)` diff --git a/vendor/golang.org/x/sys/unix/types_aix.go b/vendor/golang.org/x/sys/unix/types_aix.go deleted file mode 100644 index 40d2beede5..0000000000 --- a/vendor/golang.org/x/sys/unix/types_aix.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore -// +build aix - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - - -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -type off64 C.off64_t -type off C.off_t -type Mode_t C.mode_t - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -type Timex C.struct_timex - -type Time_t C.time_t - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -type Timezone C.struct_timezone - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit64 - -type Pid_t C.pid_t - -type _Gid_t C.gid_t - -type dev_t C.dev_t - -// Files - -type Stat_t C.struct_stat - -type StatxTimestamp C.struct_statx_timestamp - -type Statx_t C.struct_statx - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Cmsghdr C.struct_cmsghdr - -type ICMPv6Filter C.struct_icmp6_filter - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type Linger C.struct_linger - -type Msghdr C.struct_msghdr - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr -) - -type IfMsgHdr C.struct_if_msghdr - -// Misc - -type FdSet C.fd_set - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -type Sigset_t C.sigset_t - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// Terminal handling - -type Termios C.struct_termios - -type Termio C.struct_termio - -type Winsize C.struct_winsize - -//poll - -type PollFd struct { - Fd int32 - Events uint16 - Revents uint16 -} - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -//flock_t - -type Flock_t C.struct_flock64 - -// Statfs - -type Fsid_t C.struct_fsid_t -type Fsid64_t C.struct_fsid64_t - -type Statfs_t C.struct_statfs - -const RNDGETENTCNT = 0x80045200 diff --git a/vendor/golang.org/x/sys/unix/types_darwin.go b/vendor/golang.org/x/sys/unix/types_darwin.go deleted file mode 100644 index 155c2e692b..0000000000 --- a/vendor/golang.org/x/sys/unix/types_darwin.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define __DARWIN_UNIX03 0 -#define KERNEL -#define _DARWIN_USE_64_BIT_INODE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat64 - -type Statfs_t C.struct_statfs64 - -type Flock_t C.struct_flock - -type Fstore_t C.struct_fstore - -type Radvisory_t C.struct_radvisory - -type Fbootstraptransfer_t C.struct_fbootstraptransfer - -type Log2phys_t C.struct_log2phys - -type Fsid C.struct_fsid - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet4Pktinfo C.struct_in_pktinfo - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfmaMsghdr2 C.struct_ifma_msghdr2 - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// uname - -type Utsname C.struct_utsname - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_dragonfly.go b/vendor/golang.org/x/sys/unix/types_dragonfly.go deleted file mode 100644 index 3365dd79d0..0000000000 --- a/vendor/golang.org/x/sys/unix/types_dragonfly.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.struct_fsid - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Uname - -type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go deleted file mode 100644 index a121dc3368..0000000000 --- a/vendor/golang.org/x/sys/unix/types_freebsd.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define _WANT_FREEBSD11_STAT 1 -#define _WANT_FREEBSD11_STATFS 1 -#define _WANT_FREEBSD11_DIRENT 1 -#define _WANT_FREEBSD11_KEVENT 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -// This structure is a duplicate of if_data on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_data8 { - u_char ifi_type; - u_char ifi_physical; - u_char ifi_addrlen; - u_char ifi_hdrlen; - u_char ifi_link_state; - u_char ifi_spare_char1; - u_char ifi_spare_char2; - u_char ifi_datalen; - u_long ifi_mtu; - u_long ifi_metric; - u_long ifi_baudrate; - u_long ifi_ipackets; - u_long ifi_ierrors; - u_long ifi_opackets; - u_long ifi_oerrors; - u_long ifi_collisions; - u_long ifi_ibytes; - u_long ifi_obytes; - u_long ifi_imcasts; - u_long ifi_omcasts; - u_long ifi_iqdrops; - u_long ifi_noproto; - u_long ifi_hwassist; -// FIXME: these are now unions, so maybe need to change definitions? -#undef ifi_epoch - time_t ifi_epoch; -#undef ifi_lastchange - struct timeval ifi_lastchange; -}; - -// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_msghdr8 { - u_short ifm_msglen; - u_char ifm_version; - u_char ifm_type; - int ifm_addrs; - int ifm_flags; - u_short ifm_index; - struct if_data8 ifm_data; -}; -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( - _statfsVersion = C.STATFS_VERSION - _dirblksiz = C.DIRBLKSIZ -) - -type Stat_t C.struct_stat - -type stat_freebsd11_t C.struct_freebsd11_stat - -type Statfs_t C.struct_statfs - -type statfs_freebsd11_t C.struct_freebsd11_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type dirent_freebsd11 C.struct_freebsd11_dirent - -type Fsid C.struct_fsid - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPMreqn C.struct_ip_mreqn - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPMreqn = C.sizeof_struct_ip_mreqn - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_ATTACH = C.PT_ATTACH - PTRACE_CONT = C.PT_CONTINUE - PTRACE_DETACH = C.PT_DETACH - PTRACE_GETFPREGS = C.PT_GETFPREGS - PTRACE_GETFSBASE = C.PT_GETFSBASE - PTRACE_GETLWPLIST = C.PT_GETLWPLIST - PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS - PTRACE_GETREGS = C.PT_GETREGS - PTRACE_GETXSTATE = C.PT_GETXSTATE - PTRACE_IO = C.PT_IO - PTRACE_KILL = C.PT_KILL - PTRACE_LWPEVENTS = C.PT_LWP_EVENTS - PTRACE_LWPINFO = C.PT_LWPINFO - PTRACE_SETFPREGS = C.PT_SETFPREGS - PTRACE_SETREGS = C.PT_SETREGS - PTRACE_SINGLESTEP = C.PT_STEP - PTRACE_TRACEME = C.PT_TRACE_ME -) - -const ( - PIOD_READ_D = C.PIOD_READ_D - PIOD_WRITE_D = C.PIOD_WRITE_D - PIOD_READ_I = C.PIOD_READ_I - PIOD_WRITE_I = C.PIOD_WRITE_I -) - -const ( - PL_FLAG_BORN = C.PL_FLAG_BORN - PL_FLAG_EXITED = C.PL_FLAG_EXITED - PL_FLAG_SI = C.PL_FLAG_SI -) - -const ( - TRAP_BRKPT = C.TRAP_BRKPT - TRAP_TRACE = C.TRAP_TRACE -) - -type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo - -type __Siginfo C.struct___siginfo - -type Sigset_t C.sigset_t - -type Reg C.struct_reg - -type FpReg C.struct_fpreg - -type PtraceIoDesc C.struct_ptrace_io_desc - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent_freebsd11 - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - sizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 - sizeofIfData = C.sizeof_struct_if_data - SizeofIfData = C.sizeof_struct_if_data8 - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type ifMsghdr C.struct_if_msghdr - -type IfMsghdr C.struct_if_msghdr8 - -type ifData C.struct_if_data - -type IfData C.struct_if_data8 - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr - SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfZbuf C.struct_bpf_zbuf - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfZbufHeader C.struct_bpf_zbuf_header - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLINIGNEOF = C.POLLINIGNEOF - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Capabilities - -type CapRights C.struct_cap_rights - -// Uname - -type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_netbsd.go b/vendor/golang.org/x/sys/unix/types_netbsd.go deleted file mode 100644 index 4a96d72c37..0000000000 --- a/vendor/golang.org/x/sys/unix/types_netbsd.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -type Ptmget C.struct_ptmget - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Sysctl - -type Sysctlnode C.struct_sysctlnode - -// Uname - -type Utsname C.struct_utsname - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go deleted file mode 100644 index 775cb57dc8..0000000000 --- a/vendor/golang.org/x/sys/unix/types_openbsd.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Signal Sets - -type Sigset_t C.sigset_t - -// Uname - -type Utsname C.struct_utsname - -// Uvmexp - -const SizeofUvmexp = C.sizeof_struct_uvmexp - -type Uvmexp C.struct_uvmexp - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go deleted file mode 100644 index 2b716f9348..0000000000 --- a/vendor/golang.org/x/sys/unix/types_solaris.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -// These defines ensure that builds done on newer versions of Solaris are -// backwards-compatible with older versions of Solaris and -// OpenSolaris-based derivatives. -#define __USE_SUNOS_SOCKETS__ // msghdr -#define __USE_LEGACY_PROTOTYPES__ // iovec -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX - MaxHostNameLen = C.MAXHOSTNAMELEN -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -// Filesystems - -type _Fsblkcnt_t C.fsblkcnt_t - -type Statvfs_t C.struct_statvfs - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Select - -type FdSet C.fd_set - -// Misc - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_EACCESS = C.AT_EACCESS -) - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfTimeval C.struct_bpf_timeval - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Termio C.struct_termio - -type Winsize C.struct_winsize - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) diff --git a/vendor/golang.org/x/text/encoding/charmap/maketables.go b/vendor/golang.org/x/text/encoding/charmap/maketables.go deleted file mode 100644 index f7941701e8..0000000000 --- a/vendor/golang.org/x/text/encoding/charmap/maketables.go +++ /dev/null @@ -1,556 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" - "unicode/utf8" - - "golang.org/x/text/encoding" - "golang.org/x/text/internal/gen" -) - -const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - ` !"#$%&'()*+,-./0123456789:;<=>?` + - `@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` + - "`abcdefghijklmnopqrstuvwxyz{|}~\u007f" - -var encodings = []struct { - name string - mib string - comment string - varName string - replacement byte - mapping string -}{ - { - "IBM Code Page 037", - "IBM037", - "", - "CodePage037", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm", - }, - { - "IBM Code Page 437", - "PC8CodePage437", - "", - "CodePage437", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm", - }, - { - "IBM Code Page 850", - "PC850Multilingual", - "", - "CodePage850", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm", - }, - { - "IBM Code Page 852", - "PCp852", - "", - "CodePage852", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm", - }, - { - "IBM Code Page 855", - "IBM855", - "", - "CodePage855", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm", - }, - { - "Windows Code Page 858", // PC latin1 with Euro - "IBM00858", - "", - "CodePage858", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm", - }, - { - "IBM Code Page 860", - "IBM860", - "", - "CodePage860", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm", - }, - { - "IBM Code Page 862", - "PC862LatinHebrew", - "", - "CodePage862", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm", - }, - { - "IBM Code Page 863", - "IBM863", - "", - "CodePage863", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm", - }, - { - "IBM Code Page 865", - "IBM865", - "", - "CodePage865", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm", - }, - { - "IBM Code Page 866", - "IBM866", - "", - "CodePage866", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-ibm866.txt", - }, - { - "IBM Code Page 1047", - "IBM1047", - "", - "CodePage1047", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm", - }, - { - "IBM Code Page 1140", - "IBM01140", - "", - "CodePage1140", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm", - }, - { - "ISO 8859-1", - "ISOLatin1", - "", - "ISO8859_1", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm", - }, - { - "ISO 8859-2", - "ISOLatin2", - "", - "ISO8859_2", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-2.txt", - }, - { - "ISO 8859-3", - "ISOLatin3", - "", - "ISO8859_3", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-3.txt", - }, - { - "ISO 8859-4", - "ISOLatin4", - "", - "ISO8859_4", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-4.txt", - }, - { - "ISO 8859-5", - "ISOLatinCyrillic", - "", - "ISO8859_5", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-5.txt", - }, - { - "ISO 8859-6", - "ISOLatinArabic", - "", - "ISO8859_6,ISO8859_6E,ISO8859_6I", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-6.txt", - }, - { - "ISO 8859-7", - "ISOLatinGreek", - "", - "ISO8859_7", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-7.txt", - }, - { - "ISO 8859-8", - "ISOLatinHebrew", - "", - "ISO8859_8,ISO8859_8E,ISO8859_8I", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-8.txt", - }, - { - "ISO 8859-9", - "ISOLatin5", - "", - "ISO8859_9", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm", - }, - { - "ISO 8859-10", - "ISOLatin6", - "", - "ISO8859_10", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-10.txt", - }, - { - "ISO 8859-13", - "ISO885913", - "", - "ISO8859_13", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-13.txt", - }, - { - "ISO 8859-14", - "ISO885914", - "", - "ISO8859_14", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-14.txt", - }, - { - "ISO 8859-15", - "ISO885915", - "", - "ISO8859_15", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-15.txt", - }, - { - "ISO 8859-16", - "ISO885916", - "", - "ISO8859_16", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-16.txt", - }, - { - "KOI8-R", - "KOI8R", - "", - "KOI8R", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-koi8-r.txt", - }, - { - "KOI8-U", - "KOI8U", - "", - "KOI8U", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-koi8-u.txt", - }, - { - "Macintosh", - "Macintosh", - "", - "Macintosh", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-macintosh.txt", - }, - { - "Macintosh Cyrillic", - "MacintoshCyrillic", - "", - "MacintoshCyrillic", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt", - }, - { - "Windows 874", - "Windows874", - "", - "Windows874", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-874.txt", - }, - { - "Windows 1250", - "Windows1250", - "", - "Windows1250", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1250.txt", - }, - { - "Windows 1251", - "Windows1251", - "", - "Windows1251", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1251.txt", - }, - { - "Windows 1252", - "Windows1252", - "", - "Windows1252", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1252.txt", - }, - { - "Windows 1253", - "Windows1253", - "", - "Windows1253", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1253.txt", - }, - { - "Windows 1254", - "Windows1254", - "", - "Windows1254", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1254.txt", - }, - { - "Windows 1255", - "Windows1255", - "", - "Windows1255", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1255.txt", - }, - { - "Windows 1256", - "Windows1256", - "", - "Windows1256", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1256.txt", - }, - { - "Windows 1257", - "Windows1257", - "", - "Windows1257", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1257.txt", - }, - { - "Windows 1258", - "Windows1258", - "", - "Windows1258", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1258.txt", - }, - { - "X-User-Defined", - "XUserDefined", - "It is defined at http://encoding.spec.whatwg.org/#x-user-defined", - "XUserDefined", - encoding.ASCIISub, - ascii + - "\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" + - "\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" + - "\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" + - "\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" + - "\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" + - "\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" + - "\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" + - "\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" + - "\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" + - "\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" + - "\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" + - "\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" + - "\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" + - "\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" + - "\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" + - "\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff", - }, -} - -func getWHATWG(url string) string { - res, err := http.Get(url) - if err != nil { - log.Fatalf("%q: Get: %v", url, err) - } - defer res.Body.Close() - - mapping := make([]rune, 128) - for i := range mapping { - mapping[i] = '\ufffd' - } - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := 0, 0 - if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 128 <= x { - log.Fatalf("code %d is out of range", x) - } - if 0x80 <= y && y < 0xa0 { - // We diverge from the WHATWG spec by mapping control characters - // in the range [0x80, 0xa0) to U+FFFD. - continue - } - mapping[x] = rune(y) - } - return ascii + string(mapping) -} - -func getUCM(url string) string { - res, err := http.Get(url) - if err != nil { - log.Fatalf("%q: Get: %v", url, err) - } - defer res.Body.Close() - - mapping := make([]rune, 256) - for i := range mapping { - mapping[i] = '\ufffd' - } - - charsFound := 0 - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - var c byte - var r rune - if _, err := fmt.Sscanf(s, ` \x%x |0`, &r, &c); err != nil { - continue - } - mapping[c] = r - charsFound++ - } - - if charsFound < 200 { - log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound) - } - - return string(mapping) -} - -func main() { - mibs := map[string]bool{} - all := []string{} - - w := gen.NewCodeWriter() - defer w.WriteGoFile("tables.go", "charmap") - - printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) } - - printf("import (\n") - printf("\t\"golang.org/x/text/encoding\"\n") - printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n") - printf(")\n\n") - for _, e := range encodings { - varNames := strings.Split(e.varName, ",") - all = append(all, varNames...) - varName := varNames[0] - switch { - case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"): - e.mapping = getWHATWG(e.mapping) - case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"): - e.mapping = getUCM(e.mapping) - } - - asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00 - if asciiSuperset { - low = 0x80 - } - lvn := 1 - if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") { - lvn = 3 - } - lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:] - printf("// %s is the %s encoding.\n", varName, e.name) - if e.comment != "" { - printf("//\n// %s\n", e.comment) - } - printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n", - varName, lowerVarName, lowerVarName, e.name) - if mibs[e.mib] { - log.Fatalf("MIB type %q declared multiple times.", e.mib) - } - printf("mib: identifier.%s,\n", e.mib) - printf("asciiSuperset: %t,\n", asciiSuperset) - printf("low: 0x%02x,\n", low) - printf("replacement: 0x%02x,\n", e.replacement) - - printf("decode: [256]utf8Enc{\n") - i, backMapping := 0, map[rune]byte{} - for _, c := range e.mapping { - if _, ok := backMapping[c]; !ok && c != utf8.RuneError { - backMapping[c] = byte(i) - } - var buf [8]byte - n := utf8.EncodeRune(buf[:], c) - if n > 3 { - panic(fmt.Sprintf("rune %q (%U) is too long", c, c)) - } - printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2]) - if i%2 == 1 { - printf("\n") - } - i++ - } - printf("},\n") - - printf("encode: [256]uint32{\n") - encode := make([]uint32, 0, 256) - for c, i := range backMapping { - encode = append(encode, uint32(i)<<24|uint32(c)) - } - sort.Sort(byRune(encode)) - for len(encode) < cap(encode) { - encode = append(encode, encode[len(encode)-1]) - } - for i, enc := range encode { - printf("0x%08x,", enc) - if i%8 == 7 { - printf("\n") - } - } - printf("},\n}\n") - - // Add an estimate of the size of a single Charmap{} struct value, which - // includes two 256 elem arrays of 4 bytes and some extra fields, which - // align to 3 uint64s on 64-bit architectures. - w.Size += 2*4*256 + 3*8 - } - // TODO: add proper line breaking. - printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n")) -} - -type byRune []uint32 - -func (b byRune) Len() int { return len(b) } -func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff } -func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/htmlindex/gen.go b/vendor/golang.org/x/text/encoding/htmlindex/gen.go deleted file mode 100644 index ac6b4a77fd..0000000000 --- a/vendor/golang.org/x/text/encoding/htmlindex/gen.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "strings" - - "golang.org/x/text/internal/gen" -) - -type group struct { - Encodings []struct { - Labels []string - Name string - } -} - -func main() { - gen.Init() - - r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") - var groups []group - if err := json.NewDecoder(r).Decode(&groups); err != nil { - log.Fatalf("Error reading encodings.json: %v", err) - } - - w := &bytes.Buffer{} - fmt.Fprintln(w, "type htmlEncoding byte") - fmt.Fprintln(w, "const (") - for i, g := range groups { - for _, e := range g.Encodings { - key := strings.ToLower(e.Name) - name := consts[key] - if name == "" { - log.Fatalf("No const defined for %s.", key) - } - if i == 0 { - fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) - } else { - fmt.Fprintf(w, "%s\n", name) - } - } - } - fmt.Fprintln(w, "numEncodings") - fmt.Fprint(w, ")\n\n") - - fmt.Fprintln(w, "var canonical = [numEncodings]string{") - for _, g := range groups { - for _, e := range g.Encodings { - fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) - } - } - fmt.Fprint(w, "}\n\n") - - fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") - for _, g := range groups { - for _, e := range g.Encodings { - for _, l := range e.Labels { - key := strings.ToLower(e.Name) - name := consts[key] - fmt.Fprintf(w, "%q: %s,\n", l, name) - } - } - } - fmt.Fprint(w, "}\n\n") - - var tags []string - fmt.Fprintln(w, "var localeMap = []htmlEncoding{") - for _, loc := range locales { - tags = append(tags, loc.tag) - fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) - } - fmt.Fprint(w, "}\n\n") - - fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) - - gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) -} - -// consts maps canonical encoding name to internal constant. -var consts = map[string]string{ - "utf-8": "utf8", - "ibm866": "ibm866", - "iso-8859-2": "iso8859_2", - "iso-8859-3": "iso8859_3", - "iso-8859-4": "iso8859_4", - "iso-8859-5": "iso8859_5", - "iso-8859-6": "iso8859_6", - "iso-8859-7": "iso8859_7", - "iso-8859-8": "iso8859_8", - "iso-8859-8-i": "iso8859_8I", - "iso-8859-10": "iso8859_10", - "iso-8859-13": "iso8859_13", - "iso-8859-14": "iso8859_14", - "iso-8859-15": "iso8859_15", - "iso-8859-16": "iso8859_16", - "koi8-r": "koi8r", - "koi8-u": "koi8u", - "macintosh": "macintosh", - "windows-874": "windows874", - "windows-1250": "windows1250", - "windows-1251": "windows1251", - "windows-1252": "windows1252", - "windows-1253": "windows1253", - "windows-1254": "windows1254", - "windows-1255": "windows1255", - "windows-1256": "windows1256", - "windows-1257": "windows1257", - "windows-1258": "windows1258", - "x-mac-cyrillic": "macintoshCyrillic", - "gbk": "gbk", - "gb18030": "gb18030", - // "hz-gb-2312": "hzgb2312", // Was removed from WhatWG - "big5": "big5", - "euc-jp": "eucjp", - "iso-2022-jp": "iso2022jp", - "shift_jis": "shiftJIS", - "euc-kr": "euckr", - "replacement": "replacement", - "utf-16be": "utf16be", - "utf-16le": "utf16le", - "x-user-defined": "xUserDefined", -} - -// locales is taken from -// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm. -var locales = []struct{ tag, name string }{ - // The default value. Explicitly state latin to benefit from the exact - // script option, while still making 1252 the default encoding for languages - // written in Latin script. - {"und_Latn", "windows-1252"}, - {"ar", "windows-1256"}, - {"ba", "windows-1251"}, - {"be", "windows-1251"}, - {"bg", "windows-1251"}, - {"cs", "windows-1250"}, - {"el", "iso-8859-7"}, - {"et", "windows-1257"}, - {"fa", "windows-1256"}, - {"he", "windows-1255"}, - {"hr", "windows-1250"}, - {"hu", "iso-8859-2"}, - {"ja", "shift_jis"}, - {"kk", "windows-1251"}, - {"ko", "euc-kr"}, - {"ku", "windows-1254"}, - {"ky", "windows-1251"}, - {"lt", "windows-1257"}, - {"lv", "windows-1257"}, - {"mk", "windows-1251"}, - {"pl", "iso-8859-2"}, - {"ru", "windows-1251"}, - {"sah", "windows-1251"}, - {"sk", "windows-1250"}, - {"sl", "iso-8859-2"}, - {"sr", "windows-1251"}, - {"tg", "windows-1251"}, - {"th", "windows-874"}, - {"tr", "windows-1254"}, - {"tt", "windows-1251"}, - {"uk", "windows-1251"}, - {"vi", "windows-1258"}, - {"zh-hans", "gb18030"}, - {"zh-hant", "big5"}, -} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go deleted file mode 100644 index 26cfef9c6b..0000000000 --- a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bytes" - "encoding/xml" - "fmt" - "io" - "log" - "strings" - - "golang.org/x/text/internal/gen" -) - -type registry struct { - XMLName xml.Name `xml:"registry"` - Updated string `xml:"updated"` - Registry []struct { - ID string `xml:"id,attr"` - Record []struct { - Name string `xml:"name"` - Xref []struct { - Type string `xml:"type,attr"` - Data string `xml:"data,attr"` - } `xml:"xref"` - Desc struct { - Data string `xml:",innerxml"` - // Any []struct { - // Data string `xml:",chardata"` - // } `xml:",any"` - // Data string `xml:",chardata"` - } `xml:"description,"` - MIB string `xml:"value"` - Alias []string `xml:"alias"` - MIME string `xml:"preferred_alias"` - } `xml:"record"` - } `xml:"registry"` -} - -func main() { - r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") - reg := ®istry{} - if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { - log.Fatalf("Error decoding charset registry: %v", err) - } - if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { - log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) - } - - w := &bytes.Buffer{} - fmt.Fprintf(w, "const (\n") - for _, rec := range reg.Registry[0].Record { - constName := "" - for _, a := range rec.Alias { - if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { - // Some of the constant definitions have comments in them. Strip those. - constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) - } - } - if constName == "" { - switch rec.MIB { - case "2085": - constName = "HZGB2312" // Not listed as alias for some reason. - default: - log.Fatalf("No cs alias defined for %s.", rec.MIB) - } - } - if rec.MIME != "" { - rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) - } - fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) - if len(rec.Desc.Data) > 0 { - fmt.Fprint(w, "// ") - d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) - inElem := true - attr := "" - for { - t, err := d.Token() - if err != nil { - if err != io.EOF { - log.Fatal(err) - } - break - } - switch x := t.(type) { - case xml.CharData: - attr = "" // Don't need attribute info. - a := bytes.Split([]byte(x), []byte("\n")) - for i, b := range a { - if b = bytes.TrimSpace(b); len(b) != 0 { - if !inElem && i > 0 { - fmt.Fprint(w, "\n// ") - } - inElem = false - fmt.Fprintf(w, "%s ", string(b)) - } - } - case xml.StartElement: - if x.Name.Local == "xref" { - inElem = true - use := false - for _, a := range x.Attr { - if a.Name.Local == "type" { - use = use || a.Value != "person" - } - if a.Name.Local == "data" && use { - // Patch up URLs to use https. From some links, the - // https version is different from the http one. - s := a.Value - s = strings.Replace(s, "http://", "https://", -1) - s = strings.Replace(s, "/unicode/", "/", -1) - attr = s + " " - } - } - } - case xml.EndElement: - inElem = false - fmt.Fprint(w, attr) - } - } - fmt.Fprint(w, "\n") - } - for _, x := range rec.Xref { - switch x.Type { - case "rfc": - fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) - case "uri": - fmt.Fprintf(w, "// Reference: %s\n", x.Data) - } - } - fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) - fmt.Fprintln(w) - } - fmt.Fprintln(w, ")") - - gen.WriteGoFile("mib.go", "identifier", w.Bytes()) -} diff --git a/vendor/golang.org/x/text/encoding/japanese/maketables.go b/vendor/golang.org/x/text/encoding/japanese/maketables.go deleted file mode 100644 index 023957a672..0000000000 --- a/vendor/golang.org/x/text/encoding/japanese/maketables.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -// TODO: Emoji extensions? -// https://www.unicode.org/faq/emoji_dingbats.html -// https://www.unicode.org/Public/UNIDATA/EmojiSources.txt - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -type entry struct { - jisCode, table int -} - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n") - fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n") - - reverse := [65536]entry{} - for i := range reverse { - reverse[i].table = -1 - } - - tables := []struct { - url string - name string - }{ - {"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"}, - {"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"}, - } - for i, table := range tables { - res, err := http.Get(table.url) - if err != nil { - log.Fatalf("%q: Get: %v", table.url, err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := 0, uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("%q: could not parse %q", table.url, s) - } - if x < 0 || 120*94 <= x { - log.Fatalf("%q: JIS code %d is out of range", table.url, x) - } - mapping[x] = y - if reverse[y].table == -1 { - reverse[y] = entry{jisCode: x, table: i} - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("%q: scanner error: %v", table.url, err) - } - - fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n", - table.name, table.name, table.url) - fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name) - for i, m := range mapping { - if m != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, m) - } - } - fmt.Printf("}\n\n") - } - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v.table == -1 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const (\n") - fmt.Printf("\tjis0208 = 1\n") - fmt.Printf("\tjis0212 = 2\n") - fmt.Printf("\tcodeMask = 0x7f\n") - fmt.Printf("\tcodeShift = 7\n") - fmt.Printf("\ttableShift = 14\n") - fmt.Printf(")\n\n") - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("//\n") - fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n") - fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n") - fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n") - fmt.Printf("// JIS code (94*j1 + j2) within that table.\n") - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x.table == -1 { - continue - } - fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n", - j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/korean/maketables.go b/vendor/golang.org/x/text/encoding/korean/maketables.go deleted file mode 100644 index c84034fb67..0000000000 --- a/vendor/golang.org/x/text/encoding/korean/maketables.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") - fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") - - res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - reverse := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { - log.Fatalf("EUC-KR code %d is out of range", x) - } - mapping[x] = y - if reverse[y] == 0 { - c0, c1 := uint16(0), uint16(0) - if x < 178*(0xc7-0x81) { - c0 = uint16(x/178) + 0x81 - c1 = uint16(x % 178) - switch { - case c1 < 1*26: - c1 += 0x41 - case c1 < 2*26: - c1 += 0x47 - default: - c1 += 0x4d - } - } else { - x -= 178 * (0xc7 - 0x81) - c0 = uint16(x/94) + 0xc7 - c1 = uint16(x%94) + 0xa1 - } - reverse[y] = c0<<8 | c1 - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") - fmt.Printf("var decode = [...]uint16{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go deleted file mode 100644 index 55016c7862..0000000000 --- a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") - fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") - - printGB18030() - printGBK() -} - -func printGB18030() { - res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") - fmt.Printf("var gb18030 = [...][2]uint16{\n") - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint32(0), uint32(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0x10000 && y < 0x10000 { - fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) - } - } - fmt.Printf("}\n\n") -} - -func printGBK() { - res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - reverse := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 126*190 <= x { - log.Fatalf("GBK code %d is out of range", x) - } - mapping[x] = y - if reverse[y] == 0 { - c0, c1 := x/190, x%190 - if c1 >= 0x3f { - c1++ - } - reverse[y] = (0x81+c0)<<8 | (0x40 + c1) - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") - fmt.Printf("var decode = [...]uint16{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go deleted file mode 100644 index cf7fdb31a5..0000000000 --- a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") - fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") - - res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint32{} - reverse := [65536 * 4]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint32(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 126*157 <= x { - log.Fatalf("Big5 code %d is out of range", x) - } - mapping[x] = y - - // The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that - // "The index pointer for code point in index is the first pointer - // corresponding to code point in index", which would normally mean - // that the code below should be guarded by "if reverse[y] == 0", but - // last instead of first seems to match the behavior of - // "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in - // http://encoding.spec.whatwg.org/index-big5.txt, as index 2148 - // (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc") - // and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc". - c0, c1 := x/157, x%157 - if c1 < 0x3f { - c1 += 0x40 - } else { - c1 += 0x62 - } - reverse[y] = (0x81+c0)<<8 | c1 - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") - fmt.Printf("var decode = [...]uint32{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%08X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/internal/language/compact/gen.go b/vendor/golang.org/x/text/internal/language/compact/gen.go deleted file mode 100644 index 0c36a052f6..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Language tag table generator. -// Data read from the web. - -package main - -import ( - "flag" - "fmt" - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/unicode/cldr" -) - -var ( - test = flag.Bool("test", - false, - "test existing tables; can be used to compare web data with package data.") - outputFile = flag.String("output", - "tables.go", - "output file for generated tables") -) - -func main() { - gen.Init() - - w := gen.NewCodeWriter() - defer w.WriteGoFile("tables.go", "compact") - - fmt.Fprintln(w, `import "golang.org/x/text/internal/language"`) - - b := newBuilder(w) - gen.WriteCLDRVersion(w) - - b.writeCompactIndex() -} - -type builder struct { - w *gen.CodeWriter - data *cldr.CLDR - supp *cldr.SupplementalData -} - -func newBuilder(w *gen.CodeWriter) *builder { - r := gen.OpenCLDRCoreZip() - defer r.Close() - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - if err != nil { - log.Fatal(err) - } - b := builder{ - w: w, - data: data, - supp: data.Supplemental(), - } - return &b -} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_index.go b/vendor/golang.org/x/text/internal/language/compact/gen_index.go deleted file mode 100644 index 136cefaf08..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen_index.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This file generates derivative tables based on the language package itself. - -import ( - "fmt" - "log" - "sort" - "strings" - - "golang.org/x/text/internal/language" -) - -// Compact indices: -// Note -va-X variants only apply to localization variants. -// BCP variants only ever apply to language. -// The only ambiguity between tags is with regions. - -func (b *builder) writeCompactIndex() { - // Collect all language tags for which we have any data in CLDR. - m := map[language.Tag]bool{} - for _, lang := range b.data.Locales() { - // We include all locales unconditionally to be consistent with en_US. - // We want en_US, even though it has no data associated with it. - - // TODO: put any of the languages for which no data exists at the end - // of the index. This allows all components based on ICU to use that - // as the cutoff point. - // if x := data.RawLDML(lang); false || - // x.LocaleDisplayNames != nil || - // x.Characters != nil || - // x.Delimiters != nil || - // x.Measurement != nil || - // x.Dates != nil || - // x.Numbers != nil || - // x.Units != nil || - // x.ListPatterns != nil || - // x.Collations != nil || - // x.Segmentations != nil || - // x.Rbnf != nil || - // x.Annotations != nil || - // x.Metadata != nil { - - // TODO: support POSIX natively, albeit non-standard. - tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1)) - m[tag] = true - // } - } - - // TODO: plural rules are also defined for the deprecated tags: - // iw mo sh tl - // Consider removing these as compact tags. - - // Include locales for plural rules, which uses a different structure. - for _, plurals := range b.supp.Plurals { - for _, rules := range plurals.PluralRules { - for _, lang := range strings.Split(rules.Locales, " ") { - m[language.Make(lang)] = true - } - } - } - - var coreTags []language.CompactCoreInfo - var special []string - - for t := range m { - if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { - log.Fatalf("Unexpected extension %v in %v", x, t) - } - if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { - cci, ok := language.GetCompactCore(t) - if !ok { - log.Fatalf("Locale for non-basic language %q", t) - } - coreTags = append(coreTags, cci) - } else { - special = append(special, t.String()) - } - } - - w := b.w - - sort.Slice(coreTags, func(i, j int) bool { return coreTags[i] < coreTags[j] }) - sort.Strings(special) - - w.WriteComment(` - NumCompactTags is the number of common tags. The maximum tag is - NumCompactTags-1.`) - w.WriteConst("NumCompactTags", len(m)) - - fmt.Fprintln(w, "const (") - for i, t := range coreTags { - fmt.Fprintf(w, "%s ID = %d\n", ident(t.Tag().String()), i) - } - for i, t := range special { - fmt.Fprintf(w, "%s ID = %d\n", ident(t), i+len(coreTags)) - } - fmt.Fprintln(w, ")") - - w.WriteVar("coreTags", coreTags) - - w.WriteConst("specialTagsStr", strings.Join(special, " ")) -} - -func ident(s string) string { - return strings.Replace(s, "-", "", -1) + "Index" -} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go deleted file mode 100644 index 9543d58323..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/language" - "golang.org/x/text/internal/language/compact" - "golang.org/x/text/unicode/cldr" -) - -func main() { - r := gen.OpenCLDRCoreZip() - defer r.Close() - - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - if err != nil { - log.Fatalf("DecodeZip: %v", err) - } - - w := gen.NewCodeWriter() - defer w.WriteGoFile("parents.go", "compact") - - // Create parents table. - type ID uint16 - parents := make([]ID, compact.NumCompactTags) - for _, loc := range data.Locales() { - tag := language.MustParse(loc) - index, ok := compact.FromTag(tag) - if !ok { - continue - } - parentIndex := compact.ID(0) // und - for p := tag.Parent(); p != language.Und; p = p.Parent() { - if x, ok := compact.FromTag(p); ok { - parentIndex = x - break - } - } - parents[index] = ID(parentIndex) - } - - w.WriteComment(` - parents maps a compact index of a tag to the compact index of the parent of - this tag.`) - w.WriteVar("parents", parents) -} diff --git a/vendor/golang.org/x/text/internal/language/gen.go b/vendor/golang.org/x/text/internal/language/gen.go deleted file mode 100644 index cdcc7febcb..0000000000 --- a/vendor/golang.org/x/text/internal/language/gen.go +++ /dev/null @@ -1,1520 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Language tag table generator. -// Data read from the web. - -package main - -import ( - "bufio" - "flag" - "fmt" - "io" - "io/ioutil" - "log" - "math" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/tag" - "golang.org/x/text/unicode/cldr" -) - -var ( - test = flag.Bool("test", - false, - "test existing tables; can be used to compare web data with package data.") - outputFile = flag.String("output", - "tables.go", - "output file for generated tables") -) - -var comment = []string{ - ` -lang holds an alphabetically sorted list of ISO-639 language identifiers. -All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag. -For 2-byte language identifiers, the two successive bytes have the following meaning: - - if the first letter of the 2- and 3-letter ISO codes are the same: - the second and third letter of the 3-letter ISO code. - - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3. -For 3-byte language identifiers the 4th byte is 0.`, - ` -langNoIndex is a bit vector of all 3-letter language codes that are not used as an index -in lookup tables. The language ids for these language codes are derived directly -from the letters and are not consecutive.`, - ` -altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives -to 2-letter language codes that cannot be derived using the method described above. -Each 3-letter code is followed by its 1-byte langID.`, - ` -altLangIndex is used to convert indexes in altLangISO3 to langIDs.`, - ` -AliasMap maps langIDs to their suggested replacements.`, - ` -script is an alphabetically sorted list of ISO 15924 codes. The index -of the script in the string, divided by 4, is the internal scriptID.`, - ` -isoRegionOffset needs to be added to the index of regionISO to obtain the regionID -for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for -the UN.M49 codes used for groups.)`, - ` -regionISO holds a list of alphabetically sorted 2-letter ISO region codes. -Each 2-letter codes is followed by two bytes with the following meaning: - - [A-Z}{2}: the first letter of the 2-letter code plus these two - letters form the 3-letter ISO code. - - 0, n: index into altRegionISO3.`, - ` -regionTypes defines the status of a region for various standards.`, - ` -m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are -codes indicating collections of regions.`, - ` -m49Index gives indexes into fromM49 based on the three most significant bits -of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in - fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]] -for an entry where the first 7 bits match the 7 lsb of the UN.M49 code. -The region code is stored in the 9 lsb of the indexed value.`, - ` -fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.`, - ` -altRegionISO3 holds a list of 3-letter region codes that cannot be -mapped to 2-letter codes using the default algorithm. This is a short list.`, - ` -altRegionIDs holds a list of regionIDs the positions of which match those -of the 3-letter ISO codes in altRegionISO3.`, - ` -variantNumSpecialized is the number of specialized variants in variants.`, - ` -suppressScript is an index from langID to the dominant script for that language, -if it exists. If a script is given, it should be suppressed from the language tag.`, - ` -likelyLang is a lookup table, indexed by langID, for the most likely -scripts and regions given incomplete information. If more entries exist for a -given language, region and script are the index and size respectively -of the list in likelyLangList.`, - ` -likelyLangList holds lists info associated with likelyLang.`, - ` -likelyRegion is a lookup table, indexed by regionID, for the most likely -languages and scripts given incomplete information. If more entries exist -for a given regionID, lang and script are the index and size respectively -of the list in likelyRegionList. -TODO: exclude containers and user-definable regions from the list.`, - ` -likelyRegionList holds lists info associated with likelyRegion.`, - ` -likelyScript is a lookup table, indexed by scriptID, for the most likely -languages and regions given a script.`, - ` -nRegionGroups is the number of region groups.`, - ` -regionInclusion maps region identifiers to sets of regions in regionInclusionBits, -where each set holds all groupings that are directly connected in a region -containment graph.`, - ` -regionInclusionBits is an array of bit vectors where every vector represents -a set of region groupings. These sets are used to compute the distance -between two regions for the purpose of language matching.`, - ` -regionInclusionNext marks, for each entry in regionInclusionBits, the set of -all groups that are reachable from the groups set in the respective entry.`, -} - -// TODO: consider changing some of these structures to tries. This can reduce -// memory, but may increase the need for memory allocations. This could be -// mitigated if we can piggyback on language tags for common cases. - -func failOnError(e error) { - if e != nil { - log.Panic(e) - } -} - -type setType int - -const ( - Indexed setType = 1 + iota // all elements must be of same size - Linear -) - -type stringSet struct { - s []string - sorted, frozen bool - - // We often need to update values after the creation of an index is completed. - // We include a convenience map for keeping track of this. - update map[string]string - typ setType // used for checking. -} - -func (ss *stringSet) clone() stringSet { - c := *ss - c.s = append([]string(nil), c.s...) - return c -} - -func (ss *stringSet) setType(t setType) { - if ss.typ != t && ss.typ != 0 { - log.Panicf("type %d cannot be assigned as it was already %d", t, ss.typ) - } -} - -// parse parses a whitespace-separated string and initializes ss with its -// components. -func (ss *stringSet) parse(s string) { - scan := bufio.NewScanner(strings.NewReader(s)) - scan.Split(bufio.ScanWords) - for scan.Scan() { - ss.add(scan.Text()) - } -} - -func (ss *stringSet) assertChangeable() { - if ss.frozen { - log.Panic("attempt to modify a frozen stringSet") - } -} - -func (ss *stringSet) add(s string) { - ss.assertChangeable() - ss.s = append(ss.s, s) - ss.sorted = ss.frozen -} - -func (ss *stringSet) freeze() { - ss.compact() - ss.frozen = true -} - -func (ss *stringSet) compact() { - if ss.sorted { - return - } - a := ss.s - sort.Strings(a) - k := 0 - for i := 1; i < len(a); i++ { - if a[k] != a[i] { - a[k+1] = a[i] - k++ - } - } - ss.s = a[:k+1] - ss.sorted = ss.frozen -} - -type funcSorter struct { - fn func(a, b string) bool - sort.StringSlice -} - -func (s funcSorter) Less(i, j int) bool { - return s.fn(s.StringSlice[i], s.StringSlice[j]) -} - -func (ss *stringSet) sortFunc(f func(a, b string) bool) { - ss.compact() - sort.Sort(funcSorter{f, sort.StringSlice(ss.s)}) -} - -func (ss *stringSet) remove(s string) { - ss.assertChangeable() - if i, ok := ss.find(s); ok { - copy(ss.s[i:], ss.s[i+1:]) - ss.s = ss.s[:len(ss.s)-1] - } -} - -func (ss *stringSet) replace(ol, nu string) { - ss.s[ss.index(ol)] = nu - ss.sorted = ss.frozen -} - -func (ss *stringSet) index(s string) int { - ss.setType(Indexed) - i, ok := ss.find(s) - if !ok { - if i < len(ss.s) { - log.Panicf("find: item %q is not in list. Closest match is %q.", s, ss.s[i]) - } - log.Panicf("find: item %q is not in list", s) - - } - return i -} - -func (ss *stringSet) find(s string) (int, bool) { - ss.compact() - i := sort.SearchStrings(ss.s, s) - return i, i != len(ss.s) && ss.s[i] == s -} - -func (ss *stringSet) slice() []string { - ss.compact() - return ss.s -} - -func (ss *stringSet) updateLater(v, key string) { - if ss.update == nil { - ss.update = map[string]string{} - } - ss.update[v] = key -} - -// join joins the string and ensures that all entries are of the same length. -func (ss *stringSet) join() string { - ss.setType(Indexed) - n := len(ss.s[0]) - for _, s := range ss.s { - if len(s) != n { - log.Panicf("join: not all entries are of the same length: %q", s) - } - } - ss.s = append(ss.s, strings.Repeat("\xff", n)) - return strings.Join(ss.s, "") -} - -// ianaEntry holds information for an entry in the IANA Language Subtag Repository. -// All types use the same entry. -// See http://tools.ietf.org/html/bcp47#section-5.1 for a description of the various -// fields. -type ianaEntry struct { - typ string - description []string - scope string - added string - preferred string - deprecated string - suppressScript string - macro string - prefix []string -} - -type builder struct { - w *gen.CodeWriter - hw io.Writer // MultiWriter for w and w.Hash - data *cldr.CLDR - supp *cldr.SupplementalData - - // indices - locale stringSet // common locales - lang stringSet // canonical language ids (2 or 3 letter ISO codes) with data - langNoIndex stringSet // 3-letter ISO codes with no associated data - script stringSet // 4-letter ISO codes - region stringSet // 2-letter ISO or 3-digit UN M49 codes - variant stringSet // 4-8-alphanumeric variant code. - - // Region codes that are groups with their corresponding group IDs. - groups map[int]index - - // langInfo - registry map[string]*ianaEntry -} - -type index uint - -func newBuilder(w *gen.CodeWriter) *builder { - r := gen.OpenCLDRCoreZip() - defer r.Close() - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - failOnError(err) - b := builder{ - w: w, - hw: io.MultiWriter(w, w.Hash), - data: data, - supp: data.Supplemental(), - } - b.parseRegistry() - return &b -} - -func (b *builder) parseRegistry() { - r := gen.OpenIANAFile("assignments/language-subtag-registry") - defer r.Close() - b.registry = make(map[string]*ianaEntry) - - scan := bufio.NewScanner(r) - scan.Split(bufio.ScanWords) - var record *ianaEntry - for more := scan.Scan(); more; { - key := scan.Text() - more = scan.Scan() - value := scan.Text() - switch key { - case "Type:": - record = &ianaEntry{typ: value} - case "Subtag:", "Tag:": - if s := strings.SplitN(value, "..", 2); len(s) > 1 { - for a := s[0]; a <= s[1]; a = inc(a) { - b.addToRegistry(a, record) - } - } else { - b.addToRegistry(value, record) - } - case "Suppress-Script:": - record.suppressScript = value - case "Added:": - record.added = value - case "Deprecated:": - record.deprecated = value - case "Macrolanguage:": - record.macro = value - case "Preferred-Value:": - record.preferred = value - case "Prefix:": - record.prefix = append(record.prefix, value) - case "Scope:": - record.scope = value - case "Description:": - buf := []byte(value) - for more = scan.Scan(); more; more = scan.Scan() { - b := scan.Bytes() - if b[0] == '%' || b[len(b)-1] == ':' { - break - } - buf = append(buf, ' ') - buf = append(buf, b...) - } - record.description = append(record.description, string(buf)) - continue - default: - continue - } - more = scan.Scan() - } - if scan.Err() != nil { - log.Panic(scan.Err()) - } -} - -func (b *builder) addToRegistry(key string, entry *ianaEntry) { - if info, ok := b.registry[key]; ok { - if info.typ != "language" || entry.typ != "extlang" { - log.Fatalf("parseRegistry: tag %q already exists", key) - } - } else { - b.registry[key] = entry - } -} - -var commentIndex = make(map[string]string) - -func init() { - for _, s := range comment { - key := strings.TrimSpace(strings.SplitN(s, " ", 2)[0]) - commentIndex[key] = s - } -} - -func (b *builder) comment(name string) { - if s := commentIndex[name]; len(s) > 0 { - b.w.WriteComment(s) - } else { - fmt.Fprintln(b.w) - } -} - -func (b *builder) pf(f string, x ...interface{}) { - fmt.Fprintf(b.hw, f, x...) - fmt.Fprint(b.hw, "\n") -} - -func (b *builder) p(x ...interface{}) { - fmt.Fprintln(b.hw, x...) -} - -func (b *builder) addSize(s int) { - b.w.Size += s - b.pf("// Size: %d bytes", s) -} - -func (b *builder) writeConst(name string, x interface{}) { - b.comment(name) - b.w.WriteConst(name, x) -} - -// writeConsts computes f(v) for all v in values and writes the results -// as constants named _v to a single constant block. -func (b *builder) writeConsts(f func(string) int, values ...string) { - b.pf("const (") - for _, v := range values { - b.pf("\t_%s = %v", v, f(v)) - } - b.pf(")") -} - -// writeType writes the type of the given value, which must be a struct. -func (b *builder) writeType(value interface{}) { - b.comment(reflect.TypeOf(value).Name()) - b.w.WriteType(value) -} - -func (b *builder) writeSlice(name string, ss interface{}) { - b.writeSliceAddSize(name, 0, ss) -} - -func (b *builder) writeSliceAddSize(name string, extraSize int, ss interface{}) { - b.comment(name) - b.w.Size += extraSize - v := reflect.ValueOf(ss) - t := v.Type().Elem() - b.pf("// Size: %d bytes, %d elements", v.Len()*int(t.Size())+extraSize, v.Len()) - - fmt.Fprintf(b.w, "var %s = ", name) - b.w.WriteArray(ss) - b.p() -} - -type FromTo struct { - From, To uint16 -} - -func (b *builder) writeSortedMap(name string, ss *stringSet, index func(s string) uint16) { - ss.sortFunc(func(a, b string) bool { - return index(a) < index(b) - }) - m := []FromTo{} - for _, s := range ss.s { - m = append(m, FromTo{index(s), index(ss.update[s])}) - } - b.writeSlice(name, m) -} - -const base = 'z' - 'a' + 1 - -func strToInt(s string) uint { - v := uint(0) - for i := 0; i < len(s); i++ { - v *= base - v += uint(s[i] - 'a') - } - return v -} - -// converts the given integer to the original ASCII string passed to strToInt. -// len(s) must match the number of characters obtained. -func intToStr(v uint, s []byte) { - for i := len(s) - 1; i >= 0; i-- { - s[i] = byte(v%base) + 'a' - v /= base - } -} - -func (b *builder) writeBitVector(name string, ss []string) { - vec := make([]uint8, int(math.Ceil(math.Pow(base, float64(len(ss[0])))/8))) - for _, s := range ss { - v := strToInt(s) - vec[v/8] |= 1 << (v % 8) - } - b.writeSlice(name, vec) -} - -// TODO: convert this type into a list or two-stage trie. -func (b *builder) writeMapFunc(name string, m map[string]string, f func(string) uint16) { - b.comment(name) - v := reflect.ValueOf(m) - sz := v.Len() * (2 + int(v.Type().Key().Size())) - for _, k := range m { - sz += len(k) - } - b.addSize(sz) - keys := []string{} - b.pf(`var %s = map[string]uint16{`, name) - for k := range m { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - b.pf("\t%q: %v,", k, f(m[k])) - } - b.p("}") -} - -func (b *builder) writeMap(name string, m interface{}) { - b.comment(name) - v := reflect.ValueOf(m) - sz := v.Len() * (2 + int(v.Type().Key().Size()) + int(v.Type().Elem().Size())) - b.addSize(sz) - f := strings.FieldsFunc(fmt.Sprintf("%#v", m), func(r rune) bool { - return strings.IndexRune("{}, ", r) != -1 - }) - sort.Strings(f[1:]) - b.pf(`var %s = %s{`, name, f[0]) - for _, kv := range f[1:] { - b.pf("\t%s,", kv) - } - b.p("}") -} - -func (b *builder) langIndex(s string) uint16 { - if s == "und" { - return 0 - } - if i, ok := b.lang.find(s); ok { - return uint16(i) - } - return uint16(strToInt(s)) + uint16(len(b.lang.s)) -} - -// inc advances the string to its lexicographical successor. -func inc(s string) string { - const maxTagLength = 4 - var buf [maxTagLength]byte - intToStr(strToInt(strings.ToLower(s))+1, buf[:len(s)]) - for i := 0; i < len(s); i++ { - if s[i] <= 'Z' { - buf[i] -= 'a' - 'A' - } - } - return string(buf[:len(s)]) -} - -func (b *builder) parseIndices() { - meta := b.supp.Metadata - - for k, v := range b.registry { - var ss *stringSet - switch v.typ { - case "language": - if len(k) == 2 || v.suppressScript != "" || v.scope == "special" { - b.lang.add(k) - continue - } else { - ss = &b.langNoIndex - } - case "region": - ss = &b.region - case "script": - ss = &b.script - case "variant": - ss = &b.variant - default: - continue - } - ss.add(k) - } - // Include any language for which there is data. - for _, lang := range b.data.Locales() { - if x := b.data.RawLDML(lang); false || - x.LocaleDisplayNames != nil || - x.Characters != nil || - x.Delimiters != nil || - x.Measurement != nil || - x.Dates != nil || - x.Numbers != nil || - x.Units != nil || - x.ListPatterns != nil || - x.Collations != nil || - x.Segmentations != nil || - x.Rbnf != nil || - x.Annotations != nil || - x.Metadata != nil { - - from := strings.Split(lang, "_") - if lang := from[0]; lang != "root" { - b.lang.add(lang) - } - } - } - // Include locales for plural rules, which uses a different structure. - for _, plurals := range b.data.Supplemental().Plurals { - for _, rules := range plurals.PluralRules { - for _, lang := range strings.Split(rules.Locales, " ") { - if lang = strings.Split(lang, "_")[0]; lang != "root" { - b.lang.add(lang) - } - } - } - } - // Include languages in likely subtags. - for _, m := range b.supp.LikelySubtags.LikelySubtag { - from := strings.Split(m.From, "_") - b.lang.add(from[0]) - } - // Include ISO-639 alpha-3 bibliographic entries. - for _, a := range meta.Alias.LanguageAlias { - if a.Reason == "bibliographic" { - b.langNoIndex.add(a.Type) - } - } - // Include regions in territoryAlias (not all are in the IANA registry!) - for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { - if len(reg.Type) == 2 { - b.region.add(reg.Type) - } - } - - for _, s := range b.lang.s { - if len(s) == 3 { - b.langNoIndex.remove(s) - } - } - b.writeConst("NumLanguages", len(b.lang.slice())+len(b.langNoIndex.slice())) - b.writeConst("NumScripts", len(b.script.slice())) - b.writeConst("NumRegions", len(b.region.slice())) - - // Add dummy codes at the start of each list to represent "unspecified". - b.lang.add("---") - b.script.add("----") - b.region.add("---") - - // common locales - b.locale.parse(meta.DefaultContent.Locales) -} - -// TODO: region inclusion data will probably not be use used in future matchers. - -func (b *builder) computeRegionGroups() { - b.groups = make(map[int]index) - - // Create group indices. - for i := 1; b.region.s[i][0] < 'A'; i++ { // Base M49 indices on regionID. - b.groups[i] = index(len(b.groups)) - } - for _, g := range b.supp.TerritoryContainment.Group { - // Skip UN and EURO zone as they are flattening the containment - // relationship. - if g.Type == "EZ" || g.Type == "UN" { - continue - } - group := b.region.index(g.Type) - if _, ok := b.groups[group]; !ok { - b.groups[group] = index(len(b.groups)) - } - } - if len(b.groups) > 64 { - log.Fatalf("only 64 groups supported, found %d", len(b.groups)) - } - b.writeConst("nRegionGroups", len(b.groups)) -} - -var langConsts = []string{ - "af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", - "et", "fa", "fi", "fil", "fr", "gu", "he", "hi", "hr", "hu", "hy", "id", "is", - "it", "ja", "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", - "mn", "mo", "mr", "ms", "mul", "my", "nb", "ne", "nl", "no", "pa", "pl", "pt", - "ro", "ru", "sh", "si", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", - "tl", "tn", "tr", "uk", "ur", "uz", "vi", "zh", "zu", - - // constants for grandfathered tags (if not already defined) - "jbo", "ami", "bnn", "hak", "tlh", "lb", "nv", "pwn", "tao", "tay", "tsu", - "nn", "sfb", "vgt", "sgg", "cmn", "nan", "hsn", -} - -// writeLanguage generates all tables needed for language canonicalization. -func (b *builder) writeLanguage() { - meta := b.supp.Metadata - - b.writeConst("nonCanonicalUnd", b.lang.index("und")) - b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...) - b.writeConst("langPrivateStart", b.langIndex("qaa")) - b.writeConst("langPrivateEnd", b.langIndex("qtz")) - - // Get language codes that need to be mapped (overlong 3-letter codes, - // deprecated 2-letter codes, legacy and grandfathered tags.) - langAliasMap := stringSet{} - aliasTypeMap := map[string]AliasType{} - - // altLangISO3 get the alternative ISO3 names that need to be mapped. - altLangISO3 := stringSet{} - // Add dummy start to avoid the use of index 0. - altLangISO3.add("---") - altLangISO3.updateLater("---", "aa") - - lang := b.lang.clone() - for _, a := range meta.Alias.LanguageAlias { - if a.Replacement == "" { - a.Replacement = "und" - } - // TODO: support mapping to tags - repl := strings.SplitN(a.Replacement, "_", 2)[0] - if a.Reason == "overlong" { - if len(a.Replacement) == 2 && len(a.Type) == 3 { - lang.updateLater(a.Replacement, a.Type) - } - } else if len(a.Type) <= 3 { - switch a.Reason { - case "macrolanguage": - aliasTypeMap[a.Type] = Macro - case "deprecated": - // handled elsewhere - continue - case "bibliographic", "legacy": - if a.Type == "no" { - continue - } - aliasTypeMap[a.Type] = Legacy - default: - log.Fatalf("new %s alias: %s", a.Reason, a.Type) - } - langAliasMap.add(a.Type) - langAliasMap.updateLater(a.Type, repl) - } - } - // Manually add the mapping of "nb" (Norwegian) to its macro language. - // This can be removed if CLDR adopts this change. - langAliasMap.add("nb") - langAliasMap.updateLater("nb", "no") - aliasTypeMap["nb"] = Macro - - for k, v := range b.registry { - // Also add deprecated values for 3-letter ISO codes, which CLDR omits. - if v.typ == "language" && v.deprecated != "" && v.preferred != "" { - langAliasMap.add(k) - langAliasMap.updateLater(k, v.preferred) - aliasTypeMap[k] = Deprecated - } - } - // Fix CLDR mappings. - lang.updateLater("tl", "tgl") - lang.updateLater("sh", "hbs") - lang.updateLater("mo", "mol") - lang.updateLater("no", "nor") - lang.updateLater("tw", "twi") - lang.updateLater("nb", "nob") - lang.updateLater("ak", "aka") - lang.updateLater("bh", "bih") - - // Ensure that each 2-letter code is matched with a 3-letter code. - for _, v := range lang.s[1:] { - s, ok := lang.update[v] - if !ok { - if s, ok = lang.update[langAliasMap.update[v]]; !ok { - continue - } - lang.update[v] = s - } - if v[0] != s[0] { - altLangISO3.add(s) - altLangISO3.updateLater(s, v) - } - } - - // Complete canonicalized language tags. - lang.freeze() - for i, v := range lang.s { - // We can avoid these manual entries by using the IANA registry directly. - // Seems easier to update the list manually, as changes are rare. - // The panic in this loop will trigger if we miss an entry. - add := "" - if s, ok := lang.update[v]; ok { - if s[0] == v[0] { - add = s[1:] - } else { - add = string([]byte{0, byte(altLangISO3.index(s))}) - } - } else if len(v) == 3 { - add = "\x00" - } else { - log.Panicf("no data for long form of %q", v) - } - lang.s[i] += add - } - b.writeConst("lang", tag.Index(lang.join())) - - b.writeConst("langNoIndexOffset", len(b.lang.s)) - - // space of all valid 3-letter language identifiers. - b.writeBitVector("langNoIndex", b.langNoIndex.slice()) - - altLangIndex := []uint16{} - for i, s := range altLangISO3.slice() { - altLangISO3.s[i] += string([]byte{byte(len(altLangIndex))}) - if i > 0 { - idx := b.lang.index(altLangISO3.update[s]) - altLangIndex = append(altLangIndex, uint16(idx)) - } - } - b.writeConst("altLangISO3", tag.Index(altLangISO3.join())) - b.writeSlice("altLangIndex", altLangIndex) - - b.writeSortedMap("AliasMap", &langAliasMap, b.langIndex) - types := make([]AliasType, len(langAliasMap.s)) - for i, s := range langAliasMap.s { - types[i] = aliasTypeMap[s] - } - b.writeSlice("AliasTypes", types) -} - -var scriptConsts = []string{ - "Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy", - "Zzzz", -} - -func (b *builder) writeScript() { - b.writeConsts(b.script.index, scriptConsts...) - b.writeConst("script", tag.Index(b.script.join())) - - supp := make([]uint8, len(b.lang.slice())) - for i, v := range b.lang.slice()[1:] { - if sc := b.registry[v].suppressScript; sc != "" { - supp[i+1] = uint8(b.script.index(sc)) - } - } - b.writeSlice("suppressScript", supp) - - // There is only one deprecated script in CLDR. This value is hard-coded. - // We check here if the code must be updated. - for _, a := range b.supp.Metadata.Alias.ScriptAlias { - if a.Type != "Qaai" { - log.Panicf("unexpected deprecated stript %q", a.Type) - } - } -} - -func parseM49(s string) int16 { - if len(s) == 0 { - return 0 - } - v, err := strconv.ParseUint(s, 10, 10) - failOnError(err) - return int16(v) -} - -var regionConsts = []string{ - "001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US", - "ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo. -} - -func (b *builder) writeRegion() { - b.writeConsts(b.region.index, regionConsts...) - - isoOffset := b.region.index("AA") - m49map := make([]int16, len(b.region.slice())) - fromM49map := make(map[int16]int) - altRegionISO3 := "" - altRegionIDs := []uint16{} - - b.writeConst("isoRegionOffset", isoOffset) - - // 2-letter region lookup and mapping to numeric codes. - regionISO := b.region.clone() - regionISO.s = regionISO.s[isoOffset:] - regionISO.sorted = false - - regionTypes := make([]byte, len(b.region.s)) - - // Is the region valid BCP 47? - for s, e := range b.registry { - if len(s) == 2 && s == strings.ToUpper(s) { - i := b.region.index(s) - for _, d := range e.description { - if strings.Contains(d, "Private use") { - regionTypes[i] = iso3166UserAssigned - } - } - regionTypes[i] |= bcp47Region - } - } - - // Is the region a valid ccTLD? - r := gen.OpenIANAFile("domains/root/db") - defer r.Close() - - buf, err := ioutil.ReadAll(r) - failOnError(err) - re := regexp.MustCompile(`"/domains/root/db/([a-z]{2}).html"`) - for _, m := range re.FindAllSubmatch(buf, -1) { - i := b.region.index(strings.ToUpper(string(m[1]))) - regionTypes[i] |= ccTLD - } - - b.writeSlice("regionTypes", regionTypes) - - iso3Set := make(map[string]int) - update := func(iso2, iso3 string) { - i := regionISO.index(iso2) - if j, ok := iso3Set[iso3]; !ok && iso3[0] == iso2[0] { - regionISO.s[i] += iso3[1:] - iso3Set[iso3] = -1 - } else { - if ok && j >= 0 { - regionISO.s[i] += string([]byte{0, byte(j)}) - } else { - iso3Set[iso3] = len(altRegionISO3) - regionISO.s[i] += string([]byte{0, byte(len(altRegionISO3))}) - altRegionISO3 += iso3 - altRegionIDs = append(altRegionIDs, uint16(isoOffset+i)) - } - } - } - for _, tc := range b.supp.CodeMappings.TerritoryCodes { - i := regionISO.index(tc.Type) + isoOffset - if d := m49map[i]; d != 0 { - log.Panicf("%s found as a duplicate UN.M49 code of %03d", tc.Numeric, d) - } - m49 := parseM49(tc.Numeric) - m49map[i] = m49 - if r := fromM49map[m49]; r == 0 { - fromM49map[m49] = i - } else if r != i { - dep := b.registry[regionISO.s[r-isoOffset]].deprecated - if t := b.registry[tc.Type]; t != nil && dep != "" && (t.deprecated == "" || t.deprecated > dep) { - fromM49map[m49] = i - } - } - } - for _, ta := range b.supp.Metadata.Alias.TerritoryAlias { - if len(ta.Type) == 3 && ta.Type[0] <= '9' && len(ta.Replacement) == 2 { - from := parseM49(ta.Type) - if r := fromM49map[from]; r == 0 { - fromM49map[from] = regionISO.index(ta.Replacement) + isoOffset - } - } - } - for _, tc := range b.supp.CodeMappings.TerritoryCodes { - if len(tc.Alpha3) == 3 { - update(tc.Type, tc.Alpha3) - } - } - // This entries are not included in territoryCodes. Mostly 3-letter variants - // of deleted codes and an entry for QU. - for _, m := range []struct{ iso2, iso3 string }{ - {"CT", "CTE"}, - {"DY", "DHY"}, - {"HV", "HVO"}, - {"JT", "JTN"}, - {"MI", "MID"}, - {"NH", "NHB"}, - {"NQ", "ATN"}, - {"PC", "PCI"}, - {"PU", "PUS"}, - {"PZ", "PCZ"}, - {"RH", "RHO"}, - {"VD", "VDR"}, - {"WK", "WAK"}, - // These three-letter codes are used for others as well. - {"FQ", "ATF"}, - } { - update(m.iso2, m.iso3) - } - for i, s := range regionISO.s { - if len(s) != 4 { - regionISO.s[i] = s + " " - } - } - b.writeConst("regionISO", tag.Index(regionISO.join())) - b.writeConst("altRegionISO3", altRegionISO3) - b.writeSlice("altRegionIDs", altRegionIDs) - - // Create list of deprecated regions. - // TODO: consider inserting SF -> FI. Not included by CLDR, but is the only - // Transitionally-reserved mapping not included. - regionOldMap := stringSet{} - // Include regions in territoryAlias (not all are in the IANA registry!) - for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { - if len(reg.Type) == 2 && reg.Reason == "deprecated" && len(reg.Replacement) == 2 { - regionOldMap.add(reg.Type) - regionOldMap.updateLater(reg.Type, reg.Replacement) - i, _ := regionISO.find(reg.Type) - j, _ := regionISO.find(reg.Replacement) - if k := m49map[i+isoOffset]; k == 0 { - m49map[i+isoOffset] = m49map[j+isoOffset] - } - } - } - b.writeSortedMap("regionOldMap", ®ionOldMap, func(s string) uint16 { - return uint16(b.region.index(s)) - }) - // 3-digit region lookup, groupings. - for i := 1; i < isoOffset; i++ { - m := parseM49(b.region.s[i]) - m49map[i] = m - fromM49map[m] = i - } - b.writeSlice("m49", m49map) - - const ( - searchBits = 7 - regionBits = 9 - ) - if len(m49map) >= 1< %d", len(m49map), 1<>searchBits] = int16(len(fromM49)) - } - b.writeSlice("m49Index", m49Index) - b.writeSlice("fromM49", fromM49) -} - -const ( - // TODO: put these lists in regionTypes as user data? Could be used for - // various optimizations and refinements and could be exposed in the API. - iso3166Except = "AC CP DG EA EU FX IC SU TA UK" - iso3166Trans = "AN BU CS NT TP YU ZR" // SF is not in our set of Regions. - // DY and RH are actually not deleted, but indeterminately reserved. - iso3166DelCLDR = "CT DD DY FQ HV JT MI NH NQ PC PU PZ RH VD WK YD" -) - -const ( - iso3166UserAssigned = 1 << iota - ccTLD - bcp47Region -) - -func find(list []string, s string) int { - for i, t := range list { - if t == s { - return i - } - } - return -1 -} - -// writeVariants generates per-variant information and creates a map from variant -// name to index value. We assign index values such that sorting multiple -// variants by index value will result in the correct order. -// There are two types of variants: specialized and general. Specialized variants -// are only applicable to certain language or language-script pairs. Generalized -// variants apply to any language. Generalized variants always sort after -// specialized variants. We will therefore always assign a higher index value -// to a generalized variant than any other variant. Generalized variants are -// sorted alphabetically among themselves. -// Specialized variants may also sort after other specialized variants. Such -// variants will be ordered after any of the variants they may follow. -// We assume that if a variant x is followed by a variant y, then for any prefix -// p of x, p-x is a prefix of y. This allows us to order tags based on the -// maximum of the length of any of its prefixes. -// TODO: it is possible to define a set of Prefix values on variants such that -// a total order cannot be defined to the point that this algorithm breaks. -// In other words, we cannot guarantee the same order of variants for the -// future using the same algorithm or for non-compliant combinations of -// variants. For this reason, consider using simple alphabetic sorting -// of variants and ignore Prefix restrictions altogether. -func (b *builder) writeVariant() { - generalized := stringSet{} - specialized := stringSet{} - specializedExtend := stringSet{} - // Collate the variants by type and check assumptions. - for _, v := range b.variant.slice() { - e := b.registry[v] - if len(e.prefix) == 0 { - generalized.add(v) - continue - } - c := strings.Split(e.prefix[0], "-") - hasScriptOrRegion := false - if len(c) > 1 { - _, hasScriptOrRegion = b.script.find(c[1]) - if !hasScriptOrRegion { - _, hasScriptOrRegion = b.region.find(c[1]) - - } - } - if len(c) == 1 || len(c) == 2 && hasScriptOrRegion { - // Variant is preceded by a language. - specialized.add(v) - continue - } - // Variant is preceded by another variant. - specializedExtend.add(v) - prefix := c[0] + "-" - if hasScriptOrRegion { - prefix += c[1] - } - for _, p := range e.prefix { - // Verify that the prefix minus the last element is a prefix of the - // predecessor element. - i := strings.LastIndex(p, "-") - pred := b.registry[p[i+1:]] - if find(pred.prefix, p[:i]) < 0 { - log.Fatalf("prefix %q for variant %q not consistent with predecessor spec", p, v) - } - // The sorting used below does not work in the general case. It works - // if we assume that variants that may be followed by others only have - // prefixes of the same length. Verify this. - count := strings.Count(p[:i], "-") - for _, q := range pred.prefix { - if c := strings.Count(q, "-"); c != count { - log.Fatalf("variant %q preceding %q has a prefix %q of size %d; want %d", p[i+1:], v, q, c, count) - } - } - if !strings.HasPrefix(p, prefix) { - log.Fatalf("prefix %q of variant %q should start with %q", p, v, prefix) - } - } - } - - // Sort extended variants. - a := specializedExtend.s - less := func(v, w string) bool { - // Sort by the maximum number of elements. - maxCount := func(s string) (max int) { - for _, p := range b.registry[s].prefix { - if c := strings.Count(p, "-"); c > max { - max = c - } - } - return - } - if cv, cw := maxCount(v), maxCount(w); cv != cw { - return cv < cw - } - // Sort by name as tie breaker. - return v < w - } - sort.Sort(funcSorter{less, sort.StringSlice(a)}) - specializedExtend.frozen = true - - // Create index from variant name to index. - variantIndex := make(map[string]uint8) - add := func(s []string) { - for _, v := range s { - variantIndex[v] = uint8(len(variantIndex)) - } - } - add(specialized.slice()) - add(specializedExtend.s) - numSpecialized := len(variantIndex) - add(generalized.slice()) - if n := len(variantIndex); n > 255 { - log.Fatalf("maximum number of variants exceeded: was %d; want <= 255", n) - } - b.writeMap("variantIndex", variantIndex) - b.writeConst("variantNumSpecialized", numSpecialized) -} - -func (b *builder) writeLanguageInfo() { -} - -// writeLikelyData writes tables that are used both for finding parent relations and for -// language matching. Each entry contains additional bits to indicate the status of the -// data to know when it cannot be used for parent relations. -func (b *builder) writeLikelyData() { - const ( - isList = 1 << iota - scriptInFrom - regionInFrom - ) - type ( // generated types - likelyScriptRegion struct { - region uint16 - script uint8 - flags uint8 - } - likelyLangScript struct { - lang uint16 - script uint8 - flags uint8 - } - likelyLangRegion struct { - lang uint16 - region uint16 - } - // likelyTag is used for getting likely tags for group regions, where - // the likely region might be a region contained in the group. - likelyTag struct { - lang uint16 - region uint16 - script uint8 - } - ) - var ( // generated variables - likelyRegionGroup = make([]likelyTag, len(b.groups)) - likelyLang = make([]likelyScriptRegion, len(b.lang.s)) - likelyRegion = make([]likelyLangScript, len(b.region.s)) - likelyScript = make([]likelyLangRegion, len(b.script.s)) - likelyLangList = []likelyScriptRegion{} - likelyRegionList = []likelyLangScript{} - ) - type fromTo struct { - from, to []string - } - langToOther := map[int][]fromTo{} - regionToOther := map[int][]fromTo{} - for _, m := range b.supp.LikelySubtags.LikelySubtag { - from := strings.Split(m.From, "_") - to := strings.Split(m.To, "_") - if len(to) != 3 { - log.Fatalf("invalid number of subtags in %q: found %d, want 3", m.To, len(to)) - } - if len(from) > 3 { - log.Fatalf("invalid number of subtags: found %d, want 1-3", len(from)) - } - if from[0] != to[0] && from[0] != "und" { - log.Fatalf("unexpected language change in expansion: %s -> %s", from, to) - } - if len(from) == 3 { - if from[2] != to[2] { - log.Fatalf("unexpected region change in expansion: %s -> %s", from, to) - } - if from[0] != "und" { - log.Fatalf("unexpected fully specified from tag: %s -> %s", from, to) - } - } - if len(from) == 1 || from[0] != "und" { - id := 0 - if from[0] != "und" { - id = b.lang.index(from[0]) - } - langToOther[id] = append(langToOther[id], fromTo{from, to}) - } else if len(from) == 2 && len(from[1]) == 4 { - sid := b.script.index(from[1]) - likelyScript[sid].lang = uint16(b.langIndex(to[0])) - likelyScript[sid].region = uint16(b.region.index(to[2])) - } else { - r := b.region.index(from[len(from)-1]) - if id, ok := b.groups[r]; ok { - if from[0] != "und" { - log.Fatalf("region changed unexpectedly: %s -> %s", from, to) - } - likelyRegionGroup[id].lang = uint16(b.langIndex(to[0])) - likelyRegionGroup[id].script = uint8(b.script.index(to[1])) - likelyRegionGroup[id].region = uint16(b.region.index(to[2])) - } else { - regionToOther[r] = append(regionToOther[r], fromTo{from, to}) - } - } - } - b.writeType(likelyLangRegion{}) - b.writeSlice("likelyScript", likelyScript) - - for id := range b.lang.s { - list := langToOther[id] - if len(list) == 1 { - likelyLang[id].region = uint16(b.region.index(list[0].to[2])) - likelyLang[id].script = uint8(b.script.index(list[0].to[1])) - } else if len(list) > 1 { - likelyLang[id].flags = isList - likelyLang[id].region = uint16(len(likelyLangList)) - likelyLang[id].script = uint8(len(list)) - for _, x := range list { - flags := uint8(0) - if len(x.from) > 1 { - if x.from[1] == x.to[2] { - flags = regionInFrom - } else { - flags = scriptInFrom - } - } - likelyLangList = append(likelyLangList, likelyScriptRegion{ - region: uint16(b.region.index(x.to[2])), - script: uint8(b.script.index(x.to[1])), - flags: flags, - }) - } - } - } - // TODO: merge suppressScript data with this table. - b.writeType(likelyScriptRegion{}) - b.writeSlice("likelyLang", likelyLang) - b.writeSlice("likelyLangList", likelyLangList) - - for id := range b.region.s { - list := regionToOther[id] - if len(list) == 1 { - likelyRegion[id].lang = uint16(b.langIndex(list[0].to[0])) - likelyRegion[id].script = uint8(b.script.index(list[0].to[1])) - if len(list[0].from) > 2 { - likelyRegion[id].flags = scriptInFrom - } - } else if len(list) > 1 { - likelyRegion[id].flags = isList - likelyRegion[id].lang = uint16(len(likelyRegionList)) - likelyRegion[id].script = uint8(len(list)) - for i, x := range list { - if len(x.from) == 2 && i != 0 || i > 0 && len(x.from) != 3 { - log.Fatalf("unspecified script must be first in list: %v at %d", x.from, i) - } - x := likelyLangScript{ - lang: uint16(b.langIndex(x.to[0])), - script: uint8(b.script.index(x.to[1])), - } - if len(list[0].from) > 2 { - x.flags = scriptInFrom - } - likelyRegionList = append(likelyRegionList, x) - } - } - } - b.writeType(likelyLangScript{}) - b.writeSlice("likelyRegion", likelyRegion) - b.writeSlice("likelyRegionList", likelyRegionList) - - b.writeType(likelyTag{}) - b.writeSlice("likelyRegionGroup", likelyRegionGroup) -} - -func (b *builder) writeRegionInclusionData() { - var ( - // mm holds for each group the set of groups with a distance of 1. - mm = make(map[int][]index) - - // containment holds for each group the transitive closure of - // containment of other groups. - containment = make(map[index][]index) - ) - for _, g := range b.supp.TerritoryContainment.Group { - // Skip UN and EURO zone as they are flattening the containment - // relationship. - if g.Type == "EZ" || g.Type == "UN" { - continue - } - group := b.region.index(g.Type) - groupIdx := b.groups[group] - for _, mem := range strings.Split(g.Contains, " ") { - r := b.region.index(mem) - mm[r] = append(mm[r], groupIdx) - if g, ok := b.groups[r]; ok { - mm[group] = append(mm[group], g) - containment[groupIdx] = append(containment[groupIdx], g) - } - } - } - - regionContainment := make([]uint64, len(b.groups)) - for _, g := range b.groups { - l := containment[g] - - // Compute the transitive closure of containment. - for i := 0; i < len(l); i++ { - l = append(l, containment[l[i]]...) - } - - // Compute the bitmask. - regionContainment[g] = 1 << g - for _, v := range l { - regionContainment[g] |= 1 << v - } - } - b.writeSlice("regionContainment", regionContainment) - - regionInclusion := make([]uint8, len(b.region.s)) - bvs := make(map[uint64]index) - // Make the first bitvector positions correspond with the groups. - for r, i := range b.groups { - bv := uint64(1 << i) - for _, g := range mm[r] { - bv |= 1 << g - } - bvs[bv] = i - regionInclusion[r] = uint8(bvs[bv]) - } - for r := 1; r < len(b.region.s); r++ { - if _, ok := b.groups[r]; !ok { - bv := uint64(0) - for _, g := range mm[r] { - bv |= 1 << g - } - if bv == 0 { - // Pick the world for unspecified regions. - bv = 1 << b.groups[b.region.index("001")] - } - if _, ok := bvs[bv]; !ok { - bvs[bv] = index(len(bvs)) - } - regionInclusion[r] = uint8(bvs[bv]) - } - } - b.writeSlice("regionInclusion", regionInclusion) - regionInclusionBits := make([]uint64, len(bvs)) - for k, v := range bvs { - regionInclusionBits[v] = uint64(k) - } - // Add bit vectors for increasingly large distances until a fixed point is reached. - regionInclusionNext := []uint8{} - for i := 0; i < len(regionInclusionBits); i++ { - bits := regionInclusionBits[i] - next := bits - for i := uint(0); i < uint(len(b.groups)); i++ { - if bits&(1< 6 { - log.Fatalf("Too many groups: %d", i) - } - idToIndex[mv.Id] = uint8(i + 1) - // TODO: also handle '-' - for _, r := range strings.Split(mv.Value, "+") { - todo := []string{r} - for k := 0; k < len(todo); k++ { - r := todo[k] - regionToGroups[b.regionIndex(r)] |= 1 << uint8(i) - todo = append(todo, regionHierarchy[r]...) - } - } - } - b.w.WriteVar("regionToGroups", regionToGroups) - - // maps language id to in- and out-of-group region. - paradigmLocales := [][3]uint16{} - locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ") - for i := 0; i < len(locales); i += 2 { - x := [3]uint16{} - for j := 0; j < 2; j++ { - pc := strings.SplitN(locales[i+j], "-", 2) - x[0] = b.langIndex(pc[0]) - if len(pc) == 2 { - x[1+j] = uint16(b.regionIndex(pc[1])) - } - } - paradigmLocales = append(paradigmLocales, x) - } - b.w.WriteVar("paradigmLocales", paradigmLocales) - - b.w.WriteType(mutualIntelligibility{}) - b.w.WriteType(scriptIntelligibility{}) - b.w.WriteType(regionIntelligibility{}) - - matchLang := []mutualIntelligibility{} - matchScript := []scriptIntelligibility{} - matchRegion := []regionIntelligibility{} - // Convert the languageMatch entries in lists keyed by desired language. - for _, m := range lm[0].LanguageMatch { - // Different versions of CLDR use different separators. - desired := strings.Replace(m.Desired, "-", "_", -1) - supported := strings.Replace(m.Supported, "-", "_", -1) - d := strings.Split(desired, "_") - s := strings.Split(supported, "_") - if len(d) != len(s) { - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - continue - } - distance, _ := strconv.ParseInt(m.Distance, 10, 8) - switch len(d) { - case 2: - if desired == supported && desired == "*_*" { - continue - } - // language-script pair. - matchScript = append(matchScript, scriptIntelligibility{ - wantLang: uint16(b.langIndex(d[0])), - haveLang: uint16(b.langIndex(s[0])), - wantScript: uint8(b.scriptIndex(d[1])), - haveScript: uint8(b.scriptIndex(s[1])), - distance: uint8(distance), - }) - if m.Oneway != "true" { - matchScript = append(matchScript, scriptIntelligibility{ - wantLang: uint16(b.langIndex(s[0])), - haveLang: uint16(b.langIndex(d[0])), - wantScript: uint8(b.scriptIndex(s[1])), - haveScript: uint8(b.scriptIndex(d[1])), - distance: uint8(distance), - }) - } - case 1: - if desired == supported && desired == "*" { - continue - } - if distance == 1 { - // nb == no is already handled by macro mapping. Check there - // really is only this case. - if d[0] != "no" || s[0] != "nb" { - log.Fatalf("unhandled equivalence %s == %s", s[0], d[0]) - } - continue - } - // TODO: consider dropping oneway field and just doubling the entry. - matchLang = append(matchLang, mutualIntelligibility{ - want: uint16(b.langIndex(d[0])), - have: uint16(b.langIndex(s[0])), - distance: uint8(distance), - oneway: m.Oneway == "true", - }) - case 3: - if desired == supported && desired == "*_*_*" { - continue - } - if desired != supported { - // This is now supported by CLDR, but only one case, which - // should already be covered by paradigm locales. For instance, - // test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in - // testdata/CLDRLocaleMatcherTest.txt tests this. - if supported != "en_*_GB" { - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - } - continue - } - ri := regionIntelligibility{ - lang: b.langIndex(d[0]), - distance: uint8(distance), - } - if d[1] != "*" { - ri.script = uint8(b.scriptIndex(d[1])) - } - switch { - case d[2] == "*": - ri.group = 0x80 // not contained in anything - case strings.HasPrefix(d[2], "$!"): - ri.group = 0x80 - d[2] = "$" + d[2][len("$!"):] - fallthrough - case strings.HasPrefix(d[2], "$"): - ri.group |= idToIndex[d[2]] - } - matchRegion = append(matchRegion, ri) - default: - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - } - } - sort.SliceStable(matchLang, func(i, j int) bool { - return matchLang[i].distance < matchLang[j].distance - }) - b.w.WriteComment(` - matchLang holds pairs of langIDs of base languages that are typically - mutually intelligible. Each pair is associated with a confidence and - whether the intelligibility goes one or both ways.`) - b.w.WriteVar("matchLang", matchLang) - - b.w.WriteComment(` - matchScript holds pairs of scriptIDs where readers of one script - can typically also read the other. Each is associated with a confidence.`) - sort.SliceStable(matchScript, func(i, j int) bool { - return matchScript[i].distance < matchScript[j].distance - }) - b.w.WriteVar("matchScript", matchScript) - - sort.SliceStable(matchRegion, func(i, j int) bool { - return matchRegion[i].distance < matchRegion[j].distance - }) - b.w.WriteVar("matchRegion", matchRegion) -} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen.go b/vendor/golang.org/x/text/unicode/bidi/gen.go deleted file mode 100644 index 987fc169cc..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "flag" - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/triegen" - "golang.org/x/text/internal/ucd" -) - -var outputFile = flag.String("out", "tables.go", "output file") - -func main() { - gen.Init() - gen.Repackage("gen_trieval.go", "trieval.go", "bidi") - gen.Repackage("gen_ranges.go", "ranges_test.go", "bidi") - - genTables() -} - -// bidiClass names and codes taken from class "bc" in -// https://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt -var bidiClass = map[string]Class{ - "AL": AL, // ArabicLetter - "AN": AN, // ArabicNumber - "B": B, // ParagraphSeparator - "BN": BN, // BoundaryNeutral - "CS": CS, // CommonSeparator - "EN": EN, // EuropeanNumber - "ES": ES, // EuropeanSeparator - "ET": ET, // EuropeanTerminator - "L": L, // LeftToRight - "NSM": NSM, // NonspacingMark - "ON": ON, // OtherNeutral - "R": R, // RightToLeft - "S": S, // SegmentSeparator - "WS": WS, // WhiteSpace - - "FSI": Control, - "PDF": Control, - "PDI": Control, - "LRE": Control, - "LRI": Control, - "LRO": Control, - "RLE": Control, - "RLI": Control, - "RLO": Control, -} - -func genTables() { - if numClass > 0x0F { - log.Fatalf("Too many Class constants (%#x > 0x0F).", numClass) - } - w := gen.NewCodeWriter() - defer w.WriteVersionedGoFile(*outputFile, "bidi") - - gen.WriteUnicodeVersion(w) - - t := triegen.NewTrie("bidi") - - // Build data about bracket mapping. These bits need to be or-ed with - // any other bits. - orMask := map[rune]uint64{} - - xorMap := map[rune]int{} - xorMasks := []rune{0} // First value is no-op. - - ucd.Parse(gen.OpenUCDFile("BidiBrackets.txt"), func(p *ucd.Parser) { - r1 := p.Rune(0) - r2 := p.Rune(1) - xor := r1 ^ r2 - if _, ok := xorMap[xor]; !ok { - xorMap[xor] = len(xorMasks) - xorMasks = append(xorMasks, xor) - } - entry := uint64(xorMap[xor]) << xorMaskShift - switch p.String(2) { - case "o": - entry |= openMask - case "c", "n": - default: - log.Fatalf("Unknown bracket class %q.", p.String(2)) - } - orMask[r1] = entry - }) - - w.WriteComment(` - xorMasks contains masks to be xor-ed with brackets to get the reverse - version.`) - w.WriteVar("xorMasks", xorMasks) - - done := map[rune]bool{} - - insert := func(r rune, c Class) { - if !done[r] { - t.Insert(r, orMask[r]|uint64(c)) - done[r] = true - } - } - - // Insert the derived BiDi properties. - ucd.Parse(gen.OpenUCDFile("extracted/DerivedBidiClass.txt"), func(p *ucd.Parser) { - r := p.Rune(0) - class, ok := bidiClass[p.String(1)] - if !ok { - log.Fatalf("%U: Unknown BiDi class %q", r, p.String(1)) - } - insert(r, class) - }) - visitDefaults(insert) - - // TODO: use sparse blocks. This would reduce table size considerably - // from the looks of it. - - sz, err := t.Gen(w) - if err != nil { - log.Fatal(err) - } - w.Size += sz -} - -// dummy values to make methods in gen_common compile. The real versions -// will be generated by this file to tables.go. -var ( - xorMasks []rune -) diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go deleted file mode 100644 index 02c3b505d6..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "unicode" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/ucd" - "golang.org/x/text/unicode/rangetable" -) - -// These tables are hand-extracted from: -// https://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedBidiClass.txt -func visitDefaults(fn func(r rune, c Class)) { - // first write default values for ranges listed above. - visitRunes(fn, AL, []rune{ - 0x0600, 0x07BF, // Arabic - 0x08A0, 0x08FF, // Arabic Extended-A - 0xFB50, 0xFDCF, // Arabic Presentation Forms - 0xFDF0, 0xFDFF, - 0xFE70, 0xFEFF, - 0x0001EE00, 0x0001EEFF, // Arabic Mathematical Alpha Symbols - }) - visitRunes(fn, R, []rune{ - 0x0590, 0x05FF, // Hebrew - 0x07C0, 0x089F, // Nko et al. - 0xFB1D, 0xFB4F, - 0x00010800, 0x00010FFF, // Cypriot Syllabary et. al. - 0x0001E800, 0x0001EDFF, - 0x0001EF00, 0x0001EFFF, - }) - visitRunes(fn, ET, []rune{ // European Terminator - 0x20A0, 0x20Cf, // Currency symbols - }) - rangetable.Visit(unicode.Noncharacter_Code_Point, func(r rune) { - fn(r, BN) // Boundary Neutral - }) - ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) { - if p.String(1) == "Default_Ignorable_Code_Point" { - fn(p.Rune(0), BN) // Boundary Neutral - } - }) -} - -func visitRunes(fn func(r rune, c Class), c Class, runes []rune) { - for i := 0; i < len(runes); i += 2 { - lo, hi := runes[i], runes[i+1] - for j := lo; j <= hi; j++ { - fn(j, c) - } - } -} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go deleted file mode 100644 index 9cb9942894..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// Class is the Unicode BiDi class. Each rune has a single class. -type Class uint - -const ( - L Class = iota // LeftToRight - R // RightToLeft - EN // EuropeanNumber - ES // EuropeanSeparator - ET // EuropeanTerminator - AN // ArabicNumber - CS // CommonSeparator - B // ParagraphSeparator - S // SegmentSeparator - WS // WhiteSpace - ON // OtherNeutral - BN // BoundaryNeutral - NSM // NonspacingMark - AL // ArabicLetter - Control // Control LRO - PDI - - numClass - - LRO // LeftToRightOverride - RLO // RightToLeftOverride - LRE // LeftToRightEmbedding - RLE // RightToLeftEmbedding - PDF // PopDirectionalFormat - LRI // LeftToRightIsolate - RLI // RightToLeftIsolate - FSI // FirstStrongIsolate - PDI // PopDirectionalIsolate - - unknownClass = ^Class(0) -) - -var controlToClass = map[rune]Class{ - 0x202D: LRO, // LeftToRightOverride, - 0x202E: RLO, // RightToLeftOverride, - 0x202A: LRE, // LeftToRightEmbedding, - 0x202B: RLE, // RightToLeftEmbedding, - 0x202C: PDF, // PopDirectionalFormat, - 0x2066: LRI, // LeftToRightIsolate, - 0x2067: RLI, // RightToLeftIsolate, - 0x2068: FSI, // FirstStrongIsolate, - 0x2069: PDI, // PopDirectionalIsolate, -} - -// A trie entry has the following bits: -// 7..5 XOR mask for brackets -// 4 1: Bracket open, 0: Bracket close -// 3..0 Class type - -const ( - openMask = 0x10 - xorMaskShift = 5 -) diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go deleted file mode 100644 index 30a3aa9334..0000000000 --- a/vendor/golang.org/x/text/unicode/norm/maketables.go +++ /dev/null @@ -1,986 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Normalization table generator. -// Data read from the web. -// See forminfo.go for a description of the trie values associated with each rune. - -package main - -import ( - "bytes" - "encoding/binary" - "flag" - "fmt" - "io" - "log" - "sort" - "strconv" - "strings" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/triegen" - "golang.org/x/text/internal/ucd" -) - -func main() { - gen.Init() - loadUnicodeData() - compactCCC() - loadCompositionExclusions() - completeCharFields(FCanonical) - completeCharFields(FCompatibility) - computeNonStarterCounts() - verifyComputed() - printChars() - testDerived() - printTestdata() - makeTables() -} - -var ( - tablelist = flag.String("tables", - "all", - "comma-separated list of which tables to generate; "+ - "can be 'decomp', 'recomp', 'info' and 'all'") - test = flag.Bool("test", - false, - "test existing tables against DerivedNormalizationProps and generate test data for regression testing") - verbose = flag.Bool("verbose", - false, - "write data to stdout as it is parsed") -) - -const MaxChar = 0x10FFFF // anything above this shouldn't exist - -// Quick Check properties of runes allow us to quickly -// determine whether a rune may occur in a normal form. -// For a given normal form, a rune may be guaranteed to occur -// verbatim (QC=Yes), may or may not combine with another -// rune (QC=Maybe), or may not occur (QC=No). -type QCResult int - -const ( - QCUnknown QCResult = iota - QCYes - QCNo - QCMaybe -) - -func (r QCResult) String() string { - switch r { - case QCYes: - return "Yes" - case QCNo: - return "No" - case QCMaybe: - return "Maybe" - } - return "***UNKNOWN***" -} - -const ( - FCanonical = iota // NFC or NFD - FCompatibility // NFKC or NFKD - FNumberOfFormTypes -) - -const ( - MComposed = iota // NFC or NFKC - MDecomposed // NFD or NFKD - MNumberOfModes -) - -// This contains only the properties we're interested in. -type Char struct { - name string - codePoint rune // if zero, this index is not a valid code point. - ccc uint8 // canonical combining class - origCCC uint8 - excludeInComp bool // from CompositionExclusions.txt - compatDecomp bool // it has a compatibility expansion - - nTrailingNonStarters uint8 - nLeadingNonStarters uint8 // must be equal to trailing if non-zero - - forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility - - state State -} - -var chars = make([]Char, MaxChar+1) -var cccMap = make(map[uint8]uint8) - -func (c Char) String() string { - buf := new(bytes.Buffer) - - fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name) - fmt.Fprintf(buf, " ccc: %v\n", c.ccc) - fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp) - fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp) - fmt.Fprintf(buf, " state: %v\n", c.state) - fmt.Fprintf(buf, " NFC:\n") - fmt.Fprint(buf, c.forms[FCanonical]) - fmt.Fprintf(buf, " NFKC:\n") - fmt.Fprint(buf, c.forms[FCompatibility]) - - return buf.String() -} - -// In UnicodeData.txt, some ranges are marked like this: -// 3400;;Lo;0;L;;;;;N;;;;; -// 4DB5;;Lo;0;L;;;;;N;;;;; -// parseCharacter keeps a state variable indicating the weirdness. -type State int - -const ( - SNormal State = iota // known to be zero for the type - SFirst - SLast - SMissing -) - -var lastChar = rune('\u0000') - -func (c Char) isValid() bool { - return c.codePoint != 0 && c.state != SMissing -} - -type FormInfo struct { - quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed - verified [MNumberOfModes]bool // index: MComposed or MDecomposed - - combinesForward bool // May combine with rune on the right - combinesBackward bool // May combine with rune on the left - isOneWay bool // Never appears in result - inDecomp bool // Some decompositions result in this char. - decomp Decomposition - expandedDecomp Decomposition -} - -func (f FormInfo) String() string { - buf := bytes.NewBuffer(make([]byte, 0)) - - fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed]) - fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed]) - fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward) - fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward) - fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay) - fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp) - fmt.Fprintf(buf, " decomposition: %X\n", f.decomp) - fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp) - - return buf.String() -} - -type Decomposition []rune - -func parseDecomposition(s string, skipfirst bool) (a []rune, err error) { - decomp := strings.Split(s, " ") - if len(decomp) > 0 && skipfirst { - decomp = decomp[1:] - } - for _, d := range decomp { - point, err := strconv.ParseUint(d, 16, 64) - if err != nil { - return a, err - } - a = append(a, rune(point)) - } - return a, nil -} - -func loadUnicodeData() { - f := gen.OpenUCDFile("UnicodeData.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - r := p.Rune(ucd.CodePoint) - char := &chars[r] - - char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass)) - decmap := p.String(ucd.DecompMapping) - - exp, err := parseDecomposition(decmap, false) - isCompat := false - if err != nil { - if len(decmap) > 0 { - exp, err = parseDecomposition(decmap, true) - if err != nil { - log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err) - } - isCompat = true - } - } - - char.name = p.String(ucd.Name) - char.codePoint = r - char.forms[FCompatibility].decomp = exp - if !isCompat { - char.forms[FCanonical].decomp = exp - } else { - char.compatDecomp = true - } - if len(decmap) > 0 { - char.forms[FCompatibility].decomp = exp - } - } - if err := p.Err(); err != nil { - log.Fatal(err) - } -} - -// compactCCC converts the sparse set of CCC values to a continguous one, -// reducing the number of bits needed from 8 to 6. -func compactCCC() { - m := make(map[uint8]uint8) - for i := range chars { - c := &chars[i] - m[c.ccc] = 0 - } - cccs := []int{} - for v, _ := range m { - cccs = append(cccs, int(v)) - } - sort.Ints(cccs) - for i, c := range cccs { - cccMap[uint8(i)] = uint8(c) - m[uint8(c)] = uint8(i) - } - for i := range chars { - c := &chars[i] - c.origCCC = c.ccc - c.ccc = m[c.ccc] - } - if len(m) >= 1<<6 { - log.Fatalf("too many difference CCC values: %d >= 64", len(m)) - } -} - -// CompositionExclusions.txt has form: -// 0958 # ... -// See https://unicode.org/reports/tr44/ for full explanation -func loadCompositionExclusions() { - f := gen.OpenUCDFile("CompositionExclusions.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - c := &chars[p.Rune(0)] - if c.excludeInComp { - log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint) - } - c.excludeInComp = true - } - if e := p.Err(); e != nil { - log.Fatal(e) - } -} - -// hasCompatDecomp returns true if any of the recursive -// decompositions contains a compatibility expansion. -// In this case, the character may not occur in NFK*. -func hasCompatDecomp(r rune) bool { - c := &chars[r] - if c.compatDecomp { - return true - } - for _, d := range c.forms[FCompatibility].decomp { - if hasCompatDecomp(d) { - return true - } - } - return false -} - -// Hangul related constants. -const ( - HangulBase = 0xAC00 - HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28) - - JamoLBase = 0x1100 - JamoLEnd = 0x1113 - JamoVBase = 0x1161 - JamoVEnd = 0x1176 - JamoTBase = 0x11A8 - JamoTEnd = 0x11C3 - - JamoLVTCount = 19 * 21 * 28 - JamoTCount = 28 -) - -func isHangul(r rune) bool { - return HangulBase <= r && r < HangulEnd -} - -func isHangulWithoutJamoT(r rune) bool { - if !isHangul(r) { - return false - } - r -= HangulBase - return r < JamoLVTCount && r%JamoTCount == 0 -} - -func ccc(r rune) uint8 { - return chars[r].ccc -} - -// Insert a rune in a buffer, ordered by Canonical Combining Class. -func insertOrdered(b Decomposition, r rune) Decomposition { - n := len(b) - b = append(b, 0) - cc := ccc(r) - if cc > 0 { - // Use bubble sort. - for ; n > 0; n-- { - if ccc(b[n-1]) <= cc { - break - } - b[n] = b[n-1] - } - } - b[n] = r - return b -} - -// Recursively decompose. -func decomposeRecursive(form int, r rune, d Decomposition) Decomposition { - dcomp := chars[r].forms[form].decomp - if len(dcomp) == 0 { - return insertOrdered(d, r) - } - for _, c := range dcomp { - d = decomposeRecursive(form, c, d) - } - return d -} - -func completeCharFields(form int) { - // Phase 0: pre-expand decomposition. - for i := range chars { - f := &chars[i].forms[form] - if len(f.decomp) == 0 { - continue - } - exp := make(Decomposition, 0) - for _, c := range f.decomp { - exp = decomposeRecursive(form, c, exp) - } - f.expandedDecomp = exp - } - - // Phase 1: composition exclusion, mark decomposition. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - // Marks script-specific exclusions and version restricted. - f.isOneWay = c.excludeInComp - - // Singletons - f.isOneWay = f.isOneWay || len(f.decomp) == 1 - - // Non-starter decompositions - if len(f.decomp) > 1 { - chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0 - f.isOneWay = f.isOneWay || chk - } - - // Runes that decompose into more than two runes. - f.isOneWay = f.isOneWay || len(f.decomp) > 2 - - if form == FCompatibility { - f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint) - } - - for _, r := range f.decomp { - chars[r].forms[form].inDecomp = true - } - } - - // Phase 2: forward and backward combining. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - if !f.isOneWay && len(f.decomp) == 2 { - f0 := &chars[f.decomp[0]].forms[form] - f1 := &chars[f.decomp[1]].forms[form] - if !f0.isOneWay { - f0.combinesForward = true - } - if !f1.isOneWay { - f1.combinesBackward = true - } - } - if isHangulWithoutJamoT(rune(i)) { - f.combinesForward = true - } - } - - // Phase 3: quick check values. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - switch { - case len(f.decomp) > 0: - f.quickCheck[MDecomposed] = QCNo - case isHangul(rune(i)): - f.quickCheck[MDecomposed] = QCNo - default: - f.quickCheck[MDecomposed] = QCYes - } - switch { - case f.isOneWay: - f.quickCheck[MComposed] = QCNo - case (i & 0xffff00) == JamoLBase: - f.quickCheck[MComposed] = QCYes - if JamoLBase <= i && i < JamoLEnd { - f.combinesForward = true - } - if JamoVBase <= i && i < JamoVEnd { - f.quickCheck[MComposed] = QCMaybe - f.combinesBackward = true - f.combinesForward = true - } - if JamoTBase <= i && i < JamoTEnd { - f.quickCheck[MComposed] = QCMaybe - f.combinesBackward = true - } - case !f.combinesBackward: - f.quickCheck[MComposed] = QCYes - default: - f.quickCheck[MComposed] = QCMaybe - } - } -} - -func computeNonStarterCounts() { - // Phase 4: leading and trailing non-starter count - for i := range chars { - c := &chars[i] - - runes := []rune{rune(i)} - // We always use FCompatibility so that the CGJ insertion points do not - // change for repeated normalizations with different forms. - if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 { - runes = exp - } - // We consider runes that combine backwards to be non-starters for the - // purpose of Stream-Safe Text Processing. - for _, r := range runes { - if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { - break - } - c.nLeadingNonStarters++ - } - for i := len(runes) - 1; i >= 0; i-- { - if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { - break - } - c.nTrailingNonStarters++ - } - if c.nTrailingNonStarters > 3 { - log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes) - } - - if isHangul(rune(i)) { - c.nTrailingNonStarters = 2 - if isHangulWithoutJamoT(rune(i)) { - c.nTrailingNonStarters = 1 - } - } - - if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t { - log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t) - } - if t := c.nTrailingNonStarters; t > 3 { - log.Fatalf("%U: number of trailing non-starters is %d > 3", t) - } - } -} - -func printBytes(w io.Writer, b []byte, name string) { - fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b)) - fmt.Fprintf(w, "var %s = [...]byte {", name) - for i, c := range b { - switch { - case i%64 == 0: - fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63) - case i%8 == 0: - fmt.Fprintf(w, "\n") - } - fmt.Fprintf(w, "0x%.2X, ", c) - } - fmt.Fprint(w, "\n}\n\n") -} - -// See forminfo.go for format. -func makeEntry(f *FormInfo, c *Char) uint16 { - e := uint16(0) - if r := c.codePoint; HangulBase <= r && r < HangulEnd { - e |= 0x40 - } - if f.combinesForward { - e |= 0x20 - } - if f.quickCheck[MDecomposed] == QCNo { - e |= 0x4 - } - switch f.quickCheck[MComposed] { - case QCYes: - case QCNo: - e |= 0x10 - case QCMaybe: - e |= 0x18 - default: - log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed]) - } - e |= uint16(c.nTrailingNonStarters) - return e -} - -// decompSet keeps track of unique decompositions, grouped by whether -// the decomposition is followed by a trailing and/or leading CCC. -type decompSet [7]map[string]bool - -const ( - normalDecomp = iota - firstMulti - firstCCC - endMulti - firstLeadingCCC - firstCCCZeroExcept - firstStarterWithNLead - lastDecomp -) - -var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"} - -func makeDecompSet() decompSet { - m := decompSet{} - for i := range m { - m[i] = make(map[string]bool) - } - return m -} -func (m *decompSet) insert(key int, s string) { - m[key][s] = true -} - -func printCharInfoTables(w io.Writer) int { - mkstr := func(r rune, f *FormInfo) (int, string) { - d := f.expandedDecomp - s := string([]rune(d)) - if max := 1 << 6; len(s) >= max { - const msg = "%U: too many bytes in decomposition: %d >= %d" - log.Fatalf(msg, r, len(s), max) - } - head := uint8(len(s)) - if f.quickCheck[MComposed] != QCYes { - head |= 0x40 - } - if f.combinesForward { - head |= 0x80 - } - s = string([]byte{head}) + s - - lccc := ccc(d[0]) - tccc := ccc(d[len(d)-1]) - cc := ccc(r) - if cc != 0 && lccc == 0 && tccc == 0 { - log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc) - } - if tccc < lccc && lccc != 0 { - const msg = "%U: lccc (%d) must be <= tcc (%d)" - log.Fatalf(msg, r, lccc, tccc) - } - index := normalDecomp - nTrail := chars[r].nTrailingNonStarters - nLead := chars[r].nLeadingNonStarters - if tccc > 0 || lccc > 0 || nTrail > 0 { - tccc <<= 2 - tccc |= nTrail - s += string([]byte{tccc}) - index = endMulti - for _, r := range d[1:] { - if ccc(r) == 0 { - index = firstCCC - } - } - if lccc > 0 || nLead > 0 { - s += string([]byte{lccc}) - if index == firstCCC { - log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r) - } - index = firstLeadingCCC - } - if cc != lccc { - if cc != 0 { - log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc) - } - index = firstCCCZeroExcept - } - } else if len(d) > 1 { - index = firstMulti - } - return index, s - } - - decompSet := makeDecompSet() - const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail. - decompSet.insert(firstStarterWithNLead, nLeadStr) - - // Store the uniqued decompositions in a byte buffer, - // preceded by their byte length. - for _, c := range chars { - for _, f := range c.forms { - if len(f.expandedDecomp) == 0 { - continue - } - if f.combinesBackward { - log.Fatalf("%U: combinesBackward and decompose", c.codePoint) - } - index, s := mkstr(c.codePoint, &f) - decompSet.insert(index, s) - } - } - - decompositions := bytes.NewBuffer(make([]byte, 0, 10000)) - size := 0 - positionMap := make(map[string]uint16) - decompositions.WriteString("\000") - fmt.Fprintln(w, "const (") - for i, m := range decompSet { - sa := []string{} - for s := range m { - sa = append(sa, s) - } - sort.Strings(sa) - for _, s := range sa { - p := decompositions.Len() - decompositions.WriteString(s) - positionMap[s] = uint16(p) - } - if cname[i] != "" { - fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len()) - } - } - fmt.Fprintln(w, "maxDecomp = 0x8000") - fmt.Fprintln(w, ")") - b := decompositions.Bytes() - printBytes(w, b, "decomps") - size += len(b) - - varnames := []string{"nfc", "nfkc"} - for i := 0; i < FNumberOfFormTypes; i++ { - trie := triegen.NewTrie(varnames[i]) - - for r, c := range chars { - f := c.forms[i] - d := f.expandedDecomp - if len(d) != 0 { - _, key := mkstr(c.codePoint, &f) - trie.Insert(rune(r), uint64(positionMap[key])) - if c.ccc != ccc(d[0]) { - // We assume the lead ccc of a decomposition !=0 in this case. - if ccc(d[0]) == 0 { - log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc) - } - } - } else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward { - // Handle cases where it can't be detected that the nLead should be equal - // to nTrail. - trie.Insert(c.codePoint, uint64(positionMap[nLeadStr])) - } else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 { - trie.Insert(c.codePoint, uint64(0x8000|v)) - } - } - sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]})) - if err != nil { - log.Fatal(err) - } - size += sz - } - return size -} - -func contains(sa []string, s string) bool { - for _, a := range sa { - if a == s { - return true - } - } - return false -} - -func makeTables() { - w := &bytes.Buffer{} - - size := 0 - if *tablelist == "" { - return - } - list := strings.Split(*tablelist, ",") - if *tablelist == "all" { - list = []string{"recomp", "info"} - } - - // Compute maximum decomposition size. - max := 0 - for _, c := range chars { - if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max { - max = n - } - } - fmt.Fprintln(w, `import "sync"`) - fmt.Fprintln(w) - - fmt.Fprintln(w, "const (") - fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.") - fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion()) - fmt.Fprintln(w) - fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform") - fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at") - fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that") - fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.") - fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max) - fmt.Fprintln(w, ")\n") - - // Print the CCC remap table. - size += len(cccMap) - fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap)) - for i := 0; i < len(cccMap); i++ { - if i%8 == 0 { - fmt.Fprintln(w) - } - fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)]) - } - fmt.Fprintln(w, "\n}\n") - - if contains(list, "info") { - size += printCharInfoTables(w) - } - - if contains(list, "recomp") { - // Note that we use 32 bit keys, instead of 64 bit. - // This clips the bits of three entries, but we know - // this won't cause a collision. The compiler will catch - // any changes made to UnicodeData.txt that introduces - // a collision. - // Note that the recomposition map for NFC and NFKC - // are identical. - - // Recomposition map - nrentries := 0 - for _, c := range chars { - f := c.forms[FCanonical] - if !f.isOneWay && len(f.decomp) > 0 { - nrentries++ - } - } - sz := nrentries * 8 - size += sz - fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz) - fmt.Fprintln(w, "var recompMap map[uint32]rune") - fmt.Fprintln(w, "var recompMapOnce sync.Once\n") - fmt.Fprintln(w, `const recompMapPacked = "" +`) - var buf [8]byte - for i, c := range chars { - f := c.forms[FCanonical] - d := f.decomp - if !f.isOneWay && len(d) > 0 { - key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1])) - binary.BigEndian.PutUint32(buf[:4], key) - binary.BigEndian.PutUint32(buf[4:], uint32(i)) - fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i)) - } - } - // hack so we don't have to special case the trailing plus sign - fmt.Fprintf(w, ` ""`) - fmt.Fprintln(w) - } - - fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size) - gen.WriteVersionedGoFile("tables.go", "norm", w.Bytes()) -} - -func printChars() { - if *verbose { - for _, c := range chars { - if !c.isValid() || c.state == SMissing { - continue - } - fmt.Println(c) - } - } -} - -// verifyComputed does various consistency tests. -func verifyComputed() { - for i, c := range chars { - for _, f := range c.forms { - isNo := (f.quickCheck[MDecomposed] == QCNo) - if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) { - log.Fatalf("%U: NF*D QC must be No if rune decomposes", i) - } - - isMaybe := f.quickCheck[MComposed] == QCMaybe - if f.combinesBackward != isMaybe { - log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i) - } - if len(f.decomp) > 0 && f.combinesForward && isMaybe { - log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i) - } - - if len(f.expandedDecomp) != 0 { - continue - } - if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b { - // We accept these runes to be treated differently (it only affects - // segment breaking in iteration, most likely on improper use), but - // reconsider if more characters are added. - // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; - // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; - // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; - // U+318E HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; - // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; - // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; - if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) { - log.Fatalf("%U: nLead was %v; want %v", i, a, b) - } - } - } - nfc := c.forms[FCanonical] - nfkc := c.forms[FCompatibility] - if nfc.combinesBackward != nfkc.combinesBackward { - log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint) - } - } -} - -// Use values in DerivedNormalizationProps.txt to compare against the -// values we computed. -// DerivedNormalizationProps.txt has form: -// 00C0..00C5 ; NFD_QC; N # ... -// 0374 ; NFD_QC; N # ... -// See https://unicode.org/reports/tr44/ for full explanation -func testDerived() { - f := gen.OpenUCDFile("DerivedNormalizationProps.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - r := p.Rune(0) - c := &chars[r] - - var ftype, mode int - qt := p.String(1) - switch qt { - case "NFC_QC": - ftype, mode = FCanonical, MComposed - case "NFD_QC": - ftype, mode = FCanonical, MDecomposed - case "NFKC_QC": - ftype, mode = FCompatibility, MComposed - case "NFKD_QC": - ftype, mode = FCompatibility, MDecomposed - default: - continue - } - var qr QCResult - switch p.String(2) { - case "Y": - qr = QCYes - case "N": - qr = QCNo - case "M": - qr = QCMaybe - default: - log.Fatalf(`Unexpected quick check value "%s"`, p.String(2)) - } - if got := c.forms[ftype].quickCheck[mode]; got != qr { - log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr) - } - c.forms[ftype].verified[mode] = true - } - if err := p.Err(); err != nil { - log.Fatal(err) - } - // Any unspecified value must be QCYes. Verify this. - for i, c := range chars { - for j, fd := range c.forms { - for k, qr := range fd.quickCheck { - if !fd.verified[k] && qr != QCYes { - m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n" - log.Printf(m, i, j, k, qr, c.name) - } - } - } - } -} - -var testHeader = `const ( - Yes = iota - No - Maybe -) - -type formData struct { - qc uint8 - combinesForward bool - decomposition string -} - -type runeData struct { - r rune - ccc uint8 - nLead uint8 - nTrail uint8 - f [2]formData // 0: canonical; 1: compatibility -} - -func f(qc uint8, cf bool, dec string) [2]formData { - return [2]formData{{qc, cf, dec}, {qc, cf, dec}} -} - -func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { - return [2]formData{{qc, cf, d}, {qck, cfk, dk}} -} - -var testData = []runeData{ -` - -func printTestdata() { - type lastInfo struct { - ccc uint8 - nLead uint8 - nTrail uint8 - f string - } - - last := lastInfo{} - w := &bytes.Buffer{} - fmt.Fprintf(w, testHeader) - for r, c := range chars { - f := c.forms[FCanonical] - qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) - f = c.forms[FCompatibility] - qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) - s := "" - if d == dk && qc == qck && cf == cfk { - s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d) - } else { - s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk) - } - current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s} - if last != current { - fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s) - last = current - } - } - fmt.Fprintln(w, "}") - gen.WriteVersionedGoFile("data_test.go", "norm", w.Bytes()) -} diff --git a/vendor/golang.org/x/text/unicode/norm/triegen.go b/vendor/golang.org/x/text/unicode/norm/triegen.go deleted file mode 100644 index 45d711900d..0000000000 --- a/vendor/golang.org/x/text/unicode/norm/triegen.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Trie table generator. -// Used by make*tables tools to generate a go file with trie data structures -// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte -// sequence are used to lookup offsets in the index table to be used for the -// next byte. The last byte is used to index into a table with 16-bit values. - -package main - -import ( - "fmt" - "io" -) - -const maxSparseEntries = 16 - -type normCompacter struct { - sparseBlocks [][]uint64 - sparseOffset []uint16 - sparseCount int - name string -} - -func mostFrequentStride(a []uint64) int { - counts := make(map[int]int) - var v int - for _, x := range a { - if stride := int(x) - v; v != 0 && stride >= 0 { - counts[stride]++ - } - v = int(x) - } - var maxs, maxc int - for stride, cnt := range counts { - if cnt > maxc || (cnt == maxc && stride < maxs) { - maxs, maxc = stride, cnt - } - } - return maxs -} - -func countSparseEntries(a []uint64) int { - stride := mostFrequentStride(a) - var v, count int - for _, tv := range a { - if int(tv)-v != stride { - if tv != 0 { - count++ - } - } - v = int(tv) - } - return count -} - -func (c *normCompacter) Size(v []uint64) (sz int, ok bool) { - if n := countSparseEntries(v); n <= maxSparseEntries { - return (n+1)*4 + 2, true - } - return 0, false -} - -func (c *normCompacter) Store(v []uint64) uint32 { - h := uint32(len(c.sparseOffset)) - c.sparseBlocks = append(c.sparseBlocks, v) - c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount)) - c.sparseCount += countSparseEntries(v) + 1 - return h -} - -func (c *normCompacter) Handler() string { - return c.name + "Sparse.lookup" -} - -func (c *normCompacter) Print(w io.Writer) (retErr error) { - p := func(f string, x ...interface{}) { - if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil { - retErr = err - } - } - - ls := len(c.sparseBlocks) - p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2) - p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset) - - ns := c.sparseCount - p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4) - p("var %sSparseValues = [%d]valueRange {", c.name, ns) - for i, b := range c.sparseBlocks { - p("\n// Block %#x, offset %#x", i, c.sparseOffset[i]) - var v int - stride := mostFrequentStride(b) - n := countSparseEntries(b) - p("\n{value:%#04x,lo:%#02x},", stride, uint8(n)) - for i, nv := range b { - if int(nv)-v != stride { - if v != 0 { - p(",hi:%#02x},", 0x80+i-1) - } - if nv != 0 { - p("\n{value:%#04x,lo:%#02x", nv, 0x80+i) - } - } - v = int(nv) - } - if v != 0 { - p(",hi:%#02x},", 0x80+len(b)-1) - } - } - p("\n}\n\n") - return -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 296dfef6bc..ee2b5dd3e5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,8 +7,8 @@ github.com/Azure/azure-pipeline-go/pipeline # github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e github.com/Azure/azure-storage-blob-go/2018-03-28/azblob # github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 -github.com/Azure/go-ansiterm/winterm github.com/Azure/go-ansiterm +github.com/Azure/go-ansiterm/winterm # github.com/Microsoft/go-winio v0.4.13 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid @@ -27,53 +27,55 @@ github.com/apilayer/freegeoip github.com/aristanetworks/goarista/monotime # github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 github.com/btcsuite/btcd/btcec +# github.com/caarlos0/env v3.5.0+incompatible +github.com/caarlos0/env # github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd github.com/codahale/hdrhistogram # github.com/containerd/containerd v1.2.7 github.com/containerd/containerd/errdefs # github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc github.com/containerd/continuity/fs -github.com/containerd/continuity/sysx github.com/containerd/continuity/pathdriver github.com/containerd/continuity/syscallx +github.com/containerd/continuity/sysx # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea github.com/deckarep/golang-set # github.com/docker/distribution v2.7.1+incompatible -github.com/docker/distribution/reference github.com/docker/distribution/digestset +github.com/docker/distribution/reference github.com/docker/distribution/registry/api/errcode # github.com/docker/docker v0.7.3-0.20190806133308-ecdb0b22393b -github.com/docker/docker/pkg/reexec +github.com/docker/docker/api github.com/docker/docker/api/types +github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/container -github.com/docker/docker/client -github.com/docker/docker/pkg/archive -github.com/docker/docker/pkg/jsonmessage +github.com/docker/docker/api/types/events github.com/docker/docker/api/types/filters +github.com/docker/docker/api/types/image github.com/docker/docker/api/types/mount github.com/docker/docker/api/types/network github.com/docker/docker/api/types/registry -github.com/docker/docker/api/types/swarm -github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/strslice -github.com/docker/docker/api -github.com/docker/docker/api/types/events -github.com/docker/docker/api/types/image +github.com/docker/docker/api/types/swarm +github.com/docker/docker/api/types/swarm/runtime github.com/docker/docker/api/types/time github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume +github.com/docker/docker/client github.com/docker/docker/errdefs +github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/fileutils github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils +github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/longpath +github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/pools +github.com/docker/docker/pkg/reexec github.com/docker/docker/pkg/system github.com/docker/docker/pkg/term -github.com/docker/docker/api/types/swarm/runtime -github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/term/windows # github.com/docker/go-connections v0.4.0 github.com/docker/go-connections/nat @@ -87,100 +89,99 @@ github.com/edsrzf/mmap-go github.com/elastic/gosigar github.com/elastic/gosigar/sys/windows # github.com/ethereum/go-ethereum v1.9.2 -github.com/ethereum/go-ethereum/accounts/abi/bind -github.com/ethereum/go-ethereum/common -github.com/ethereum/go-ethereum/ethclient -github.com/ethereum/go-ethereum/metrics -github.com/ethereum/go-ethereum/p2p -github.com/ethereum/go-ethereum/params -github.com/ethereum/go-ethereum/rpc -github.com/ethereum/go-ethereum/common/hexutil -github.com/ethereum/go-ethereum/core/types -github.com/ethereum/go-ethereum/crypto -github.com/ethereum/go-ethereum/crypto/ecies -github.com/ethereum/go-ethereum/node -github.com/ethereum/go-ethereum/p2p/enode -github.com/ethereum/go-ethereum/log -github.com/ethereum/go-ethereum/accounts -github.com/ethereum/go-ethereum/accounts/keystore -github.com/ethereum/go-ethereum/cmd/utils -github.com/ethereum/go-ethereum/console -github.com/ethereum/go-ethereum/p2p/nat -github.com/ethereum/go-ethereum/rlp -github.com/ethereum/go-ethereum/metrics/influxdb -github.com/ethereum/go-ethereum/p2p/simulations -github.com/ethereum/go-ethereum/p2p/simulations/adapters github.com/ethereum/go-ethereum +github.com/ethereum/go-ethereum/accounts github.com/ethereum/go-ethereum/accounts/abi -github.com/ethereum/go-ethereum/event -github.com/ethereum/go-ethereum/metrics/exp -github.com/ethereum/go-ethereum/p2p/enr -github.com/ethereum/go-ethereum/common/bitutil +github.com/ethereum/go-ethereum/accounts/abi/bind +github.com/ethereum/go-ethereum/accounts/abi/bind/backends github.com/ethereum/go-ethereum/accounts/external -github.com/ethereum/go-ethereum/common/mclock -github.com/ethereum/go-ethereum/p2p/discover -github.com/ethereum/go-ethereum/p2p/discv5 -github.com/ethereum/go-ethereum/p2p/netutil -github.com/ethereum/go-ethereum/trie -github.com/ethereum/go-ethereum/common/math -github.com/ethereum/go-ethereum/crypto/secp256k1 +github.com/ethereum/go-ethereum/accounts/keystore github.com/ethereum/go-ethereum/accounts/scwallet github.com/ethereum/go-ethereum/accounts/usbwallet -github.com/ethereum/go-ethereum/core/rawdb -github.com/ethereum/go-ethereum/ethdb -github.com/ethereum/go-ethereum/internal/debug +github.com/ethereum/go-ethereum/accounts/usbwallet/trezor +github.com/ethereum/go-ethereum/cmd/utils +github.com/ethereum/go-ethereum/common +github.com/ethereum/go-ethereum/common/bitutil github.com/ethereum/go-ethereum/common/fdlimit +github.com/ethereum/go-ethereum/common/hexutil +github.com/ethereum/go-ethereum/common/math +github.com/ethereum/go-ethereum/common/mclock +github.com/ethereum/go-ethereum/common/prque github.com/ethereum/go-ethereum/consensus github.com/ethereum/go-ethereum/consensus/clique github.com/ethereum/go-ethereum/consensus/ethash +github.com/ethereum/go-ethereum/consensus/misc +github.com/ethereum/go-ethereum/console +github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract github.com/ethereum/go-ethereum/core +github.com/ethereum/go-ethereum/core/bloombits +github.com/ethereum/go-ethereum/core/forkid +github.com/ethereum/go-ethereum/core/rawdb +github.com/ethereum/go-ethereum/core/state +github.com/ethereum/go-ethereum/core/types github.com/ethereum/go-ethereum/core/vm +github.com/ethereum/go-ethereum/crypto +github.com/ethereum/go-ethereum/crypto/bn256 +github.com/ethereum/go-ethereum/crypto/bn256/cloudflare +github.com/ethereum/go-ethereum/crypto/bn256/google +github.com/ethereum/go-ethereum/crypto/ecies +github.com/ethereum/go-ethereum/crypto/secp256k1 github.com/ethereum/go-ethereum/dashboard github.com/ethereum/go-ethereum/eth github.com/ethereum/go-ethereum/eth/downloader +github.com/ethereum/go-ethereum/eth/fetcher +github.com/ethereum/go-ethereum/eth/filters github.com/ethereum/go-ethereum/eth/gasprice +github.com/ethereum/go-ethereum/eth/tracers +github.com/ethereum/go-ethereum/eth/tracers/internal/tracers +github.com/ethereum/go-ethereum/ethclient +github.com/ethereum/go-ethereum/ethdb +github.com/ethereum/go-ethereum/ethdb/leveldb +github.com/ethereum/go-ethereum/ethdb/memorydb github.com/ethereum/go-ethereum/ethstats +github.com/ethereum/go-ethereum/event github.com/ethereum/go-ethereum/graphql -github.com/ethereum/go-ethereum/les -github.com/ethereum/go-ethereum/miner -github.com/ethereum/go-ethereum/whisper/whisperv6 +github.com/ethereum/go-ethereum/internal/debug +github.com/ethereum/go-ethereum/internal/ethapi github.com/ethereum/go-ethereum/internal/jsre +github.com/ethereum/go-ethereum/internal/jsre/deps github.com/ethereum/go-ethereum/internal/web3ext -github.com/ethereum/go-ethereum/p2p/simulations/pipes -github.com/ethereum/go-ethereum/accounts/abi/bind/backends -github.com/ethereum/go-ethereum/metrics/prometheus -github.com/ethereum/go-ethereum/internal/ethapi -github.com/ethereum/go-ethereum/signer/core -github.com/ethereum/go-ethereum/common/prque -github.com/ethereum/go-ethereum/accounts/usbwallet/trezor -github.com/ethereum/go-ethereum/ethdb/leveldb -github.com/ethereum/go-ethereum/ethdb/memorydb -github.com/ethereum/go-ethereum/core/state -github.com/ethereum/go-ethereum/consensus/misc -github.com/ethereum/go-ethereum/crypto/bn256 -github.com/ethereum/go-ethereum/core/bloombits -github.com/ethereum/go-ethereum/core/forkid -github.com/ethereum/go-ethereum/eth/fetcher -github.com/ethereum/go-ethereum/eth/filters -github.com/ethereum/go-ethereum/eth/tracers -github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/les github.com/ethereum/go-ethereum/les/flowcontrol github.com/ethereum/go-ethereum/light -github.com/ethereum/go-ethereum/internal/jsre/deps +github.com/ethereum/go-ethereum/log +github.com/ethereum/go-ethereum/metrics +github.com/ethereum/go-ethereum/metrics/exp +github.com/ethereum/go-ethereum/metrics/influxdb +github.com/ethereum/go-ethereum/metrics/prometheus +github.com/ethereum/go-ethereum/miner +github.com/ethereum/go-ethereum/node +github.com/ethereum/go-ethereum/p2p +github.com/ethereum/go-ethereum/p2p/discover +github.com/ethereum/go-ethereum/p2p/discv5 +github.com/ethereum/go-ethereum/p2p/enode +github.com/ethereum/go-ethereum/p2p/enr +github.com/ethereum/go-ethereum/p2p/nat +github.com/ethereum/go-ethereum/p2p/netutil +github.com/ethereum/go-ethereum/p2p/simulations +github.com/ethereum/go-ethereum/p2p/simulations/adapters +github.com/ethereum/go-ethereum/p2p/simulations/pipes +github.com/ethereum/go-ethereum/params +github.com/ethereum/go-ethereum/rlp +github.com/ethereum/go-ethereum/rpc +github.com/ethereum/go-ethereum/signer/core github.com/ethereum/go-ethereum/signer/storage -github.com/ethereum/go-ethereum/crypto/bn256/cloudflare -github.com/ethereum/go-ethereum/crypto/bn256/google -github.com/ethereum/go-ethereum/eth/tracers/internal/tracers -github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract +github.com/ethereum/go-ethereum/trie +github.com/ethereum/go-ethereum/whisper/whisperv6 # github.com/ethersphere/go-sw3 v0.1.1 github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswap github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswapfactory -github.com/ethersphere/go-sw3/contracts-v0-1-0/simpleswap # github.com/fatih/color v1.7.0 github.com/fatih/color # github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc -github.com/fjl/memsize/memsizeui github.com/fjl/memsize +github.com/fjl/memsize/memsizeui # github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c github.com/gballet/go-libpcsclite # github.com/go-ole/go-ole v1.2.4 @@ -210,10 +211,10 @@ github.com/googleapis/gnostic/extensions github.com/gorilla/websocket # github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 github.com/graph-gophers/graphql-go -github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/errors github.com/graph-gophers/graphql-go/internal/common github.com/graph-gophers/graphql-go/internal/exec +github.com/graph-gophers/graphql-go/internal/exec/packer github.com/graph-gophers/graphql-go/internal/exec/resolvable github.com/graph-gophers/graphql-go/internal/exec/selected github.com/graph-gophers/graphql-go/internal/query @@ -221,8 +222,8 @@ github.com/graph-gophers/graphql-go/internal/schema github.com/graph-gophers/graphql-go/internal/validation github.com/graph-gophers/graphql-go/introspection github.com/graph-gophers/graphql-go/log +github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/trace -github.com/graph-gophers/graphql-go/internal/exec/packer # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru @@ -276,15 +277,15 @@ github.com/olekukonko/tablewriter # github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/image-spec/specs-go/v1 github.com/opencontainers/image-spec/specs-go +github.com/opencontainers/image-spec/specs-go/v1 # github.com/opencontainers/runc v0.1.1 github.com/opencontainers/runc/libcontainer/system github.com/opencontainers/runc/libcontainer/user # github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go -github.com/opentracing/opentracing-go/log github.com/opentracing/opentracing-go/ext +github.com/opentracing/opentracing-go/log # github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e github.com/oschwald/maxminddb-golang # github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 @@ -309,6 +310,12 @@ github.com/robertkrimen/otto/token github.com/rs/cors # github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 github.com/rs/xhandler +# github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 +github.com/rsksmart/rds-swarm/config +github.com/rsksmart/rds-swarm/resolver +github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver +github.com/rsksmart/rds-swarm/resolver/rsk_resolver +github.com/rsksmart/rds-swarm/utils # github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus # github.com/spf13/pflag v1.0.3 @@ -321,17 +328,17 @@ github.com/steakknife/bloomfilter github.com/steakknife/hamming # github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 github.com/syndtr/goleveldb/leveldb -github.com/syndtr/goleveldb/leveldb/opt -github.com/syndtr/goleveldb/leveldb/iterator -github.com/syndtr/goleveldb/leveldb/storage -github.com/syndtr/goleveldb/leveldb/util -github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/cache github.com/syndtr/goleveldb/leveldb/comparer +github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/filter +github.com/syndtr/goleveldb/leveldb/iterator github.com/syndtr/goleveldb/leveldb/journal github.com/syndtr/goleveldb/leveldb/memdb +github.com/syndtr/goleveldb/leveldb/opt +github.com/syndtr/goleveldb/leveldb/storage github.com/syndtr/goleveldb/leveldb/table +github.com/syndtr/goleveldb/leveldb/util # github.com/tilinna/clock v1.0.2 github.com/tilinna/clock # github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef @@ -341,55 +348,56 @@ github.com/tyler-smith/go-bip39/wordlists github.com/uber/jaeger-client-go github.com/uber/jaeger-client-go/config github.com/uber/jaeger-client-go/internal/baggage +github.com/uber/jaeger-client-go/internal/baggage/remote github.com/uber/jaeger-client-go/internal/spanlog github.com/uber/jaeger-client-go/internal/throttler +github.com/uber/jaeger-client-go/internal/throttler/remote github.com/uber/jaeger-client-go/log +github.com/uber/jaeger-client-go/rpcmetrics github.com/uber/jaeger-client-go/thrift +github.com/uber/jaeger-client-go/thrift-gen/agent +github.com/uber/jaeger-client-go/thrift-gen/baggage github.com/uber/jaeger-client-go/thrift-gen/jaeger github.com/uber/jaeger-client-go/thrift-gen/sampling github.com/uber/jaeger-client-go/thrift-gen/zipkincore github.com/uber/jaeger-client-go/utils -github.com/uber/jaeger-client-go/internal/baggage/remote -github.com/uber/jaeger-client-go/internal/throttler/remote -github.com/uber/jaeger-client-go/rpcmetrics -github.com/uber/jaeger-client-go/thrift-gen/agent -github.com/uber/jaeger-client-go/thrift-gen/baggage # github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7 github.com/uber/jaeger-lib/metrics # github.com/vbauerster/mpb v3.4.0+incompatible github.com/vbauerster/mpb -github.com/vbauerster/mpb/decor github.com/vbauerster/mpb/cwriter +github.com/vbauerster/mpb/decor github.com/vbauerster/mpb/internal # github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 github.com/wsddn/go-ecdh # golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 -golang.org/x/crypto/scrypt -golang.org/x/crypto/sha3 +golang.org/x/crypto/cast5 +golang.org/x/crypto/curve25519 golang.org/x/crypto/openpgp -golang.org/x/crypto/pbkdf2 golang.org/x/crypto/openpgp/armor +golang.org/x/crypto/openpgp/elgamal golang.org/x/crypto/openpgp/errors golang.org/x/crypto/openpgp/packet golang.org/x/crypto/openpgp/s2k -golang.org/x/crypto/ssh/terminal +golang.org/x/crypto/pbkdf2 golang.org/x/crypto/ripemd160 -golang.org/x/crypto/cast5 -golang.org/x/crypto/openpgp/elgamal -golang.org/x/crypto/curve25519 -# golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 +golang.org/x/crypto/scrypt +golang.org/x/crypto/sha3 +golang.org/x/crypto/ssh/terminal +# golang.org/x/net v0.0.0-20191105084925-a882066a44e0 golang.org/x/net/context +golang.org/x/net/context/ctxhttp golang.org/x/net/html -golang.org/x/net/websocket -golang.org/x/net/http2 golang.org/x/net/html/atom golang.org/x/net/html/charset -golang.org/x/net/proxy golang.org/x/net/http/httpguts +golang.org/x/net/http2 golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/internal/socks -golang.org/x/net/context/ctxhttp +golang.org/x/net/proxy +golang.org/x/net/publicsuffix +golang.org/x/net/websocket # golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 golang.org/x/oauth2/internal @@ -402,44 +410,44 @@ golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 -golang.org/x/text/unicode/norm -golang.org/x/text/transform golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex -golang.org/x/text/secure/bidirule -golang.org/x/text/unicode/bidi -golang.org/x/text/encoding/internal/identifier golang.org/x/text/encoding/internal +golang.org/x/text/encoding/internal/identifier golang.org/x/text/encoding/japanese golang.org/x/text/encoding/korean golang.org/x/text/encoding/simplifiedchinese golang.org/x/text/encoding/traditionalchinese golang.org/x/text/encoding/unicode -golang.org/x/text/language -golang.org/x/text/internal/utf8internal -golang.org/x/text/runes golang.org/x/text/internal/language golang.org/x/text/internal/language/compact golang.org/x/text/internal/tag +golang.org/x/text/internal/utf8internal +golang.org/x/text/language +golang.org/x/text/runes +golang.org/x/text/secure/bidirule +golang.org/x/text/transform +golang.org/x/text/unicode/bidi +golang.org/x/text/unicode/norm # golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/time/rate # google.golang.org/appengine v1.6.1 -google.golang.org/appengine/urlfetch google.golang.org/appengine/internal -google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/base google.golang.org/appengine/internal/datastore google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api +google.golang.org/appengine/internal/urlfetch +google.golang.org/appengine/urlfetch # google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 google.golang.org/genproto/googleapis/rpc/status # google.golang.org/grpc v1.22.1 google.golang.org/grpc/codes -google.golang.org/grpc/status -google.golang.org/grpc/internal google.golang.org/grpc/connectivity google.golang.org/grpc/grpclog +google.golang.org/grpc/internal +google.golang.org/grpc/status # gopkg.in/inf.v0 v0.9.1 gopkg.in/inf.v0 # gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce @@ -454,10 +462,8 @@ gopkg.in/urfave/cli.v1 # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190703205437-39734b2a72fe -k8s.io/api/core/v1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1 -k8s.io/api/autoscaling/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/auditregistration/v1alpha1 @@ -465,6 +471,7 @@ k8s.io/api/authentication/v1 k8s.io/api/authentication/v1beta1 k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 +k8s.io/api/autoscaling/v1 k8s.io/api/autoscaling/v2beta1 k8s.io/api/autoscaling/v2beta2 k8s.io/api/batch/v1 @@ -473,13 +480,14 @@ k8s.io/api/batch/v2alpha1 k8s.io/api/certificates/v1beta1 k8s.io/api/coordination/v1 k8s.io/api/coordination/v1beta1 -k8s.io/api/policy/v1beta1 +k8s.io/api/core/v1 k8s.io/api/events/v1beta1 k8s.io/api/extensions/v1beta1 k8s.io/api/networking/v1 k8s.io/api/networking/v1beta1 k8s.io/api/node/v1alpha1 k8s.io/api/node/v1beta1 +k8s.io/api/policy/v1beta1 k8s.io/api/rbac/v1 k8s.io/api/rbac/v1alpha1 k8s.io/api/rbac/v1beta1 @@ -491,45 +499,44 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 # k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76 +k8s.io/apimachinery/pkg/api/errors +k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 -k8s.io/apimachinery/pkg/runtime -k8s.io/apimachinery/pkg/runtime/schema -k8s.io/apimachinery/pkg/types -k8s.io/apimachinery/pkg/util/intstr +k8s.io/apimachinery/pkg/apis/meta/v1/unstructured k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/conversion/queryparams k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/labels -k8s.io/apimachinery/pkg/selection -k8s.io/apimachinery/pkg/util/runtime -k8s.io/apimachinery/pkg/watch -k8s.io/apimachinery/pkg/api/errors -k8s.io/apimachinery/pkg/runtime/serializer/streaming -k8s.io/apimachinery/pkg/util/net -k8s.io/apimachinery/pkg/util/sets -k8s.io/apimachinery/pkg/util/errors -k8s.io/apimachinery/pkg/util/validation -k8s.io/apimachinery/pkg/conversion/queryparams -k8s.io/apimachinery/pkg/util/json -k8s.io/apimachinery/pkg/util/naming -k8s.io/apimachinery/third_party/forked/golang/reflect +k8s.io/apimachinery/pkg/runtime +k8s.io/apimachinery/pkg/runtime/schema k8s.io/apimachinery/pkg/runtime/serializer -k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/util/clock -k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/runtime/serializer/json -k8s.io/apimachinery/pkg/runtime/serializer/versioning k8s.io/apimachinery/pkg/runtime/serializer/protobuf k8s.io/apimachinery/pkg/runtime/serializer/recognizer -k8s.io/apimachinery/pkg/api/meta +k8s.io/apimachinery/pkg/runtime/serializer/streaming +k8s.io/apimachinery/pkg/runtime/serializer/versioning +k8s.io/apimachinery/pkg/selection +k8s.io/apimachinery/pkg/types +k8s.io/apimachinery/pkg/util/clock +k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/framer +k8s.io/apimachinery/pkg/util/intstr +k8s.io/apimachinery/pkg/util/json +k8s.io/apimachinery/pkg/util/naming +k8s.io/apimachinery/pkg/util/net +k8s.io/apimachinery/pkg/util/runtime +k8s.io/apimachinery/pkg/util/sets +k8s.io/apimachinery/pkg/util/validation +k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/util/yaml -k8s.io/apimachinery/pkg/apis/meta/v1/unstructured +k8s.io/apimachinery/pkg/version +k8s.io/apimachinery/pkg/watch +k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/client-go v0.0.0-20190706005506-4ed54556a14a -k8s.io/client-go/kubernetes -k8s.io/client-go/rest -k8s.io/client-go/tools/clientcmd k8s.io/client-go/discovery +k8s.io/client-go/kubernetes +k8s.io/client-go/kubernetes/scheme k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1 k8s.io/client-go/kubernetes/typed/apps/v1beta1 @@ -566,25 +573,26 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1 k8s.io/client-go/kubernetes/typed/storage/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1beta1 -k8s.io/client-go/util/flowcontrol +k8s.io/client-go/pkg/apis/clientauthentication +k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 +k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/pkg/version k8s.io/client-go/plugin/pkg/client/auth/exec +k8s.io/client-go/rest k8s.io/client-go/rest/watch +k8s.io/client-go/tools/auth +k8s.io/client-go/tools/clientcmd k8s.io/client-go/tools/clientcmd/api +k8s.io/client-go/tools/clientcmd/api/latest +k8s.io/client-go/tools/clientcmd/api/v1 k8s.io/client-go/tools/metrics +k8s.io/client-go/tools/reference k8s.io/client-go/transport k8s.io/client-go/util/cert -k8s.io/client-go/tools/auth -k8s.io/client-go/tools/clientcmd/api/latest -k8s.io/client-go/util/homedir -k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/tools/reference -k8s.io/client-go/pkg/apis/clientauthentication -k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 -k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/util/connrotation +k8s.io/client-go/util/flowcontrol +k8s.io/client-go/util/homedir k8s.io/client-go/util/keyutil -k8s.io/client-go/tools/clientcmd/api/v1 # k8s.io/klog v0.3.1 k8s.io/klog # k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a From b437f784282a30bfab14cbee3cda73278a27cdb4 Mon Sep 17 00:00:00 2001 From: mortelli Date: Fri, 8 Nov 2019 13:54:09 -0300 Subject: [PATCH 17/49] api: update rns library, add ErrNoContent to resolver test --- api/api_test.go | 3 +- go.mod | 40 +++-------------- go.sum | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 35 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 73cc5d64e2..26f87aa6f1 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -37,6 +37,7 @@ import ( "github.com/ethersphere/swarm/sctx" "github.com/ethersphere/swarm/storage" "github.com/ethersphere/swarm/testutil" + rns "github.com/rsksmart/rds-swarm/resolver" ) func init() { @@ -327,7 +328,7 @@ func TestRNSResolve(t *testing.T) { desc: "invalid RSK domain", addr: ".rsk", content: resolvedContent, - expectedErr: errors.New("domain without registered content in RNS Resolvers"), + expectedErr: rns.ErrNoContent, }, } diff --git a/go.mod b/go.mod index b60d5f02da..7f027e1729 100644 --- a/go.mod +++ b/go.mod @@ -11,87 +11,59 @@ require ( github.com/Microsoft/hcsshim v0.8.6 // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/VividCortex/ewma v1.1.1 // indirect - github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 // indirect github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 // indirect - github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect - github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 // indirect - github.com/caarlos0/env v3.5.0+incompatible // indirect github.com/cespare/cp v1.1.1 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect github.com/containerd/containerd v1.2.7 // indirect github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect - github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/docker v0.7.3-0.20190806133308-ecdb0b22393b github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c // indirect - github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa // indirect - github.com/ethereum/go-ethereum v1.9.2 + github.com/ethereum/go-ethereum v1.9.7 github.com/ethersphere/go-sw3 v0.1.1 github.com/fatih/color v1.7.0 // indirect github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc - github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c // indirect github.com/go-kit/kit v0.9.0 // indirect - github.com/go-logfmt/logfmt v0.4.0 // indirect github.com/go-ole/go-ole v1.2.4 // indirect github.com/gogo/protobuf v1.2.1 // indirect - github.com/golang/protobuf v1.3.2 // indirect github.com/googleapis/gnostic v0.0.0-20190624222214-25d8b0b66985 // indirect github.com/gorilla/mux v1.7.3 // indirect - github.com/gorilla/websocket v1.4.0 // indirect github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 // indirect github.com/hashicorp/golang-lru v0.5.3 github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607 // indirect - github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 // indirect github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883 // indirect - github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 // indirect - github.com/json-iterator/go v1.1.7 // indirect - github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.2 github.com/mattn/go-isatty v0.0.8 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416 - github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect github.com/opentracing/opentracing-go v1.1.0 github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e // indirect - github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 + github.com/pborman/uuid v1.2.0 github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7 // indirect - github.com/prometheus/tsdb v0.10.0 // indirect - github.com/rjeczalik/notify v0.9.1 // indirect github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect - github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 + github.com/rs/cors v1.7.0 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 - github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect - github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect - github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect - github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 + github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 + github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tilinna/clock v1.0.2 - github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef // indirect github.com/uber-go/atomic v1.4.0 // indirect github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6 github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7 // indirect github.com/vbauerster/mpb v3.4.0+incompatible - github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect go.uber.org/atomic v1.4.0 // indirect - golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 + golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 golang.org/x/net v0.0.0-20191105084925-a882066a44e0 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 - golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect google.golang.org/appengine v1.6.1 // indirect - google.golang.org/grpc v1.22.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/urfave/cli.v1 v1.20.0 diff --git a/go.sum b/go.sum index 44e2e59a45..4beec79431 100644 --- a/go.sum +++ b/go.sum @@ -10,27 +10,47 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7O github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs= github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI= github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 h1:9uC+gZZ11spzCoystXtG2/fSO0kmGO7zUK3pnfavJCw= github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU= +github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks= +github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb h1:gXDS2cX8AS8KbnP32J6XMSjzC1FhHEdHfUUCy018VrA= +github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns= +github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= @@ -43,11 +63,14 @@ github.com/containerd/containerd v1.2.7 h1:8lqLbl7u1j3MmiL9cJ/O275crSq7bfwUayvva github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= +github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -59,13 +82,22 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s= github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo= +github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/ethereum/go-ethereum v1.9.2 h1:RMIHDO/diqXEgORSVzYx8xW9x2+S32PoAX5lQwya0Lw= github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= +github.com/ethereum/go-ethereum v1.9.7 h1:p4O+z0MGzB7xxngHbplcYNloxkFwGkeComhkzWnq0ig= +github.com/ethereum/go-ethereum v1.9.7/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethersphere/go-sw3 v0.1.1 h1:czLnLSU0/XJLJt/GyPiEAds9YYnIgZZzfy+OQyiYQtk= github.com/ethersphere/go-sw3 v0.1.1/go.mod h1:HukT0aZ6QdW/d7zuD/0g5xlw6ewu9QeqHojxLDsaERQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -75,8 +107,11 @@ github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepB github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c h1:gID5iWto0hEmbyMl+15Rkju0P+8uvF0jSn1cWdyv+5M= github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= @@ -110,6 +145,8 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20190624222214-25d8b0b66985 h1:MSqFuS90bN+x1aGLZpPX9Iprdxbxw7X5Jg9WfjS/bYk= @@ -119,9 +156,12 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 h1:9WiNlI9Cds5S5YITwRpRs8edNaq0nxTEymhDW20A1QE= github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= @@ -132,12 +172,21 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= +github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883 h1:HsZXaxH4mZRDDcxGk5m1+o3R/ofaT5YrMG+aR0altIw= github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA= github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= +github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -145,9 +194,14 @@ github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8uXRLnpdSb9noCEj+vHacjmhp68= github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 h1:ZHuwnjpP8LsVsUYqTqeVAI+GfDfJ6UNPrExZF+vX/DQ= +github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 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= @@ -167,6 +221,8 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -187,13 +243,20 @@ github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c h1:2j4kdCOg5xiOVCTQpv0SgbzndaVJKliD6oRbMxTw6v4= github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2 h1:sq53g+DWf0J6/ceFUHpQ0nAEb6WgM++fq16MZ91cS6o= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc= +github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -206,34 +269,49 @@ github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e h1:omG1V github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7 h1:Imx0QZXGB4siHjlmDJ/kx/bU+D36ytDj5dgy/TkIQ+A= github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 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/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d h1:ouzpe+YhpIfnjR40gSkJHWsvXmB6TiPKqMtMpfyU9DE= github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 h1:u+awngKkvwHGxPJ4Lk3Yy6A10ThdtyaiQP9OloHK6ao= github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= +github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 h1:saHKOwJeSkV5PzZeTnw97JMLycaDBJnF2P/1sDVWuq8= +github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -244,6 +322,8 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= @@ -255,10 +335,17 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 h1:V/AztY/q2oW5ghho7YMgUJQkKvSACHRxpeDyT5DxpIo= github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= +github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= +github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= +github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef h1:luEzjJzktS9eU0CmI0uApXHLP/lKzOoRPrJhd71J8ik= github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o= github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6 h1:x2aYRH9ayk4SeB/gdpG0HTkyL798WfmJC8zMr6KY8SE= @@ -269,27 +356,38 @@ github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tL github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= +github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 h1:VsmCukA2gDdC3Mu6evOIT0QjLSQWiJIwzv1Bdj4jdzU= +golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -303,17 +401,23 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII= +golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/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= @@ -326,6 +430,8 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b h1:mSUCVIwDx4hfXJfWsOPfdzEHxzb2Xjl6BQ8YgPnazQA= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -335,7 +441,9 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= 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= @@ -344,10 +452,16 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= +gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= +gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= +gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74Ck/DJYc+R8zpq8KGm7uJvpdLRQED/IedA= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= From 0fb8d6b8918be7cf326c133961495ff31310a839 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 11 Nov 2019 13:50:27 -0300 Subject: [PATCH 18/49] vendor: rollback --- go.mod | 2 +- go.sum | 7 +- .../btcsuite/btcd/btcec/genprecomps.go | 63 + .../docker/pkg/archive/example_changes.go | 97 + .../crypto/secp256k1/libsecp256k1/.gitignore | 49 + .../crypto/secp256k1/libsecp256k1/.travis.yml | 69 + .../crypto/secp256k1/libsecp256k1/COPYING | 19 + .../crypto/secp256k1/libsecp256k1/Makefile.am | 177 + .../crypto/secp256k1/libsecp256k1/README.md | 61 + .../crypto/secp256k1/libsecp256k1/TODO | 3 + .../crypto/secp256k1/libsecp256k1/autogen.sh | 3 + .../build-aux/m4/ax_jni_include_dir.m4 | 140 + .../build-aux/m4/ax_prog_cc_for_build.m4 | 125 + .../libsecp256k1/build-aux/m4/bitcoin_secp.m4 | 69 + .../secp256k1/libsecp256k1/configure.ac | 493 + .../libsecp256k1/contrib/lax_der_parsing.c | 150 + .../libsecp256k1/contrib/lax_der_parsing.h | 91 + .../contrib/lax_der_privatekey_parsing.c | 113 + .../contrib/lax_der_privatekey_parsing.h | 90 + .../libsecp256k1/include/secp256k1.h | 577 + .../libsecp256k1/include/secp256k1_ecdh.h | 31 + .../libsecp256k1/include/secp256k1_recovery.h | 110 + .../secp256k1/libsecp256k1/libsecp256k1.pc.in | 13 + .../secp256k1/libsecp256k1/obj/.gitignore | 0 .../libsecp256k1/sage/group_prover.sage | 322 + .../libsecp256k1/sage/secp256k1.sage | 306 + .../libsecp256k1/sage/weierstrass_prover.sage | 264 + .../libsecp256k1/src/asm/field_10x26_arm.s | 919 ++ .../secp256k1/libsecp256k1/src/basic-config.h | 32 + .../crypto/secp256k1/libsecp256k1/src/bench.h | 66 + .../secp256k1/libsecp256k1/src/bench_ecdh.c | 54 + .../libsecp256k1/src/bench_internal.c | 382 + .../libsecp256k1/src/bench_recover.c | 60 + .../libsecp256k1/src/bench_schnorr_verify.c | 73 + .../secp256k1/libsecp256k1/src/bench_sign.c | 56 + .../secp256k1/libsecp256k1/src/bench_verify.c | 112 + .../crypto/secp256k1/libsecp256k1/src/ecdsa.h | 21 + .../secp256k1/libsecp256k1/src/ecdsa_impl.h | 315 + .../crypto/secp256k1/libsecp256k1/src/eckey.h | 25 + .../secp256k1/libsecp256k1/src/eckey_impl.h | 99 + .../secp256k1/libsecp256k1/src/ecmult.h | 31 + .../secp256k1/libsecp256k1/src/ecmult_const.h | 15 + .../libsecp256k1/src/ecmult_const_impl.h | 239 + .../secp256k1/libsecp256k1/src/ecmult_gen.h | 43 + .../libsecp256k1/src/ecmult_gen_impl.h | 210 + .../secp256k1/libsecp256k1/src/ecmult_impl.h | 406 + .../crypto/secp256k1/libsecp256k1/src/field.h | 132 + .../secp256k1/libsecp256k1/src/field_10x26.h | 47 + .../libsecp256k1/src/field_10x26_impl.h | 1140 ++ .../secp256k1/libsecp256k1/src/field_5x52.h | 47 + .../libsecp256k1/src/field_5x52_asm_impl.h | 502 + .../libsecp256k1/src/field_5x52_impl.h | 451 + .../libsecp256k1/src/field_5x52_int128_impl.h | 277 + .../secp256k1/libsecp256k1/src/field_impl.h | 315 + .../secp256k1/libsecp256k1/src/gen_context.c | 74 + .../crypto/secp256k1/libsecp256k1/src/group.h | 144 + .../secp256k1/libsecp256k1/src/group_impl.h | 700 ++ .../crypto/secp256k1/libsecp256k1/src/hash.h | 41 + .../secp256k1/libsecp256k1/src/hash_impl.h | 281 + .../src/java/org/bitcoin/NativeSecp256k1.java | 446 + .../java/org/bitcoin/NativeSecp256k1Test.java | 226 + .../java/org/bitcoin/NativeSecp256k1Util.java | 45 + .../java/org/bitcoin/Secp256k1Context.java | 51 + .../src/java/org_bitcoin_NativeSecp256k1.c | 377 + .../src/java/org_bitcoin_NativeSecp256k1.h | 119 + .../src/java/org_bitcoin_Secp256k1Context.c | 15 + .../src/java/org_bitcoin_Secp256k1Context.h | 22 + .../src/modules/ecdh/Makefile.am.include | 8 + .../libsecp256k1/src/modules/ecdh/main_impl.h | 54 + .../src/modules/ecdh/tests_impl.h | 105 + .../src/modules/recovery/Makefile.am.include | 8 + .../src/modules/recovery/main_impl.h | 193 + .../src/modules/recovery/tests_impl.h | 393 + .../crypto/secp256k1/libsecp256k1/src/num.h | 74 + .../secp256k1/libsecp256k1/src/num_gmp.h | 20 + .../secp256k1/libsecp256k1/src/num_gmp_impl.h | 288 + .../secp256k1/libsecp256k1/src/num_impl.h | 24 + .../secp256k1/libsecp256k1/src/scalar.h | 106 + .../secp256k1/libsecp256k1/src/scalar_4x64.h | 19 + .../libsecp256k1/src/scalar_4x64_impl.h | 949 ++ .../secp256k1/libsecp256k1/src/scalar_8x32.h | 19 + .../libsecp256k1/src/scalar_8x32_impl.h | 721 ++ .../secp256k1/libsecp256k1/src/scalar_impl.h | 370 + .../secp256k1/libsecp256k1/src/scalar_low.h | 15 + .../libsecp256k1/src/scalar_low_impl.h | 114 + .../secp256k1/libsecp256k1/src/secp256k1.c | 559 + .../secp256k1/libsecp256k1/src/testrand.h | 38 + .../libsecp256k1/src/testrand_impl.h | 110 + .../crypto/secp256k1/libsecp256k1/src/tests.c | 4525 ++++++++ .../libsecp256k1/src/tests_exhaustive.c | 470 + .../crypto/secp256k1/libsecp256k1/src/util.h | 113 + .../karalabe/usb/hidapi/AUTHORS.txt | 16 + .../karalabe/usb/hidapi/LICENSE-bsd.txt | 26 + .../karalabe/usb/hidapi/LICENSE-gpl3.txt | 674 ++ .../karalabe/usb/hidapi/LICENSE-orig.txt | 9 + .../karalabe/usb/hidapi/LICENSE.txt | 13 + .../github.com/karalabe/usb/hidapi/README.txt | 339 + .../karalabe/usb/hidapi/hidapi/hidapi.h | 390 + .../karalabe/usb/hidapi/libusb/hid.c | 1512 +++ .../github.com/karalabe/usb/hidapi/mac/hid.c | 1110 ++ .../karalabe/usb/hidapi/windows/hid.c | 944 ++ vendor/github.com/karalabe/usb/libusb/AUTHORS | 119 + vendor/github.com/karalabe/usb/libusb/COPYING | 504 + .../karalabe/usb/libusb/libusb/config.h | 3 + .../karalabe/usb/libusb/libusb/core.c | 2579 +++++ .../karalabe/usb/libusb/libusb/descriptor.c | 1192 ++ .../karalabe/usb/libusb/libusb/hotplug.c | 373 + .../karalabe/usb/libusb/libusb/hotplug.h | 99 + .../karalabe/usb/libusb/libusb/io.c | 2822 +++++ .../karalabe/usb/libusb/libusb/libusb.h | 2039 ++++ .../karalabe/usb/libusb/libusb/libusbi.h | 1165 ++ .../usb/libusb/libusb/os/darwin_usb.c | 2142 ++++ .../usb/libusb/libusb/os/darwin_usb.h | 199 + .../usb/libusb/libusb/os/haiku_pollfs.cpp | 367 + .../karalabe/usb/libusb/libusb/os/haiku_usb.h | 112 + .../libusb/libusb/os/haiku_usb_backend.cpp | 517 + .../usb/libusb/libusb/os/haiku_usb_raw.cpp | 253 + .../usb/libusb/libusb/os/haiku_usb_raw.h | 180 + .../usb/libusb/libusb/os/linux_netlink.c | 409 + .../usb/libusb/libusb/os/linux_udev.c | 329 + .../usb/libusb/libusb/os/linux_usbfs.c | 2800 +++++ .../usb/libusb/libusb/os/linux_usbfs.h | 194 + .../usb/libusb/libusb/os/netbsd_usb.c | 677 ++ .../usb/libusb/libusb/os/openbsd_usb.c | 771 ++ .../usb/libusb/libusb/os/poll_posix.c | 84 + .../usb/libusb/libusb/os/poll_posix.h | 11 + .../usb/libusb/libusb/os/poll_windows.c | 364 + .../usb/libusb/libusb/os/poll_windows.h | 97 + .../karalabe/usb/libusb/libusb/os/sunos_usb.c | 1675 +++ .../karalabe/usb/libusb/libusb/os/sunos_usb.h | 80 + .../usb/libusb/libusb/os/threads_posix.c | 80 + .../usb/libusb/libusb/os/threads_posix.h | 102 + .../usb/libusb/libusb/os/threads_windows.c | 126 + .../usb/libusb/libusb/os/threads_windows.h | 111 + .../karalabe/usb/libusb/libusb/os/wince_usb.c | 888 ++ .../karalabe/usb/libusb/libusb/os/wince_usb.h | 126 + .../usb/libusb/libusb/os/windows_common.h | 128 + .../usb/libusb/libusb/os/windows_nt_common.c | 1008 ++ .../usb/libusb/libusb/os/windows_nt_common.h | 110 + .../libusb/os/windows_nt_shared_types.h | 138 + .../usb/libusb/libusb/os/windows_usbdk.c | 830 ++ .../usb/libusb/libusb/os/windows_usbdk.h | 103 + .../usb/libusb/libusb/os/windows_winusb.c | 3009 +++++ .../usb/libusb/libusb/os/windows_winusb.h | 680 ++ .../karalabe/usb/libusb/libusb/strerror.c | 202 + .../karalabe/usb/libusb/libusb/sync.c | 327 + .../karalabe/usb/libusb/libusb/version.h | 18 + .../karalabe/usb/libusb/libusb/version_nano.h | 1 + vendor/golang.org/x/net/html/atom/gen.go | 712 ++ vendor/golang.org/x/net/html/token.go | 6 - vendor/golang.org/x/net/http2/hpack/encode.go | 2 +- vendor/golang.org/x/net/http2/pipe.go | 7 +- vendor/golang.org/x/net/http2/server.go | 58 +- vendor/golang.org/x/net/http2/transport.go | 52 +- vendor/golang.org/x/net/http2/writesched.go | 8 +- .../x/net/http2/writesched_priority.go | 2 +- .../x/net/http2/writesched_random.go | 9 +- vendor/golang.org/x/net/idna/tables11.0.0.go | 2 +- vendor/golang.org/x/net/idna/tables12.00.go | 4733 -------- .../golang.org/x/net/internal/socks/socks.go | 2 +- vendor/golang.org/x/net/publicsuffix/list.go | 181 - vendor/golang.org/x/net/publicsuffix/table.go | 9962 ----------------- .../golang.org/x/net/websocket/websocket.go | 6 +- vendor/golang.org/x/sys/unix/mkasm_darwin.go | 61 + vendor/golang.org/x/sys/unix/mkpost.go | 122 + vendor/golang.org/x/sys/unix/mksyscall.go | 407 + .../x/sys/unix/mksyscall_aix_ppc.go | 415 + .../x/sys/unix/mksyscall_aix_ppc64.go | 614 + .../x/sys/unix/mksyscall_solaris.go | 335 + .../golang.org/x/sys/unix/mksysctl_openbsd.go | 355 + vendor/golang.org/x/sys/unix/mksysnum.go | 190 + vendor/golang.org/x/sys/unix/types_aix.go | 237 + vendor/golang.org/x/sys/unix/types_darwin.go | 283 + .../golang.org/x/sys/unix/types_dragonfly.go | 263 + vendor/golang.org/x/sys/unix/types_freebsd.go | 400 + vendor/golang.org/x/sys/unix/types_netbsd.go | 290 + vendor/golang.org/x/sys/unix/types_openbsd.go | 283 + vendor/golang.org/x/sys/unix/types_solaris.go | 266 + .../x/text/encoding/charmap/maketables.go | 556 + .../x/text/encoding/htmlindex/gen.go | 173 + .../text/encoding/internal/identifier/gen.go | 142 + .../x/text/encoding/japanese/maketables.go | 161 + .../x/text/encoding/korean/maketables.go | 143 + .../encoding/simplifiedchinese/maketables.go | 161 + .../encoding/traditionalchinese/maketables.go | 140 + .../x/text/internal/language/compact/gen.go | 64 + .../internal/language/compact/gen_index.go | 113 + .../internal/language/compact/gen_parents.go | 54 + .../x/text/internal/language/gen.go | 1520 +++ .../x/text/internal/language/gen_common.go | 20 + vendor/golang.org/x/text/language/gen.go | 305 + vendor/golang.org/x/text/unicode/bidi/gen.go | 133 + .../x/text/unicode/bidi/gen_ranges.go | 57 + .../x/text/unicode/bidi/gen_trieval.go | 64 + .../x/text/unicode/norm/maketables.go | 986 ++ .../golang.org/x/text/unicode/norm/triegen.go | 117 + vendor/k8s.io/client-go/pkg/version/base.go | 4 +- vendor/modules.txt | 322 +- 198 files changed, 66847 insertions(+), 15176 deletions(-) create mode 100644 vendor/github.com/btcsuite/btcd/btcec/genprecomps.go create mode 100644 vendor/github.com/docker/docker/pkg/archive/example_changes.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h create mode 100644 vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/LICENSE.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/README.txt create mode 100644 vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h create mode 100644 vendor/github.com/karalabe/usb/hidapi/libusb/hid.c create mode 100644 vendor/github.com/karalabe/usb/hidapi/mac/hid.c create mode 100644 vendor/github.com/karalabe/usb/hidapi/windows/hid.c create mode 100644 vendor/github.com/karalabe/usb/libusb/AUTHORS create mode 100644 vendor/github.com/karalabe/usb/libusb/COPYING create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/config.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/core.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/io.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/libusb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/strerror.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/sync.c create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/version.h create mode 100644 vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h create mode 100644 vendor/golang.org/x/net/html/atom/gen.go delete mode 100644 vendor/golang.org/x/net/idna/tables12.00.go delete mode 100644 vendor/golang.org/x/net/publicsuffix/list.go delete mode 100644 vendor/golang.org/x/net/publicsuffix/table.go create mode 100644 vendor/golang.org/x/sys/unix/mkasm_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/mkpost.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/mksysnum.go create mode 100644 vendor/golang.org/x/sys/unix/types_aix.go create mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go create mode 100644 vendor/golang.org/x/text/encoding/charmap/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/htmlindex/gen.go create mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/gen.go create mode 100644 vendor/golang.org/x/text/encoding/japanese/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/korean/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_index.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_parents.go create mode 100644 vendor/golang.org/x/text/internal/language/gen.go create mode 100644 vendor/golang.org/x/text/internal/language/gen_common.go create mode 100644 vendor/golang.org/x/text/language/gen.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go create mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go create mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go diff --git a/go.mod b/go.mod index 7f027e1729..3ed0a7e834 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/vbauerster/mpb v3.4.0+incompatible go.uber.org/atomic v1.4.0 // indirect golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 - golang.org/x/net v0.0.0-20191105084925-a882066a44e0 + golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 google.golang.org/appengine v1.6.1 // indirect diff --git a/go.sum b/go.sum index 4beec79431..5f1f6a511c 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.20.0-beta h1:DnZGUjFbRkpytojHWwy6nfUSA7vFrzWXDLpFNzt74ZA= github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -307,8 +308,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 h1:u+awngKkvwHGxPJ4Lk3Yy6A10ThdtyaiQP9OloHK6ao= -github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40/go.mod h1:OubQGgQet774hs5o+jd48lChnHv4+BMHdcSAY6sxaJw= github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 h1:saHKOwJeSkV5PzZeTnw97JMLycaDBJnF2P/1sDVWuq8= github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -387,9 +386,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191105084925-a882066a44e0 h1:QPlSTtPE2k6PZPasQUbzuK3p9JbS+vMXYVto8g/yrsg= -golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -441,6 +439,7 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= diff --git a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go new file mode 100644 index 0000000000..d4a9c1b830 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go @@ -0,0 +1,63 @@ +// Copyright 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// This file is ignored during the regular build due to the following build tag. +// It is called by go generate and used to automatically generate pre-computed +// tables used to accelerate operations. +// +build ignore + +package main + +import ( + "bytes" + "compress/zlib" + "encoding/base64" + "fmt" + "log" + "os" + + "github.com/btcsuite/btcd/btcec" +) + +func main() { + fi, err := os.Create("secp256k1.go") + if err != nil { + log.Fatal(err) + } + defer fi.Close() + + // Compress the serialized byte points. + serialized := btcec.S256().SerializedBytePoints() + var compressed bytes.Buffer + w := zlib.NewWriter(&compressed) + if _, err := w.Write(serialized); err != nil { + fmt.Println(err) + os.Exit(1) + } + w.Close() + + // Encode the compressed byte points with base64. + encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len())) + base64.StdEncoding.Encode(encoded, compressed.Bytes()) + + fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers") + fmt.Fprintln(fi, "// Use of this source code is governed by an ISC") + fmt.Fprintln(fi, "// license that can be found in the LICENSE file.") + fmt.Fprintln(fi) + fmt.Fprintln(fi, "package btcec") + fmt.Fprintln(fi) + fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)") + fmt.Fprintln(fi, "// DO NOT EDIT") + fmt.Fprintln(fi) + fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded)) + + a1, b1, a2, b2 := btcec.S256().EndomorphismVectors() + fmt.Println("The following values are the computed linearly " + + "independent vectors needed to make use of the secp256k1 " + + "endomorphism:") + fmt.Printf("a1: %x\n", a1) + fmt.Printf("b1: %x\n", b1) + fmt.Printf("a2: %x\n", a2) + fmt.Printf("b2: %x\n", b2) +} diff --git a/vendor/github.com/docker/docker/pkg/archive/example_changes.go b/vendor/github.com/docker/docker/pkg/archive/example_changes.go new file mode 100644 index 0000000000..495db809e9 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/example_changes.go @@ -0,0 +1,97 @@ +// +build ignore + +// Simple tool to create an archive stream from an old and new directory +// +// By default it will stream the comparison of two temporary directories with junk files +package main + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "path" + + "github.com/docker/docker/pkg/archive" + "github.com/sirupsen/logrus" +) + +var ( + flDebug = flag.Bool("D", false, "debugging output") + flNewDir = flag.String("newdir", "", "") + flOldDir = flag.String("olddir", "", "") + log = logrus.New() +) + +func main() { + flag.Usage = func() { + fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") + fmt.Printf("%s [OPTIONS]\n", os.Args[0]) + flag.PrintDefaults() + } + flag.Parse() + log.Out = os.Stderr + if (len(os.Getenv("DEBUG")) > 0) || *flDebug { + logrus.SetLevel(logrus.DebugLevel) + } + var newDir, oldDir string + + if len(*flNewDir) == 0 { + var err error + newDir, err = ioutil.TempDir("", "docker-test-newDir") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(newDir) + if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { + log.Fatal(err) + } + } else { + newDir = *flNewDir + } + + if len(*flOldDir) == 0 { + oldDir, err := ioutil.TempDir("", "docker-test-oldDir") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(oldDir) + } else { + oldDir = *flOldDir + } + + changes, err := archive.ChangesDirs(newDir, oldDir) + if err != nil { + log.Fatal(err) + } + + a, err := archive.ExportChanges(newDir, changes) + if err != nil { + log.Fatal(err) + } + defer a.Close() + + i, err := io.Copy(os.Stdout, a) + if err != nil && err != io.EOF { + log.Fatal(err) + } + fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) +} + +func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { + fileData := []byte("fooo") + for n := 0; n < numberOfFiles; n++ { + fileName := fmt.Sprintf("file-%d", n) + if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { + return 0, err + } + if makeLinks { + if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { + return 0, err + } + } + } + totalSize := numberOfFiles * len(fileData) + return totalSize, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore new file mode 100644 index 0000000000..87fea161ba --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore @@ -0,0 +1,49 @@ +bench_inv +bench_ecdh +bench_sign +bench_verify +bench_schnorr_verify +bench_recover +bench_internal +tests +exhaustive_tests +gen_context +*.exe +*.so +*.a +!.gitignore + +Makefile +configure +.libs/ +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +*.tar.gz +*.la +libtool +.deps/ +.dirstamp +*.lo +*.o +*~ +src/libsecp256k1-config.h +src/libsecp256k1-config.h.in +src/ecmult_static_context.h +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/m4/libtool.m4 +build-aux/m4/lt~obsolete.m4 +build-aux/m4/ltoptions.m4 +build-aux/m4/ltsugar.m4 +build-aux/m4/ltversion.m4 +build-aux/missing +build-aux/compile +build-aux/test-driver +src/stamp-h1 +libsecp256k1.pc diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml new file mode 100644 index 0000000000..2439529242 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml @@ -0,0 +1,69 @@ +language: c +sudo: false +addons: + apt: + packages: libgmp-dev +compiler: + - clang + - gcc +cache: + directories: + - src/java/guava/ +env: + global: + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no + - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar + matrix: + - SCALAR=32bit RECOVERY=yes + - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes + - SCALAR=64bit + - FIELD=64bit RECOVERY=yes + - FIELD=64bit ENDOMORPHISM=yes + - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes + - FIELD=64bit ASM=x86_64 + - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 + - FIELD=32bit ENDOMORPHISM=yes + - BIGNUM=no + - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes + - BIGNUM=no STATICPRECOMPUTATION=no + - BUILD=distcheck + - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC + - EXTRAFLAGS=CFLAGS=-O0 + - BUILD=check-java ECDH=yes EXPERIMENTAL=yes +matrix: + fast_finish: true + include: + - compiler: clang + env: HOST=i686-linux-gnu ENDOMORPHISM=yes + addons: + apt: + packages: + - gcc-multilib + - libgmp-dev:i386 + - compiler: clang + env: HOST=i686-linux-gnu + addons: + apt: + packages: + - gcc-multilib + - compiler: gcc + env: HOST=i686-linux-gnu ENDOMORPHISM=yes + addons: + apt: + packages: + - gcc-multilib + - compiler: gcc + env: HOST=i686-linux-gnu + addons: + apt: + packages: + - gcc-multilib + - libgmp-dev:i386 +before_install: mkdir -p `dirname $GUAVA_JAR` +install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi +before_script: ./autogen.sh +script: + - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi + - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD +os: linux diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING new file mode 100644 index 0000000000..4522a5990e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2013 Pieter Wuille + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am new file mode 100644 index 0000000000..c071fbe275 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am @@ -0,0 +1,177 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +lib_LTLIBRARIES = libsecp256k1.la +if USE_JNI +JNI_LIB = libsecp256k1_jni.la +noinst_LTLIBRARIES = $(JNI_LIB) +else +JNI_LIB = +endif +include_HEADERS = include/secp256k1.h +noinst_HEADERS = +noinst_HEADERS += src/scalar.h +noinst_HEADERS += src/scalar_4x64.h +noinst_HEADERS += src/scalar_8x32.h +noinst_HEADERS += src/scalar_low.h +noinst_HEADERS += src/scalar_impl.h +noinst_HEADERS += src/scalar_4x64_impl.h +noinst_HEADERS += src/scalar_8x32_impl.h +noinst_HEADERS += src/scalar_low_impl.h +noinst_HEADERS += src/group.h +noinst_HEADERS += src/group_impl.h +noinst_HEADERS += src/num_gmp.h +noinst_HEADERS += src/num_gmp_impl.h +noinst_HEADERS += src/ecdsa.h +noinst_HEADERS += src/ecdsa_impl.h +noinst_HEADERS += src/eckey.h +noinst_HEADERS += src/eckey_impl.h +noinst_HEADERS += src/ecmult.h +noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_const.h +noinst_HEADERS += src/ecmult_const_impl.h +noinst_HEADERS += src/ecmult_gen.h +noinst_HEADERS += src/ecmult_gen_impl.h +noinst_HEADERS += src/num.h +noinst_HEADERS += src/num_impl.h +noinst_HEADERS += src/field_10x26.h +noinst_HEADERS += src/field_10x26_impl.h +noinst_HEADERS += src/field_5x52.h +noinst_HEADERS += src/field_5x52_impl.h +noinst_HEADERS += src/field_5x52_int128_impl.h +noinst_HEADERS += src/field_5x52_asm_impl.h +noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h +noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h +noinst_HEADERS += src/util.h +noinst_HEADERS += src/testrand.h +noinst_HEADERS += src/testrand_impl.h +noinst_HEADERS += src/hash.h +noinst_HEADERS += src/hash_impl.h +noinst_HEADERS += src/field.h +noinst_HEADERS += src/field_impl.h +noinst_HEADERS += src/bench.h +noinst_HEADERS += contrib/lax_der_parsing.h +noinst_HEADERS += contrib/lax_der_parsing.c +noinst_HEADERS += contrib/lax_der_privatekey_parsing.h +noinst_HEADERS += contrib/lax_der_privatekey_parsing.c + +if USE_EXTERNAL_ASM +COMMON_LIB = libsecp256k1_common.la +noinst_LTLIBRARIES = $(COMMON_LIB) +else +COMMON_LIB = +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsecp256k1.pc + +if USE_EXTERNAL_ASM +if USE_ASM_ARM +libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s +endif +endif + +libsecp256k1_la_SOURCES = src/secp256k1.c +libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) +libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) + +libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c +libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) + +noinst_PROGRAMS = +if USE_BENCHMARK +noinst_PROGRAMS += bench_verify bench_sign bench_internal +bench_verify_SOURCES = src/bench_verify.c +bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_sign_SOURCES = src/bench_sign.c +bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_internal_SOURCES = src/bench_internal.c +bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) +endif + +TESTS = +if USE_TESTS +noinst_PROGRAMS += tests +tests_SOURCES = src/tests.c +tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +if !ENABLE_COVERAGE +tests_CPPFLAGS += -DVERIFY +endif +tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +tests_LDFLAGS = -static +TESTS += tests +endif + +if USE_EXHAUSTIVE_TESTS +noinst_PROGRAMS += exhaustive_tests +exhaustive_tests_SOURCES = src/tests_exhaustive.c +exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +if !ENABLE_COVERAGE +exhaustive_tests_CPPFLAGS += -DVERIFY +endif +exhaustive_tests_LDADD = $(SECP_LIBS) +exhaustive_tests_LDFLAGS = -static +TESTS += exhaustive_tests +endif + +JAVAROOT=src/java +JAVAORG=org/bitcoin +JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar +CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) +JAVA_FILES= \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ + $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java + +if USE_JNI + +$(JAVA_GUAVA): + @echo Guava is missing. Fetch it via: \ + wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) + @false + +.stamp-java: $(JAVA_FILES) + @echo Compiling $^ + $(AM_V_at)$(CLASSPATH_ENV) javac $^ + @touch $@ + +if USE_TESTS + +check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java + $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test + +endif +endif + +if USE_ECMULT_STATIC_PRECOMPUTATION +CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) +CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function + +gen_context_OBJECTS = gen_context.o +gen_context_BIN = gen_context$(BUILD_EXEEXT) +gen_%.o: src/gen_%.c + $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + +$(gen_context_BIN): $(gen_context_OBJECTS) + $(CC_FOR_BUILD) $^ -o $@ + +$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h +$(tests_OBJECTS): src/ecmult_static_context.h +$(bench_internal_OBJECTS): src/ecmult_static_context.h + +src/ecmult_static_context.h: $(gen_context_BIN) + ./$(gen_context_BIN) + +CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java +endif + +EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) + +if ENABLE_MODULE_ECDH +include src/modules/ecdh/Makefile.am.include +endif + +if ENABLE_MODULE_RECOVERY +include src/modules/recovery/Makefile.am.include +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md new file mode 100644 index 0000000000..8cd344ea81 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md @@ -0,0 +1,61 @@ +libsecp256k1 +============ + +[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) + +Optimized C library for EC operations on curve secp256k1. + +This library is a work in progress and is being used to research best practices. Use at your own risk. + +Features: +* secp256k1 ECDSA signing/verification and key generation. +* Adding/multiplying private/public keys. +* Serialization/parsing of private keys, public keys, signatures. +* Constant time, constant memory access signing and pubkey generation. +* Derandomized DSA (via RFC6979 or with a caller provided function.) +* Very efficient implementation. + +Implementation details +---------------------- + +* General + * No runtime heap allocation. + * Extensive testing infrastructure. + * Structured to facilitate review and analysis. + * Intended to be portable to any system with a C89 compiler and uint64_t support. + * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") +* Field operations + * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). + * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). + * Using 10 26-bit limbs. + * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). +* Scalar operations + * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. + * Using 4 64-bit limbs (relying on __int128 support in the compiler). + * Using 8 32-bit limbs. +* Group operations + * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). + * Use addition between points in Jacobian and affine coordinates where possible. + * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. + * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. +* Point multiplication for verification (a*P + b*G). + * Use wNAF notation for point multiplicands. + * Use a much larger window for multiples of G, using precomputed multiples. + * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. + * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. +* Point multiplication for signing + * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. + * Access the table with branch-free conditional moves so memory access is uniform. + * No data-dependent branches + * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. + +Build steps +----------- + +libsecp256k1 is built using autotools: + + $ ./autogen.sh + $ ./configure + $ make + $ ./tests + $ sudo make install # optional diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO new file mode 100644 index 0000000000..a300e1c5eb --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO @@ -0,0 +1,3 @@ +* Unit tests for fieldelem/groupelem, including ones intended to + trigger fieldelem's boundary cases. +* Complete constant-time operations for signing/keygen diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh new file mode 100644 index 0000000000..65286b9353 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh +set -e +autoreconf -if --warnings=all diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 new file mode 100644 index 0000000000..1fc3627614 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 @@ -0,0 +1,140 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_JNI_INCLUDE_DIR +# +# DESCRIPTION +# +# AX_JNI_INCLUDE_DIR finds include directories needed for compiling +# programs using the JNI interface. +# +# JNI include directories are usually in the Java distribution. This is +# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in +# that order. When this macro completes, a list of directories is left in +# the variable JNI_INCLUDE_DIRS. +# +# Example usage follows: +# +# AX_JNI_INCLUDE_DIR +# +# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS +# do +# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" +# done +# +# If you want to force a specific compiler: +# +# - at the configure.in level, set JAVAC=yourcompiler before calling +# AX_JNI_INCLUDE_DIR +# +# - at the configure level, setenv JAVAC +# +# Note: This macro can work with the autoconf M4 macros for Java programs. +# This particular macro is not part of the original set of macros. +# +# LICENSE +# +# Copyright (c) 2008 Don Anderson +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) +AC_DEFUN([AX_JNI_INCLUDE_DIR],[ + +JNI_INCLUDE_DIRS="" + +if test "x$JAVA_HOME" != x; then + _JTOPDIR="$JAVA_HOME" +else + if test "x$JAVAC" = x; then + JAVAC=javac + fi + AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) + if test "x$_ACJNI_JAVAC" = xno; then + AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) + fi + _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") + _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` +fi + +case "$host_os" in + darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + _JINC="$_JTOPDIR/Headers";; + *) _JINC="$_JTOPDIR/include";; +esac +_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) +_AS_ECHO_LOG([_JINC=$_JINC]) + +# On Mac OS X 10.6.4, jni.h is a symlink: +# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h +# -> ../../CurrentJDK/Headers/jni.h. + +AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, +[ +if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" +else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + ac_cv_jni_header_path=none + fi +fi +]) + + + +# get the likely subdirectories for system specific java includes +case "$host_os" in +bsdi*) _JNI_INC_SUBDIRS="bsdos";; +darwin*) _JNI_INC_SUBDIRS="darwin";; +freebsd*) _JNI_INC_SUBDIRS="freebsd";; +linux*) _JNI_INC_SUBDIRS="linux genunix";; +osf*) _JNI_INC_SUBDIRS="alpha";; +solaris*) _JNI_INC_SUBDIRS="solaris";; +mingw*) _JNI_INC_SUBDIRS="win32";; +cygwin*) _JNI_INC_SUBDIRS="win32";; +*) _JNI_INC_SUBDIRS="genunix";; +esac + +if test "x$ac_cv_jni_header_path" != "xnone"; then + # add any subdirectories that are present + for JINCSUBDIR in $_JNI_INC_SUBDIRS + do + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi + done +fi +]) + +# _ACJNI_FOLLOW_SYMLINKS +# Follows symbolic links on , +# finally setting variable _ACJNI_FOLLOWED +# ---------------------------------------- +AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ +# find the include directory relative to the javac executable +_cur="$1" +while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do + AC_MSG_CHECKING([symlink for $_cur]) + _slink=`ls -ld "$_cur" | sed 's/.* -> //'` + case "$_slink" in + /*) _cur="$_slink";; + # 'X' avoids triggering unwanted echo options. + *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; + esac + AC_MSG_RESULT([$_cur]) +done +_ACJNI_FOLLOWED="$_cur" +])# _ACJNI diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 new file mode 100644 index 0000000000..77fd346a79 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 @@ -0,0 +1,125 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_CC_FOR_BUILD +# +# DESCRIPTION +# +# This macro searches for a C compiler that generates native executables, +# that is a C compiler that surely is not a cross-compiler. This can be +# useful if you have to generate source code at compile-time like for +# example GCC does. +# +# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything +# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). +# The value of these variables can be overridden by the user by specifying +# a compiler with an environment variable (like you do for standard CC). +# +# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object +# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if +# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are +# substituted in the Makefile. +# +# LICENSE +# +# Copyright (c) 2008 Paolo Bonzini +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) +AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +AC_REQUIRE([AC_EXEEXT])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl + +dnl Use the standard macros, but make them use other variable names +dnl +pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl +pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl +pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl +pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl +pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl +pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl +pushdef([ac_cv_objext], ac_cv_build_objext)dnl +pushdef([ac_exeext], ac_build_exeext)dnl +pushdef([ac_objext], ac_build_objext)dnl +pushdef([CC], CC_FOR_BUILD)dnl +pushdef([CPP], CPP_FOR_BUILD)dnl +pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl +pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl +pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl +pushdef([host], build)dnl +pushdef([host_alias], build_alias)dnl +pushdef([host_cpu], build_cpu)dnl +pushdef([host_vendor], build_vendor)dnl +pushdef([host_os], build_os)dnl +pushdef([ac_cv_host], ac_cv_build)dnl +pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl +pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl +pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl +pushdef([ac_cv_host_os], ac_cv_build_os)dnl +pushdef([ac_cpp], ac_build_cpp)dnl +pushdef([ac_compile], ac_build_compile)dnl +pushdef([ac_link], ac_build_link)dnl + +save_cross_compiling=$cross_compiling +save_ac_tool_prefix=$ac_tool_prefix +cross_compiling=no +ac_tool_prefix= + +AC_PROG_CC +AC_PROG_CPP +AC_EXEEXT + +ac_tool_prefix=$save_ac_tool_prefix +cross_compiling=$save_cross_compiling + +dnl Restore the old definitions +dnl +popdef([ac_link])dnl +popdef([ac_compile])dnl +popdef([ac_cpp])dnl +popdef([ac_cv_host_os])dnl +popdef([ac_cv_host_vendor])dnl +popdef([ac_cv_host_cpu])dnl +popdef([ac_cv_host_alias])dnl +popdef([ac_cv_host])dnl +popdef([host_os])dnl +popdef([host_vendor])dnl +popdef([host_cpu])dnl +popdef([host_alias])dnl +popdef([host])dnl +popdef([LDFLAGS])dnl +popdef([CPPFLAGS])dnl +popdef([CFLAGS])dnl +popdef([CPP])dnl +popdef([CC])dnl +popdef([ac_objext])dnl +popdef([ac_exeext])dnl +popdef([ac_cv_objext])dnl +popdef([ac_cv_exeext])dnl +popdef([ac_cv_prog_cc_g])dnl +popdef([ac_cv_prog_cc_cross])dnl +popdef([ac_cv_prog_cc_works])dnl +popdef([ac_cv_prog_gcc])dnl +popdef([ac_cv_prog_CPP])dnl + +dnl Finally, set Makefile variables +dnl +BUILD_EXEEXT=$ac_build_exeext +BUILD_OBJEXT=$ac_build_objext +AC_SUBST(BUILD_EXEEXT)dnl +AC_SUBST(BUILD_OBJEXT)dnl +AC_SUBST([CFLAGS_FOR_BUILD])dnl +AC_SUBST([CPPFLAGS_FOR_BUILD])dnl +AC_SUBST([LDFLAGS_FOR_BUILD])dnl +]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 new file mode 100644 index 0000000000..b74acb8c13 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 @@ -0,0 +1,69 @@ +dnl libsecp25k1 helper checks +AC_DEFUN([SECP_INT128_CHECK],[ +has_int128=$ac_cv_type___int128 +]) + +dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. +AC_DEFUN([SECP_64BIT_ASM_CHECK],[ +AC_MSG_CHECKING(for x86_64 assembly availability) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include ]],[[ + uint64_t a = 11, tmp; + __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); + ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) +AC_MSG_RESULT([$has_64bit_asm]) +]) + +dnl +AC_DEFUN([SECP_OPENSSL_CHECK],[ + has_libcrypto=no + m4_ifdef([PKG_CHECK_MODULES],[ + PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) + if test x"$has_libcrypto" = x"yes"; then + TEMP_LIBS="$LIBS" + LIBS="$LIBS $CRYPTO_LIBS" + AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) + LIBS="$TEMP_LIBS" + fi + ]) + if test x$has_libcrypto = xno; then + AC_CHECK_HEADER(openssl/crypto.h,[ + AC_CHECK_LIB(crypto, main,[ + has_libcrypto=yes + CRYPTO_LIBS=-lcrypto + AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed]) + ]) + ]) + LIBS= + fi +if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then + AC_MSG_CHECKING(for EC functions in libcrypto) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + #include ]],[[ + EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); + ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); + ECDSA_verify(0, NULL, 0, NULL, 0, eckey); + EC_KEY_free(eckey); + ECDSA_SIG *sig_openssl; + sig_openssl = ECDSA_SIG_new(); + (void)sig_openssl->r; + ECDSA_SIG_free(sig_openssl); + ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) + AC_MSG_RESULT([$has_openssl_ec]) +fi +]) + +dnl +AC_DEFUN([SECP_GMP_CHECK],[ +if test x"$has_gmp" != x"yes"; then + CPPFLAGS_TEMP="$CPPFLAGS" + CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" + LIBS_TEMP="$LIBS" + LIBS="$GMP_LIBS $LIBS" + AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) + CPPFLAGS="$CPPFLAGS_TEMP" + LIBS="$LIBS_TEMP" +fi +]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac new file mode 100644 index 0000000000..e5fcbcb4ed --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac @@ -0,0 +1,493 @@ +AC_PREREQ([2.60]) +AC_INIT([libsecp256k1],[0.1]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CANONICAL_HOST +AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) +AH_TOP([#define LIBSECP256K1_CONFIG_H]) +AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) +LT_INIT + +dnl make the compilation flags quiet unless V=1 is used +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +PKG_PROG_PKG_CONFIG + +AC_PATH_TOOL(AR, ar) +AC_PATH_TOOL(RANLIB, ranlib) +AC_PATH_TOOL(STRIP, strip) +AX_PROG_CC_FOR_BUILD + +if test "x$CFLAGS" = "x"; then + CFLAGS="-g" +fi + +AM_PROG_CC_C_O + +AC_PROG_CC_C89 +if test x"$ac_cv_prog_cc_c89" = x"no"; then + AC_MSG_ERROR([c89 compiler support required]) +fi +AM_PROG_AS + +case $host_os in + *darwin*) + if test x$cross_compiling != xyes; then + AC_PATH_PROG([BREW],brew,) + if test x$BREW != x; then + dnl These Homebrew packages may be keg-only, meaning that they won't be found + dnl in expected paths because they may conflict with system files. Ask + dnl Homebrew where each one is located, then adjust paths accordingly. + + openssl_prefix=`$BREW --prefix openssl 2>/dev/null` + gmp_prefix=`$BREW --prefix gmp 2>/dev/null` + if test x$openssl_prefix != x; then + PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" + export PKG_CONFIG_PATH + fi + if test x$gmp_prefix != x; then + GMP_CPPFLAGS="-I$gmp_prefix/include" + GMP_LIBS="-L$gmp_prefix/lib" + fi + else + AC_PATH_PROG([PORT],port,) + dnl if homebrew isn't installed and macports is, add the macports default paths + dnl as a last resort. + if test x$PORT != x; then + CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" + LDFLAGS="$LDFLAGS -L/opt/local/lib" + fi + fi + fi + ;; +esac + +CFLAGS="$CFLAGS -W" + +warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings" +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $warn_CFLAGS" +AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fvisibility=hidden" +AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + +AC_ARG_ENABLE(benchmark, + AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), + [use_benchmark=$enableval], + [use_benchmark=no]) + +AC_ARG_ENABLE(coverage, + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), + [enable_coverage=$enableval], + [enable_coverage=no]) + +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + [use_tests=$enableval], + [use_tests=yes]) + +AC_ARG_ENABLE(openssl_tests, + AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), + [enable_openssl_tests=$enableval], + [enable_openssl_tests=auto]) + +AC_ARG_ENABLE(experimental, + AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), + [use_experimental=$enableval], + [use_experimental=no]) + +AC_ARG_ENABLE(exhaustive_tests, + AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), + [use_exhaustive_tests=$enableval], + [use_exhaustive_tests=yes]) + +AC_ARG_ENABLE(endomorphism, + AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), + [use_endomorphism=$enableval], + [use_endomorphism=no]) + +AC_ARG_ENABLE(ecmult_static_precomputation, + AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), + [use_ecmult_static_precomputation=$enableval], + [use_ecmult_static_precomputation=auto]) + +AC_ARG_ENABLE(module_ecdh, + AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), + [enable_module_ecdh=$enableval], + [enable_module_ecdh=no]) + +AC_ARG_ENABLE(module_recovery, + AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), + [enable_module_recovery=$enableval], + [enable_module_recovery=no]) + +AC_ARG_ENABLE(jni, + AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), + [use_jni=$enableval], + [use_jni=auto]) + +AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], +[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) + +AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], +[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) + +AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], +[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) + +AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] +[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) + +AC_CHECK_TYPES([__int128]) + +AC_MSG_CHECKING([for __builtin_expect]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], + [ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ], + [ AC_MSG_RESULT([no]) + ]) + +if test x"$enable_coverage" = x"yes"; then + AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) + CFLAGS="$CFLAGS -O0 --coverage" + LDFLAGS="--coverage" +else + CFLAGS="$CFLAGS -O3" +fi + +if test x"$use_ecmult_static_precomputation" != x"no"; then + save_cross_compiling=$cross_compiling + cross_compiling=no + TEMP_CC="$CC" + CC="$CC_FOR_BUILD" + AC_MSG_CHECKING([native compiler: ${CC_FOR_BUILD}]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([], [return 0])], + [working_native_cc=yes], + [working_native_cc=no],[dnl]) + CC="$TEMP_CC" + cross_compiling=$save_cross_compiling + + if test x"$working_native_cc" = x"no"; then + set_precomp=no + if test x"$use_ecmult_static_precomputation" = x"yes"; then + AC_MSG_ERROR([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + else + AC_MSG_RESULT([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + fi + else + AC_MSG_RESULT([ok]) + set_precomp=yes + fi +else + set_precomp=no +fi + +if test x"$req_asm" = x"auto"; then + SECP_64BIT_ASM_CHECK + if test x"$has_64bit_asm" = x"yes"; then + set_asm=x86_64 + fi + if test x"$set_asm" = x; then + set_asm=no + fi +else + set_asm=$req_asm + case $set_asm in + x86_64) + SECP_64BIT_ASM_CHECK + if test x"$has_64bit_asm" != x"yes"; then + AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) + fi + ;; + arm) + ;; + no) + ;; + *) + AC_MSG_ERROR([invalid assembly optimization selection]) + ;; + esac +fi + +if test x"$req_field" = x"auto"; then + if test x"set_asm" = x"x86_64"; then + set_field=64bit + fi + if test x"$set_field" = x; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_field=64bit + fi + fi + if test x"$set_field" = x; then + set_field=32bit + fi +else + set_field=$req_field + case $set_field in + 64bit) + if test x"$set_asm" != x"x86_64"; then + SECP_INT128_CHECK + if test x"$has_int128" != x"yes"; then + AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available]) + fi + fi + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid field implementation selection]) + ;; + esac +fi + +if test x"$req_scalar" = x"auto"; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_scalar=64bit + fi + if test x"$set_scalar" = x; then + set_scalar=32bit + fi +else + set_scalar=$req_scalar + case $set_scalar in + 64bit) + SECP_INT128_CHECK + if test x"$has_int128" != x"yes"; then + AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available]) + fi + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid scalar implementation selected]) + ;; + esac +fi + +if test x"$req_bignum" = x"auto"; then + SECP_GMP_CHECK + if test x"$has_gmp" = x"yes"; then + set_bignum=gmp + fi + + if test x"$set_bignum" = x; then + set_bignum=no + fi +else + set_bignum=$req_bignum + case $set_bignum in + gmp) + SECP_GMP_CHECK + if test x"$has_gmp" != x"yes"; then + AC_MSG_ERROR([gmp bignum explicitly requested but libgmp not available]) + fi + ;; + no) + ;; + *) + AC_MSG_ERROR([invalid bignum implementation selection]) + ;; + esac +fi + +# select assembly optimization +use_external_asm=no + +case $set_asm in +x86_64) + AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) + ;; +arm) + use_external_asm=yes + ;; +no) + ;; +*) + AC_MSG_ERROR([invalid assembly optimizations]) + ;; +esac + +# select field implementation +case $set_field in +64bit) + AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) + ;; +32bit) + AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) + ;; +*) + AC_MSG_ERROR([invalid field implementation]) + ;; +esac + +# select bignum implementation +case $set_bignum in +gmp) + AC_DEFINE(HAVE_LIBGMP, 1, [Define this symbol if libgmp is installed]) + AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation for num]) + AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation]) + AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation]) + ;; +no) + AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation]) + AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation]) + AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation]) + ;; +*) + AC_MSG_ERROR([invalid bignum implementation]) + ;; +esac + +#select scalar implementation +case $set_scalar in +64bit) + AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) + ;; +32bit) + AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) + ;; +*) + AC_MSG_ERROR([invalid scalar implementation]) + ;; +esac + +if test x"$use_tests" = x"yes"; then + SECP_OPENSSL_CHECK + if test x"$has_openssl_ec" = x"yes"; then + if test x"$enable_openssl_tests" != x"no"; then + AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) + SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" + SECP_TEST_LIBS="$CRYPTO_LIBS" + + case $host in + *mingw*) + SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" + ;; + esac + fi + else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) + fi + fi +else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) + fi +fi + +if test x"$use_jni" != x"no"; then + AX_JNI_INCLUDE_DIR + have_jni_dependencies=yes + if test x"$enable_module_ecdh" = x"no"; then + have_jni_dependencies=no + fi + if test "x$JNI_INCLUDE_DIRS" = "x"; then + have_jni_dependencies=no + fi + if test "x$have_jni_dependencies" = "xno"; then + if test x"$use_jni" = x"yes"; then + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) + fi + AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) + use_jni=no + else + use_jni=yes + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do + JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" + done + fi +fi + +if test x"$set_bignum" = x"gmp"; then + SECP_LIBS="$SECP_LIBS $GMP_LIBS" + SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" +fi + +if test x"$use_endomorphism" = x"yes"; then + AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) +fi + +if test x"$set_precomp" = x"yes"; then + AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) +fi + +if test x"$enable_module_ecdh" = x"yes"; then + AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) +fi + +if test x"$enable_module_recovery" = x"yes"; then + AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) +fi + +AC_C_BIGENDIAN() + +if test x"$use_external_asm" = x"yes"; then + AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) +fi + +AC_MSG_NOTICE([Using static precomputation: $set_precomp]) +AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) +AC_MSG_NOTICE([Using field implementation: $set_field]) +AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) +AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) +AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) +AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) +AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) +AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) +AC_MSG_NOTICE([Using jni: $use_jni]) + +if test x"$enable_experimental" = x"yes"; then + AC_MSG_NOTICE([******]) + AC_MSG_NOTICE([WARNING: experimental build]) + AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) + AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) + AC_MSG_NOTICE([******]) +else + if test x"$enable_module_ecdh" = x"yes"; then + AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) + fi + if test x"$set_asm" = x"arm"; then + AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) + fi +fi + +AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) +AC_CONFIG_FILES([Makefile libsecp256k1.pc]) +AC_SUBST(JNI_INCLUDES) +AC_SUBST(SECP_INCLUDES) +AC_SUBST(SECP_LIBS) +AC_SUBST(SECP_TEST_LIBS) +AC_SUBST(SECP_TEST_INCLUDES) +AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) +AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) +AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) +AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) +AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) +AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) +AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) +AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) + +dnl make sure nothing new is exported so that we don't break the cache +PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" +unset PKG_CONFIG_PATH +PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" + +AC_OUTPUT diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c new file mode 100644 index 0000000000..5b141a9948 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c @@ -0,0 +1,150 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "lax_der_parsing.h" + +int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + size_t rpos, rlen, spos, slen; + size_t pos = 0; + size_t lenbyte; + unsigned char tmpsig[64] = {0}; + int overflow = 0; + + /* Hack to initialize sig with a correctly-parsed but invalid signature. */ + secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + + /* Sequence tag byte */ + if (pos == inputlen || input[pos] != 0x30) { + return 0; + } + pos++; + + /* Sequence length bytes */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + pos += lenbyte; + } + + /* Integer tag byte for R */ + if (pos == inputlen || input[pos] != 0x02) { + return 0; + } + pos++; + + /* Integer length for R */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + while (lenbyte > 0 && input[pos] == 0) { + pos++; + lenbyte--; + } + if (lenbyte >= sizeof(size_t)) { + return 0; + } + rlen = 0; + while (lenbyte > 0) { + rlen = (rlen << 8) + input[pos]; + pos++; + lenbyte--; + } + } else { + rlen = lenbyte; + } + if (rlen > inputlen - pos) { + return 0; + } + rpos = pos; + pos += rlen; + + /* Integer tag byte for S */ + if (pos == inputlen || input[pos] != 0x02) { + return 0; + } + pos++; + + /* Integer length for S */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + while (lenbyte > 0 && input[pos] == 0) { + pos++; + lenbyte--; + } + if (lenbyte >= sizeof(size_t)) { + return 0; + } + slen = 0; + while (lenbyte > 0) { + slen = (slen << 8) + input[pos]; + pos++; + lenbyte--; + } + } else { + slen = lenbyte; + } + if (slen > inputlen - pos) { + return 0; + } + spos = pos; + pos += slen; + + /* Ignore leading zeroes in R */ + while (rlen > 0 && input[rpos] == 0) { + rlen--; + rpos++; + } + /* Copy R value */ + if (rlen > 32) { + overflow = 1; + } else { + memcpy(tmpsig + 32 - rlen, input + rpos, rlen); + } + + /* Ignore leading zeroes in S */ + while (slen > 0 && input[spos] == 0) { + slen--; + spos++; + } + /* Copy S value */ + if (slen > 32) { + overflow = 1; + } else { + memcpy(tmpsig + 64 - slen, input + spos, slen); + } + + if (!overflow) { + overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + } + if (overflow) { + memset(tmpsig, 0, 64); + secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + } + return 1; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h new file mode 100644 index 0000000000..6d27871a7c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h @@ -0,0 +1,91 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/**** + * Please do not link this file directly. It is not part of the libsecp256k1 + * project and does not promise any stability in its API, functionality or + * presence. Projects which use this code should instead copy this header + * and its accompanying .c file directly into their codebase. + ****/ + +/* This file defines a function that parses DER with various errors and + * violations. This is not a part of the library itself, because the allowed + * violations are chosen arbitrarily and do not follow or establish any + * standard. + * + * In many places it matters that different implementations do not only accept + * the same set of valid signatures, but also reject the same set of signatures. + * The only means to accomplish that is by strictly obeying a standard, and not + * accepting anything else. + * + * Nonetheless, sometimes there is a need for compatibility with systems that + * use signatures which do not strictly obey DER. The snippet below shows how + * certain violations are easily supported. You may need to adapt it. + * + * Do not use this for new systems. Use well-defined DER or compact signatures + * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and + * secp256k1_ecdsa_signature_parse_compact). + * + * The supported violations are: + * - All numbers are parsed as nonnegative integers, even though X.609-0207 + * section 8.3.3 specifies that integers are always encoded as two's + * complement. + * - Integers can have length 0, even though section 8.3.1 says they can't. + * - Integers with overly long padding are accepted, violation section + * 8.3.2. + * - 127-byte long length descriptors are accepted, even though section + * 8.1.3.5.c says that they are not. + * - Trailing garbage data inside or after the signature is ignored. + * - The length descriptor of the sequence is ignored. + * + * Compared to for example OpenSSL, many violations are NOT supported: + * - Using overly long tag descriptors for the sequence or integers inside, + * violating section 8.1.2.2. + * - Encoding primitive integers as constructed values, violating section + * 8.3.1. + */ + +#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ + +#include + +# ifdef __cplusplus +extern "C" { +# endif + +/** Parse a signature in "lax DER" format + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. In addition, it will accept signatures + * which violate the DER spec in various ways. Its purpose is to allow + * validation of the Bitcoin blockchain, which includes non-DER signatures + * from before the network rules were updated to enforce DER. Note that + * the set of supported violations is a strict subset of what OpenSSL will + * accept. + * + * After the call, sig will always be initialized. If parsing failed or the + * encoded numbers are out of range, signature validation with it is + * guaranteed to fail for every message and public key. + */ +int ecdsa_signature_parse_der_lax( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c new file mode 100644 index 0000000000..c2e63b4b8d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c @@ -0,0 +1,113 @@ +/********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "lax_der_privatekey_parsing.h" + +int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { + const unsigned char *end = privkey + privkeylen; + int lenb = 0; + int len = 0; + memset(out32, 0, 32); + /* sequence header */ + if (end < privkey+1 || *privkey != 0x30) { + return 0; + } + privkey++; + /* sequence length constructor */ + if (end < privkey+1 || !(*privkey & 0x80)) { + return 0; + } + lenb = *privkey & ~0x80; privkey++; + if (lenb < 1 || lenb > 2) { + return 0; + } + if (end < privkey+lenb) { + return 0; + } + /* sequence length */ + len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + privkey += lenb; + if (end < privkey+len) { + return 0; + } + /* sequence element 0: version number (=1) */ + if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { + return 0; + } + privkey += 3; + /* sequence element 1: octet string, up to 32 bytes */ + if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { + return 0; + } + memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); + if (!secp256k1_ec_seckey_verify(ctx, out32)) { + memset(out32, 0, 32); + return 0; + } + return 1; +} + +int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { + secp256k1_pubkey pubkey; + size_t pubkeylen = 0; + if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { + *privkeylen = 0; + return 0; + } + if (compressed) { + static const unsigned char begin[] = { + 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + memcpy(ptr, key32, 32); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + pubkeylen = 33; + secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } else { + static const unsigned char begin[] = { + 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, + 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, + 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + memcpy(ptr, key32, 32); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + pubkeylen = 65; + secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } + return 1; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h new file mode 100644 index 0000000000..2fd088f8ab --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h @@ -0,0 +1,90 @@ +/********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/**** + * Please do not link this file directly. It is not part of the libsecp256k1 + * project and does not promise any stability in its API, functionality or + * presence. Projects which use this code should instead copy this header + * and its accompanying .c file directly into their codebase. + ****/ + +/* This file contains code snippets that parse DER private keys with + * various errors and violations. This is not a part of the library + * itself, because the allowed violations are chosen arbitrarily and + * do not follow or establish any standard. + * + * It also contains code to serialize private keys in a compatible + * manner. + * + * These functions are meant for compatibility with applications + * that require BER encoded keys. When working with secp256k1-specific + * code, the simple 32-byte private keys normally used by the + * library are sufficient. + */ + +#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ +#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ + +#include + +# ifdef __cplusplus +extern "C" { +# endif + +/** Export a private key in DER format. + * + * Returns: 1 if the private key was valid. + * Args: ctx: pointer to a context object, initialized for signing (cannot + * be NULL) + * Out: privkey: pointer to an array for storing the private key in BER. + * Should have space for 279 bytes, and cannot be NULL. + * privkeylen: Pointer to an int where the length of the private key in + * privkey will be stored. + * In: seckey: pointer to a 32-byte secret key to export. + * compressed: 1 if the key should be exported in + * compressed format, 0 otherwise + * + * This function is purely meant for compatibility with applications that + * require BER encoded keys. When working with secp256k1-specific code, the + * simple 32-byte private keys are sufficient. + * + * Note that this function does not guarantee correct DER output. It is + * guaranteed to be parsable by secp256k1_ec_privkey_import_der + */ +SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( + const secp256k1_context* ctx, + unsigned char *privkey, + size_t *privkeylen, + const unsigned char *seckey, + int compressed +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Import a private key in DER format. + * Returns: 1 if a private key was extracted. + * Args: ctx: pointer to a context object (cannot be NULL). + * Out: seckey: pointer to a 32-byte array for storing the private key. + * (cannot be NULL). + * In: privkey: pointer to a private key in DER format (cannot be NULL). + * privkeylen: length of the DER private key pointed to be privkey. + * + * This function will accept more than just strict DER, and even allow some BER + * violations. The public key stored inside the DER-encoded private key is not + * verified for correctness, nor are the curve parameters. Use this function + * only if you know in advance it is supposed to contain a secp256k1 private + * key. + */ +SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *privkey, + size_t privkeylen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h new file mode 100644 index 0000000000..f268e309d0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h @@ -0,0 +1,577 @@ +#ifndef _SECP256K1_ +# define _SECP256K1_ + +# ifdef __cplusplus +extern "C" { +# endif + +#include + +/* These rules specify the order of arguments in API calls: + * + * 1. Context pointers go first, followed by output arguments, combined + * output/input arguments, and finally input-only arguments. + * 2. Array lengths always immediately the follow the argument whose length + * they describe, even if this violates rule 1. + * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated + * later go first. This means: signatures, public nonces, private nonces, + * messages, public keys, secret keys, tweaks. + * 4. Arguments that are not data pointers go last, from more complex to less + * complex: function pointers, algorithm names, messages, void pointers, + * counts, flags, booleans. + * 5. Opaque data pointers follow the function pointer they are to be passed to. + */ + +/** Opaque data structure that holds context information (precomputed tables etc.). + * + * The purpose of context structures is to cache large precomputed data tables + * that are expensive to construct, and also to maintain the randomization data + * for blinding. + * + * Do not create a new context object for each operation, as construction is + * far slower than all other API calls (~100 times slower than an ECDSA + * verification). + * + * A constructed context can safely be used from multiple threads + * simultaneously, but API call that take a non-const pointer to a context + * need exclusive access to it. In particular this is the case for + * secp256k1_context_destroy and secp256k1_context_randomize. + * + * Regarding randomization, either do it once at creation time (in which case + * you do not need any locking for the other calls), or use a read-write lock. + */ +typedef struct secp256k1_context_struct secp256k1_context; + +/** Opaque data structure that holds a parsed and valid public key. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_pubkey; + +/** Opaque data structured that holds a parsed ECDSA signature. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use the secp256k1_ecdsa_signature_serialize_* and + * secp256k1_ecdsa_signature_serialize_* functions. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_ecdsa_signature; + +/** A pointer to a function to deterministically generate a nonce. + * + * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. + * Out: nonce32: pointer to a 32-byte array to be filled by the function. + * In: msg32: the 32-byte message hash being verified (will not be NULL) + * key32: pointer to a 32-byte secret key (will not be NULL) + * algo16: pointer to a 16-byte array describing the signature + * algorithm (will be NULL for ECDSA for compatibility). + * data: Arbitrary data pointer that is passed through. + * attempt: how many iterations we have tried to find a nonce. + * This will almost always be 0, but different attempt values + * are required to result in a different nonce. + * + * Except for test cases, this function should compute some cryptographic hash of + * the message, the algorithm, the key and the attempt. + */ +typedef int (*secp256k1_nonce_function)( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *algo16, + void *data, + unsigned int attempt +); + +# if !defined(SECP256K1_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define SECP256K1_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(2,7) +# define SECP256K1_INLINE __inline__ +# elif (defined(_MSC_VER)) +# define SECP256K1_INLINE __inline +# else +# define SECP256K1_INLINE +# endif +# else +# define SECP256K1_INLINE inline +# endif + +#ifndef SECP256K1_API +# if defined(_WIN32) +# ifdef SECP256K1_BUILD +# define SECP256K1_API __declspec(dllexport) +# else +# define SECP256K1_API +# endif +# elif defined(__GNUC__) && defined(SECP256K1_BUILD) +# define SECP256K1_API __attribute__ ((visibility ("default"))) +# else +# define SECP256K1_API +# endif +#endif + +/**Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ +# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +# else +# define SECP256K1_WARN_UNUSED_RESULT +# endif +# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +# else +# define SECP256K1_ARG_NONNULL(_x) +# endif + +/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ +#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) +#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) +#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) +/** The higher bits contain the actual data. Do not use directly. */ +#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) +#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) + +/** Flags to pass to secp256k1_context_create. */ +#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) +#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ +#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) +#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) + +/** Create a secp256k1 context object. + * + * Returns: a newly created context object. + * In: flags: which parts of the context to initialize. + */ +SECP256K1_API secp256k1_context* secp256k1_context_create( + unsigned int flags +) SECP256K1_WARN_UNUSED_RESULT; + +/** Copies a secp256k1 context object. + * + * Returns: a newly created context object. + * Args: ctx: an existing context to copy (cannot be NULL) + */ +SECP256K1_API secp256k1_context* secp256k1_context_clone( + const secp256k1_context* ctx +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Destroy a secp256k1 context object. + * + * The context pointer may not be used afterwards. + * Args: ctx: an existing context to destroy (cannot be NULL) + */ +SECP256K1_API void secp256k1_context_destroy( + secp256k1_context* ctx +); + +/** Set a callback function to be called when an illegal argument is passed to + * an API call. It will only trigger for violations that are mentioned + * explicitly in the header. + * + * The philosophy is that these shouldn't be dealt with through a + * specific return value, as calling code should not have branches to deal with + * the case that this code itself is broken. + * + * On the other hand, during debug stage, one would want to be informed about + * such mistakes, and the default (crashing) may be inadvisable. + * When this callback is triggered, the API function called is guaranteed not + * to cause a crash, though its return value and output arguments are + * undefined. + * + * Args: ctx: an existing context object (cannot be NULL) + * In: fun: a pointer to a function to call when an illegal argument is + * passed to the API, taking a message and an opaque pointer + * (NULL restores a default handler that calls abort). + * data: the opaque pointer to pass to fun above. + */ +SECP256K1_API void secp256k1_context_set_illegal_callback( + secp256k1_context* ctx, + void (*fun)(const char* message, void* data), + const void* data +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an internal consistency check + * fails. The default is crashing. + * + * This can only trigger in case of a hardware failure, miscompilation, + * memory corruption, serious bug in the library, or other error would can + * otherwise result in undefined behaviour. It will not trigger due to mere + * incorrect usage of the API (see secp256k1_context_set_illegal_callback + * for that). After this callback returns, anything may happen, including + * crashing. + * + * Args: ctx: an existing context object (cannot be NULL) + * In: fun: a pointer to a function to call when an internal error occurs, + * taking a message and an opaque pointer (NULL restores a default + * handler that calls abort). + * data: the opaque pointer to pass to fun above. + */ +SECP256K1_API void secp256k1_context_set_error_callback( + secp256k1_context* ctx, + void (*fun)(const char* message, void* data), + const void* data +) SECP256K1_ARG_NONNULL(1); + +/** Parse a variable-length public key into the pubkey object. + * + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * Args: ctx: a secp256k1 context object. + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, its value is undefined. + * In: input: pointer to a serialized public key + * inputlen: length of the array pointed to by input + * + * This function supports parsing compressed (33 bytes, header byte 0x02 or + * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header + * byte 0x06 or 0x07) format public keys. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( + const secp256k1_context* ctx, + secp256k1_pubkey* pubkey, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a pubkey object into a serialized byte sequence. + * + * Returns: 1 always. + * Args: ctx: a secp256k1 context object. + * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * compressed==1) byte array to place the serialized key + * in. + * In/Out: outputlen: a pointer to an integer which is initially set to the + * size of output, and is overwritten with the written + * size. + * In: pubkey: a pointer to a secp256k1_pubkey containing an + * initialized public key. + * flags: SECP256K1_EC_COMPRESSED if serialization should be in + * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. + */ +SECP256K1_API int secp256k1_ec_pubkey_serialize( + const secp256k1_context* ctx, + unsigned char *output, + size_t *outputlen, + const secp256k1_pubkey* pubkey, + unsigned int flags +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Parse an ECDSA signature in compact (64 bytes) format. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input64: a pointer to the 64-byte array to parse + * + * The signature must consist of a 32-byte big endian R value, followed by a + * 32-byte big endian S value. If R or S fall outside of [0..order-1], the + * encoding is invalid. R and S with value 0 are allowed in the encoding. + * + * After the call, sig will always be initialized. If parsing failed or R or + * S are zero, the resulting sig value is guaranteed to fail validation for any + * message and public key. + */ +SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a DER ECDSA signature. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. + * + * After the call, sig will always be initialized. If parsing failed or the + * encoded numbers are out of range, signature validation with it is + * guaranteed to fail for every message and public key. + */ +SECP256K1_API int secp256k1_ecdsa_signature_parse_der( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in DER format. + * + * Returns: 1 if enough space was available to serialize, 0 otherwise + * Args: ctx: a secp256k1 context object + * Out: output: a pointer to an array to store the DER serialization + * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * should be set to the length of output. After the call + * it will be set to the length of the serialization (even + * if 0 was returned). + * In: sig: a pointer to an initialized signature object + */ +SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( + const secp256k1_context* ctx, + unsigned char *output, + size_t *outputlen, + const secp256k1_ecdsa_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Serialize an ECDSA signature in compact (64 byte) format. + * + * Returns: 1 + * Args: ctx: a secp256k1 context object + * Out: output64: a pointer to a 64-byte array to store the compact serialization + * In: sig: a pointer to an initialized signature object + * + * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. + */ +SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( + const secp256k1_context* ctx, + unsigned char *output64, + const secp256k1_ecdsa_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Verify an ECDSA signature. + * + * Returns: 1: correct signature + * 0: incorrect or unparseable signature + * Args: ctx: a secp256k1 context object, initialized for verification. + * In: sig: the signature being verified (cannot be NULL) + * msg32: the 32-byte message hash being verified (cannot be NULL) + * pubkey: pointer to an initialized public key to verify with (cannot be NULL) + * + * To avoid accepting malleable signatures, only ECDSA signatures in lower-S + * form are accepted. + * + * If you need to accept ECDSA signatures from sources that do not obey this + * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to + * validation, but be aware that doing so results in malleable signatures. + * + * For details, see the comments for that function. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( + const secp256k1_context* ctx, + const secp256k1_ecdsa_signature *sig, + const unsigned char *msg32, + const secp256k1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Convert a signature to a normalized lower-S form. + * + * Returns: 1 if sigin was not normalized, 0 if it already was. + * Args: ctx: a secp256k1 context object + * Out: sigout: a pointer to a signature to fill with the normalized form, + * or copy if the input was already normalized. (can be NULL if + * you're only interested in whether the input was already + * normalized). + * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, + * can be identical to sigout) + * + * With ECDSA a third-party can forge a second distinct signature of the same + * message, given a single initial signature, but without knowing the key. This + * is done by negating the S value modulo the order of the curve, 'flipping' + * the sign of the random point R which is not included in the signature. + * + * Forgery of the same message isn't universally problematic, but in systems + * where message malleability or uniqueness of signatures is important this can + * cause issues. This forgery can be blocked by all verifiers forcing signers + * to use a normalized form. + * + * The lower-S form reduces the size of signatures slightly on average when + * variable length encodings (such as DER) are used and is cheap to verify, + * making it a good choice. Security of always using lower-S is assured because + * anyone can trivially modify a signature after the fact to enforce this + * property anyway. + * + * The lower S value is always between 0x1 and + * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + * inclusive. + * + * No other forms of ECDSA malleability are known and none seem likely, but + * there is no formal proof that ECDSA, even with this additional restriction, + * is free of other malleability. Commonly used serialization schemes will also + * accept various non-unique encodings, so care should be taken when this + * property is required for an application. + * + * The secp256k1_ecdsa_sign function will by default create signatures in the + * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case + * signatures come from a system that cannot enforce this property, + * secp256k1_ecdsa_signature_normalize must be called before verification. + */ +SECP256K1_API int secp256k1_ecdsa_signature_normalize( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature *sigout, + const secp256k1_ecdsa_signature *sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * extra entropy. + */ +SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; + +/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ +SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; + +/** Create an ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the private key was invalid. + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) + * In: msg32: the 32-byte message hash being signed (cannot be NULL) + * seckey: pointer to a 32-byte secret key (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + * + * The created signature is always in lower-S form. See + * secp256k1_ecdsa_signature_normalize for more details. + */ +SECP256K1_API int secp256k1_ecdsa_sign( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature *sig, + const unsigned char *msg32, + const unsigned char *seckey, + secp256k1_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Verify an ECDSA secret key. + * + * Returns: 1: secret key is valid + * 0: secret key is invalid + * Args: ctx: pointer to a context object (cannot be NULL) + * In: seckey: pointer to a 32-byte secret key (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( + const secp256k1_context* ctx, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Compute the public key for a secret key. + * + * Returns: 1: secret was valid, public key stores + * 0: secret was invalid, try again + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: pubkey: pointer to the created public key (cannot be NULL) + * In: seckey: pointer to a 32-byte private key (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a private key by adding tweak to it. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or if the resulting private key + * would be invalid (only when the tweak is the complement of the + * private key). 1 otherwise. + * Args: ctx: pointer to a context object (cannot be NULL). + * In/Out: seckey: pointer to a 32-byte private key. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a public key by adding tweak times the generator to it. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or if the resulting public key + * would be invalid (only when the tweak is the complement of the + * corresponding private key). 1 otherwise. + * Args: ctx: pointer to a context object initialized for validation + * (cannot be NULL). + * In/Out: pubkey: pointer to a public key object. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a private key by multiplying it by a tweak. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. + * Args: ctx: pointer to a context object (cannot be NULL). + * In/Out: seckey: pointer to a 32-byte private key. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a public key by multiplying it by a tweak value. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. + * Args: ctx: pointer to a context object initialized for validation + * (cannot be NULL). + * In/Out: pubkey: pointer to a public key obkect. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Updates the context randomization. + * Returns: 1: randomization successfully updated + * 0: error + * Args: ctx: pointer to a context object (cannot be NULL) + * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( + secp256k1_context* ctx, + const unsigned char *seed32 +) SECP256K1_ARG_NONNULL(1); + +/** Add a number of public keys together. + * Returns: 1: the sum of the public keys is valid. + * 0: the sum of the public keys is not valid. + * Args: ctx: pointer to a context object + * Out: out: pointer to a public key object for placing the resulting public key + * (cannot be NULL) + * In: ins: pointer to array of pointers to public keys (cannot be NULL) + * n: the number of public keys to add together (must be at least 1) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( + const secp256k1_context* ctx, + secp256k1_pubkey *out, + const secp256k1_pubkey * const * ins, + size_t n +) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h new file mode 100644 index 0000000000..4b84d7a963 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h @@ -0,0 +1,31 @@ +#ifndef _SECP256K1_ECDH_ +# define _SECP256K1_ECDH_ + +# include "secp256k1.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/** Compute an EC Diffie-Hellman secret in constant time + * Returns: 1: exponentiation was successful + * 0: scalar was invalid (zero or overflow) + * Args: ctx: pointer to a context object (cannot be NULL) + * Out: result: a 32-byte array which will be populated by an ECDH + * secret computed from the point and scalar + * In: pubkey: a pointer to a secp256k1_pubkey containing an + * initialized public key + * privkey: a 32-byte scalar with which to multiply the point + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( + const secp256k1_context* ctx, + unsigned char *result, + const secp256k1_pubkey *pubkey, + const unsigned char *privkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h new file mode 100644 index 0000000000..0553797253 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h @@ -0,0 +1,110 @@ +#ifndef _SECP256K1_RECOVERY_ +# define _SECP256K1_RECOVERY_ + +# include "secp256k1.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/** Opaque data structured that holds a parsed ECDSA signature, + * supporting pubkey recovery. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 65 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage or transmission, use + * the secp256k1_ecdsa_signature_serialize_* and + * secp256k1_ecdsa_signature_parse_* functions. + * + * Furthermore, it is guaranteed that identical signatures (including their + * recoverability) will have identical representation, so they can be + * memcmp'ed. + */ +typedef struct { + unsigned char data[65]; +} secp256k1_ecdsa_recoverable_signature; + +/** Parse a compact ECDSA signature (64 bytes + recovery id). + * + * Returns: 1 when the signature could be parsed, 0 otherwise + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input64: a pointer to a 64-byte compact signature + * recid: the recovery id (0, 1, 2 or 3) + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( + const secp256k1_context* ctx, + secp256k1_ecdsa_recoverable_signature* sig, + const unsigned char *input64, + int recid +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Convert a recoverable signature into a normal signature. + * + * Returns: 1 + * Out: sig: a pointer to a normal signature (cannot be NULL). + * In: sigin: a pointer to a recoverable signature (cannot be NULL). + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const secp256k1_ecdsa_recoverable_signature* sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). + * + * Returns: 1 + * Args: ctx: a secp256k1 context object + * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) + * recid: a pointer to an integer to hold the recovery id (can be NULL). + * In: sig: a pointer to an initialized signature object (cannot be NULL) + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( + const secp256k1_context* ctx, + unsigned char *output64, + int *recid, + const secp256k1_ecdsa_recoverable_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Create a recoverable ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the private key was invalid. + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) + * In: msg32: the 32-byte message hash being signed (cannot be NULL) + * seckey: pointer to a 32-byte secret key (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + */ +SECP256K1_API int secp256k1_ecdsa_sign_recoverable( + const secp256k1_context* ctx, + secp256k1_ecdsa_recoverable_signature *sig, + const unsigned char *msg32, + const unsigned char *seckey, + secp256k1_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Recover an ECDSA public key from a signature. + * + * Returns: 1: public key successfully recovered (which guarantees a correct signature). + * 0: otherwise. + * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) + * Out: pubkey: pointer to the recovered public key (cannot be NULL) + * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) + * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const secp256k1_ecdsa_recoverable_signature *sig, + const unsigned char *msg32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in new file mode 100644 index 0000000000..a0d006f113 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsecp256k1 +Description: Optimized C library for EC operations on curve secp256k1 +URL: https://github.com/bitcoin-core/secp256k1 +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs.private: @SECP_LIBS@ +Libs: -L${libdir} -lsecp256k1 + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage new file mode 100644 index 0000000000..ab580c5b23 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage @@ -0,0 +1,322 @@ +# This code supports verifying group implementations which have branches +# or conditional statements (like cmovs), by allowing each execution path +# to independently set assumptions on input or intermediary variables. +# +# The general approach is: +# * A constraint is a tuple of two sets of of symbolic expressions: +# the first of which are required to evaluate to zero, the second of which +# are required to evaluate to nonzero. +# - A constraint is said to be conflicting if any of its nonzero expressions +# is in the ideal with basis the zero expressions (in other words: when the +# zero expressions imply that one of the nonzero expressions are zero). +# * There is a list of laws that describe the intended behaviour, including +# laws for addition and doubling. Each law is called with the symbolic point +# coordinates as arguments, and returns: +# - A constraint describing the assumptions under which it is applicable, +# called "assumeLaw" +# - A constraint describing the requirements of the law, called "require" +# * Implementations are transliterated into functions that operate as well on +# algebraic input points, and are called once per combination of branches +# exectured. Each execution returns: +# - A constraint describing the assumptions this implementation requires +# (such as Z1=1), called "assumeFormula" +# - A constraint describing the assumptions this specific branch requires, +# but which is by construction guaranteed to cover the entire space by +# merging the results from all branches, called "assumeBranch" +# - The result of the computation +# * All combinations of laws with implementation branches are tried, and: +# - If the combination of assumeLaw, assumeFormula, and assumeBranch results +# in a conflict, it means this law does not apply to this branch, and it is +# skipped. +# - For others, we try to prove the require constraints hold, assuming the +# information in assumeLaw + assumeFormula + assumeBranch, and if this does +# not succeed, we fail. +# + To prove an expression is zero, we check whether it belongs to the +# ideal with the assumed zero expressions as basis. This test is exact. +# + To prove an expression is nonzero, we check whether each of its +# factors is contained in the set of nonzero assumptions' factors. +# This test is not exact, so various combinations of original and +# reduced expressions' factors are tried. +# - If we succeed, we print out the assumptions from assumeFormula that +# weren't implied by assumeLaw already. Those from assumeBranch are skipped, +# as we assume that all constraints in it are complementary with each other. +# +# Based on the sage verification scripts used in the Explicit-Formulas Database +# by Tanja Lange and others, see http://hyperelliptic.org/EFD + +class fastfrac: + """Fractions over rings.""" + + def __init__(self,R,top,bot=1): + """Construct a fractional, given a ring, a numerator, and denominator.""" + self.R = R + if parent(top) == ZZ or parent(top) == R: + self.top = R(top) + self.bot = R(bot) + elif top.__class__ == fastfrac: + self.top = top.top + self.bot = top.bot * bot + else: + self.top = R(numerator(top)) + self.bot = R(denominator(top)) * bot + + def iszero(self,I): + """Return whether this fraction is zero given an ideal.""" + return self.top in I and self.bot not in I + + def reduce(self,assumeZero): + zero = self.R.ideal(map(numerator, assumeZero)) + return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) + + def __add__(self,other): + """Add two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top + self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __sub__(self,other): + """Subtract two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top - self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __neg__(self): + """Return the negation of a fraction.""" + return fastfrac(self.R,-self.top,self.bot) + + def __mul__(self,other): + """Multiply two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.top,self.bot * other.bot) + return NotImplemented + + def __rmul__(self,other): + """Multiply something else with a fraction.""" + return self.__mul__(other) + + def __div__(self,other): + """Divide two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top,self.bot * other) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot,self.bot * other.top) + return NotImplemented + + def __pow__(self,other): + """Compute a power of a fraction.""" + if parent(other) == ZZ: + if other < 0: + # Negative powers require flipping top and bottom + return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) + else: + return fastfrac(self.R,self.top ^ other,self.bot ^ other) + return NotImplemented + + def __str__(self): + return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" + def __repr__(self): + return "%s" % self + + def numerator(self): + return self.top + +class constraints: + """A set of constraints, consisting of zero and nonzero expressions. + + Constraints can either be used to express knowledge or a requirement. + + Both the fields zero and nonzero are maps from expressions to description + strings. The expressions that are the keys in zero are required to be zero, + and the expressions that are the keys in nonzero are required to be nonzero. + + Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in + nonzero could be multiplied into a single key. This is often much less + efficient to work with though, so we keep them separate inside the + constraints. This allows higher-level code to do fast checks on the individual + nonzero elements, or combine them if needed for stronger checks. + + We can't multiply the different zero elements, as it would suffice for one of + the factors to be zero, instead of all of them. Instead, the zero elements are + typically combined into an ideal first. + """ + + def __init__(self, **kwargs): + if 'zero' in kwargs: + self.zero = dict(kwargs['zero']) + else: + self.zero = dict() + if 'nonzero' in kwargs: + self.nonzero = dict(kwargs['nonzero']) + else: + self.nonzero = dict() + + def negate(self): + return constraints(zero=self.nonzero, nonzero=self.zero) + + def __add__(self, other): + zero = self.zero.copy() + zero.update(other.zero) + nonzero = self.nonzero.copy() + nonzero.update(other.nonzero) + return constraints(zero=zero, nonzero=nonzero) + + def __str__(self): + return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) + + def __repr__(self): + return "%s" % self + + +def conflicts(R, con): + """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" + zero = R.ideal(map(numerator, con.zero)) + if 1 in zero: + return True + # First a cheap check whether any of the individual nonzero terms conflict on + # their own. + for nonzero in con.nonzero: + if nonzero.iszero(zero): + return True + # It can be the case that entries in the nonzero set do not individually + # conflict with the zero set, but their combination does. For example, knowing + # that either x or y is zero is equivalent to having x*y in the zero set. + # Having x or y individually in the nonzero set is not a conflict, but both + # simultaneously is, so that is the right thing to check for. + if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): + return True + return False + + +def get_nonzero_set(R, assume): + """Calculate a simple set of nonzero expressions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = set() + for nz in map(numerator, assume.nonzero): + for (f,n) in nz.factor(): + nonzero.add(f) + rnz = zero.reduce(nz) + for (f,n) in rnz.factor(): + nonzero.add(f) + return nonzero + + +def prove_nonzero(R, exprs, assume): + """Check whether an expression is provably nonzero, given assumptions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = get_nonzero_set(R, assume) + expl = set() + ok = True + for expr in exprs: + if numerator(expr) in zero: + return (False, [exprs[expr]]) + allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) + for (f, n) in allexprs.factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for (f, n) in zero.reduce(numerator(allexprs)).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in numerator(expr).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in zero.reduce(numerator(expr)).factor(): + if f not in nonzero: + expl.add(exprs[expr]) + if expl: + return (False, list(expl)) + else: + return (True, None) + + +def prove_zero(R, exprs, assume): + """Check whether all of the passed expressions are provably zero, given assumptions""" + r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) + if not r: + return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) + zero = R.ideal(map(numerator, assume.zero)) + nonzero = prod(x for x in assume.nonzero) + expl = [] + for expr in exprs: + if not expr.iszero(zero): + expl.append(exprs[expr]) + if not expl: + return (True, None) + return (False, expl) + + +def describe_extra(R, assume, assumeExtra): + """Describe what assumptions are added, given existing assumptions""" + zerox = assume.zero.copy() + zerox.update(assumeExtra.zero) + zero = R.ideal(map(numerator, assume.zero)) + zeroextra = R.ideal(map(numerator, zerox)) + nonzero = get_nonzero_set(R, assume) + ret = set() + # Iterate over the extra zero expressions + for base in assumeExtra.zero: + if base not in zero: + add = [] + for (f, n) in numerator(base).factor(): + if f not in nonzero: + add += ["%s" % f] + if add: + ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) + # Iterate over the extra nonzero expressions + for nz in assumeExtra.nonzero: + nzr = zeroextra.reduce(numerator(nz)) + if nzr not in zeroextra: + for (f,n) in nzr.factor(): + if zeroextra.reduce(f) not in nonzero: + ret.add("%s != 0" % zeroextra.reduce(f)) + return ", ".join(x for x in ret) + + +def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): + """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" + assume = assumeLaw + assumeAssert + assumeBranch + + if conflicts(R, assume): + # This formula does not apply + return None + + describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) + + ok, msg = prove_zero(R, require.zero, assume) + if not ok: + return "FAIL, %s fails (assuming %s)" % (str(msg), describe) + + res, expl = prove_nonzero(R, require.nonzero, assume) + if not res: + return "FAIL, %s fails (assuming %s)" % (str(expl), describe) + + if describe != "": + return "OK (assuming %s)" % describe + else: + return "OK" + + +def concrete_verify(c): + for k in c.zero: + if k != 0: + return (False, c.zero[k]) + for k in c.nonzero: + if k == 0: + return (False, c.nonzero[k]) + return (True, None) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage new file mode 100644 index 0000000000..a97e732f7f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage @@ -0,0 +1,306 @@ +# Test libsecp256k1' group operation implementations using prover.sage + +import sys + +load("group_prover.sage") +load("weierstrass_prover.sage") + +def formula_secp256k1_gej_double_var(a): + """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" + rz = a.Z * a.Y + rz = rz * 2 + t1 = a.X^2 + t1 = t1 * 3 + t2 = t1^2 + t3 = a.Y^2 + t3 = t3 * 2 + t4 = t3^2 + t4 = t4 * 2 + t3 = t3 * a.X + rx = t3 + rx = rx * 4 + rx = -rx + rx = rx + t2 + t2 = -t2 + t3 = t3 * 6 + t3 = t3 + t2 + ry = t1 * t3 + t2 = -t4 + ry = ry + t2 + return jacobianpoint(rx, ry, rz) + +def formula_secp256k1_gej_add_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_var""" + if branch == 0: + return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z22 = b.Z^2 + z12 = a.Z^2 + u1 = a.X * z22 + u2 = b.X * z12 + s1 = a.Y * z22 + s1 = s1 * b.Z + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) + if branch == 3: + return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h2 * h + h = h * b.Z + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" + if branch == 0: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z12 = a.Z^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if (branch == 2): + r = formula_secp256k1_gej_double_var(a) + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if (branch == 3): + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_zinv_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_zinv_var""" + bzinv = b.Z^(-1) + if branch == 0: + return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) + if branch == 1: + bzinv2 = bzinv^2 + bzinv3 = bzinv2 * bzinv + rx = b.X * bzinv2 + ry = b.Y * bzinv3 + rz = 1 + return (constraints(), constraints(zero={b.Infinity : 'b_finite'}, nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz)) + azz = a.Z * bzinv + z12 = azz^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * azz + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if branch == 3: + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z + rz = rz * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge""" + zeroes = {} + nonzeroes = {} + a_infinity = False + if (branch & 4) != 0: + nonzeroes.update({a.Infinity : 'a_infinite'}) + a_infinity = True + else: + zeroes.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + rr = t^2 + m_alt = -u2 + tt = u1 * m_alt + rr = rr + tt + degenerate = (branch & 3) == 3 + if (branch & 1) != 0: + zeroes.update({m : 'm_zero'}) + else: + nonzeroes.update({m : 'm_nonzero'}) + if (branch & 2) != 0: + zeroes.update({rr : 'rr_zero'}) + else: + nonzeroes.update({rr : 'rr_nonzero'}) + rr_alt = s1 + rr_alt = rr_alt * 2 + m_alt = m_alt + u1 + if not degenerate: + rr_alt = rr + m_alt = m + n = m_alt^2 + q = n * t + n = n^2 + if degenerate: + n = m + t = rr_alt^2 + rz = a.Z * m_alt + infinity = False + if (branch & 8) != 0: + if not a_infinity: + infinity = True + zeroes.update({rz : 'r.z=0'}) + else: + nonzeroes.update({rz : 'r.z!=0'}) + rz = rz * 2 + q = -q + t = t + q + rx = t + t = t * 2 + t = t + q + t = t * rr_alt + t = t + n + ry = -t + rx = rx * 4 + ry = ry * 4 + if a_infinity: + rx = b.X + ry = b.Y + rz = 1 + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_old(branch, a, b): + """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" + a_infinity = (branch & 1) != 0 + zero = {} + nonzero = {} + if a_infinity: + nonzero.update({a.Infinity : 'a_infinite'}) + else: + zero.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + z = a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + n = m^2 + q = n * t + n = n^2 + rr = t^2 + t = u1 * u2 + t = -t + rr = rr + t + t = rr^2 + rz = m * z + infinity = False + if (branch & 2) != 0: + if not a_infinity: + infinity = True + else: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) + zero.update({rz : 'r.z=0'}) + else: + nonzero.update({rz : 'r.z!=0'}) + rz = rz * (0 if a_infinity else 2) + rx = t + q = -q + rx = rx + q + q = q * 3 + t = t * 2 + t = t + q + t = t * rr + t = t + n + ry = -t + rx = rx * (0 if a_infinity else 4) + ry = ry * (0 if a_infinity else 4) + t = b.X + t = t * (1 if a_infinity else 0) + rx = rx + t + t = b.Y + t = t * (1 if a_infinity else 0) + ry = ry + t + t = (1 if a_infinity else 0) + rz = rz + t + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) + +if __name__ == "__main__": + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) + + if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage new file mode 100644 index 0000000000..03ef2ec901 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage @@ -0,0 +1,264 @@ +# Prover implementation for Weierstrass curves of the form +# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws +# operating on affine and Jacobian coordinates, including the point at infinity +# represented by a 4th variable in coordinates. + +load("group_prover.sage") + + +class affinepoint: + def __init__(self, x, y, infinity=0): + self.x = x + self.y = y + self.infinity = infinity + def __str__(self): + return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) + + +class jacobianpoint: + def __init__(self, x, y, z, infinity=0): + self.X = x + self.Y = y + self.Z = z + self.Infinity = infinity + def __str__(self): + return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) + + +def point_at_infinity(): + return jacobianpoint(1, 1, 1, 1) + + +def negate(p): + if p.__class__ == affinepoint: + return affinepoint(p.x, -p.y) + if p.__class__ == jacobianpoint: + return jacobianpoint(p.X, -p.Y, p.Z) + assert(False) + + +def on_weierstrass_curve(A, B, p): + """Return a set of zero-expressions for an affine point to be on the curve""" + return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) + + +def tangential_to_weierstrass_curve(A, B, p12, p3): + """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" + return constraints(zero={ + (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' + }) + + +def colinear(p1, p2, p3): + """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" + return constraints(zero={ + (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', + (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', + (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' + }) + + +def good_affine_point(p): + return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) + + +def good_jacobian_point(p): + return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) + + +def good_point(p): + return constraints(nonzero={p.Z^6 : 'nonzero_X'}) + + +def finite(p, *affine_fns): + con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) + if p.Z != 0: + return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) + else: + return con + +def infinite(p): + return constraints(nonzero={p.Infinity : 'infinite_point'}) + + +def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(nonzero={pa.x - pb.x : 'different_x'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + colinear(pa, pb, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) + require = infinite(pC) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pb) + + infinite(pA) + + finite(pB)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + infinite(pB) + + finite(pA)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + infinite(pA) + + infinite(pB)) + require = infinite(pC) + return (assumeLaw, require) + + +laws_jacobian_weierstrass = { + 'add': law_jacobian_weierstrass_add, + 'double': law_jacobian_weierstrass_double, + 'add_opposite': law_jacobian_weierstrass_add_opposites, + 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, + 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, + 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab +} + + +def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" + F = Integers(p) + print "Formula %s on Z%i:" % (name, p) + points = [] + for x in xrange(0, p): + for y in xrange(0, p): + point = affinepoint(F(x), F(y)) + r, e = concrete_verify(on_weierstrass_curve(A, B, point)) + if r: + points.append(point) + + for za in xrange(1, p): + for zb in xrange(1, p): + for pa in points: + for pb in points: + for ia in xrange(2): + for ib in xrange(2): + pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) + pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) + for branch in xrange(0, branches): + assumeAssert, assumeBranch, pC = formula(branch, pA, pB) + pC.X = F(pC.X) + pC.Y = F(pC.Y) + pC.Z = F(pC.Z) + pC.Infinity = F(pC.Infinity) + r, e = concrete_verify(assumeAssert + assumeBranch) + if r: + match = False + for key in laws_jacobian_weierstrass: + assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) + r, e = concrete_verify(assumeLaw) + if r: + if match: + print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) + else: + match = True + r, e = concrete_verify(require) + if not r: + print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) + print + + +def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): + assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) + return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) + +def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" + R. = PolynomialRing(QQ,8,order='invlex') + lift = lambda x: fastfrac(R,x) + ax = lift(ax) + ay = lift(ay) + Az = lift(Az) + bx = lift(bx) + by = lift(by) + Bz = lift(Bz) + Ai = lift(Ai) + Bi = lift(Bi) + + pa = affinepoint(ax, ay, Ai) + pb = affinepoint(bx, by, Bi) + pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) + pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) + + res = {} + + for key in laws_jacobian_weierstrass: + res[key] = [] + + print ("Formula " + name + ":") + count = 0 + for branch in xrange(branches): + assumeFormula, assumeBranch, pC = formula(branch, pA, pB) + pC.X = lift(pC.X) + pC.Y = lift(pC.Y) + pC.Z = lift(pC.Z) + pC.Infinity = lift(pC.Infinity) + + for key in laws_jacobian_weierstrass: + res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) + + for key in res: + print " %s:" % key + val = res[key] + for x in val: + if x[0] is not None: + print " branch %i: %s" % (x[1], x[0]) + + print diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s new file mode 100644 index 0000000000..1e2d7ff961 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s @@ -0,0 +1,919 @@ +@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: +/********************************************************************** + * Copyright (c) 2014 Wladimir J. van der Laan * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +/* +ARM implementation of field_10x26 inner loops. + +Note: + +- To avoid unnecessary loads and make use of available registers, two + 'passes' have every time been interleaved, with the odd passes accumulating c' and d' + which will be added to c and d respectively in the the even passes + +*/ + + .syntax unified + .arch armv7-a + @ eabi attributes - see readelf -A + .eabi_attribute 8, 1 @ Tag_ARM_ISA_use = yes + .eabi_attribute 9, 0 @ Tag_Thumb_ISA_use = no + .eabi_attribute 10, 0 @ Tag_FP_arch = none + .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte + .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP + .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed + .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 + .text + + @ Field constants + .set field_R0, 0x3d10 + .set field_R1, 0x400 + .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff + + .align 2 + .global secp256k1_fe_mul_inner + .type secp256k1_fe_mul_inner, %function + @ Arguments: + @ r0 r Restrict: can overlap with a, not with b + @ r1 a + @ r2 b + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_mul_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r7,r8 scratch + r1 a (pointer) + r2 b (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + + /* A - interleaved with B */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #9*4] @ b[9] + ldr r0, [r1, #1*4] @ a[1] + umull r5, r6, r7, r8 @ d = a[0] * b[9] + ldr r14, [r2, #8*4] @ b[8] + umull r9, r10, r0, r8 @ d' = a[1] * b[9] + ldr r7, [r1, #2*4] @ a[2] + umlal r5, r6, r0, r14 @ d += a[1] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r14 @ d' += a[2] * b[8] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r8 @ d += a[2] * b[7] + ldr r14, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r8 @ d' += a[3] * b[7] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r14 @ d += a[3] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r14 @ d' += a[4] * b[6] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r8 @ d += a[4] * b[5] + ldr r14, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r8 @ d' += a[5] * b[5] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r14 @ d += a[5] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r14 @ d' += a[6] * b[4] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[3] + ldr r14, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r8 @ d' += a[7] * b[3] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[7] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r9, r10, r7, r14 @ d' += a[8] * b[2] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r8 @ d += a[8] * b[1] + ldr r14, [r2, #0*4] @ b[0] + umlal r9, r10, r0, r8 @ d' += a[9] * b[1] + ldr r7, [r1, #0*4] @ a[0] + umlal r5, r6, r0, r14 @ d += a[9] * b[0] + @ r7,r14 used in B + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 4*9] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + umull r3, r4, r7, r14 @ c = a[0] * b[0] + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C - interleaved with D */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #2*4] @ b[2] + ldr r14, [r2, #1*4] @ b[1] + umull r11, r12, r7, r8 @ c' = a[0] * b[2] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[1] * b[1] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[2] * b[0] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r14 @ d += a[2] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[3] * b[9] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r8 @ d += a[3] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[4] * b[8] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r14 @ d += a[4] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[5] * b[7] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r8 @ d += a[5] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r8 @ d' += a[6] * b[6] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r14 @ d' += a[7] * b[5] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r8 @ d' += a[8] * b[4] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r14 @ d' += a[9] * b[3] + umlal r5, r6, r0, r8 @ d += a[9] * b[2] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E - interleaved with F */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #4*4] @ b[4] + umull r11, r12, r7, r8 @ c' = a[0] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r3, r4, r7, r8 @ c += a[0] * b[3] + ldr r7, [r1, #1*4] @ a[1] + umlal r11, r12, r7, r8 @ c' += a[1] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r3, r4, r7, r8 @ c += a[1] * b[2] + ldr r7, [r1, #2*4] @ a[2] + umlal r11, r12, r7, r8 @ c' += a[2] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r3, r4, r7, r8 @ c += a[2] * b[1] + ldr r7, [r1, #3*4] @ a[3] + umlal r11, r12, r7, r8 @ c' += a[3] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r3, r4, r7, r8 @ c += a[3] * b[0] + ldr r7, [r1, #4*4] @ a[4] + umlal r11, r12, r7, r8 @ c' += a[4] * b[0] + ldr r8, [r2, #9*4] @ b[9] + umlal r5, r6, r7, r8 @ d += a[4] * b[9] + ldr r7, [r1, #5*4] @ a[5] + umull r9, r10, r7, r8 @ d' = a[5] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umlal r5, r6, r7, r8 @ d += a[5] * b[8] + ldr r7, [r1, #6*4] @ a[6] + umlal r9, r10, r7, r8 @ d' += a[6] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[7] + ldr r7, [r1, #7*4] @ a[7] + umlal r9, r10, r7, r8 @ d' += a[7] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r5, r6, r7, r8 @ d += a[7] * b[6] + ldr r7, [r1, #8*4] @ a[8] + umlal r9, r10, r7, r8 @ d' += a[8] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r5, r6, r7, r8 @ d += a[8] * b[5] + ldr r7, [r1, #9*4] @ a[9] + umlal r9, r10, r7, r8 @ d' += a[9] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r5, r6, r7, r8 @ d += a[9] * b[4] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G - interleaved with H */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #6*4] @ b[6] + ldr r14, [r2, #5*4] @ b[5] + umull r11, r12, r7, r8 @ c' = a[0] * b[6] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[1] * b[5] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[2] * b[4] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[3] * b[3] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[4] * b[2] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[5] * b[1] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[6] * b[0] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[7] * b[9] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[8] * b[8] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[9] * b[7] + umlal r5, r6, r0, r8 @ d += a[9] * b[6] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I - interleaved with J */ + ldr r8, [r2, #8*4] @ b[8] + ldr r7, [r1, #0*4] @ a[0] + ldr r14, [r2, #7*4] @ b[7] + umull r11, r12, r7, r8 @ c' = a[0] * b[8] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r11, r12, r0, r14 @ c' += a[1] * b[7] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r11, r12, r7, r8 @ c' += a[2] * b[6] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[3] * b[5] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[4] * b[4] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[5] * b[3] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[6] * b[2] + ldr r0, [r1, #7*4] @ a[7] + umlal r3, r4, r7, r14 @ c += a[6] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[7] * b[1] + ldr r7, [r1, #8*4] @ a[8] + umlal r3, r4, r0, r8 @ c += a[7] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[8] * b[0] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[9] * b[9] + umlal r5, r6, r0, r8 @ d += a[9] * b[8] + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner + + .align 2 + .global secp256k1_fe_sqr_inner + .type secp256k1_fe_sqr_inner, %function + @ Arguments: + @ r0 r Can overlap with a + @ r1 a + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_sqr_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r2,r7,r8 scratch + r1 a (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + /* A interleaved with B */ + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r7, [r1, #0*4] @ a[0] + mov r0, r0, asl #1 + ldr r14, [r1, #9*4] @ a[9] + umull r3, r4, r7, r7 @ c = a[0] * a[0] + ldr r8, [r1, #8*4] @ a[8] + mov r7, r7, asl #1 + umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] + ldr r7, [r1, #2*4] @ a[2]*2 + umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #3*4] @ a[3]*2 + umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] + ldr r14, [r1, #5*4] @ a[5] + mov r7, r7, asl #1 + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] + umlal r9, r10, r14, r14 @ d' += a[5] * a[5] + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 9*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C interleaved with D */ + ldr r0, [r1, #0*4] @ a[0]*2 + ldr r14, [r1, #1*4] @ a[1] + mov r0, r0, asl #1 + ldr r8, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] + mov r7, r8, asl #1 @ a[2]*2 + umull r11, r12, r14, r14 @ c' = a[1] * a[1] + ldr r14, [r1, #9*4] @ a[9] + umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] + ldr r0, [r1, #3*4] @ a[3]*2 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] + umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] + umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] + umlal r9, r10, r8, r8 @ d' += a[6] * a[6] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E interleaved with F */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r14, [r1, #2*4] @ a[2] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + ldr r2, [r1, #4*4] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] + mov r2, r2, asl #1 @ a[4]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] + ldr r8, [r1, #9*4] @ a[9] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r11, r12, r14, r14 @ c' += a[2] * a[2] + ldr r14, [r1, #8*4] @ a[8] + mov r0, r0, asl #1 + umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] + ldr r7, [r1, #6*4] @ a[6]*2 + umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] + umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] + umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] + umlal r9, r10, r8, r8 @ d' += a[7] * a[7] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G interleaved with H */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #5*4] @ a[5] + ldr r2, [r1, #6*4] @ a[6] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] + mov r0, r2, asl #1 @ a[6]*2 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] + ldr r14, [r1, #9*4] @ a[9] + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] + ldr r7, [r1, #7*4] @ a[7]*2 + umlal r11, r12, r8, r8 @ c' += a[3] * a[3] + mov r7, r7, asl #1 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] + umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] + umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] + umlal r9, r10, r8, r8 @ d' += a[8] * a[8] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I interleaved with J */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + ldr r2, [r1, #8*4] @ a[8] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] + ldr r14, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] + ldr r8, [r1, #5*4] @ a[5] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] + ldr r0, [r1, #3*4] @ a[3]*2 + mov r7, r7, asl #1 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] + mov r2, r2, asl #1 @ a[8]*2 + umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] + umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] + umlal r11, r12, r14, r14 @ c' += a[4] * a[4] + ldr r8, [r1, #9*4] @ a[9] + umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] + @ r8 will be used in J + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + umlal r5, r6, r8, r8 @ d += a[9] * a[9] + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h new file mode 100644 index 0000000000..c4c16eb7ca --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h @@ -0,0 +1,32 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_BASIC_CONFIG_ +#define _SECP256K1_BASIC_CONFIG_ + +#ifdef USE_BASIC_CONFIG + +#undef USE_ASM_X86_64 +#undef USE_ENDOMORPHISM +#undef USE_FIELD_10X26 +#undef USE_FIELD_5X52 +#undef USE_FIELD_INV_BUILTIN +#undef USE_FIELD_INV_NUM +#undef USE_NUM_GMP +#undef USE_NUM_NONE +#undef USE_SCALAR_4X64 +#undef USE_SCALAR_8X32 +#undef USE_SCALAR_INV_BUILTIN +#undef USE_SCALAR_INV_NUM + +#define USE_NUM_NONE 1 +#define USE_FIELD_INV_BUILTIN 1 +#define USE_SCALAR_INV_BUILTIN 1 +#define USE_FIELD_10X26 1 +#define USE_SCALAR_8X32 1 + +#endif // USE_BASIC_CONFIG +#endif // _SECP256K1_BASIC_CONFIG_ diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h new file mode 100644 index 0000000000..3a71b4aafa --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h @@ -0,0 +1,66 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_BENCH_H_ +#define _SECP256K1_BENCH_H_ + +#include +#include +#include "sys/time.h" + +static double gettimedouble(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec * 0.000001 + tv.tv_sec; +} + +void print_number(double x) { + double y = x; + int c = 0; + if (y < 0.0) { + y = -y; + } + while (y < 100.0) { + y *= 10.0; + c++; + } + printf("%.*f", c, x); +} + +void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { + int i; + double min = HUGE_VAL; + double sum = 0.0; + double max = 0.0; + for (i = 0; i < count; i++) { + double begin, total; + if (setup != NULL) { + setup(data); + } + begin = gettimedouble(); + benchmark(data); + total = gettimedouble() - begin; + if (teardown != NULL) { + teardown(data); + } + if (total < min) { + min = total; + } + if (total > max) { + max = total; + } + sum += total; + } + printf("%s: min ", name); + print_number(min * 1000000.0 / iter); + printf("us / avg "); + print_number((sum / count) * 1000000.0 / iter); + printf("us / max "); + print_number(max * 1000000.0 / iter); + printf("us\n"); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c new file mode 100644 index 0000000000..cde5e2dbb4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c @@ -0,0 +1,54 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include + +#include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context *ctx; + secp256k1_pubkey point; + unsigned char scalar[32]; +} bench_ecdh_t; + +static void bench_ecdh_setup(void* arg) { + int i; + bench_ecdh_t *data = (bench_ecdh_t*)arg; + const unsigned char point[] = { + 0x03, + 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, + 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, + 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, + 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f + }; + + /* create a context with no capabilities */ + data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); + for (i = 0; i < 32; i++) { + data->scalar[i] = i + 1; + } + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); +} + +static void bench_ecdh(void* arg) { + int i; + unsigned char res[32]; + bench_ecdh_t *data = (bench_ecdh_t*)arg; + + for (i = 0; i < 20000; i++) { + CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); + } +} + +int main(void) { + bench_ecdh_t data; + + run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c new file mode 100644 index 0000000000..0809f77bda --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c @@ -0,0 +1,382 @@ +/********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include + +#include "include/secp256k1.h" + +#include "util.h" +#include "hash_impl.h" +#include "num_impl.h" +#include "field_impl.h" +#include "group_impl.h" +#include "scalar_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_impl.h" +#include "bench.h" +#include "secp256k1.c" + +typedef struct { + secp256k1_scalar scalar_x, scalar_y; + secp256k1_fe fe_x, fe_y; + secp256k1_ge ge_x, ge_y; + secp256k1_gej gej_x, gej_y; + unsigned char data[64]; + int wnaf[256]; +} bench_inv_t; + +void bench_setup(void* arg) { + bench_inv_t *data = (bench_inv_t*)arg; + + static const unsigned char init_x[32] = { + 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, + 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, + 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, + 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 + }; + + static const unsigned char init_y[32] = { + 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, + 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, + 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, + 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 + }; + + secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); + secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); + secp256k1_fe_set_b32(&data->fe_x, init_x); + secp256k1_fe_set_b32(&data->fe_y, init_y); + CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); + CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); + secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); + secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); + memcpy(data->data, init_x, 32); + memcpy(data->data + 32, init_y, 32); +} + +void bench_scalar_add(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_scalar_negate(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); + } +} + +void bench_scalar_sqr(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); + } +} + +void bench_scalar_mul(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +#ifdef USE_ENDOMORPHISM +void bench_scalar_split(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_scalar l, r; + secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} +#endif + +void bench_scalar_inverse(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000; i++) { + secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_scalar_inverse_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000; i++) { + secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_field_normalize(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_fe_normalize(&data->fe_x); + } +} + +void bench_field_normalize_weak(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_fe_normalize_weak(&data->fe_x); + } +} + +void bench_field_mul(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); + } +} + +void bench_field_sqr(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_fe_sqr(&data->fe_x, &data->fe_x); + } +} + +void bench_field_inverse(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_inv(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_field_inverse_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_field_sqrt(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_group_double_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); + } +} + +void bench_group_add_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); + } +} + +void bench_group_add_affine(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); + } +} + +void bench_group_add_affine_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); + } +} + +void bench_group_jacobi_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_gej_has_quad_y_var(&data->gej_x); + } +} + +void bench_ecmult_wnaf(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_wnaf_const(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + + +void bench_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_sha256_t sha; + + for (i = 0; i < 20000; i++) { + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, data->data, 32); + secp256k1_sha256_finalize(&sha, data->data); + } +} + +void bench_hmac_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_hmac_sha256_t hmac; + + for (i = 0; i < 20000; i++) { + secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); + secp256k1_hmac_sha256_write(&hmac, data->data, 32); + secp256k1_hmac_sha256_finalize(&hmac, data->data); + } +} + +void bench_rfc6979_hmac_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_rfc6979_hmac_sha256_t rng; + + for (i = 0; i < 20000; i++) { + secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); + secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + } +} + +void bench_context_verify(void* arg) { + int i; + (void)arg; + for (i = 0; i < 20; i++) { + secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); + } +} + +void bench_context_sign(void* arg) { + int i; + (void)arg; + for (i = 0; i < 200; i++) { + secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); + } +} + +#ifndef USE_NUM_NONE +void bench_num_jacobi(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_num nx, norder; + + secp256k1_scalar_get_num(&nx, &data->scalar_x); + secp256k1_scalar_order_get_num(&norder); + secp256k1_scalar_get_num(&norder, &data->scalar_y); + + for (i = 0; i < 200000; i++) { + secp256k1_num_jacobi(&nx, &norder); + } +} +#endif + +int have_flag(int argc, char** argv, char *flag) { + char** argm = argv + argc; + argv++; + if (argv == argm) { + return 1; + } + while (argv != NULL && argv != argm) { + if (strcmp(*argv, flag) == 0) { + return 1; + } + argv++; + } + return 0; +} + +int main(int argc, char **argv) { + bench_inv_t data; + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000); +#ifdef USE_ENDOMORPHISM + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000); +#endif + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); + + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); + if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); + +#ifndef USE_NUM_NONE + if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); +#endif + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c new file mode 100644 index 0000000000..6489378cc6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c @@ -0,0 +1,60 @@ +/********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" +#include "include/secp256k1_recovery.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + unsigned char sig[64]; +} bench_recover_t; + +void bench_recover(void* arg) { + int i; + bench_recover_t *data = (bench_recover_t*)arg; + secp256k1_pubkey pubkey; + unsigned char pubkeyc[33]; + + for (i = 0; i < 20000; i++) { + int j; + size_t pubkeylen = 33; + secp256k1_ecdsa_recoverable_signature sig; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); + for (j = 0; j < 32; j++) { + data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ + data->msg[j] = data->sig[j]; /* Move former R to message. */ + data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ + } + } +} + +void bench_recover_setup(void* arg) { + int i; + bench_recover_t *data = (bench_recover_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = 1 + i; + } + for (i = 0; i < 64; i++) { + data->sig[i] = 65 + i; + } +} + +int main(void) { + bench_recover_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + + run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c new file mode 100644 index 0000000000..5f137dda23 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c @@ -0,0 +1,73 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "include/secp256k1.h" +#include "include/secp256k1_schnorr.h" +#include "util.h" +#include "bench.h" + +typedef struct { + unsigned char key[32]; + unsigned char sig[64]; + unsigned char pubkey[33]; + size_t pubkeylen; +} benchmark_schnorr_sig_t; + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + benchmark_schnorr_sig_t sigs[64]; + int numsigs; +} benchmark_schnorr_verify_t; + +static void benchmark_schnorr_init(void* arg) { + int i, k; + benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = 1 + i; + } + for (k = 0; k < data->numsigs; k++) { + secp256k1_pubkey pubkey; + for (i = 0; i < 32; i++) { + data->sigs[k].key[i] = 33 + i + k; + } + secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); + data->sigs[k].pubkeylen = 33; + CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); + } +} + +static void benchmark_schnorr_verify(void* arg) { + int i; + benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; + + for (i = 0; i < 20000 / data->numsigs; i++) { + secp256k1_pubkey pubkey; + data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); + CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); + data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); + } +} + + + +int main(void) { + benchmark_schnorr_verify_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + data.numsigs = 1; + run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c new file mode 100644 index 0000000000..ed7224d757 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c @@ -0,0 +1,56 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context* ctx; + unsigned char msg[32]; + unsigned char key[32]; +} bench_sign_t; + +static void bench_sign_setup(void* arg) { + int i; + bench_sign_t *data = (bench_sign_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = i + 1; + } + for (i = 0; i < 32; i++) { + data->key[i] = i + 65; + } +} + +static void bench_sign(void* arg) { + int i; + bench_sign_t *data = (bench_sign_t*)arg; + + unsigned char sig[74]; + for (i = 0; i < 20000; i++) { + size_t siglen = 74; + int j; + secp256k1_ecdsa_signature signature; + CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); + for (j = 0; j < 32; j++) { + data->msg[j] = sig[j]; + data->key[j] = sig[j + 32]; + } + } +} + +int main(void) { + bench_sign_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + + run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c new file mode 100644 index 0000000000..418defa0aa --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c @@ -0,0 +1,112 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "include/secp256k1.h" +#include "util.h" +#include "bench.h" + +#ifdef ENABLE_OPENSSL_TESTS +#include +#include +#include +#endif + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + unsigned char key[32]; + unsigned char sig[72]; + size_t siglen; + unsigned char pubkey[33]; + size_t pubkeylen; +#ifdef ENABLE_OPENSSL_TESTS + EC_GROUP* ec_group; +#endif +} benchmark_verify_t; + +static void benchmark_verify(void* arg) { + int i; + benchmark_verify_t* data = (benchmark_verify_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); + CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + } +} + +#ifdef ENABLE_OPENSSL_TESTS +static void benchmark_verify_openssl(void* arg) { + int i; + benchmark_verify_t* data = (benchmark_verify_t*)arg; + + for (i = 0; i < 20000; i++) { + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + { + EC_KEY *pkey = EC_KEY_new(); + const unsigned char *pubkey = &data->pubkey[0]; + int result; + + CHECK(pkey != NULL); + result = EC_KEY_set_group(pkey, data->ec_group); + CHECK(result); + result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; + CHECK(result); + result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); + CHECK(result); + EC_KEY_free(pkey); + } + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + } +} +#endif + +int main(void) { + int i; + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + benchmark_verify_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + for (i = 0; i < 32; i++) { + data.msg[i] = 1 + i; + } + for (i = 0; i < 32; i++) { + data.key[i] = 33 + i; + } + data.siglen = 72; + CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); + CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); + data.pubkeylen = 33; + CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + + run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); +#ifdef ENABLE_OPENSSL_TESTS + data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); + run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); + EC_GROUP_free(data.ec_group); +#endif + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h new file mode 100644 index 0000000000..54ae101b92 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECDSA_ +#define _SECP256K1_ECDSA_ + +#include + +#include "scalar.h" +#include "group.h" +#include "ecmult.h" + +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); +static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h new file mode 100644 index 0000000000..453bb11880 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h @@ -0,0 +1,315 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + + +#ifndef _SECP256K1_ECDSA_IMPL_H_ +#define _SECP256K1_ECDSA_IMPL_H_ + +#include "scalar.h" +#include "field.h" +#include "group.h" +#include "ecmult.h" +#include "ecmult_gen.h" +#include "ecdsa.h" + +/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 + * sage: for t in xrange(1023, -1, -1): + * .. p = 2**256 - 2**32 - t + * .. if p.is_prime(): + * .. print '%x'%p + * .. break + * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' + * sage: a = 0 + * sage: b = 7 + * sage: F = FiniteField (p) + * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) + * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' + */ +static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL +); + +/** Difference between field and order, values 'p' and 'n' values defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + * sage: a = 0 + * sage: b = 7 + * sage: F = FiniteField (p) + * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) + * '14551231950b75fc4402da1722fc9baee' + */ +static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( + 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL +); + +static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { + int lenleft, b1; + size_t ret = 0; + if (*sigp >= sigend) { + return -1; + } + b1 = *((*sigp)++); + if (b1 == 0xFF) { + /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ + return -1; + } + if ((b1 & 0x80) == 0) { + /* X.690-0207 8.1.3.4 short form length octets */ + return b1; + } + if (b1 == 0x80) { + /* Indefinite length is not allowed in DER. */ + return -1; + } + /* X.690-207 8.1.3.5 long form length octets */ + lenleft = b1 & 0x7F; + if (lenleft > sigend - *sigp) { + return -1; + } + if (**sigp == 0) { + /* Not the shortest possible length encoding. */ + return -1; + } + if ((size_t)lenleft > sizeof(size_t)) { + /* The resulting length would exceed the range of a size_t, so + * certainly longer than the passed array size. + */ + return -1; + } + while (lenleft > 0) { + if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { + } + ret = (ret << 8) | **sigp; + if (ret + lenleft > (size_t)(sigend - *sigp)) { + /* Result exceeds the length of the passed array. */ + return -1; + } + (*sigp)++; + lenleft--; + } + if (ret < 128) { + /* Not the shortest possible length encoding. */ + return -1; + } + return ret; +} + +static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { + int overflow = 0; + unsigned char ra[32] = {0}; + int rlen; + + if (*sig == sigend || **sig != 0x02) { + /* Not a primitive integer (X.690-0207 8.3.1). */ + return 0; + } + (*sig)++; + rlen = secp256k1_der_read_len(sig, sigend); + if (rlen <= 0 || (*sig) + rlen > sigend) { + /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ + return 0; + } + if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { + /* Excessive 0x00 padding. */ + return 0; + } + if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { + /* Excessive 0xFF padding. */ + return 0; + } + if ((**sig & 0x80) == 0x80) { + /* Negative. */ + overflow = 1; + } + while (rlen > 0 && **sig == 0) { + /* Skip leading zero bytes */ + rlen--; + (*sig)++; + } + if (rlen > 32) { + overflow = 1; + } + if (!overflow) { + memcpy(ra + 32 - rlen, *sig, rlen); + secp256k1_scalar_set_b32(r, ra, &overflow); + } + if (overflow) { + secp256k1_scalar_set_int(r, 0); + } + (*sig) += rlen; + return 1; +} + +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { + const unsigned char *sigend = sig + size; + int rlen; + if (sig == sigend || *(sig++) != 0x30) { + /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ + return 0; + } + rlen = secp256k1_der_read_len(&sig, sigend); + if (rlen < 0 || sig + rlen > sigend) { + /* Tuple exceeds bounds */ + return 0; + } + if (sig + rlen != sigend) { + /* Garbage after tuple. */ + return 0; + } + + if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { + return 0; + } + if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { + return 0; + } + + if (sig != sigend) { + /* Trailing garbage inside tuple. */ + return 0; + } + + return 1; +} + +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { + unsigned char r[33] = {0}, s[33] = {0}; + unsigned char *rp = r, *sp = s; + size_t lenR = 33, lenS = 33; + secp256k1_scalar_get_b32(&r[1], ar); + secp256k1_scalar_get_b32(&s[1], as); + while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } + while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } + if (*size < 6+lenS+lenR) { + *size = 6 + lenS + lenR; + return 0; + } + *size = 6 + lenS + lenR; + sig[0] = 0x30; + sig[1] = 4 + lenS + lenR; + sig[2] = 0x02; + sig[3] = lenR; + memcpy(sig+4, rp, lenR); + sig[4+lenR] = 0x02; + sig[5+lenR] = lenS; + memcpy(sig+lenR+6, sp, lenS); + return 1; +} + +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { + unsigned char c[32]; + secp256k1_scalar sn, u1, u2; +#if !defined(EXHAUSTIVE_TEST_ORDER) + secp256k1_fe xr; +#endif + secp256k1_gej pubkeyj; + secp256k1_gej pr; + + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { + return 0; + } + + secp256k1_scalar_inverse_var(&sn, sigs); + secp256k1_scalar_mul(&u1, &sn, message); + secp256k1_scalar_mul(&u2, &sn, sigr); + secp256k1_gej_set_ge(&pubkeyj, pubkey); + secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); + if (secp256k1_gej_is_infinity(&pr)) { + return 0; + } + +#if defined(EXHAUSTIVE_TEST_ORDER) +{ + secp256k1_scalar computed_r; + secp256k1_ge pr_ge; + secp256k1_ge_set_gej(&pr_ge, &pr); + secp256k1_fe_normalize(&pr_ge.x); + + secp256k1_fe_get_b32(c, &pr_ge.x); + secp256k1_scalar_set_b32(&computed_r, c, NULL); + return secp256k1_scalar_eq(sigr, &computed_r); +} +#else + secp256k1_scalar_get_b32(c, sigr); + secp256k1_fe_set_b32(&xr, c); + + /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) + * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), + * compute the remainder modulo n, and compare it to xr. However: + * + * xr == X(pr) mod n + * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) + * [Since 2 * n > p, h can only be 0 or 1] + * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) + * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] + * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) + * [Multiplying both sides of the equations by pr.z^2 mod p] + * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) + * + * Thus, we can avoid the inversion, but we have to check both cases separately. + * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. + */ + if (secp256k1_gej_eq_x_var(&xr, &pr)) { + /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ + return 1; + } + if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { + /* xr + n >= p, so we can skip testing the second case. */ + return 0; + } + secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); + if (secp256k1_gej_eq_x_var(&xr, &pr)) { + /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ + return 1; + } + return 0; +#endif +} + +static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { + unsigned char b[32]; + secp256k1_gej rp; + secp256k1_ge r; + secp256k1_scalar n; + int overflow = 0; + + secp256k1_ecmult_gen(ctx, &rp, nonce); + secp256k1_ge_set_gej(&r, &rp); + secp256k1_fe_normalize(&r.x); + secp256k1_fe_normalize(&r.y); + secp256k1_fe_get_b32(b, &r.x); + secp256k1_scalar_set_b32(sigr, b, &overflow); + /* These two conditions should be checked before calling */ + VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); + VERIFY_CHECK(overflow == 0); + + if (recid) { + /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log + * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. + */ + *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); + } + secp256k1_scalar_mul(&n, sigr, seckey); + secp256k1_scalar_add(&n, &n, message); + secp256k1_scalar_inverse(sigs, nonce); + secp256k1_scalar_mul(sigs, sigs, &n); + secp256k1_scalar_clear(&n); + secp256k1_gej_clear(&rp); + secp256k1_ge_clear(&r); + if (secp256k1_scalar_is_zero(sigs)) { + return 0; + } + if (secp256k1_scalar_is_high(sigs)) { + secp256k1_scalar_negate(sigs, sigs); + if (recid) { + *recid ^= 1; + } + } + return 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h new file mode 100644 index 0000000000..42739a3bea --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h @@ -0,0 +1,25 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_ +#define _SECP256K1_ECKEY_ + +#include + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" +#include "ecmult_gen.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h new file mode 100644 index 0000000000..ce38071ac2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h @@ -0,0 +1,99 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_IMPL_H_ +#define _SECP256K1_ECKEY_IMPL_H_ + +#include "eckey.h" + +#include "scalar.h" +#include "field.h" +#include "group.h" +#include "ecmult_gen.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + secp256k1_fe x; + return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); + } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { + secp256k1_fe x, y; + if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { + return 0; + } + secp256k1_ge_set_xy(elem, &x, &y); + if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { + return 0; + } + return secp256k1_ge_is_valid_var(elem); + } else { + return 0; + } +} + +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { + if (secp256k1_ge_is_infinity(elem)) { + return 0; + } + secp256k1_fe_normalize_var(&elem->x); + secp256k1_fe_normalize_var(&elem->y); + secp256k1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + } else { + *size = 65; + pub[0] = 0x04; + secp256k1_fe_get_b32(&pub[33], &elem->y); + } + return 1; +} + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { + secp256k1_scalar_add(key, key, tweak); + if (secp256k1_scalar_is_zero(key)) { + return 0; + } + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { + secp256k1_gej pt; + secp256k1_scalar one; + secp256k1_gej_set_ge(&pt, key); + secp256k1_scalar_set_int(&one, 1); + secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); + + if (secp256k1_gej_is_infinity(&pt)) { + return 0; + } + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { + if (secp256k1_scalar_is_zero(tweak)) { + return 0; + } + + secp256k1_scalar_mul(key, key, tweak); + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { + secp256k1_scalar zero; + secp256k1_gej pt; + if (secp256k1_scalar_is_zero(tweak)) { + return 0; + } + + secp256k1_scalar_set_int(&zero, 0); + secp256k1_gej_set_ge(&pt, key); + secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h new file mode 100644 index 0000000000..20484134f5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h @@ -0,0 +1,31 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_ +#define _SECP256K1_ECMULT_ + +#include "num.h" +#include "group.h" + +typedef struct { + /* For accelerating the computation of a*P + b*G: */ + secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ +#endif +} secp256k1_ecmult_context; + +static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); +static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); +static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, + const secp256k1_ecmult_context *src, const secp256k1_callback *cb); +static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); +static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); + +/** Double multiply: R = na*A + ng*G */ +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h new file mode 100644 index 0000000000..2b0097655c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h @@ -0,0 +1,15 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_CONST_ +#define _SECP256K1_ECMULT_CONST_ + +#include "scalar.h" +#include "group.h" + +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h new file mode 100644 index 0000000000..0db314c48e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h @@ -0,0 +1,239 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_CONST_IMPL_ +#define _SECP256K1_ECMULT_CONST_IMPL_ + +#include "scalar.h" +#include "group.h" +#include "ecmult_const.h" +#include "ecmult_impl.h" + +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) + +/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ +#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ + int m; \ + int abs_n = (n) * (((n) > 0) * 2 - 1); \ + int idx_n = abs_n / 2; \ + secp256k1_fe neg_y; \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ + VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ + for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ + /* This loop is used to avoid secret data in array indices. See + * the comment in ecmult_gen_impl.h for rationale. */ \ + secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ + secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ + } \ + (r)->infinity = 0; \ + secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ + secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ +} while(0) + + +/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) + * with the following guarantees: + * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) + * - each wnaf[i] is nonzero + * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w + * + * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar + * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) + * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 + * + * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 + */ +static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { + int global_sign; + int skew = 0; + int word = 0; + + /* 1 2 3 */ + int u_last; + int u; + + int flip; + int bit; + secp256k1_scalar neg_s; + int not_neg_one; + /* Note that we cannot handle even numbers by negating them to be odd, as is + * done in other implementations, since if our scalars were specified to have + * width < 256 for performance reasons, their negations would have width 256 + * and we'd lose any performance benefit. Instead, we use a technique from + * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) + * or 2 (for odd) to the number we are encoding, returning a skew value indicating + * this, and having the caller compensate after doing the multiplication. */ + + /* Negative numbers will be negated to keep their bit representation below the maximum width */ + flip = secp256k1_scalar_is_high(&s); + /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ + bit = flip ^ !secp256k1_scalar_is_even(&s); + /* We check for negative one, since adding 2 to it will cause an overflow */ + secp256k1_scalar_negate(&neg_s, &s); + not_neg_one = !secp256k1_scalar_is_one(&neg_s); + secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); + /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects + * that we added two to it and flipped it. In fact for -1 these operations are + * identical. We only flipped, but since skewing is required (in the sense that + * the skew must be 1 or 2, never zero) and flipping is not, we need to change + * our flags to claim that we only skewed. */ + global_sign = secp256k1_scalar_cond_negate(&s, flip); + global_sign *= not_neg_one * 2 - 1; + skew = 1 << bit; + + /* 4 */ + u_last = secp256k1_scalar_shr_int(&s, w); + while (word * w < WNAF_BITS) { + int sign; + int even; + + /* 4.1 4.4 */ + u = secp256k1_scalar_shr_int(&s, w); + /* 4.2 */ + even = ((u & 1) == 0); + sign = 2 * (u_last > 0) - 1; + u += sign * even; + u_last -= sign * even * (1 << w); + + /* 4.3, adapted for global sign change */ + wnaf[word++] = u_last * global_sign; + + u_last = u; + } + wnaf[word] = u * global_sign; + + VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); + VERIFY_CHECK(word == WNAF_SIZE(w)); + return skew; +} + + +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge tmpa; + secp256k1_fe Z; + + int skew_1; + int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; +#ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; + int skew_lam; + secp256k1_scalar q_1, q_lam; +#endif + + int i; + secp256k1_scalar sc = *scalar; + + /* build wnaf representation for q. */ +#ifdef USE_ENDOMORPHISM + /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); + skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); + skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); +#else + skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); +#endif + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + */ + secp256k1_gej_set_ge(r, a); + secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_fe_normalize_weak(&pre_a[i].y); + } +#ifdef USE_ENDOMORPHISM + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } +#endif + + /* first loop iteration (separated out so we can directly set r, rather + * than having it start at infinity, get doubled several times, then have + * its new value added to it) */ + i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); + secp256k1_gej_set_ge(r, &tmpa); +#ifdef USE_ENDOMORPHISM + i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); + secp256k1_gej_add_ge(r, r, &tmpa); +#endif + /* remaining loop iterations */ + for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { + int n; + int j; + for (j = 0; j < WINDOW_A - 1; ++j) { + secp256k1_gej_double_nonzero(r, r, NULL); + } + + n = wnaf_1[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + VERIFY_CHECK(n != 0); + secp256k1_gej_add_ge(r, r, &tmpa); +#ifdef USE_ENDOMORPHISM + n = wnaf_lam[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + VERIFY_CHECK(n != 0); + secp256k1_gej_add_ge(r, r, &tmpa); +#endif + } + + secp256k1_fe_mul(&r->z, &r->z, &Z); + + { + /* Correct for wNAF skew */ + secp256k1_ge correction = *a; + secp256k1_ge_storage correction_1_stor; +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage correction_lam_stor; +#endif + secp256k1_ge_storage a2_stor; + secp256k1_gej tmpj; + secp256k1_gej_set_ge(&tmpj, &correction); + secp256k1_gej_double_var(&tmpj, &tmpj, NULL); + secp256k1_ge_set_gej(&correction, &tmpj); + secp256k1_ge_to_storage(&correction_1_stor, a); +#ifdef USE_ENDOMORPHISM + secp256k1_ge_to_storage(&correction_lam_stor, a); +#endif + secp256k1_ge_to_storage(&a2_stor, &correction); + + /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ + secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); +#endif + + /* Apply the correction */ + secp256k1_ge_from_storage(&correction, &correction_1_stor); + secp256k1_ge_neg(&correction, &correction); + secp256k1_gej_add_ge(r, r, &correction); + +#ifdef USE_ENDOMORPHISM + secp256k1_ge_from_storage(&correction, &correction_lam_stor); + secp256k1_ge_neg(&correction, &correction); + secp256k1_ge_mul_lambda(&correction, &correction); + secp256k1_gej_add_ge(r, r, &correction); +#endif + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h new file mode 100644 index 0000000000..eb2cc9ead6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_ +#define _SECP256K1_ECMULT_GEN_ + +#include "scalar.h" +#include "group.h" + +typedef struct { + /* For accelerating the computation of a*G: + * To harden against timing attacks, use the following mechanism: + * * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. + * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: + * * U_i = U * 2^i (for i=0..62) + * * U_i = U * (1-2^63) (for i=63) + * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. + * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is + * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). + * None of the resulting prec group elements have a known scalar, and neither do any of + * the intermediate sums while computing a*G. + */ + secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ + secp256k1_scalar blind; + secp256k1_gej initial; +} secp256k1_ecmult_gen_context; + +static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); +static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, + const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); +static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); +static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); + +/** Multiply with the generator: R = a*G */ +static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); + +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h new file mode 100644 index 0000000000..35f2546077 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h @@ -0,0 +1,210 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ +#define _SECP256K1_ECMULT_GEN_IMPL_H_ + +#include "scalar.h" +#include "group.h" +#include "ecmult_gen.h" +#include "hash_impl.h" +#ifdef USE_ECMULT_STATIC_PRECOMPUTATION +#include "ecmult_static_context.h" +#endif +static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { + ctx->prec = NULL; +} + +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + secp256k1_ge prec[1024]; + secp256k1_gej gj; + secp256k1_gej nums_gej; + int i, j; +#endif + + if (ctx->prec != NULL) { + return; + } +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); + + /* get the generator */ + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + + /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ + { + static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; + secp256k1_fe nums_x; + secp256k1_ge nums_ge; + int r; + r = secp256k1_fe_set_b32(&nums_x, nums_b32); + (void)r; + VERIFY_CHECK(r); + r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); + (void)r; + VERIFY_CHECK(r); + secp256k1_gej_set_ge(&nums_gej, &nums_ge); + /* Add G to make the bits in x uniformly distributed. */ + secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); + } + + /* compute prec. */ + { + secp256k1_gej precj[1024]; /* Jacobian versions of prec. */ + secp256k1_gej gbase; + secp256k1_gej numsbase; + gbase = gj; /* 16^j * G */ + numsbase = nums_gej; /* 2^j * nums. */ + for (j = 0; j < 64; j++) { + /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ + precj[j*16] = numsbase; + for (i = 1; i < 16; i++) { + secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); + } + /* Multiply gbase by 16. */ + for (i = 0; i < 4; i++) { + secp256k1_gej_double_var(&gbase, &gbase, NULL); + } + /* Multiply numbase by 2. */ + secp256k1_gej_double_var(&numsbase, &numsbase, NULL); + if (j == 62) { + /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ + secp256k1_gej_neg(&numsbase, &numsbase); + secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); + } + } + secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); + } + for (j = 0; j < 64; j++) { + for (i = 0; i < 16; i++) { + secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); + } + } +#else + (void)cb; + ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context; +#endif + secp256k1_ecmult_gen_blind(ctx, NULL); +} + +static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { + return ctx->prec != NULL; +} + +static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, + const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { + if (src->prec == NULL) { + dst->prec = NULL; + } else { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); + memcpy(dst->prec, src->prec, sizeof(*dst->prec)); +#else + (void)cb; + dst->prec = src->prec; +#endif + dst->initial = src->initial; + dst->blind = src->blind; + } +} + +static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + free(ctx->prec); +#endif + secp256k1_scalar_clear(&ctx->blind); + secp256k1_gej_clear(&ctx->initial); + ctx->prec = NULL; +} + +static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { + secp256k1_ge add; + secp256k1_ge_storage adds; + secp256k1_scalar gnb; + int bits; + int i, j; + memset(&adds, 0, sizeof(adds)); + *r = ctx->initial; + /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ + secp256k1_scalar_add(&gnb, gn, &ctx->blind); + add.infinity = 0; + for (j = 0; j < 64; j++) { + bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); + for (i = 0; i < 16; i++) { + /** This uses a conditional move to avoid any secret data in array indexes. + * _Any_ use of secret indexes has been demonstrated to result in timing + * sidechannels, even when the cache-line access patterns are uniform. + * See also: + * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe + * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and + * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, + * by Dag Arne Osvik, Adi Shamir, and Eran Tromer + * (http://www.tau.ac.il/~tromer/papers/cache.pdf) + */ + secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); + } + secp256k1_ge_from_storage(&add, &adds); + secp256k1_gej_add_ge(r, r, &add); + } + bits = 0; + secp256k1_ge_clear(&add); + secp256k1_scalar_clear(&gnb); +} + +/* Setup blinding values for secp256k1_ecmult_gen. */ +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { + secp256k1_scalar b; + secp256k1_gej gb; + secp256k1_fe s; + unsigned char nonce32[32]; + secp256k1_rfc6979_hmac_sha256_t rng; + int retry; + unsigned char keydata[64] = {0}; + if (seed32 == NULL) { + /* When seed is NULL, reset the initial point and blinding value. */ + secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); + secp256k1_gej_neg(&ctx->initial, &ctx->initial); + secp256k1_scalar_set_int(&ctx->blind, 1); + } + /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ + secp256k1_scalar_get_b32(nonce32, &ctx->blind); + /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, + * and guards against weak or adversarial seeds. This is a simpler and safer interface than + * asking the caller for blinding values directly and expecting them to retry on failure. + */ + memcpy(keydata, nonce32, 32); + if (seed32 != NULL) { + memcpy(keydata + 32, seed32, 32); + } + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); + memset(keydata, 0, sizeof(keydata)); + /* Retry for out of range results to achieve uniformity. */ + do { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + retry = !secp256k1_fe_set_b32(&s, nonce32); + retry |= secp256k1_fe_is_zero(&s); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ + /* Randomize the projection to defend against multiplier sidechannels. */ + secp256k1_gej_rescale(&ctx->initial, &s); + secp256k1_fe_clear(&s); + do { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_scalar_set_b32(&b, nonce32, &retry); + /* A blinding value of 0 works, but would undermine the projection hardening. */ + retry |= secp256k1_scalar_is_zero(&b); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + memset(nonce32, 0, 32); + secp256k1_ecmult_gen(ctx, &gb, &b); + secp256k1_scalar_negate(&b, &b); + ctx->blind = b; + ctx->initial = gb; + secp256k1_scalar_clear(&b); + secp256k1_gej_clear(&gb); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h new file mode 100644 index 0000000000..4e40104ad4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h @@ -0,0 +1,406 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_IMPL_H_ +#define _SECP256K1_ECMULT_IMPL_H_ + +#include + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" + +#if defined(EXHAUSTIVE_TEST_ORDER) +/* We need to lower these values for exhaustive tests because + * the tables cannot have infinities in them (this breaks the + * affine-isomorphism stuff which tracks z-ratios) */ +# if EXHAUSTIVE_TEST_ORDER > 128 +# define WINDOW_A 5 +# define WINDOW_G 8 +# elif EXHAUSTIVE_TEST_ORDER > 8 +# define WINDOW_A 4 +# define WINDOW_G 4 +# else +# define WINDOW_A 2 +# define WINDOW_G 2 +# endif +#else +/* optimal for 128-bit and 256-bit exponents. */ +#define WINDOW_A 5 +/** larger numbers may result in slightly better performance, at the cost of + exponentially larger precomputed tables. */ +#ifdef USE_ENDOMORPHISM +/** Two tables for window size 15: 1.375 MiB. */ +#define WINDOW_G 15 +#else +/** One table for window size 16: 1.375 MiB. */ +#define WINDOW_G 16 +#endif +#endif + +/** The number of entries a table with precomputed multiples needs to have. */ +#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) + +/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain + * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will + * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. + * Prej's Z values are undefined, except for the last value. + */ +static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { + secp256k1_gej d; + secp256k1_ge a_ge, d_ge; + int i; + + VERIFY_CHECK(!a->infinity); + + secp256k1_gej_double_var(&d, a, NULL); + + /* + * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate + * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. + */ + d_ge.x = d.x; + d_ge.y = d.y; + d_ge.infinity = 0; + + secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); + prej[0].x = a_ge.x; + prej[0].y = a_ge.y; + prej[0].z = a->z; + prej[0].infinity = 0; + + zr[0] = d.z; + for (i = 1; i < n; i++) { + secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); + } + + /* + * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only + * the final point's z coordinate is actually used though, so just update that. + */ + secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); +} + +/** Fill a table 'pre' with precomputed odd multiples of a. + * + * There are two versions of this function: + * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its + * resulting point set to a single constant Z denominator, stores the X and Y + * coordinates as ge_storage points in pre, and stores the global Z in rz. + * It only operates on tables sized for WINDOW_A wnaf multiples. + * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its + * resulting point set to actually affine points, and stores those in pre. + * It operates on tables of any size, but uses heap-allocated temporaries. + * + * To compute a*P + b*G, we compute a table for P using the first function, + * and for G using the second (which requires an inverse, but it only needs to + * happen once). + */ +static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { + secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; + + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); + /* Bring them to the same Z denominator. */ + secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); +} + +static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { + secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); + secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); + secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); + int i; + + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); + /* Convert them in batch to affine coordinates. */ + secp256k1_ge_set_table_gej_var(prea, prej, zr, n); + /* Convert them to compact storage form. */ + for (i = 0; i < n; i++) { + secp256k1_ge_to_storage(&pre[i], &prea[i]); + } + + free(prea); + free(prej); + free(zr); +} + +/** The following two macro retrieves a particular odd multiple from a table + * of precomputed multiples. */ +#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + if ((n) > 0) { \ + *(r) = (pre)[((n)-1)/2]; \ + } else { \ + secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ + } \ +} while(0) + +#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + if ((n) > 0) { \ + secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ + } else { \ + secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ + secp256k1_ge_neg((r), (r)); \ + } \ +} while(0) + +static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { + ctx->pre_g = NULL; +#ifdef USE_ENDOMORPHISM + ctx->pre_g_128 = NULL; +#endif +} + +static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { + secp256k1_gej gj; + + if (ctx->pre_g != NULL) { + return; + } + + /* get the generator */ + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + + ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); + + /* precompute the tables with odd multiples */ + secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); + +#ifdef USE_ENDOMORPHISM + { + secp256k1_gej g_128j; + int i; + + ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); + + /* calculate 2^128*generator */ + g_128j = gj; + for (i = 0; i < 128; i++) { + secp256k1_gej_double_var(&g_128j, &g_128j, NULL); + } + secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); + } +#endif +} + +static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, + const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { + if (src->pre_g == NULL) { + dst->pre_g = NULL; + } else { + size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); + dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); + memcpy(dst->pre_g, src->pre_g, size); + } +#ifdef USE_ENDOMORPHISM + if (src->pre_g_128 == NULL) { + dst->pre_g_128 = NULL; + } else { + size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); + dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); + memcpy(dst->pre_g_128, src->pre_g_128, size); + } +#endif +} + +static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { + return ctx->pre_g != NULL; +} + +static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { + free(ctx->pre_g); +#ifdef USE_ENDOMORPHISM + free(ctx->pre_g_128); +#endif + secp256k1_ecmult_context_init(ctx); +} + +/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), + * with the following guarantees: + * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) + * - two non-zero entries in wnaf are separated by at least w-1 zeroes. + * - the number of set values in wnaf is returned. This number is at most 256, and at most one more + * than the number of bits in the (absolute value) of the input. + */ +static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { + secp256k1_scalar s = *a; + int last_set_bit = -1; + int bit = 0; + int sign = 1; + int carry = 0; + + VERIFY_CHECK(wnaf != NULL); + VERIFY_CHECK(0 <= len && len <= 256); + VERIFY_CHECK(a != NULL); + VERIFY_CHECK(2 <= w && w <= 31); + + memset(wnaf, 0, len * sizeof(wnaf[0])); + + if (secp256k1_scalar_get_bits(&s, 255, 1)) { + secp256k1_scalar_negate(&s, &s); + sign = -1; + } + + while (bit < len) { + int now; + int word; + if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { + bit++; + continue; + } + + now = w; + if (now > len - bit) { + now = len - bit; + } + + word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; + + carry = (word >> (w-1)) & 1; + word -= carry << w; + + wnaf[bit] = sign * word; + last_set_bit = bit; + + bit += now; + } +#ifdef VERIFY + CHECK(carry == 0); + while (bit < 256) { + CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); + } +#endif + return last_set_bit + 1; +} + +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge tmpa; + secp256k1_fe Z; +#ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_scalar na_1, na_lam; + /* Splitted G factors. */ + secp256k1_scalar ng_1, ng_128; + int wnaf_na_1[130]; + int wnaf_na_lam[130]; + int bits_na_1; + int bits_na_lam; + int wnaf_ng_1[129]; + int bits_ng_1; + int wnaf_ng_128[129]; + int bits_ng_128; +#else + int wnaf_na[256]; + int bits_na; + int wnaf_ng[256]; + int bits_ng; +#endif + int i; + int bits; + +#ifdef USE_ENDOMORPHISM + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&na_1, &na_lam, na); + + /* build wnaf representation for na_1 and na_lam. */ + bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); + bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); + VERIFY_CHECK(bits_na_1 <= 130); + VERIFY_CHECK(bits_na_lam <= 130); + bits = bits_na_1; + if (bits_na_lam > bits) { + bits = bits_na_lam; + } +#else + /* build wnaf representation for na. */ + bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); + bits = bits_na; +#endif + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + * The exception is the precomputed G table points, which are actually + * affine. Compared to the base used for other points, they have a Z ratio + * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same + * isomorphism to efficiently add with a known Z inverse. + */ + secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); + +#ifdef USE_ENDOMORPHISM + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } + + /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); + + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; + } +#else + bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; + } +#endif + + secp256k1_gej_set_infinity(r); + + for (i = bits - 1; i >= 0; i--) { + int n; + secp256k1_gej_double_var(r, r, NULL); +#ifdef USE_ENDOMORPHISM + if (i < bits_na_1 && (n = wnaf_na_1[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_na_lam && (n = wnaf_na_lam[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } + if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#else + if (i < bits_na && (n = wnaf_na[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_ng && (n = wnaf_ng[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#endif + } + + if (!r->infinity) { + secp256k1_fe_mul(&r->z, &r->z, &Z); + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h new file mode 100644 index 0000000000..bbb1ee866c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h @@ -0,0 +1,132 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_ +#define _SECP256K1_FIELD_ + +/** Field element module. + * + * Field elements can be represented in several ways, but code accessing + * it (and implementations) need to take certain properties into account: + * - Each field element can be normalized or not. + * - Each field element has a magnitude, which represents how far away + * its representation is away from normalization. Normalized elements + * always have a magnitude of 1, but a magnitude of 1 doesn't imply + * normality. + */ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_FIELD_10X26) +#include "field_10x26.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52.h" +#else +#error "Please select field implementation" +#endif + +#include "util.h" + +/** Normalize a field element. */ +static void secp256k1_fe_normalize(secp256k1_fe *r); + +/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */ +static void secp256k1_fe_normalize_weak(secp256k1_fe *r); + +/** Normalize a field element, without constant-time guarantee. */ +static void secp256k1_fe_normalize_var(secp256k1_fe *r); + +/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field + * implementation may optionally normalize the input, but this should not be relied upon. */ +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r); + +/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field + * implementation may optionally normalize the input, but this should not be relied upon. */ +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); + +/** Set a field element equal to a small integer. Resulting field element is normalized. */ +static void secp256k1_fe_set_int(secp256k1_fe *r, int a); + +/** Sets a field element equal to zero, initializing all fields. */ +static void secp256k1_fe_clear(secp256k1_fe *a); + +/** Verify whether a field element is zero. Requires the input to be normalized. */ +static int secp256k1_fe_is_zero(const secp256k1_fe *a); + +/** Check the "oddness" of a field element. Requires the input to be normalized. */ +static int secp256k1_fe_is_odd(const secp256k1_fe *a); + +/** Compare two field elements. Requires magnitude-1 inputs. */ +static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Same as secp256k1_fe_equal, but may be variable time. */ +static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Compare two field elements. Requires both inputs to be normalized */ +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */ +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); + +/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input + * as an argument. The magnitude of the output is one higher. */ +static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); + +/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that + * small integer. */ +static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); + +/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ +static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); + +/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); + +/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); + +/** If a has a square root, it is computed in r and 1 is returned. If a does not + * have a square root, the root of its negation is computed and 0 is returned. + * The input's magnitude can be at most 8. The output magnitude is 1 (but not + * guaranteed to be normalized). The result in r will always be a square + * itself. */ +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); + +/** Checks whether a field element is a quadratic residue. */ +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); + +/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be + * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); + +/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ +static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); + +/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be + * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and + * outputs must not overlap in memory. */ +static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len); + +/** Convert a field element to the storage type. */ +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); + +/** Convert a field element back from the storage type. */ +static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h new file mode 100644 index 0000000000..61ee1e0965 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h @@ -0,0 +1,47 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include + +typedef struct { + /* X = sum(i=0..9, elem[i]*2^26) mod n */ + uint32_t n[10]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe; + +/* Unpacks a constant into a overlapping multi-limbed FE element. */ +#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ + (d0) & 0x3FFFFFFUL, \ + (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ + (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ + (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ + (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ + (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ + (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ + (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ + (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ + (((uint32_t)d7) >> 10) \ +} + +#ifdef VERIFY +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} +#else +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} +#endif + +typedef struct { + uint32_t n[8]; +} secp256k1_fe_storage; + +#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} +#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h new file mode 100644 index 0000000000..5fb092f1be --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h @@ -0,0 +1,1140 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#include "util.h" +#include "num.h" +#include "field.h" + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe *a) { + const uint32_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + r &= (d[0] <= 0x3FFFFFFUL * m); + r &= (d[1] <= 0x3FFFFFFUL * m); + r &= (d[2] <= 0x3FFFFFFUL * m); + r &= (d[3] <= 0x3FFFFFFUL * m); + r &= (d[4] <= 0x3FFFFFFUL * m); + r &= (d[5] <= 0x3FFFFFFUL * m); + r &= (d[6] <= 0x3FFFFFFUL * m); + r &= (d[7] <= 0x3FFFFFFUL * m); + r &= (d[8] <= 0x3FFFFFFUL * m); + r &= (d[9] <= 0x03FFFFFUL * m); + r &= (a->magnitude >= 0); + r &= (a->magnitude <= 32); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[9] == 0x03FFFFFUL)) { + uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; + if (mid == 0x3FFFFFFUL) { + r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); + } + } + } + VERIFY_CHECK(r == 1); +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t m; + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) + & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ + VERIFY_CHECK(t9 >> 22 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t9 &= 0x03FFFFFUL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_var(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t m; + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) + & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); + + if (x) { + t0 += 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ + VERIFY_CHECK(t9 >> 22 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t9 &= 0x03FFFFFUL; + } + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + uint32_t z0, z1; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; + z0 |= t9; z1 &= t9 ^ 0x3C00000UL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + return (z0 == 0) | (z1 == 0x3FFFFFFUL); +} + +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint32_t z0, z1; + uint32_t x; + + t0 = r->n[0]; + t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + x = t9 >> 22; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + z0 = t0 & 0x3FFFFFFUL; + z1 = z0 ^ 0x3D0UL; + + /* Fast return path should catch the majority of cases */ + if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { + return 0; + } + + t1 = r->n[1]; + t2 = r->n[2]; + t3 = r->n[3]; + t4 = r->n[4]; + t5 = r->n[5]; + t6 = r->n[6]; + t7 = r->n[7]; + t8 = r->n[8]; + + t9 &= 0x03FFFFFUL; + t1 += (x << 6); + + t1 += (t0 >> 26); + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; + z0 |= t9; z1 &= t9 ^ 0x3C00000UL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + return (z0 == 0) | (z1 == 0x3FFFFFFUL); +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { + const uint32_t *t = a->n; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { + int i; +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (i=0; i<10; i++) { + a->n[i] = 0; + } +} + +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (i = 9; i >= 0; i--) { + if (a->n[i] > b->n[i]) { + return 1; + } + if (a->n[i] < b->n[i]) { + return -1; + } + } + return 0; +} + +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; + } + } + if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { + return 0; + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif + return 1; +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; + r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; + r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; + r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; + r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; + r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; + r->n[5] *= a; + r->n[6] *= a; + r->n[7] *= a; + r->n[8] *= a; + r->n[9] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; + r->n[5] += a->n[5]; + r->n[6] += a->n[6]; + r->n[7] += a->n[7]; + r->n[8] += a->n[8]; + r->n[9] += a->n[9]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +#if defined(USE_EXTERNAL_ASM) + +/* External assembler implementation */ +void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); +void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); + +#else + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { + uint64_t c, d; + uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; + uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + VERIFY_BITS(b[0], 30); + VERIFY_BITS(b[1], 30); + VERIFY_BITS(b[2], 30); + VERIFY_BITS(b[3], 30); + VERIFY_BITS(b[4], 30); + VERIFY_BITS(b[5], 30); + VERIFY_BITS(b[6], 30); + VERIFY_BITS(b[7], 30); + VERIFY_BITS(b[8], 30); + VERIFY_BITS(b[9], 26); + + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + d = (uint64_t)a[0] * b[9] + + (uint64_t)a[1] * b[8] + + (uint64_t)a[2] * b[7] + + (uint64_t)a[3] * b[6] + + (uint64_t)a[4] * b[5] + + (uint64_t)a[5] * b[4] + + (uint64_t)a[6] * b[3] + + (uint64_t)a[7] * b[2] + + (uint64_t)a[8] * b[1] + + (uint64_t)a[9] * b[0]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * b[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)a[1] * b[9] + + (uint64_t)a[2] * b[8] + + (uint64_t)a[3] * b[7] + + (uint64_t)a[4] * b[6] + + (uint64_t)a[5] * b[5] + + (uint64_t)a[6] * b[4] + + (uint64_t)a[7] * b[3] + + (uint64_t)a[8] * b[2] + + (uint64_t)a[9] * b[1]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)a[0] * b[1] + + (uint64_t)a[1] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)a[2] * b[9] + + (uint64_t)a[3] * b[8] + + (uint64_t)a[4] * b[7] + + (uint64_t)a[5] * b[6] + + (uint64_t)a[6] * b[5] + + (uint64_t)a[7] * b[4] + + (uint64_t)a[8] * b[3] + + (uint64_t)a[9] * b[2]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)a[0] * b[2] + + (uint64_t)a[1] * b[1] + + (uint64_t)a[2] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)a[3] * b[9] + + (uint64_t)a[4] * b[8] + + (uint64_t)a[5] * b[7] + + (uint64_t)a[6] * b[6] + + (uint64_t)a[7] * b[5] + + (uint64_t)a[8] * b[4] + + (uint64_t)a[9] * b[3]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[3] + + (uint64_t)a[1] * b[2] + + (uint64_t)a[2] * b[1] + + (uint64_t)a[3] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)a[4] * b[9] + + (uint64_t)a[5] * b[8] + + (uint64_t)a[6] * b[7] + + (uint64_t)a[7] * b[6] + + (uint64_t)a[8] * b[5] + + (uint64_t)a[9] * b[4]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[4] + + (uint64_t)a[1] * b[3] + + (uint64_t)a[2] * b[2] + + (uint64_t)a[3] * b[1] + + (uint64_t)a[4] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[5] * b[9] + + (uint64_t)a[6] * b[8] + + (uint64_t)a[7] * b[7] + + (uint64_t)a[8] * b[6] + + (uint64_t)a[9] * b[5]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[5] + + (uint64_t)a[1] * b[4] + + (uint64_t)a[2] * b[3] + + (uint64_t)a[3] * b[2] + + (uint64_t)a[4] * b[1] + + (uint64_t)a[5] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[6] * b[9] + + (uint64_t)a[7] * b[8] + + (uint64_t)a[8] * b[7] + + (uint64_t)a[9] * b[6]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[6] + + (uint64_t)a[1] * b[5] + + (uint64_t)a[2] * b[4] + + (uint64_t)a[3] * b[3] + + (uint64_t)a[4] * b[2] + + (uint64_t)a[5] * b[1] + + (uint64_t)a[6] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[7] * b[9] + + (uint64_t)a[8] * b[8] + + (uint64_t)a[9] * b[7]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[7] + + (uint64_t)a[1] * b[6] + + (uint64_t)a[2] * b[5] + + (uint64_t)a[3] * b[4] + + (uint64_t)a[4] * b[3] + + (uint64_t)a[5] * b[2] + + (uint64_t)a[6] * b[1] + + (uint64_t)a[7] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[8] * b[9] + + (uint64_t)a[9] * b[8]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[8] + + (uint64_t)a[1] * b[7] + + (uint64_t)a[2] * b[6] + + (uint64_t)a[3] * b[5] + + (uint64_t)a[4] * b[4] + + (uint64_t)a[5] * b[3] + + (uint64_t)a[6] * b[2] + + (uint64_t)a[7] * b[1] + + (uint64_t)a[8] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * b[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { + uint64_t c, d; + uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; + uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + d = (uint64_t)(a[0]*2) * a[9] + + (uint64_t)(a[1]*2) * a[8] + + (uint64_t)(a[2]*2) * a[7] + + (uint64_t)(a[3]*2) * a[6] + + (uint64_t)(a[4]*2) * a[5]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * a[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)(a[1]*2) * a[9] + + (uint64_t)(a[2]*2) * a[8] + + (uint64_t)(a[3]*2) * a[7] + + (uint64_t)(a[4]*2) * a[6] + + (uint64_t)a[5] * a[5]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)(a[0]*2) * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)(a[2]*2) * a[9] + + (uint64_t)(a[3]*2) * a[8] + + (uint64_t)(a[4]*2) * a[7] + + (uint64_t)(a[5]*2) * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[2] + + (uint64_t)a[1] * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)(a[3]*2) * a[9] + + (uint64_t)(a[4]*2) * a[8] + + (uint64_t)(a[5]*2) * a[7] + + (uint64_t)a[6] * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[3] + + (uint64_t)(a[1]*2) * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)(a[4]*2) * a[9] + + (uint64_t)(a[5]*2) * a[8] + + (uint64_t)(a[6]*2) * a[7]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[4] + + (uint64_t)(a[1]*2) * a[3] + + (uint64_t)a[2] * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[5]*2) * a[9] + + (uint64_t)(a[6]*2) * a[8] + + (uint64_t)a[7] * a[7]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[5] + + (uint64_t)(a[1]*2) * a[4] + + (uint64_t)(a[2]*2) * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[6]*2) * a[9] + + (uint64_t)(a[7]*2) * a[8]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[6] + + (uint64_t)(a[1]*2) * a[5] + + (uint64_t)(a[2]*2) * a[4] + + (uint64_t)a[3] * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[7]*2) * a[9] + + (uint64_t)a[8] * a[8]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[7] + + (uint64_t)(a[1]*2) * a[6] + + (uint64_t)(a[2]*2) * a[5] + + (uint64_t)(a[3]*2) * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[8]*2) * a[9]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[8] + + (uint64_t)(a[1]*2) * a[7] + + (uint64_t)(a[2]*2) * a[6] + + (uint64_t)(a[3]*2) * a[5] + + (uint64_t)a[4] * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * a[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} +#endif + +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); + VERIFY_CHECK(r != b); +#endif + secp256k1_fe_mul_inner(r->n, a->n, b->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(r->n, a->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { + uint32_t mask0, mask1; + mask0 = flag + ~((uint32_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); + r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); + r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); + r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); + r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); + r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); +#ifdef VERIFY + if (a->magnitude > r->magnitude) { + r->magnitude = a->magnitude; + } + r->normalized &= a->normalized; +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { + uint32_t mask0, mask1; + mask0 = flag + ~((uint32_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); + r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); + r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); + r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); +} + +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); +#endif + r->n[0] = a->n[0] | a->n[1] << 26; + r->n[1] = a->n[1] >> 6 | a->n[2] << 20; + r->n[2] = a->n[2] >> 12 | a->n[3] << 14; + r->n[3] = a->n[3] >> 18 | a->n[4] << 8; + r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; + r->n[5] = a->n[6] >> 4 | a->n[7] << 22; + r->n[6] = a->n[7] >> 10 | a->n[8] << 16; + r->n[7] = a->n[8] >> 16 | a->n[9] << 10; +} + +static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { + r->n[0] = a->n[0] & 0x3FFFFFFUL; + r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); + r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); + r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); + r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); + r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; + r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); + r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); + r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); + r->n[9] = a->n[7] >> 10; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h new file mode 100644 index 0000000000..8e69a560dc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h @@ -0,0 +1,47 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include + +typedef struct { + /* X = sum(i=0..4, elem[i]*2^52) mod n */ + uint64_t n[5]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe; + +/* Unpacks a constant into a overlapping multi-limbed FE element. */ +#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ + (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ + ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ + ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ + ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ + ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ +} + +#ifdef VERIFY +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} +#else +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} +#endif + +typedef struct { + uint64_t n[4]; +} secp256k1_fe_storage; + +#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ + (d0) | (((uint64_t)(d1)) << 32), \ + (d2) | (((uint64_t)(d3)) << 32), \ + (d4) | (((uint64_t)(d5)) << 32), \ + (d6) | (((uint64_t)(d7)) << 32) \ +}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h new file mode 100644 index 0000000000..98cc004bf0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h @@ -0,0 +1,502 @@ +/********************************************************************** + * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/** + * Changelog: + * - March 2013, Diederik Huys: original version + * - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm + * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly + */ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { +/** + * Registers: rdx:rax = multiplication accumulator + * r9:r8 = c + * r15:rcx = d + * r10-r14 = a0-a4 + * rbx = b + * rdi = r + * rsi = a / t? + */ + uint64_t tmp1, tmp2, tmp3; +__asm__ __volatile__( + "movq 0(%%rsi),%%r10\n" + "movq 8(%%rsi),%%r11\n" + "movq 16(%%rsi),%%r12\n" + "movq 24(%%rsi),%%r13\n" + "movq 32(%%rsi),%%r14\n" + + /* d += a3 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r13\n" + "movq %%rax,%%rcx\n" + "movq %%rdx,%%r15\n" + /* d += a2 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d = a0 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c = a4 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r14\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += (c & M) * R */ + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* t3 (tmp1) = d & M */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + "movq %%rsi,%q1\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* d += a4 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a0 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += c * R */ + "movq %%r8,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* t4 = d & M (%%rsi) */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* tx = t4 >> 48 (tmp3) */ + "movq %%rsi,%%rax\n" + "shrq $48,%%rax\n" + "movq %%rax,%q3\n" + /* t4 &= (M >> 4) (tmp2) */ + "movq $0xffffffffffff,%%rax\n" + "andq %%rax,%%rsi\n" + "movq %%rsi,%q2\n" + /* c = a0 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r10\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += a4 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* u0 = d & M (%%rsi) */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* u0 = (u0 << 4) | tx (%%rsi) */ + "shlq $4,%%rsi\n" + "movq %q3,%%rax\n" + "orq %%rax,%%rsi\n" + /* c += u0 * (R >> 4) */ + "movq $0x1000003d1,%%rax\n" + "mulq %%rsi\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[0] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,0(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a1 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a0 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a4 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c += (d & M) * R */ + "movq %%rcx,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* r[1] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,8(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a2 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a1 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a0 * b2 (last use of %%r10 = a0) */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */ + "movq %q2,%%rsi\n" + "movq %q1,%%r10\n" + /* d += a4 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c += (d & M) * R */ + "movq %%rcx,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 (%%rcx only) */ + "shrdq $52,%%r15,%%rcx\n" + /* r[2] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,16(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += t3 */ + "addq %%r10,%%r8\n" + /* c += d * R */ + "movq %%rcx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[3] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,24(%%rdi)\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* c += t4 (%%r8 only) */ + "addq %%rsi,%%r8\n" + /* r[4] = c */ + "movq %%r8,32(%%rdi)\n" +: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) +: "b"(b), "D"(r) +: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" +); +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { +/** + * Registers: rdx:rax = multiplication accumulator + * r9:r8 = c + * rcx:rbx = d + * r10-r14 = a0-a4 + * r15 = M (0xfffffffffffff) + * rdi = r + * rsi = a / t? + */ + uint64_t tmp1, tmp2, tmp3; +__asm__ __volatile__( + "movq 0(%%rsi),%%r10\n" + "movq 8(%%rsi),%%r11\n" + "movq 16(%%rsi),%%r12\n" + "movq 24(%%rsi),%%r13\n" + "movq 32(%%rsi),%%r14\n" + "movq $0xfffffffffffff,%%r15\n" + + /* d = (a0*2) * a3 */ + "leaq (%%r10,%%r10,1),%%rax\n" + "mulq %%r13\n" + "movq %%rax,%%rbx\n" + "movq %%rdx,%%rcx\n" + /* d += (a1*2) * a2 */ + "leaq (%%r11,%%r11,1),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c = a4 * a4 */ + "movq %%r14,%%rax\n" + "mulq %%r14\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += (c & M) * R */ + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* t3 (tmp1) = d & M */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + "movq %%rsi,%q1\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* a4 *= 2 */ + "addq %%r14,%%r14\n" + /* d += a0 * a4 */ + "movq %%r10,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d+= (a1*2) * a3 */ + "leaq (%%r11,%%r11,1),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += a2 * a2 */ + "movq %%r12,%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += c * R */ + "movq %%r8,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* t4 = d & M (%%rsi) */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* tx = t4 >> 48 (tmp3) */ + "movq %%rsi,%%rax\n" + "shrq $48,%%rax\n" + "movq %%rax,%q3\n" + /* t4 &= (M >> 4) (tmp2) */ + "movq $0xffffffffffff,%%rax\n" + "andq %%rax,%%rsi\n" + "movq %%rsi,%q2\n" + /* c = a0 * a0 */ + "movq %%r10,%%rax\n" + "mulq %%r10\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += a1 * a4 */ + "movq %%r11,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += (a2*2) * a3 */ + "leaq (%%r12,%%r12,1),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* u0 = d & M (%%rsi) */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* u0 = (u0 << 4) | tx (%%rsi) */ + "shlq $4,%%rsi\n" + "movq %q3,%%rax\n" + "orq %%rax,%%rsi\n" + /* c += u0 * (R >> 4) */ + "movq $0x1000003d1,%%rax\n" + "mulq %%rsi\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[0] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,0(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* a0 *= 2 */ + "addq %%r10,%%r10\n" + /* c += a0 * a1 */ + "movq %%r10,%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a2 * a4 */ + "movq %%r12,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += a3 * a3 */ + "movq %%r13,%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c += (d & M) * R */ + "movq %%rbx,%%rax\n" + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* r[1] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,8(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a0 * a2 (last use of %%r10) */ + "movq %%r10,%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */ + "movq %q2,%%rsi\n" + "movq %q1,%%r10\n" + /* c += a1 * a1 */ + "movq %%r11,%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a3 * a4 */ + "movq %%r13,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c += (d & M) * R */ + "movq %%rbx,%%rax\n" + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 (%%rbx only) */ + "shrdq $52,%%rcx,%%rbx\n" + /* r[2] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,16(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += t3 */ + "addq %%r10,%%r8\n" + /* c += d * R */ + "movq %%rbx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[3] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,24(%%rdi)\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* c += t4 (%%r8 only) */ + "addq %%rsi,%%r8\n" + /* r[4] = c */ + "movq %%r8,32(%%rdi)\n" +: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) +: "D"(r) +: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" +); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h new file mode 100644 index 0000000000..dd88f38c77 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h @@ -0,0 +1,451 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "util.h" +#include "num.h" +#include "field.h" + +#if defined(USE_ASM_X86_64) +#include "field_5x52_asm_impl.h" +#else +#include "field_5x52_int128_impl.h" +#endif + +/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, + * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, + * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element + * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations + * accept any input with magnitude at most M, and have different rules for propagating magnitude to their + * output. + */ + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe *a) { + const uint64_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); + r &= (a->magnitude >= 0); + r &= (a->magnitude <= 2048); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { + r &= (d[0] < 0xFFFFEFFFFFC2FULL); + } + } + VERIFY_CHECK(r == 1); +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t m; + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) + & (t0 >= 0xFFFFEFFFFFC2FULL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ + VERIFY_CHECK(t4 >> 48 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t4 &= 0x0FFFFFFFFFFFFULL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_var(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t m; + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) + & (t0 >= 0xFFFFEFFFFFC2FULL)); + + if (x) { + t0 += 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ + VERIFY_CHECK(t4 >> 48 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t4 &= 0x0FFFFFFFFFFFFULL; + } + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + uint64_t z0, z1; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; + z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); +} + +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { + uint64_t t0, t1, t2, t3, t4; + uint64_t z0, z1; + uint64_t x; + + t0 = r->n[0]; + t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + x = t4 >> 48; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + z0 = t0 & 0xFFFFFFFFFFFFFULL; + z1 = z0 ^ 0x1000003D0ULL; + + /* Fast return path should catch the majority of cases */ + if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { + return 0; + } + + t1 = r->n[1]; + t2 = r->n[2]; + t3 = r->n[3]; + + t4 &= 0x0FFFFFFFFFFFFULL; + + t1 += (t0 >> 52); + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; + z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { + const uint64_t *t = a->n; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { + int i; +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (i=0; i<5; i++) { + a->n[i] = 0; + } +} + +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (i = 4; i >= 0; i--) { + if (a->n[i] > b->n[i]) { + return 1; + } + if (a->n[i] < b->n[i]) { + return -1; + } + } + return 0; +} + +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; + } + } + if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { + return 0; + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif + return 1; +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); + VERIFY_CHECK(r != b); +#endif + secp256k1_fe_mul_inner(r->n, a->n, b->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(r->n, a->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { + uint64_t mask0, mask1; + mask0 = flag + ~((uint64_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); +#ifdef VERIFY + if (a->magnitude > r->magnitude) { + r->magnitude = a->magnitude; + } + r->normalized &= a->normalized; +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { + uint64_t mask0, mask1; + mask0 = flag + ~((uint64_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); +} + +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); +#endif + r->n[0] = a->n[0] | a->n[1] << 52; + r->n[1] = a->n[1] >> 12 | a->n[2] << 40; + r->n[2] = a->n[2] >> 24 | a->n[3] << 28; + r->n[3] = a->n[3] >> 36 | a->n[4] << 16; +} + +static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { + r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; + r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); + r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); + r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); + r->n[4] = a->n[3] >> 16; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h new file mode 100644 index 0000000000..0bf22bdd3e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h @@ -0,0 +1,277 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +#include + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { + uint128_t c, d; + uint64_t t3, t4, tx, u0; + uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + VERIFY_BITS(b[0], 56); + VERIFY_BITS(b[1], 56); + VERIFY_BITS(b[2], 56); + VERIFY_BITS(b[3], 56); + VERIFY_BITS(b[4], 52); + VERIFY_CHECK(r != b); + + /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + d = (uint128_t)a0 * b[3] + + (uint128_t)a1 * b[2] + + (uint128_t)a2 * b[1] + + (uint128_t)a3 * b[0]; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (uint128_t)a4 * b[4]; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + d += (uint128_t)a0 * b[4] + + (uint128_t)a1 * b[3] + + (uint128_t)a2 * b[2] + + (uint128_t)a3 * b[1] + + (uint128_t)a4 * b[0]; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (uint128_t)a0 * b[0]; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (uint128_t)a1 * b[4] + + (uint128_t)a2 * b[3] + + (uint128_t)a3 * b[2] + + (uint128_t)a4 * b[1]; + VERIFY_BITS(d, 115); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 63); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (uint128_t)u0 * (R >> 4); + VERIFY_BITS(c, 115); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + r[0] = c & M; c >>= 52; + VERIFY_BITS(r[0], 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + c += (uint128_t)a0 * b[1] + + (uint128_t)a1 * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (uint128_t)a2 * b[4] + + (uint128_t)a3 * b[3] + + (uint128_t)a4 * b[2]; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + r[1] = c & M; c >>= 52; + VERIFY_BITS(r[1], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (uint128_t)a0 * b[2] + + (uint128_t)a1 * b[1] + + (uint128_t)a2 * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint128_t)a3 * b[4] + + (uint128_t)a4 * b[3]; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R + t3; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { + uint128_t c, d; + uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; + int64_t t3, t4, tx, u0; + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + + /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + d = (uint128_t)(a0*2) * a3 + + (uint128_t)(a1*2) * a2; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (uint128_t)a4 * a4; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + a4 *= 2; + d += (uint128_t)a0 * a4 + + (uint128_t)(a1*2) * a3 + + (uint128_t)a2 * a2; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (uint128_t)a0 * a0; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (uint128_t)a1 * a4 + + (uint128_t)(a2*2) * a3; + VERIFY_BITS(d, 114); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 62); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (uint128_t)u0 * (R >> 4); + VERIFY_BITS(c, 113); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + r[0] = c & M; c >>= 52; + VERIFY_BITS(r[0], 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + a0 *= 2; + c += (uint128_t)a0 * a1; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (uint128_t)a2 * a4 + + (uint128_t)a3 * a3; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + r[1] = c & M; c >>= 52; + VERIFY_BITS(r[1], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (uint128_t)a0 * a2 + + (uint128_t)a1 * a1; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint128_t)a3 * a4; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += d * R + t3; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h new file mode 100644 index 0000000000..5127b279bc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h @@ -0,0 +1,315 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_IMPL_H_ +#define _SECP256K1_FIELD_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "util.h" + +#if defined(USE_FIELD_10X26) +#include "field_10x26_impl.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52_impl.h" +#else +#error "Please select field implementation" +#endif + +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe na; + secp256k1_fe_negate(&na, a, 1); + secp256k1_fe_add(&na, b); + return secp256k1_fe_normalizes_to_zero(&na); +} + +SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe na; + secp256k1_fe_negate(&na, a, 1); + secp256k1_fe_add(&na, b); + return secp256k1_fe_normalizes_to_zero_var(&na); +} + +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { + /** Given that p is congruent to 3 mod 4, we can compute the square root of + * a mod p as the (p+1)/4'th power of a. + * + * As (p+1)/4 is an even number, it will have the same result for a and for + * (-a). Only one of these two numbers actually has a square root however, + * so we test at the end by squaring and comparing to the input. + * Also because (p+1)/4 is an even number, the computed square root is + * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). + */ + secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; + int j; + + /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in + * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x6, &x6); + } + secp256k1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x9, &x9); + } + secp256k1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&x11, &x11); + } + secp256k1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + secp256k1_fe_sqr(&x22, &x22); + } + secp256k1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + secp256k1_fe_sqr(&x44, &x44); + } + secp256k1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x88, &x88); + } + secp256k1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + secp256k1_fe_sqr(&x176, &x176); + } + secp256k1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x220, &x220); + } + secp256k1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x223, &x223); + } + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + t1 = x223; + for (j=0; j<23; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x22); + for (j=0; j<6; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x2); + secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_sqr(r, &t1); + + /* Check that a square root was actually calculated */ + + secp256k1_fe_sqr(&t1, r); + return secp256k1_fe_equal(&t1, a); +} + +static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { + secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; + int j; + + /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in + * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x6, &x6); + } + secp256k1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x9, &x9); + } + secp256k1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&x11, &x11); + } + secp256k1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + secp256k1_fe_sqr(&x22, &x22); + } + secp256k1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + secp256k1_fe_sqr(&x44, &x44); + } + secp256k1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x88, &x88); + } + secp256k1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + secp256k1_fe_sqr(&x176, &x176); + } + secp256k1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x220, &x220); + } + secp256k1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x223, &x223); + } + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + t1 = x223; + for (j=0; j<23; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x22); + for (j=0; j<5; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, a); + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x2); + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(r, a, &t1); +} + +static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) { +#if defined(USE_FIELD_INV_BUILTIN) + secp256k1_fe_inv(r, a); +#elif defined(USE_FIELD_INV_NUM) + secp256k1_num n, m; + static const secp256k1_fe negone = SECP256K1_FE_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL + ); + /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + static const unsigned char prime[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + unsigned char b[32]; + int res; + secp256k1_fe c = *a; + secp256k1_fe_normalize_var(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_set_bin(&m, prime, 32); + secp256k1_num_mod_inverse(&n, &n, &m); + secp256k1_num_get_bin(b, 32, &n); + res = secp256k1_fe_set_b32(r, b); + (void)res; + VERIFY_CHECK(res); + /* Verify the result is the (unique) valid inverse using non-GMP code. */ + secp256k1_fe_mul(&c, &c, r); + secp256k1_fe_add(&c, &negone); + CHECK(secp256k1_fe_normalizes_to_zero_var(&c)); +#else +#error "Please select field inverse implementation" +#endif +} + +static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) { + secp256k1_fe u; + size_t i; + if (len < 1) { + return; + } + + VERIFY_CHECK((r + len <= a) || (a + len <= r)); + + r[0] = a[0]; + + i = 0; + while (++i < len) { + secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); + } + + secp256k1_fe_inv_var(&u, &r[--i]); + + while (i > 0) { + size_t j = i--; + secp256k1_fe_mul(&r[j], &r[i], &u); + secp256k1_fe_mul(&u, &u, &a[j]); + } + + r[0] = u; +} + +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { +#ifndef USE_NUM_NONE + unsigned char b[32]; + secp256k1_num n; + secp256k1_num m; + /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + static const unsigned char prime[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + + secp256k1_fe c = *a; + secp256k1_fe_normalize_var(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_set_bin(&m, prime, 32); + return secp256k1_num_jacobi(&n, &m) >= 0; +#else + secp256k1_fe r; + return secp256k1_fe_sqrt(&r, a); +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c new file mode 100644 index 0000000000..1835fd491d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c @@ -0,0 +1,74 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#define USE_BASIC_CONFIG 1 + +#include "basic-config.h" +#include "include/secp256k1.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_gen_impl.h" + +static void default_error_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); + abort(); +} + +static const secp256k1_callback default_error_callback = { + default_error_callback_fn, + NULL +}; + +int main(int argc, char **argv) { + secp256k1_ecmult_gen_context ctx; + int inner; + int outer; + FILE* fp; + + (void)argc; + (void)argv; + + fp = fopen("src/ecmult_static_context.h","w"); + if (fp == NULL) { + fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); + return -1; + } + + fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); + fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); + fprintf(fp, "#include \"group.h\"\n"); + fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); + fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); + + secp256k1_ecmult_gen_context_init(&ctx); + secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); + for(outer = 0; outer != 64; outer++) { + fprintf(fp,"{\n"); + for(inner = 0; inner != 16; inner++) { + fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); + if (inner != 15) { + fprintf(fp,",\n"); + } else { + fprintf(fp,"\n"); + } + } + if (outer != 63) { + fprintf(fp,"},\n"); + } else { + fprintf(fp,"}\n"); + } + } + fprintf(fp,"};\n"); + secp256k1_ecmult_gen_context_clear(&ctx); + + fprintf(fp, "#undef SC\n"); + fprintf(fp, "#endif\n"); + fclose(fp); + + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h new file mode 100644 index 0000000000..4957b248fe --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h @@ -0,0 +1,144 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_ +#define _SECP256K1_GROUP_ + +#include "num.h" +#include "field.h" + +/** A group element of the secp256k1 curve, in affine coordinates. */ +typedef struct { + secp256k1_fe x; + secp256k1_fe y; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_ge; + +#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} +#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} + +/** A group element of the secp256k1 curve, in jacobian coordinates. */ +typedef struct { + secp256k1_fe x; /* actual X: x/z^2 */ + secp256k1_fe y; /* actual Y: y/z^3 */ + secp256k1_fe z; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_gej; + +#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} +#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} + +typedef struct { + secp256k1_fe_storage x; + secp256k1_fe_storage y; +} secp256k1_ge_storage; + +#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} + +#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) + +/** Set a group element equal to the point with given X and Y coordinates */ +static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); + +/** Set a group element (affine) equal to the point with the given X coordinate + * and a Y coordinate that is a quadratic residue modulo p. The return value + * is true iff a coordinate with the given X coordinate exists. + */ +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); + +/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness + * for Y. Return value indicates whether the result is valid. */ +static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_ge_is_infinity(const secp256k1_ge *a); + +/** Check whether a group element is valid (i.e., on the curve). */ +static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); + +static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); + +/** Set a group element equal to another which is given in jacobian coordinates */ +static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); + +/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); + +/** Set a batch of group elements equal to the inputs given in jacobian + * coordinates (with known z-ratios). zr must contain the known z-ratios such + * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ +static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len); + +/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to + * the same global z "denominator". zr must contain the known z-ratios such + * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y + * coordinates of the result are stored in r, the common z coordinate is + * stored in globalz. */ +static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); + +/** Set a group element (jacobian) equal to the point at infinity. */ +static void secp256k1_gej_set_infinity(secp256k1_gej *r); + +/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ +static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); + +/** Compare the X coordinate of a group element (jacobian). */ +static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); + +/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ +static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_gej_is_infinity(const secp256k1_gej *a); + +/** Check whether a group element's y coordinate is a quadratic residue. */ +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); + +/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). + * a may not be zero. Constant time. */ +static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); + +/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ +static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ +static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ +static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); + +/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient + than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time + guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ +static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ +static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); + +#ifdef USE_ENDOMORPHISM +/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ +static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); +#endif + +/** Clear a secp256k1_gej to prevent leaking sensitive information. */ +static void secp256k1_gej_clear(secp256k1_gej *r); + +/** Clear a secp256k1_ge to prevent leaking sensitive information. */ +static void secp256k1_ge_clear(secp256k1_ge *r); + +/** Convert a group element to the storage type. */ +static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); + +/** Convert a group element back from the storage type. */ +static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); + +/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ +static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h new file mode 100644 index 0000000000..7d723532ff --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h @@ -0,0 +1,700 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_IMPL_H_ +#define _SECP256K1_GROUP_IMPL_H_ + +#include "num.h" +#include "field.h" +#include "group.h" + +/* These points can be generated in sage as follows: + * + * 0. Setup a worksheet with the following parameters. + * b = 4 # whatever CURVE_B will be set to + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (b)]) + * + * 1. Determine all the small orders available to you. (If there are + * no satisfactory ones, go back and change b.) + * print C.order().factor(limit=1000) + * + * 2. Choose an order as one of the prime factors listed in the above step. + * (You can also multiply some to get a composite order, though the + * tests will crash trying to invert scalars during signing.) We take a + * random point and scale it to drop its order to the desired value. + * There is some probability this won't work; just try again. + * order = 199 + * P = C.random_point() + * P = (int(P.order()) / int(order)) * P + * assert(P.order() == order) + * + * 3. Print the values. You'll need to use a vim macro or something to + * split the hex output into 4-byte chunks. + * print "%x %x" % P.xy() + */ +#if defined(EXHAUSTIVE_TEST_ORDER) +# if EXHAUSTIVE_TEST_ORDER == 199 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, + 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, + 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, + 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED +); + +const int CURVE_B = 4; +# elif EXHAUSTIVE_TEST_ORDER == 13 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, + 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, + 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, + 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac +); +const int CURVE_B = 2; +# else +# error No known generator for the specified exhaustive test group order. +# endif +#else +/** Generator for secp256k1, value 'g' defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + */ +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, + 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, + 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, + 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL +); + +const int CURVE_B = 7; +#endif + +static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { + secp256k1_fe zi2; + secp256k1_fe zi3; + secp256k1_fe_sqr(&zi2, zi); + secp256k1_fe_mul(&zi3, &zi2, zi); + secp256k1_fe_mul(&r->x, &a->x, &zi2); + secp256k1_fe_mul(&r->y, &a->y, &zi3); + r->infinity = a->infinity; +} + +static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { + r->infinity = 0; + r->x = *x; + r->y = *y; +} + +static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { + return a->infinity; +} + +static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { + *r = *a; + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { + secp256k1_fe z2, z3; + r->infinity = a->infinity; + secp256k1_fe_inv(&a->z, &a->z); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { + secp256k1_fe z2, z3; + r->infinity = a->infinity; + if (a->infinity) { + return; + } + secp256k1_fe_inv_var(&a->z, &a->z); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { + secp256k1_fe *az; + secp256k1_fe *azi; + size_t i; + size_t count = 0; + az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); + for (i = 0; i < len; i++) { + if (!a[i].infinity) { + az[count++] = a[i].z; + } + } + + azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); + secp256k1_fe_inv_all_var(azi, az, count); + free(az); + + count = 0; + for (i = 0; i < len; i++) { + r[i].infinity = a[i].infinity; + if (!a[i].infinity) { + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); + } + } + free(azi); +} + +static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { + size_t i = len - 1; + secp256k1_fe zi; + + if (len > 0) { + /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ + secp256k1_fe_inv(&zi, &a[i].z); + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); + + /* Work out way backwards, using the z-ratios to scale the x/y values. */ + while (i > 0) { + secp256k1_fe_mul(&zi, &zi, &zr[i]); + i--; + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); + } + } +} + +static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { + size_t i = len - 1; + secp256k1_fe zs; + + if (len > 0) { + /* The z of the final point gives us the "global Z" for the table. */ + r[i].x = a[i].x; + r[i].y = a[i].y; + *globalz = a[i].z; + r[i].infinity = 0; + zs = zr[i]; + + /* Work our way backwards, using the z-ratios to scale the x/y values. */ + while (i > 0) { + if (i != len - 1) { + secp256k1_fe_mul(&zs, &zs, &zr[i]); + } + i--; + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); + } + } +} + +static void secp256k1_gej_set_infinity(secp256k1_gej *r) { + r->infinity = 1; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_gej_clear(secp256k1_gej *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_ge_clear(secp256k1_ge *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); +} + +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { + secp256k1_fe x2, x3, c; + r->x = *x; + secp256k1_fe_sqr(&x2, x); + secp256k1_fe_mul(&x3, x, &x2); + r->infinity = 0; + secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_add(&c, &x3); + return secp256k1_fe_sqrt(&r->y, &c); +} + +static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { + if (!secp256k1_ge_set_xquad(r, x)) { + return 0; + } + secp256k1_fe_normalize_var(&r->y); + if (secp256k1_fe_is_odd(&r->y) != odd) { + secp256k1_fe_negate(&r->y, &r->y, 1); + } + return 1; + +} + +static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + secp256k1_fe_set_int(&r->z, 1); +} + +static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { + secp256k1_fe r, r2; + VERIFY_CHECK(!a->infinity); + secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); + r2 = a->x; secp256k1_fe_normalize_weak(&r2); + return secp256k1_fe_equal_var(&r, &r2); +} + +static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + r->z = a->z; + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { + return a->infinity; +} + +static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { + secp256k1_fe y2, x3, z2, z6; + if (a->infinity) { + return 0; + } + /** y^2 = x^3 + 7 + * (Y/Z^3)^2 = (X/Z^2)^3 + 7 + * Y^2 / Z^6 = X^3 / Z^6 + 7 + * Y^2 = X^3 + 7*Z^6 + */ + secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); + secp256k1_fe_mul_int(&z6, CURVE_B); + secp256k1_fe_add(&x3, &z6); + secp256k1_fe_normalize_weak(&x3); + return secp256k1_fe_equal_var(&y2, &x3); +} + +static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { + secp256k1_fe y2, x3, c; + if (a->infinity) { + return 0; + } + /* y^2 = x^3 + 7 */ + secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_add(&x3, &c); + secp256k1_fe_normalize_weak(&x3); + return secp256k1_fe_equal_var(&y2, &x3); +} + +static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { + /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. + * + * Note that there is an implementation described at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + * which trades a multiply for a square, but in practice this is actually slower, + * mainly because it requires more normalizations. + */ + secp256k1_fe t1,t2,t3,t4; + /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, + * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have + * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. + * + * Having said this, if this function receives a point on a sextic twist, e.g. by + * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, + * since -6 does have a cube root mod p. For this point, this function will not set + * the infinity flag even though the point doubles to infinity, and the result + * point will be gibberish (z = 0 but infinity = 0). + */ + r->infinity = a->infinity; + if (r->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + return; + } + + if (rzr != NULL) { + *rzr = a->y; + secp256k1_fe_normalize_weak(rzr); + secp256k1_fe_mul_int(rzr, 2); + } + + secp256k1_fe_mul(&r->z, &a->z, &a->y); + secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ + secp256k1_fe_sqr(&t1, &a->x); + secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ + secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ + secp256k1_fe_sqr(&t3, &a->y); + secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ + secp256k1_fe_sqr(&t4, &t3); + secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ + secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ + r->x = t3; + secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ + secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ + secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ + secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ + secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ + secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ + secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ + secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ + secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ +} + +static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { + VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); + secp256k1_gej_double_var(r, a, rzr); +} + +static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { + /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ + secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + + if (a->infinity) { + VERIFY_CHECK(rzr == NULL); + *r = *b; + return; + } + + if (b->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + + r->infinity = 0; + secp256k1_fe_sqr(&z22, &b->z); + secp256k1_fe_sqr(&z12, &a->z); + secp256k1_fe_mul(&u1, &a->x, &z22); + secp256k1_fe_mul(&u2, &b->x, &z12); + secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + secp256k1_fe_mul(&h, &h, &b->z); + if (rzr != NULL) { + *rzr = h; + } + secp256k1_fe_mul(&r->z, &a->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { + /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + if (a->infinity) { + VERIFY_CHECK(rzr == NULL); + secp256k1_gej_set_ge(r, b); + return; + } + if (b->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + r->infinity = 0; + + secp256k1_fe_sqr(&z12, &a->z); + u1 = a->x; secp256k1_fe_normalize_weak(&u1); + secp256k1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; secp256k1_fe_normalize_weak(&s1); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + if (rzr != NULL) { + *rzr = h; + } + secp256k1_fe_mul(&r->z, &a->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { + /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + + if (b->infinity) { + *r = *a; + return; + } + if (a->infinity) { + secp256k1_fe bzinv2, bzinv3; + r->infinity = b->infinity; + secp256k1_fe_sqr(&bzinv2, bzinv); + secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); + secp256k1_fe_mul(&r->x, &b->x, &bzinv2); + secp256k1_fe_mul(&r->y, &b->y, &bzinv3); + secp256k1_fe_set_int(&r->z, 1); + return; + } + r->infinity = 0; + + /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to + * secp256k1's isomorphism we can multiply the Z coordinates on both sides + * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). + * This means that (rx,ry,rz) can be calculated as + * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. + * The variable az below holds the modified Z coordinate for a, which is used + * for the computation of rx and ry, but not for rz. + */ + secp256k1_fe_mul(&az, &a->z, bzinv); + + secp256k1_fe_sqr(&z12, &az); + u1 = a->x; secp256k1_fe_normalize_weak(&u1); + secp256k1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; secp256k1_fe_normalize_weak(&s1); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, NULL); + } else { + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + + +static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { + /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ + static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; + secp256k1_fe m_alt, rr_alt; + int infinity, degenerate; + VERIFY_CHECK(!b->infinity); + VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); + + /** In: + * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. + * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. + * we find as solution for a unified addition/doubling formula: + * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. + * x3 = lambda^2 - (x1 + x2) + * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). + * + * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: + * U1 = X1*Z2^2, U2 = X2*Z1^2 + * S1 = Y1*Z2^3, S2 = Y2*Z1^3 + * Z = Z1*Z2 + * T = U1+U2 + * M = S1+S2 + * Q = T*M^2 + * R = T^2-U1*U2 + * X3 = 4*(R^2-Q) + * Y3 = 4*(R*(3*Q-2*R^2)-M^4) + * Z3 = 2*M*Z + * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) + * + * This formula has the benefit of being the same for both addition + * of distinct points and doubling. However, it breaks down in the + * case that either point is infinity, or that y1 = -y2. We handle + * these cases in the following ways: + * + * - If b is infinity we simply bail by means of a VERIFY_CHECK. + * + * - If a is infinity, we detect this, and at the end of the + * computation replace the result (which will be meaningless, + * but we compute to be constant-time) with b.x : b.y : 1. + * + * - If a = -b, we have y1 = -y2, which is a degenerate case. + * But here the answer is infinity, so we simply set the + * infinity flag of the result, overriding the computed values + * without even needing to cmov. + * + * - If y1 = -y2 but x1 != x2, which does occur thanks to certain + * properties of our curve (specifically, 1 has nontrivial cube + * roots in our field, and the curve equation has no x coefficient) + * then the answer is not infinity but also not given by the above + * equation. In this case, we cmov in place an alternate expression + * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these + * expressions for lambda are defined, they are equal, and can be + * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) + * then substitution of x^3 + 7 for y^2 (using the curve equation). + * For all pairs of nonzero points (a, b) at least one is defined, + * so this covers everything. + */ + + secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ + u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ + secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ + s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ + secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ + secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ + t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ + m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ + secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ + secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ + secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ + secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ + /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" + * case that Z = z1z2 = 0, and this is special-cased later on). */ + degenerate = secp256k1_fe_normalizes_to_zero(&m) & + secp256k1_fe_normalizes_to_zero(&rr); + /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. + * This means either x1 == beta*x2 or beta*x1 == x2, where beta is + * a nontrivial cube root of one. In either case, an alternate + * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), + * so we set R/M equal to this. */ + rr_alt = s1; + secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ + secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ + + secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); + secp256k1_fe_cmov(&m_alt, &m, !degenerate); + /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. + * From here on out Ralt and Malt represent the numerator + * and denominator of lambda; R and M represent the explicit + * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ + secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ + secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ + /* These two lines use the observation that either M == Malt or M == 0, + * so M^3 * Malt is either Malt^4 (which is computed by squaring), or + * zero (which is "computed" by cmov). So the cost is one squaring + * versus two multiplications. */ + secp256k1_fe_sqr(&n, &n); + secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ + secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ + secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ + infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); + secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ + secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ + secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ + secp256k1_fe_normalize_weak(&t); + r->x = t; /* r->x = Ralt^2-Q (1) */ + secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ + secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ + secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ + secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ + secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ + secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ + + /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ + secp256k1_fe_cmov(&r->x, &b->x, a->infinity); + secp256k1_fe_cmov(&r->y, &b->y, a->infinity); + secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); + r->infinity = infinity; +} + +static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { + /* Operations: 4 mul, 1 sqr */ + secp256k1_fe zz; + VERIFY_CHECK(!secp256k1_fe_is_zero(s)); + secp256k1_fe_sqr(&zz, s); + secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ + secp256k1_fe_mul(&r->y, &r->y, &zz); + secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ + secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ +} + +static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { + secp256k1_fe x, y; + VERIFY_CHECK(!a->infinity); + x = a->x; + secp256k1_fe_normalize(&x); + y = a->y; + secp256k1_fe_normalize(&y); + secp256k1_fe_to_storage(&r->x, &x); + secp256k1_fe_to_storage(&r->y, &y); +} + +static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { + secp256k1_fe_from_storage(&r->x, &a->x); + secp256k1_fe_from_storage(&r->y, &a->y); + r->infinity = 0; +} + +static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { + secp256k1_fe_storage_cmov(&r->x, &a->x, flag); + secp256k1_fe_storage_cmov(&r->y, &a->y, flag); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { + static const secp256k1_fe beta = SECP256K1_FE_CONST( + 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, + 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul + ); + *r = *a; + secp256k1_fe_mul(&r->x, &r->x, &beta); +} +#endif + +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { + secp256k1_fe yz; + + if (a->infinity) { + return 0; + } + + /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as + * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z + is */ + secp256k1_fe_mul(&yz, &a->y, &a->z); + return secp256k1_fe_is_quad_var(&yz); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h new file mode 100644 index 0000000000..fca98cab9f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h @@ -0,0 +1,41 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_HASH_ +#define _SECP256K1_HASH_ + +#include +#include + +typedef struct { + uint32_t s[8]; + uint32_t buf[16]; /* In big endian */ + size_t bytes; +} secp256k1_sha256_t; + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); + +typedef struct { + secp256k1_sha256_t inner, outer; +} secp256k1_hmac_sha256_t; + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); + +typedef struct { + unsigned char v[32]; + unsigned char k[32]; + int retry; +} secp256k1_rfc6979_hmac_sha256_t; + +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h new file mode 100644 index 0000000000..b47e65f830 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h @@ -0,0 +1,281 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_HASH_IMPL_H_ +#define _SECP256K1_HASH_IMPL_H_ + +#include "hash.h" + +#include +#include +#include + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) +#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) +#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) +#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) + +#define Round(a,b,c,d,e,f,g,h,k,w) do { \ + uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ + uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ + (d) += t1; \ + (h) = t1 + t2; \ +} while(0) + +#ifdef WORDS_BIGENDIAN +#define BE32(x) (x) +#else +#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) +#endif + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { + hash->s[0] = 0x6a09e667ul; + hash->s[1] = 0xbb67ae85ul; + hash->s[2] = 0x3c6ef372ul; + hash->s[3] = 0xa54ff53aul; + hash->s[4] = 0x510e527ful; + hash->s[5] = 0x9b05688cul; + hash->s[6] = 0x1f83d9abul; + hash->s[7] = 0x5be0cd19ul; + hash->bytes = 0; +} + +/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ +static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { + size_t bufsize = hash->bytes & 0x3F; + hash->bytes += len; + while (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); + data += 64 - bufsize; + len -= 64 - bufsize; + secp256k1_sha256_transform(hash->s, hash->buf); + bufsize = 0; + } + if (len) { + /* Fill the buffer with what remains. */ + memcpy(((unsigned char*)hash->buf) + bufsize, data, len); + } +} + +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { + static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t sizedesc[2]; + uint32_t out[8]; + int i = 0; + sizedesc[0] = BE32(hash->bytes >> 29); + sizedesc[1] = BE32(hash->bytes << 3); + secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); + for (i = 0; i < 8; i++) { + out[i] = BE32(hash->s[i]); + hash->s[i] = 0; + } + memcpy(out32, (const unsigned char*)out, 32); +} + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { + int n; + unsigned char rkey[64]; + if (keylen <= 64) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 64 - keylen); + } else { + secp256k1_sha256_t sha256; + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, key, keylen); + secp256k1_sha256_finalize(&sha256, rkey); + memset(rkey + 32, 0, 32); + } + + secp256k1_sha256_initialize(&hash->outer); + for (n = 0; n < 64; n++) { + rkey[n] ^= 0x5c; + } + secp256k1_sha256_write(&hash->outer, rkey, 64); + + secp256k1_sha256_initialize(&hash->inner); + for (n = 0; n < 64; n++) { + rkey[n] ^= 0x5c ^ 0x36; + } + secp256k1_sha256_write(&hash->inner, rkey, 64); + memset(rkey, 0, 64); +} + +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { + secp256k1_sha256_write(&hash->inner, data, size); +} + +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { + unsigned char temp[32]; + secp256k1_sha256_finalize(&hash->inner, temp); + secp256k1_sha256_write(&hash->outer, temp, 32); + memset(temp, 0, 32); + secp256k1_sha256_finalize(&hash->outer, out32); +} + + +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { + secp256k1_hmac_sha256_t hmac; + static const unsigned char zero[1] = {0x00}; + static const unsigned char one[1] = {0x01}; + + memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ + memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ + + /* RFC6979 3.2.d. */ + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + + /* RFC6979 3.2.f. */ + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, one, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + rng->retry = 0; +} + +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { + /* RFC6979 3.2.h. */ + static const unsigned char zero[1] = {0x00}; + if (rng->retry) { + secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + } + + while (outlen > 0) { + secp256k1_hmac_sha256_t hmac; + int now = outlen; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + if (now > 32) { + now = 32; + } + memcpy(out, rng->v, now); + out += now; + outlen -= now; + } + + rng->retry = 1; +} + +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { + memset(rng->k, 0, 32); + memset(rng->v, 0, 32); + rng->retry = 0; +} + +#undef BE32 +#undef Round +#undef sigma1 +#undef sigma0 +#undef Sigma1 +#undef Sigma0 +#undef Maj +#undef Ch + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java new file mode 100644 index 0000000000..1c67802fba --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -0,0 +1,446 @@ +/* + * Copyright 2013 Google Inc. + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import java.math.BigInteger; +import com.google.common.base.Preconditions; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + *

This class holds native methods to handle ECDSA verification.

+ * + *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

+ * + *

To build secp256k1 for use with bitcoinj, run + * `./configure --enable-jni --enable-experimental --enable-module-ecdh` + * and `make` then copy `.libs/libsecp256k1.so` to your system library path + * or point the JVM to the folder containing it with -Djava.library.path + *

+ */ +public class NativeSecp256k1 { + + private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private static final Lock r = rwl.readLock(); + private static final Lock w = rwl.writeLock(); + private static ThreadLocal nativeECDSABuffer = new ThreadLocal(); + /** + * Verifies the given secp256k1 signature in native code. + * Calling when enabled == false is undefined (probably library not loaded) + * + * @param data The data which was signed, must be exactly 32 bytes + * @param signature The signature + * @param pub The public key which did the signing + */ + public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 520) { + byteBuff = ByteBuffer.allocateDirect(520); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(signature); + byteBuff.put(pub); + + byte[][] retByteArray; + + r.lock(); + try { + return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; + } finally { + r.unlock(); + } + } + + /** + * libsecp256k1 Create an ECDSA signature. + * + * @param data Message hash, 32 bytes + * @param key Secret key, 32 bytes + * + * Return values + * @param sig byte array of signature + */ + public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + 32) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] sigArr = retByteArray[0]; + int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(sigArr.length, sigLen, "Got bad signature length."); + + return retVal == 0 ? new byte[0] : sigArr; + } + + /** + * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid + * + * @param seckey ECDSA Secret key, 32 bytes + */ + public static boolean secKeyVerify(byte[] seckey) { + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + r.lock(); + try { + return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; + } finally { + r.unlock(); + } + } + + + /** + * libsecp256k1 Compute Pubkey - computes public key from secret key + * + * @param seckey ECDSA Secret key, 32 bytes + * + * Return values + * @param pubkey ECDSA Public key, 33 or 65 bytes + */ + //TODO add a 'compressed' arg + public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + return retVal == 0 ? new byte[0]: pubArr; + } + + /** + * libsecp256k1 Cleanup - This destroys the secp256k1 context object + * This should be called at the end of the program for proper cleanup of the context. + */ + public static synchronized void cleanup() { + w.lock(); + try { + secp256k1_destroy_context(Secp256k1Context.getContext()); + } finally { + w.unlock(); + } + } + + public static long cloneContext() { + r.lock(); + try { + return secp256k1_ctx_clone(Secp256k1Context.getContext()); + } finally { r.unlock(); } + } + + /** + * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey + */ + public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; + } + + /** + * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey + */ + public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; + } + + /** + * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 create ECDH secret - constant time ECDH calculation + * + * @param seckey byte array of secret key used in exponentiaion + * @param pubkey byte array of public key used in exponentiaion + */ + public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { + byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + byteBuff.put(pubkey); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] resArr = retByteArray[0]; + int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + + assertEquals(resArr.length, 32, "Got bad result length."); + assertEquals(retVal, 1, "Failed return value check."); + + return resArr; + } + + /** + * libsecp256k1 randomize - updates the context randomization + * + * @param seed 32-byte random seed + */ + public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ + Preconditions.checkArgument(seed.length == 32 || seed == null); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seed.length) { + byteBuff = ByteBuffer.allocateDirect(seed.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seed); + + w.lock(); + try { + return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + } finally { + w.unlock(); + } + } + + private static native long secp256k1_ctx_clone(long context); + + private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); + + private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); + + private static native void secp256k1_destroy_context(long context); + + private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); + + private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); + + private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); + + private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); + +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java new file mode 100644 index 0000000000..c00d08899b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -0,0 +1,226 @@ +package org.bitcoin; + +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.math.BigInteger; +import javax.xml.bind.DatatypeConverter; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + * This class holds test cases defined for testing this library. + */ +public class NativeSecp256k1Test { + + //TODO improve comments/add more tests + /** + * This tests verify() for a valid signature + */ + public static void testVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + assertEquals( result, true , "testVerifyPos"); + } + + /** + * This tests verify() for a non-valid signature + */ + public static void testVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testVerifyNeg"); + } + + /** + * This tests secret key verify() for a valid secretkey + */ + public static void testSecKeyVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, true , "testSecKeyVerifyPos"); + } + + /** + * This tests secret key verify() for a invalid secretkey + */ + public static void testSecKeyVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testSecKeyVerifyNeg"); + } + + /** + * This tests public key create() for a valid secretkey + */ + public static void testPubKeyCreatePos() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); + } + + /** + * This tests public key create() for a invalid secretkey + */ + public static void testPubKeyCreateNeg() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); + } + + /** + * This tests sign() for a valid secretkey + */ + public static void testSignPos() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); + } + + /** + * This tests sign() for a invalid secretkey + */ + public static void testSignNeg() throws AssertFailException{ + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "" , "testSignNeg"); + } + + /** + * This tests private key tweak-add + */ + public static void testPrivKeyTweakAdd_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); + } + + /** + * This tests private key tweak-mul + */ + public static void testPrivKeyTweakMul_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); + } + + /** + * This tests private key tweak-add uncompressed + */ + public static void testPrivKeyTweakAdd_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); + } + + /** + * This tests private key tweak-mul uncompressed + */ + public static void testPrivKeyTweakMul_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); + } + + /** + * This tests seed randomization + */ + public static void testRandomize() throws AssertFailException { + byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" + boolean result = NativeSecp256k1.randomize(seed); + assertEquals( result, true, "testRandomize"); + } + + public static void testCreateECDHSecret() throws AssertFailException{ + + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); + String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); + } + + public static void main(String[] args) throws AssertFailException{ + + + System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); + + assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); + + //Test verify() success/fail + testVerifyPos(); + testVerifyNeg(); + + //Test secKeyVerify() success/fail + testSecKeyVerifyPos(); + testSecKeyVerifyNeg(); + + //Test computePubkey() success/fail + testPubKeyCreatePos(); + testPubKeyCreateNeg(); + + //Test sign() success/fail + testSignPos(); + testSignNeg(); + + //Test privKeyTweakAdd() 1 + testPrivKeyTweakAdd_1(); + + //Test privKeyTweakMul() 2 + testPrivKeyTweakMul_1(); + + //Test privKeyTweakAdd() 3 + testPrivKeyTweakAdd_2(); + + //Test privKeyTweakMul() 4 + testPrivKeyTweakMul_2(); + + //Test randomize() + testRandomize(); + + //Test ECDH + testCreateECDHSecret(); + + NativeSecp256k1.cleanup(); + + System.out.println(" All tests passed." ); + + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java new file mode 100644 index 0000000000..04732ba044 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +public class NativeSecp256k1Util{ + + public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + } + + public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ + if( !val.equals(val2) ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static class AssertFailException extends Exception { + public AssertFailException(String message) { + super( message ); + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java new file mode 100644 index 0000000000..216c986a8b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +/** + * This class holds the context reference used in native methods + * to handle ECDSA operations. + */ +public class Secp256k1Context { + private static final boolean enabled; //true if the library is loaded + private static final long context; //ref to pointer to context obj + + static { //static initializer + boolean isEnabled = true; + long contextRef = -1; + try { + System.loadLibrary("secp256k1"); + contextRef = secp256k1_init_context(); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError: " + e.toString()); + isEnabled = false; + } + enabled = isEnabled; + context = contextRef; + } + + public static boolean isEnabled() { + return enabled; + } + + public static long getContext() { + if(!enabled) return -1; //sanity check + return context; + } + + private static native long secp256k1_init_context(); +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c new file mode 100644 index 0000000000..bcef7b32ce --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -0,0 +1,377 @@ +#include +#include +#include +#include "org_bitcoin_NativeSecp256k1.h" +#include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "include/secp256k1_recovery.h" + + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx); + + (void)classObject;(void)env; + + return ctx_clone_l; + +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_context_randomize(ctx, seed); + +} + +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + secp256k1_context_destroy(ctx); + + (void)classObject;(void)env; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* sigdata = { (unsigned char*) (data + 32) }; + const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; + + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pubkey; + + int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); + + if( ret ) { + ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if( ret ) { + ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); + } + } + + (void)classObject; + + return ret; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[2]; + + secp256k1_ecdsa_signature sig[72]; + + int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); + + unsigned char outputSer[72]; + size_t outputLen = 72; + + if( ret ) { + int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_ec_seckey_verify(ctx, secKey); +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + secp256k1_pubkey pubkey; + + jobjectArray retArray; + jbyteArray pubkeyArray, intsByteArray; + unsigned char intsarray[2]; + + int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); + + unsigned char outputSer[65]; + size_t outputLen = 65; + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubkeyArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; + +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; +/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if( ret ) { + ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if ( ret ) { + ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine + (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) +{ + (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; + + return 0; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* pubdata = (const unsigned char*) (secdata + 32); + + jobjectArray retArray; + jbyteArray outArray, intsByteArray; + unsigned char intsarray[1]; + secp256k1_pubkey pubkey; + unsigned char nonce_res[32]; + size_t outputLen = 32; + + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if (ret) { + ret = secp256k1_ecdh( + ctx, + nonce_res, + &pubkey, + secdata + ); + } + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + outArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); + (*env)->SetObjectArrayElement(env, retArray, 0, outArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h new file mode 100644 index 0000000000..fe613c9e9e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -0,0 +1,119 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_NativeSecp256k1 */ + +#ifndef _Included_org_bitcoin_NativeSecp256k1 +#define _Included_org_bitcoin_NativeSecp256k1 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ctx_clone + * Signature: (J)J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_context_randomize + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_destroy_context + * Signature: (J)V + */ +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_verify + * Signature: (Ljava/nio/ByteBuffer;JII)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv *, jclass, jobject, jlong, jint, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_seckey_verify + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_create + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_parse + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdh + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c new file mode 100644 index 0000000000..a52939e7e7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c @@ -0,0 +1,15 @@ +#include +#include +#include "org_bitcoin_Secp256k1Context.h" +#include "include/secp256k1.h" + +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv* env, jclass classObject) +{ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + (void)classObject;(void)env; + + return (uintptr_t)ctx; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h new file mode 100644 index 0000000000..0d2bc84b7f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_Secp256k1Context */ + +#ifndef _Included_org_bitcoin_Secp256k1Context +#define _Included_org_bitcoin_Secp256k1Context +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_Secp256k1Context + * Method: secp256k1_init_context + * Signature: ()J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include new file mode 100644 index 0000000000..e3088b4697 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/secp256k1_ecdh.h +noinst_HEADERS += src/modules/ecdh/main_impl.h +noinst_HEADERS += src/modules/ecdh/tests_impl.h +if USE_BENCHMARK +noinst_PROGRAMS += bench_ecdh +bench_ecdh_SOURCES = src/bench_ecdh.c +bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h new file mode 100644 index 0000000000..9e30fb73dd --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h @@ -0,0 +1,54 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_ECDH_MAIN_ +#define _SECP256K1_MODULE_ECDH_MAIN_ + +#include "include/secp256k1_ecdh.h" +#include "ecmult_const_impl.h" + +int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { + int ret = 0; + int overflow = 0; + secp256k1_gej res; + secp256k1_ge pt; + secp256k1_scalar s; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(result != NULL); + ARG_CHECK(point != NULL); + ARG_CHECK(scalar != NULL); + + secp256k1_pubkey_load(ctx, &pt, point); + secp256k1_scalar_set_b32(&s, scalar, &overflow); + if (overflow || secp256k1_scalar_is_zero(&s)) { + ret = 0; + } else { + unsigned char x[32]; + unsigned char y[1]; + secp256k1_sha256_t sha; + + secp256k1_ecmult_const(&res, &pt, &s); + secp256k1_ge_set_gej(&pt, &res); + /* Compute a hash of the point in compressed form + * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not + * expect its output to be secret and has a timing sidechannel. */ + secp256k1_fe_normalize(&pt.x); + secp256k1_fe_normalize(&pt.y); + secp256k1_fe_get_b32(x, &pt.x); + y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); + + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, y, sizeof(y)); + secp256k1_sha256_write(&sha, x, sizeof(x)); + secp256k1_sha256_finalize(&sha, result); + ret = 1; + } + + secp256k1_scalar_clear(&s); + return ret; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h new file mode 100644 index 0000000000..85a5d0a9a6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h @@ -0,0 +1,105 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_ECDH_TESTS_ +#define _SECP256K1_MODULE_ECDH_TESTS_ + +void test_ecdh_api(void) { + /* Setup context that just counts errors */ + secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_pubkey point; + unsigned char res[32]; + unsigned char s_one[32] = { 0 }; + int32_t ecount = 0; + s_one[31] = 1; + + secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); + + /* Check all NULLs are detected */ + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 3); + + /* Cleanup */ + secp256k1_context_destroy(tctx); +} + +void test_ecdh_generator_basepoint(void) { + unsigned char s_one[32] = { 0 }; + secp256k1_pubkey point[2]; + int i; + + s_one[31] = 1; + /* Check against pubkey creation when the basepoint is the generator */ + for (i = 0; i < 100; ++i) { + secp256k1_sha256_t sha; + unsigned char s_b32[32]; + unsigned char output_ecdh[32]; + unsigned char output_ser[32]; + unsigned char point_ser[33]; + size_t point_ser_len = sizeof(point_ser); + secp256k1_scalar s; + + random_scalar_order(&s); + secp256k1_scalar_get_b32(s_b32, &s); + + /* compute using ECDH function */ + CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); + CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); + /* compute "explicitly" */ + CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); + CHECK(point_ser_len == sizeof(point_ser)); + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, point_ser, point_ser_len); + secp256k1_sha256_finalize(&sha, output_ser); + /* compare */ + CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); + } +} + +void test_bad_scalar(void) { + unsigned char s_zero[32] = { 0 }; + unsigned char s_overflow[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 + }; + unsigned char s_rand[32] = { 0 }; + unsigned char output[32]; + secp256k1_scalar rand; + secp256k1_pubkey point; + + /* Create random point */ + random_scalar_order(&rand); + secp256k1_scalar_get_b32(s_rand, &rand); + CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); + + /* Try to multiply it by bad values */ + CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); + CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); + /* ...and a good one */ + s_overflow[31] -= 1; + CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); +} + +void run_ecdh_tests(void) { + test_ecdh_api(); + test_ecdh_generator_basepoint(); + test_bad_scalar(); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include new file mode 100644 index 0000000000..bf23c26e71 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/secp256k1_recovery.h +noinst_HEADERS += src/modules/recovery/main_impl.h +noinst_HEADERS += src/modules/recovery/tests_impl.h +if USE_BENCHMARK +noinst_PROGRAMS += bench_recover +bench_recover_SOURCES = src/bench_recover.c +bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h new file mode 100644 index 0000000000..c6fbe23981 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h @@ -0,0 +1,193 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ +#define _SECP256K1_MODULE_RECOVERY_MAIN_ + +#include "include/secp256k1_recovery.h" + +static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { + (void)ctx; + if (sizeof(secp256k1_scalar) == 32) { + /* When the secp256k1_scalar type is exactly 32 byte, use its + * representation inside secp256k1_ecdsa_signature, as conversion is very fast. + * Note that secp256k1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); + } + *recid = sig->data[64]; +} + +static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { + if (sizeof(secp256k1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); + } + sig->data[64] = recid; +} + +int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { + secp256k1_scalar r, s; + int ret = 1; + int overflow = 0; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + ARG_CHECK(recid >= 0 && recid <= 3); + + secp256k1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + secp256k1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { + secp256k1_scalar r, s; + + (void)ctx; + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(recid != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); + secp256k1_scalar_get_b32(&output64[0], &r); + secp256k1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { + secp256k1_scalar r, s; + int recid; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(sigin != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); + secp256k1_ecdsa_signature_save(sig, &r, &s); + return 1; +} + +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { + unsigned char brx[32]; + secp256k1_fe fx; + secp256k1_ge x; + secp256k1_gej xj; + secp256k1_scalar rn, u1, u2; + secp256k1_gej qj; + int r; + + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { + return 0; + } + + secp256k1_scalar_get_b32(brx, sigr); + r = secp256k1_fe_set_b32(&fx, brx); + (void)r; + VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ + if (recid & 2) { + if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { + return 0; + } + secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); + } + if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { + return 0; + } + secp256k1_gej_set_ge(&xj, &x); + secp256k1_scalar_inverse_var(&rn, sigr); + secp256k1_scalar_mul(&u1, &rn, message); + secp256k1_scalar_negate(&u1, &u1); + secp256k1_scalar_mul(&u2, &rn, sigs); + secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); + secp256k1_ge_set_gej_var(pubkey, &qj); + return !secp256k1_gej_is_infinity(&qj); +} + +int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { + secp256k1_scalar r, s; + secp256k1_scalar sec, non, msg; + int recid; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !secp256k1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + secp256k1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + if (!secp256k1_scalar_is_zero(&non) && !overflow) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + } + if (ret) { + secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { + secp256k1_ge q; + secp256k1_scalar r, s; + secp256k1_scalar m; + int recid; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(pubkey != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); + VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ + secp256k1_scalar_set_b32(&m, msg32, NULL); + if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { + secp256k1_pubkey_save(pubkey, &q); + return 1; + } else { + memset(pubkey, 0, sizeof(*pubkey)); + return 0; + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h new file mode 100644 index 0000000000..765c7dd81e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h @@ -0,0 +1,393 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ +#define _SECP256K1_MODULE_RECOVERY_TESTS_ + +static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void) msg32; + (void) key32; + (void) algo16; + (void) data; + + /* On the first run, return 0 to force a second run */ + if (counter == 0) { + memset(nonce32, 0, 32); + return 1; + } + /* On the second run, return an overflow to force a third run */ + if (counter == 1) { + memset(nonce32, 0xff, 32); + return 1; + } + /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ + memset(nonce32, 1, 32); + return secp256k1_rand_bits(1); +} + +void test_ecdsa_recovery_api(void) { + /* Setup contexts that just count errors */ + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + secp256k1_ecdsa_signature normal_sig; + secp256k1_ecdsa_recoverable_signature recsig; + unsigned char privkey[32] = { 1 }; + unsigned char message[32] = { 2 }; + int32_t ecount = 0; + int recid = 0; + unsigned char sig[74]; + unsigned char zero_privkey[32] = { 0 }; + unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Check bad contexts and NULLs for signing */ + ecount = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); + CHECK(ecount == 5); + /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ + secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); + CHECK(ecount == 5); + /* These will all fail, but not in ARG_CHECK way */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); + /* This one will succeed. */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 5); + + /* Check signing with a goofy nonce function */ + + /* Check bad contexts and NULLs for recovery */ + ecount = 0; + CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); + CHECK(ecount == 5); + + /* Check NULLs for conversion */ + CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); + + /* Check NULLs for de/serialization */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); + CHECK(ecount == 7); + /* overflow in signature will fail but not affect ecount */ + memcpy(sig, over_privkey, 32); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); + CHECK(ecount == 7); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); +} + +void test_ecdsa_recovery_end_to_end(void) { + unsigned char extra[32] = {0x00}; + unsigned char privkey[32]; + unsigned char message[32]; + secp256k1_ecdsa_signature signature[5]; + secp256k1_ecdsa_recoverable_signature rsignature[5]; + unsigned char sig[74]; + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + int recid = 0; + + /* Generate a random key and message. */ + { + secp256k1_scalar msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(privkey, &key); + secp256k1_scalar_get_b32(message, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Serialize/parse compact and verify/recover. */ + extra[0] = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(memcmp(&signature[4], &signature[0], 64) == 0); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + memset(&rsignature[4], 0, sizeof(rsignature[4])); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + /* Parse compact (with recovery id) and recover. */ + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); + CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); + /* Serialize/destroy/parse signature and verify again. */ + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + sig[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); + /* Recover again */ + CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || + memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); +} + +/* Tests several edge cases. */ +void test_ecdsa_recovery_edge_cases(void) { + const unsigned char msg32[32] = { + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', + 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', + 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', + 's', 's', 'a', 'g', 'e', '.', '.', '.' + }; + const unsigned char sig64[64] = { + /* Generated by signing the above message with nonce 'This is the nonce we will use...' + * and secret key 0 (which is not valid), resulting in recid 0. */ + 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, + 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, + 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, + 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, + 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, + 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, + 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, + 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 + }; + secp256k1_pubkey pubkey; + /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ + const unsigned char sigb64[64] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + }; + secp256k1_pubkey pubkeyb; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + int recid; + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + + for (recid = 0; recid < 4; recid++) { + int i; + int recid2; + /* (4,4) encoded in DER. */ + unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; + unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; + unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; + unsigned char sigbderalt1[39] = { + 0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, + }; + unsigned char sigbderalt2[39] = { + 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + }; + unsigned char sigbderalt3[40] = { + 0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, + }; + unsigned char sigbderalt4[40] = { + 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + }; + /* (order + r,4) encoded in DER. */ + unsigned char sigbderlong[40] = { + 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, + 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, + 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 + }; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); + for (recid2 = 0; recid2 < 4; recid2++) { + secp256k1_pubkey pubkey2b; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); + /* Verifying with (order + r,4) should always fail. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + } + /* DER parsing tests. */ + /* Zero length r/s. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); + /* Leading zeros. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); + sigbderalt3[4] = 1; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbderalt4[7] = 1; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + /* Damage signature. */ + sigbder[7]++; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbder[7]--; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); + for(i = 0; i < 8; i++) { + int c; + unsigned char orig = sigbder[i]; + /*Try every single-byte change.*/ + for (c = 0; c < 256; c++) { + if (c == orig ) { + continue; + } + sigbder[i] = c; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + } + sigbder[i] = orig; + } + } + + /* Test r/s equal to zero */ + { + /* (1,1) encoded in DER. */ + unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; + unsigned char sigc64[64] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }; + secp256k1_pubkey pubkeyc; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); + sigcder[4] = 0; + sigc64[31] = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); + sigcder[4] = 1; + sigcder[7] = 0; + sigc64[31] = 1; + sigc64[63] = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); + } +} + +void run_recovery_tests(void) { + int i; + for (i = 0; i < count; i++) { + test_ecdsa_recovery_api(); + } + for (i = 0; i < 64*count; i++) { + test_ecdsa_recovery_end_to_end(); + } + test_ecdsa_recovery_edge_cases(); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h new file mode 100644 index 0000000000..eff842200f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h @@ -0,0 +1,74 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_ +#define _SECP256K1_NUM_ + +#ifndef USE_NUM_NONE + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_NUM_GMP) +#include "num_gmp.h" +#else +#error "Please select num implementation" +#endif + +/** Copy a number. */ +static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a); + +/** Convert a number's absolute value to a binary big-endian string. + * There must be enough place. */ +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a); + +/** Set a number to the value of a binary big-endian string. */ +static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen); + +/** Compute a modular inverse. The input must be less than the modulus. */ +static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); + +/** Compute the jacobi symbol (a|b). b must be positive and odd. */ +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); + +/** Compare the absolute value of two numbers. */ +static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); + +/** Test whether two number are equal (including sign). */ +static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b); + +/** Add two (signed) numbers. */ +static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Subtract two (signed) numbers. */ +static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Multiply two (signed) numbers. */ +static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, + even if r was negative. */ +static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m); + +/** Right-shift the passed number by bits. */ +static void secp256k1_num_shift(secp256k1_num *r, int bits); + +/** Check whether a number is zero. */ +static int secp256k1_num_is_zero(const secp256k1_num *a); + +/** Check whether a number is one. */ +static int secp256k1_num_is_one(const secp256k1_num *a); + +/** Check whether a number is strictly negative. */ +static int secp256k1_num_is_neg(const secp256k1_num *a); + +/** Change a number's sign. */ +static void secp256k1_num_negate(secp256k1_num *r); + +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h new file mode 100644 index 0000000000..7dd813088a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h @@ -0,0 +1,20 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_ +#define _SECP256K1_NUM_REPR_ + +#include + +#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) + +typedef struct { + mp_limb_t data[2*NUM_LIMBS]; + int neg; + int limbs; +} secp256k1_num; + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h new file mode 100644 index 0000000000..3a46495eea --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h @@ -0,0 +1,288 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_IMPL_H_ +#define _SECP256K1_NUM_REPR_IMPL_H_ + +#include +#include +#include + +#include "util.h" +#include "num.h" + +#ifdef VERIFY +static void secp256k1_num_sanity(const secp256k1_num *a) { + VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); +} +#else +#define secp256k1_num_sanity(a) do { } while(0) +#endif + +static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { + *r = *a; +} + +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { + unsigned char tmp[65]; + int len = 0; + int shift = 0; + if (a->limbs>1 || a->data[0] != 0) { + len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); + } + while (shift < len && tmp[shift] == 0) shift++; + VERIFY_CHECK(len-shift <= (int)rlen); + memset(r, 0, rlen - len + shift); + if (len > shift) { + memcpy(r + rlen - len + shift, tmp + shift, len - shift); + } + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { + int len; + VERIFY_CHECK(alen > 0); + VERIFY_CHECK(alen <= 64); + len = mpn_set_str(r->data, a, alen, 256); + if (len == 0) { + r->data[0] = 0; + len = 1; + } + VERIFY_CHECK(len <= NUM_LIMBS*2); + r->limbs = len; + r->neg = 0; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); + r->limbs = a->limbs; + if (c != 0) { + VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); + r->data[r->limbs++] = c; + } +} + +static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); + (void)c; + VERIFY_CHECK(c == 0); + r->limbs = a->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { + secp256k1_num_sanity(r); + secp256k1_num_sanity(m); + + if (r->limbs >= m->limbs) { + mp_limb_t t[2*NUM_LIMBS]; + mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); + memset(t, 0, sizeof(t)); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } + } + + if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { + secp256k1_num_sub_abs(r, m, r); + r->neg = 0; + } +} + +static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) { + int i; + mp_limb_t g[NUM_LIMBS+1]; + mp_limb_t u[NUM_LIMBS+1]; + mp_limb_t v[NUM_LIMBS+1]; + mp_size_t sn; + mp_size_t gn; + secp256k1_num_sanity(a); + secp256k1_num_sanity(m); + + /** mpn_gcdext computes: (G,S) = gcdext(U,V), where + * * G = gcd(U,V) + * * G = U*S + V*T + * * U has equal or more limbs than V, and V has no padding + * If we set U to be (a padded version of) a, and V = m: + * G = a*S + m*T + * G = a*S mod m + * Assuming G=1: + * S = 1/a mod m + */ + VERIFY_CHECK(m->limbs <= NUM_LIMBS); + VERIFY_CHECK(m->data[m->limbs-1] != 0); + for (i = 0; i < m->limbs; i++) { + u[i] = (i < a->limbs) ? a->data[i] : 0; + v[i] = m->data[i]; + } + sn = NUM_LIMBS+1; + gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); + (void)gn; + VERIFY_CHECK(gn == 1); + VERIFY_CHECK(g[0] == 1); + r->neg = a->neg ^ m->neg; + if (sn < 0) { + mpn_sub(r->data, m->data, m->limbs, r->data, -sn); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } + } else { + r->limbs = sn; + } + memset(g, 0, sizeof(g)); + memset(u, 0, sizeof(u)); + memset(v, 0, sizeof(v)); +} + +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { + int ret; + mpz_t ga, gb; + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); + + mpz_inits(ga, gb, NULL); + + mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); + mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); + if (a->neg) { + mpz_neg(ga, ga); + } + + ret = mpz_jacobi(ga, gb); + + mpz_clears(ga, gb, NULL); + + return ret; +} + +static int secp256k1_num_is_one(const secp256k1_num *a) { + return (a->limbs == 1 && a->data[0] == 1); +} + +static int secp256k1_num_is_zero(const secp256k1_num *a) { + return (a->limbs == 1 && a->data[0] == 0); +} + +static int secp256k1_num_is_neg(const secp256k1_num *a) { + return (a->limbs > 1 || a->data[0] != 0) && a->neg; +} + +static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { + if (a->limbs > b->limbs) { + return 1; + } + if (a->limbs < b->limbs) { + return -1; + } + return mpn_cmp(a->data, b->data, a->limbs); +} + +static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { + if (a->limbs > b->limbs) { + return 0; + } + if (a->limbs < b->limbs) { + return 0; + } + if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) { + return 0; + } + return mpn_cmp(a->data, b->data, a->limbs) == 0; +} + +static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) { + if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ + r->neg = a->neg; + if (a->limbs >= b->limbs) { + secp256k1_num_add_abs(r, a, b); + } else { + secp256k1_num_add_abs(r, b, a); + } + } else { + if (secp256k1_num_cmp(a, b) > 0) { + r->neg = a->neg; + secp256k1_num_sub_abs(r, a, b); + } else { + r->neg = b->neg ^ bneg; + secp256k1_num_sub_abs(r, b, a); + } + } +} + +static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 0); +} + +static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 1); +} + +static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t tmp[2*NUM_LIMBS+1]; + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + + VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); + if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { + r->limbs = 1; + r->neg = 0; + r->data[0] = 0; + return; + } + if (a->limbs >= b->limbs) { + mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); + } else { + mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); + } + r->limbs = a->limbs + b->limbs; + if (r->limbs > 1 && tmp[r->limbs - 1]==0) { + r->limbs--; + } + VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); + mpn_copyi(r->data, tmp, r->limbs); + r->neg = a->neg ^ b->neg; + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_shift(secp256k1_num *r, int bits) { + if (bits % GMP_NUMB_BITS) { + /* Shift within limbs. */ + mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); + } + if (bits >= GMP_NUMB_BITS) { + int i; + /* Shift full limbs. */ + for (i = 0; i < r->limbs; i++) { + int index = i + (bits / GMP_NUMB_BITS); + if (index < r->limbs && index < 2*NUM_LIMBS) { + r->data[i] = r->data[index]; + } else { + r->data[i] = 0; + } + } + } + while (r->limbs>1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_negate(secp256k1_num *r) { + r->neg ^= 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h new file mode 100644 index 0000000000..0b0e3a072a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h @@ -0,0 +1,24 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_IMPL_H_ +#define _SECP256K1_NUM_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "num.h" + +#if defined(USE_NUM_GMP) +#include "num_gmp_impl.h" +#elif defined(USE_NUM_NONE) +/* Nothing. */ +#else +#error "Please select num implementation" +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h new file mode 100644 index 0000000000..27e9d8375e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h @@ -0,0 +1,106 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_ +#define _SECP256K1_SCALAR_ + +#include "num.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32.h" +#else +#error "Please select scalar implementation" +#endif + +/** Clear a scalar to prevent the leak of sensitive data. */ +static void secp256k1_scalar_clear(secp256k1_scalar *r); + +/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ +static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); + +/** Access bits from a scalar. Not constant time. */ +static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); + +/** Set a scalar from a big endian byte array. */ +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); + +/** Set a scalar to an unsigned integer. */ +static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); + +/** Convert a scalar to a byte array. */ +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); + +/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); + +/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); + +/** Multiply two scalars (modulo the group order). */ +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); + +/** Shift a scalar right by some amount strictly between 0 and 16, returning + * the low bits that were shifted off */ +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); + +/** Compute the square of a scalar (modulo the group order). */ +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order). */ +static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ +static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the complement of a scalar (modulo the group order). */ +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Check whether a scalar equals zero. */ +static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); + +/** Check whether a scalar equals one. */ +static int secp256k1_scalar_is_one(const secp256k1_scalar *a); + +/** Check whether a scalar, considered as an nonnegative integer, is even. */ +static int secp256k1_scalar_is_even(const secp256k1_scalar *a); + +/** Check whether a scalar is higher than the group order divided by 2. */ +static int secp256k1_scalar_is_high(const secp256k1_scalar *a); + +/** Conditionally negate a number, in constant time. + * Returns -1 if the number was negated, 1 otherwise */ +static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); + +#ifndef USE_NUM_NONE +/** Convert a scalar to a number. */ +static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); + +/** Get the order of the group as a number. */ +static void secp256k1_scalar_order_get_num(secp256k1_num *r); +#endif + +/** Compare two scalars. */ +static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); + +#ifdef USE_ENDOMORPHISM +/** Find r1 and r2 such that r1+r2*2^128 = a. */ +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); +/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); +#endif + +/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ +static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h new file mode 100644 index 0000000000..cff406038f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint64_t d[4]; +} secp256k1_scalar; + +#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h new file mode 100644 index 0000000000..56e7bd82af --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h @@ -0,0 +1,949 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) +#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) +#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) +#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) +#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) +#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); + return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 6 == offset >> 6) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 6) + 1 < 4); + return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); + } +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ + no |= (a->d[2] < SECP256K1_N_2); + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1); + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { + uint128_t t; + VERIFY_CHECK(overflow <= 1); + t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint64_t)r->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; + return overflow; +} + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + int overflow; + uint128_t t = (uint128_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + overflow = t + secp256k1_scalar_check_overflow(r); + VERIFY_CHECK(overflow == 0 || overflow == 1); + secp256k1_scalar_reduce(r, overflow); + return overflow; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + uint128_t t; + VERIFY_CHECK(bit < 256); + bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ + t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 64) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + int over; + r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; + r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; + r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; + r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; + over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; + bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; + bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; + bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); + uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_H_3); + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + /* If we are flag = 0, mask = 00...00 and this is a no-op; + * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ + uint64_t mask = !flag - 1; + uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; + uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + r->d[0] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); + r->d[1] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); + r->d[2] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); + r->d[3] = t & nonzero; + return 2 * (mask == 0) - 1; +} + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint64_t tl, th, th2, tl2; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + unsigned int over; \ + c0 += (a); /* overflow is handled on the next line */ \ + over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { +#ifdef USE_ASM_X86_64 + /* Reduce 512 bits into 385. */ + uint64_t m0, m1, m2, m3, m4, m5, m6; + uint64_t p0, p1, p2, p3, p4; + uint64_t c; + + __asm__ __volatile__( + /* Preload. */ + "movq 32(%%rsi), %%r11\n" + "movq 40(%%rsi), %%r12\n" + "movq 48(%%rsi), %%r13\n" + "movq 56(%%rsi), %%r14\n" + /* Initialize r8,r9,r10 */ + "movq 0(%%rsi), %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9) += n0 * c0 */ + "movq %8, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* extract m0 */ + "movq %%r8, %q0\n" + "xorq %%r8, %%r8\n" + /* (r9,r10) += l1 */ + "addq 8(%%rsi), %%r9\n" + "adcq $0, %%r10\n" + /* (r9,r10,r8) += n1 * c0 */ + "movq %8, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += n0 * c1 */ + "movq %9, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* extract m1 */ + "movq %%r9, %q1\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += l2 */ + "addq 16(%%rsi), %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n2 * c0 */ + "movq %8, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n1 * c1 */ + "movq %9, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n0 */ + "addq %%r11, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* extract m2 */ + "movq %%r10, %q2\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += l3 */ + "addq 24(%%rsi), %%r8\n" + "adcq $0, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n3 * c0 */ + "movq %8, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n2 * c1 */ + "movq %9, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n1 */ + "addq %%r12, %%r8\n" + "adcq $0, %%r9\n" + "adcq $0, %%r10\n" + /* extract m3 */ + "movq %%r8, %q3\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += n3 * c1 */ + "movq %9, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += n2 */ + "addq %%r13, %%r9\n" + "adcq $0, %%r10\n" + "adcq $0, %%r8\n" + /* extract m4 */ + "movq %%r9, %q4\n" + /* (r10,r8) += n3 */ + "addq %%r14, %%r10\n" + "adcq $0, %%r8\n" + /* extract m5 */ + "movq %%r10, %q5\n" + /* extract m6 */ + "movq %%r8, %q6\n" + : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) + : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); + + /* Reduce 385 bits into 258. */ + __asm__ __volatile__( + /* Preload */ + "movq %q9, %%r11\n" + "movq %q10, %%r12\n" + "movq %q11, %%r13\n" + /* Initialize (r8,r9,r10) */ + "movq %q5, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9) += m4 * c0 */ + "movq %12, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* extract p0 */ + "movq %%r8, %q0\n" + "xorq %%r8, %%r8\n" + /* (r9,r10) += m1 */ + "addq %q6, %%r9\n" + "adcq $0, %%r10\n" + /* (r9,r10,r8) += m5 * c0 */ + "movq %12, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += m4 * c1 */ + "movq %13, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* extract p1 */ + "movq %%r9, %q1\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += m2 */ + "addq %q7, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m6 * c0 */ + "movq %12, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m5 * c1 */ + "movq %13, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m4 */ + "addq %%r11, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* extract p2 */ + "movq %%r10, %q2\n" + /* (r8,r9) += m3 */ + "addq %q8, %%r8\n" + "adcq $0, %%r9\n" + /* (r8,r9) += m6 * c1 */ + "movq %13, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* (r8,r9) += m5 */ + "addq %%r12, %%r8\n" + "adcq $0, %%r9\n" + /* extract p3 */ + "movq %%r8, %q3\n" + /* (r9) += m6 */ + "addq %%r13, %%r9\n" + /* extract p4 */ + "movq %%r9, %q4\n" + : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) + : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); + + /* Reduce 258 bits into 256. */ + __asm__ __volatile__( + /* Preload */ + "movq %q5, %%r10\n" + /* (rax,rdx) = p4 * c0 */ + "movq %7, %%rax\n" + "mulq %%r10\n" + /* (rax,rdx) += p0 */ + "addq %q1, %%rax\n" + "adcq $0, %%rdx\n" + /* extract r0 */ + "movq %%rax, 0(%q6)\n" + /* Move to (r8,r9) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + /* (r8,r9) += p1 */ + "addq %q2, %%r8\n" + "adcq $0, %%r9\n" + /* (r8,r9) += p4 * c1 */ + "movq %8, %%rax\n" + "mulq %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* Extract r1 */ + "movq %%r8, 8(%q6)\n" + "xorq %%r8, %%r8\n" + /* (r9,r8) += p4 */ + "addq %%r10, %%r9\n" + "adcq $0, %%r8\n" + /* (r9,r8) += p2 */ + "addq %q3, %%r9\n" + "adcq $0, %%r8\n" + /* Extract r2 */ + "movq %%r9, 16(%q6)\n" + "xorq %%r9, %%r9\n" + /* (r8,r9) += p3 */ + "addq %q4, %%r8\n" + "adcq $0, %%r9\n" + /* Extract r3 */ + "movq %%r8, 24(%q6)\n" + /* Extract c */ + "movq %%r9, %q0\n" + : "=g"(c) + : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); +#else + uint128_t c; + uint64_t c0, c1, c2; + uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; + uint64_t m0, m1, m2, m3, m4, m5; + uint32_t m6; + uint64_t p0, p1, p2, p3; + uint32_t p4; + + /* Reduce 512 bits into 385. */ + /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + sumadd(n0); + extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + sumadd(n1); + extract(m3); + muladd(n3, SECP256K1_N_C_1); + sumadd(n2); + extract(m4); + sumadd_fast(n3); + extract_fast(m5); + VERIFY_CHECK(c0 <= 1); + m6 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m4, SECP256K1_N_C_0); + extract_fast(p0); + sumadd_fast(m1); + muladd(m5, SECP256K1_N_C_0); + muladd(m4, SECP256K1_N_C_1); + extract(p1); + sumadd(m2); + muladd(m6, SECP256K1_N_C_0); + muladd(m5, SECP256K1_N_C_1); + sumadd(m4); + extract(p2); + sumadd_fast(m3); + muladd_fast(m6, SECP256K1_N_C_1); + sumadd_fast(m5); + extract_fast(p3); + p4 = c0 + m6; + VERIFY_CHECK(p4 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ + c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; + r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; + r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p2 + (uint128_t)p4; + r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p3; + r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; +#endif + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { +#ifdef USE_ASM_X86_64 + const uint64_t *pb = b->d; + __asm__ __volatile__( + /* Preload */ + "movq 0(%%rdi), %%r15\n" + "movq 8(%%rdi), %%rbx\n" + "movq 16(%%rdi), %%rcx\n" + "movq 0(%%rdx), %%r11\n" + "movq 8(%%rdx), %%r12\n" + "movq 16(%%rdx), %%r13\n" + "movq 24(%%rdx), %%r14\n" + /* (rax,rdx) = a0 * b0 */ + "movq %%r15, %%rax\n" + "mulq %%r11\n" + /* Extract l0 */ + "movq %%rax, 0(%%rsi)\n" + /* (r8,r9,r10) = (rdx) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += a0 * b1 */ + "movq %%r15, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a1 * b0 */ + "movq %%rbx, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l1 */ + "movq %%r8, 8(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += a0 * b2 */ + "movq %%r15, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a1 * b1 */ + "movq %%rbx, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a2 * b0 */ + "movq %%rcx, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l2 */ + "movq %%r9, 16(%%rsi)\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += a0 * b3 */ + "movq %%r15, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Preload a3 */ + "movq 24(%%rdi), %%r15\n" + /* (r10,r8,r9) += a1 * b2 */ + "movq %%rbx, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += a2 * b1 */ + "movq %%rcx, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += a3 * b0 */ + "movq %%r15, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Extract l3 */ + "movq %%r10, 24(%%rsi)\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += a1 * b3 */ + "movq %%rbx, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a2 * b2 */ + "movq %%rcx, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a3 * b1 */ + "movq %%r15, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l4 */ + "movq %%r8, 32(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += a2 * b3 */ + "movq %%rcx, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a3 * b2 */ + "movq %%r15, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l5 */ + "movq %%r9, 40(%%rsi)\n" + /* (r10,r8) += a3 * b3 */ + "movq %%r15, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + /* Extract l6 */ + "movq %%r10, 48(%%rsi)\n" + /* Extract l7 */ + "movq %%r8, 56(%%rsi)\n" + : "+d"(pb) + : "S"(l), "D"(a->d) + : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); +#else + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + extract(l[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + extract(l[5]); + muladd_fast(a->d[3], b->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 == 0); + l[7] = c0; +#endif +} + +static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { +#ifdef USE_ASM_X86_64 + __asm__ __volatile__( + /* Preload */ + "movq 0(%%rdi), %%r11\n" + "movq 8(%%rdi), %%r12\n" + "movq 16(%%rdi), %%r13\n" + "movq 24(%%rdi), %%r14\n" + /* (rax,rdx) = a0 * a0 */ + "movq %%r11, %%rax\n" + "mulq %%r11\n" + /* Extract l0 */ + "movq %%rax, 0(%%rsi)\n" + /* (r8,r9,r10) = (rdx,0) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += 2 * a0 * a1 */ + "movq %%r11, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l1 */ + "movq %%r8, 8(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += 2 * a0 * a2 */ + "movq %%r11, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a1 * a1 */ + "movq %%r12, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l2 */ + "movq %%r9, 16(%%rsi)\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += 2 * a0 * a3 */ + "movq %%r11, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += 2 * a1 * a2 */ + "movq %%r12, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Extract l3 */ + "movq %%r10, 24(%%rsi)\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += 2 * a1 * a3 */ + "movq %%r12, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a2 * a2 */ + "movq %%r13, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l4 */ + "movq %%r8, 32(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += 2 * a2 * a3 */ + "movq %%r13, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l5 */ + "movq %%r9, 40(%%rsi)\n" + /* (r10,r8) += a3 * a3 */ + "movq %%r14, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + /* Extract l6 */ + "movq %%r10, 48(%%rsi)\n" + /* Extract l7 */ + "movq %%r8, 56(%%rsi)\n" + : + : "S"(l), "D"(a->d) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); +#else + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd_fast(a->d[3], a->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 == 0); + l[7] = c0; +#endif +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + uint64_t l[8]; + secp256k1_scalar_mul_512(l, a, b); + secp256k1_scalar_reduce_512(r, l); +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); + r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); + r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); + r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); + r->d[3] = (r->d[3] >> n); + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint64_t l[8]; + secp256k1_scalar_sqr_512(l, a); + secp256k1_scalar_reduce_512(r, l); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = 0; + r1->d[3] = 0; + r2->d[0] = a->d[2]; + r2->d[1] = a->d[3]; + r2->d[2] = 0; + r2->d[3] = 0; +} +#endif + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { + uint64_t l[8]; + unsigned int shiftlimbs; + unsigned int shiftlow; + unsigned int shifthigh; + VERIFY_CHECK(shift >= 256); + secp256k1_scalar_mul_512(l, a, b); + shiftlimbs = shift >> 6; + shiftlow = shift & 0x3F; + shifthigh = 64 - shiftlow; + r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; + secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h new file mode 100644 index 0000000000..1319664f65 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint32_t d[8]; +} secp256k1_scalar; + +#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h new file mode 100644 index 0000000000..aae4f35c08 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h @@ -0,0 +1,721 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) +#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) +#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) +#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) +#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) +#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (~SECP256K1_N_2) +#define SECP256K1_N_C_3 (~SECP256K1_N_3) +#define SECP256K1_N_C_4 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) +#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) +#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) +#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) +#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); + return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 5 == offset >> 5) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 5) + 1 < 8); + return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); + } +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ + no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_4); + yes |= (a->d[4] > SECP256K1_N_4) & ~no; + no |= (a->d[3] < SECP256K1_N_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_3) & ~no; + no |= (a->d[2] < SECP256K1_N_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { + uint64_t t; + VERIFY_CHECK(overflow <= 1); + t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; + r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; + r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[5]; + r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[6]; + r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[7]; + r->d[7] = t & 0xFFFFFFFFUL; + return overflow; +} + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + int overflow; + uint64_t t = (uint64_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[4] + b->d[4]; + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[5] + b->d[5]; + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[6] + b->d[6]; + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[7] + b->d[7]; + r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; + overflow = t + secp256k1_scalar_check_overflow(r); + VERIFY_CHECK(overflow == 0 || overflow == 1); + secp256k1_scalar_reduce(r, overflow); + return overflow; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + uint64_t t; + VERIFY_CHECK(bit < 256); + bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ + t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); + r->d[7] = t & 0xFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 32) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + int over; + r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; + r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; + r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; + r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; + r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; + r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; + r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; + r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; + over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; + bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; + bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; + bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; + bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; + bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; + bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; + bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); + uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; + r->d[4] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; + r->d[5] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; + r->d[6] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; + r->d[7] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_H_7); + yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; + no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ + no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + /* If we are flag = 0, mask = 00...00 and this is a no-op; + * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ + uint32_t mask = !flag - 1; + uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); + uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + r->d[0] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); + r->d[1] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); + r->d[2] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); + r->d[3] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); + r->d[4] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); + r->d[5] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); + r->d[6] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); + r->d[7] = t & nonzero; + return 2 * (mask == 0) - 1; +} + + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint32_t tl, th, th2, tl2; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + unsigned int over; \ + c0 += (a); /* overflow is handled on the next line */ \ + over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { + uint64_t c; + uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; + uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; + uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; + + /* 96 bit accumulator. */ + uint32_t c0, c1, c2; + + /* Reduce 512 bits into 385. */ + /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + muladd(n0, SECP256K1_N_C_2); + extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + muladd(n1, SECP256K1_N_C_2); + muladd(n0, SECP256K1_N_C_3); + extract(m3); + sumadd(l[4]); + muladd(n4, SECP256K1_N_C_0); + muladd(n3, SECP256K1_N_C_1); + muladd(n2, SECP256K1_N_C_2); + muladd(n1, SECP256K1_N_C_3); + sumadd(n0); + extract(m4); + sumadd(l[5]); + muladd(n5, SECP256K1_N_C_0); + muladd(n4, SECP256K1_N_C_1); + muladd(n3, SECP256K1_N_C_2); + muladd(n2, SECP256K1_N_C_3); + sumadd(n1); + extract(m5); + sumadd(l[6]); + muladd(n6, SECP256K1_N_C_0); + muladd(n5, SECP256K1_N_C_1); + muladd(n4, SECP256K1_N_C_2); + muladd(n3, SECP256K1_N_C_3); + sumadd(n2); + extract(m6); + sumadd(l[7]); + muladd(n7, SECP256K1_N_C_0); + muladd(n6, SECP256K1_N_C_1); + muladd(n5, SECP256K1_N_C_2); + muladd(n4, SECP256K1_N_C_3); + sumadd(n3); + extract(m7); + muladd(n7, SECP256K1_N_C_1); + muladd(n6, SECP256K1_N_C_2); + muladd(n5, SECP256K1_N_C_3); + sumadd(n4); + extract(m8); + muladd(n7, SECP256K1_N_C_2); + muladd(n6, SECP256K1_N_C_3); + sumadd(n5); + extract(m9); + muladd(n7, SECP256K1_N_C_3); + sumadd(n6); + extract(m10); + sumadd_fast(n7); + extract_fast(m11); + VERIFY_CHECK(c0 <= 1); + m12 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m8, SECP256K1_N_C_0); + extract_fast(p0); + sumadd_fast(m1); + muladd(m9, SECP256K1_N_C_0); + muladd(m8, SECP256K1_N_C_1); + extract(p1); + sumadd(m2); + muladd(m10, SECP256K1_N_C_0); + muladd(m9, SECP256K1_N_C_1); + muladd(m8, SECP256K1_N_C_2); + extract(p2); + sumadd(m3); + muladd(m11, SECP256K1_N_C_0); + muladd(m10, SECP256K1_N_C_1); + muladd(m9, SECP256K1_N_C_2); + muladd(m8, SECP256K1_N_C_3); + extract(p3); + sumadd(m4); + muladd(m12, SECP256K1_N_C_0); + muladd(m11, SECP256K1_N_C_1); + muladd(m10, SECP256K1_N_C_2); + muladd(m9, SECP256K1_N_C_3); + sumadd(m8); + extract(p4); + sumadd(m5); + muladd(m12, SECP256K1_N_C_1); + muladd(m11, SECP256K1_N_C_2); + muladd(m10, SECP256K1_N_C_3); + sumadd(m9); + extract(p5); + sumadd(m6); + muladd(m12, SECP256K1_N_C_2); + muladd(m11, SECP256K1_N_C_3); + sumadd(m10); + extract(p6); + sumadd_fast(m7); + muladd_fast(m12, SECP256K1_N_C_3); + sumadd_fast(m11); + extract_fast(p7); + p8 = c0 + m12; + VERIFY_CHECK(p8 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ + c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; + r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; + c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; + r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; + c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; + r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; + c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; + r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; + c += p4 + (uint64_t)p8; + r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; + c += p5; + r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; + c += p6; + r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; + c += p7; + r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + /* l[0..15] = a[0..7] * b[0..7]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[0], b->d[4]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + muladd(a->d[4], b->d[0]); + extract(l[4]); + muladd(a->d[0], b->d[5]); + muladd(a->d[1], b->d[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + muladd(a->d[4], b->d[1]); + muladd(a->d[5], b->d[0]); + extract(l[5]); + muladd(a->d[0], b->d[6]); + muladd(a->d[1], b->d[5]); + muladd(a->d[2], b->d[4]); + muladd(a->d[3], b->d[3]); + muladd(a->d[4], b->d[2]); + muladd(a->d[5], b->d[1]); + muladd(a->d[6], b->d[0]); + extract(l[6]); + muladd(a->d[0], b->d[7]); + muladd(a->d[1], b->d[6]); + muladd(a->d[2], b->d[5]); + muladd(a->d[3], b->d[4]); + muladd(a->d[4], b->d[3]); + muladd(a->d[5], b->d[2]); + muladd(a->d[6], b->d[1]); + muladd(a->d[7], b->d[0]); + extract(l[7]); + muladd(a->d[1], b->d[7]); + muladd(a->d[2], b->d[6]); + muladd(a->d[3], b->d[5]); + muladd(a->d[4], b->d[4]); + muladd(a->d[5], b->d[3]); + muladd(a->d[6], b->d[2]); + muladd(a->d[7], b->d[1]); + extract(l[8]); + muladd(a->d[2], b->d[7]); + muladd(a->d[3], b->d[6]); + muladd(a->d[4], b->d[5]); + muladd(a->d[5], b->d[4]); + muladd(a->d[6], b->d[3]); + muladd(a->d[7], b->d[2]); + extract(l[9]); + muladd(a->d[3], b->d[7]); + muladd(a->d[4], b->d[6]); + muladd(a->d[5], b->d[5]); + muladd(a->d[6], b->d[4]); + muladd(a->d[7], b->d[3]); + extract(l[10]); + muladd(a->d[4], b->d[7]); + muladd(a->d[5], b->d[6]); + muladd(a->d[6], b->d[5]); + muladd(a->d[7], b->d[4]); + extract(l[11]); + muladd(a->d[5], b->d[7]); + muladd(a->d[6], b->d[6]); + muladd(a->d[7], b->d[5]); + extract(l[12]); + muladd(a->d[6], b->d[7]); + muladd(a->d[7], b->d[6]); + extract(l[13]); + muladd_fast(a->d[7], b->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; +} + +static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + /* l[0..15] = a[0..7]^2. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[0], a->d[4]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[0], a->d[5]); + muladd2(a->d[1], a->d[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd2(a->d[0], a->d[6]); + muladd2(a->d[1], a->d[5]); + muladd2(a->d[2], a->d[4]); + muladd(a->d[3], a->d[3]); + extract(l[6]); + muladd2(a->d[0], a->d[7]); + muladd2(a->d[1], a->d[6]); + muladd2(a->d[2], a->d[5]); + muladd2(a->d[3], a->d[4]); + extract(l[7]); + muladd2(a->d[1], a->d[7]); + muladd2(a->d[2], a->d[6]); + muladd2(a->d[3], a->d[5]); + muladd(a->d[4], a->d[4]); + extract(l[8]); + muladd2(a->d[2], a->d[7]); + muladd2(a->d[3], a->d[6]); + muladd2(a->d[4], a->d[5]); + extract(l[9]); + muladd2(a->d[3], a->d[7]); + muladd2(a->d[4], a->d[6]); + muladd(a->d[5], a->d[5]); + extract(l[10]); + muladd2(a->d[4], a->d[7]); + muladd2(a->d[5], a->d[6]); + extract(l[11]); + muladd2(a->d[5], a->d[7]); + muladd(a->d[6], a->d[6]); + extract(l[12]); + muladd2(a->d[6], a->d[7]); + extract(l[13]); + muladd_fast(a->d[7], a->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + uint32_t l[16]; + secp256k1_scalar_mul_512(l, a, b); + secp256k1_scalar_reduce_512(r, l); +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); + r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); + r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); + r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n)); + r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n)); + r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n)); + r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); + r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); + r->d[7] = (r->d[7] >> n); + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint32_t l[16]; + secp256k1_scalar_sqr_512(l, a); + secp256k1_scalar_reduce_512(r, l); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = a->d[2]; + r1->d[3] = a->d[3]; + r1->d[4] = 0; + r1->d[5] = 0; + r1->d[6] = 0; + r1->d[7] = 0; + r2->d[0] = a->d[4]; + r2->d[1] = a->d[5]; + r2->d[2] = a->d[6]; + r2->d[3] = a->d[7]; + r2->d[4] = 0; + r2->d[5] = 0; + r2->d[6] = 0; + r2->d[7] = 0; +} +#endif + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { + uint32_t l[16]; + unsigned int shiftlimbs; + unsigned int shiftlow; + unsigned int shifthigh; + VERIFY_CHECK(shift >= 256); + secp256k1_scalar_mul_512(l, a, b); + shiftlimbs = shift >> 5; + shiftlow = shift & 0x1F; + shifthigh = 32 - shiftlow; + r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; + secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h new file mode 100644 index 0000000000..f5b2376407 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h @@ -0,0 +1,370 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_IMPL_H_ +#define _SECP256K1_SCALAR_IMPL_H_ + +#include "group.h" +#include "scalar.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low_impl.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64_impl.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32_impl.h" +#else +#error "Please select scalar implementation" +#endif + +#ifndef USE_NUM_NONE +static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) { + unsigned char c[32]; + secp256k1_scalar_get_b32(c, a); + secp256k1_num_set_bin(r, c, 32); +} + +/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ +static void secp256k1_scalar_order_get_num(secp256k1_num *r) { +#if defined(EXHAUSTIVE_TEST_ORDER) + static const unsigned char order[32] = { + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER + }; +#else + static const unsigned char order[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 + }; +#endif + secp256k1_num_set_bin(r, order, 32); +} +#endif + +static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { +#if defined(EXHAUSTIVE_TEST_ORDER) + int i; + *r = 0; + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) + if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) + *r = i; + /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus + * have a composite group order; fix it in exhaustive_tests.c). */ + VERIFY_CHECK(*r != 0); +} +#else + secp256k1_scalar *t; + int i; + /* First compute x ^ (2^N - 1) for some values of N. */ + secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; + + secp256k1_scalar_sqr(&x2, x); + secp256k1_scalar_mul(&x2, &x2, x); + + secp256k1_scalar_sqr(&x3, &x2); + secp256k1_scalar_mul(&x3, &x3, x); + + secp256k1_scalar_sqr(&x4, &x3); + secp256k1_scalar_mul(&x4, &x4, x); + + secp256k1_scalar_sqr(&x6, &x4); + secp256k1_scalar_sqr(&x6, &x6); + secp256k1_scalar_mul(&x6, &x6, &x2); + + secp256k1_scalar_sqr(&x7, &x6); + secp256k1_scalar_mul(&x7, &x7, x); + + secp256k1_scalar_sqr(&x8, &x7); + secp256k1_scalar_mul(&x8, &x8, x); + + secp256k1_scalar_sqr(&x15, &x8); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x15, &x15); + } + secp256k1_scalar_mul(&x15, &x15, &x7); + + secp256k1_scalar_sqr(&x30, &x15); + for (i = 0; i < 14; i++) { + secp256k1_scalar_sqr(&x30, &x30); + } + secp256k1_scalar_mul(&x30, &x30, &x15); + + secp256k1_scalar_sqr(&x60, &x30); + for (i = 0; i < 29; i++) { + secp256k1_scalar_sqr(&x60, &x60); + } + secp256k1_scalar_mul(&x60, &x60, &x30); + + secp256k1_scalar_sqr(&x120, &x60); + for (i = 0; i < 59; i++) { + secp256k1_scalar_sqr(&x120, &x120); + } + secp256k1_scalar_mul(&x120, &x120, &x60); + + secp256k1_scalar_sqr(&x127, &x120); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x127, &x127); + } + secp256k1_scalar_mul(&x127, &x127, &x7); + + /* Then accumulate the final result (t starts at x127). */ + t = &x127; + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 5; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 10; i++) { /* 0000000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 9; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 000000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 6; i++) { /* 00000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(r, t, &x6); /* 111111 */ +} + +SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + return !(a->d[0] & 1); +} +#endif + +static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { +#if defined(USE_SCALAR_INV_BUILTIN) + secp256k1_scalar_inverse(r, x); +#elif defined(USE_SCALAR_INV_NUM) + unsigned char b[32]; + secp256k1_num n, m; + secp256k1_scalar t = *x; + secp256k1_scalar_get_b32(b, &t); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_scalar_order_get_num(&m); + secp256k1_num_mod_inverse(&n, &n, &m); + secp256k1_num_get_bin(b, 32, &n); + secp256k1_scalar_set_b32(r, b, NULL); + /* Verify that the inverse was computed correctly, without GMP code. */ + secp256k1_scalar_mul(&t, &t, r); + CHECK(secp256k1_scalar_is_one(&t)); +#else +#error "Please select scalar inverse implementation" +#endif +} + +#ifdef USE_ENDOMORPHISM +#if defined(EXHAUSTIVE_TEST_ORDER) +/** + * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the + * full case we don't bother making k1 and k2 be small, we just want them to be + * nontrivial to get full test coverage for the exhaustive tests. We therefore + * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. + */ +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; + *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; +} +#else +/** + * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where + * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, + * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} + * + * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm + * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 + * and k2 have a small size. + * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: + * + * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} + * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} + * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} + * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} + * + * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives + * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and + * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2. + * + * g1, g2 are precomputed constants used to replace division with a rounded multiplication + * when decomposing the scalar for an endomorphism-based point multiplication. + * + * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve + * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. + * + * The derivation is described in the paper "Efficient Software Implementation of Public-Key + * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), + * Section 4.3 (here we use a somewhat higher-precision estimate): + * d = a1*b2 - b1*a2 + * g1 = round((2^272)*b2/d) + * g2 = round((2^272)*b1/d) + * + * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found + * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). + * + * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). + */ + +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + secp256k1_scalar c1, c2; + static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST( + 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, + 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL + ); + static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, + 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL + ); + static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL + ); + static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, + 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL + ); + static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, + 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL + ); + VERIFY_CHECK(r1 != a); + VERIFY_CHECK(r2 != a); + /* these _var calls are constant time since the shift amount is constant */ + secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); + secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); + secp256k1_scalar_mul(&c1, &c1, &minus_b1); + secp256k1_scalar_mul(&c2, &c2, &minus_b2); + secp256k1_scalar_add(r2, &c1, &c2); + secp256k1_scalar_mul(r1, r2, &minus_lambda); + secp256k1_scalar_add(r1, r1, a); +} +#endif +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h new file mode 100644 index 0000000000..5574c44c7a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h @@ -0,0 +1,15 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef uint32_t secp256k1_scalar; + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h new file mode 100644 index 0000000000..4f94441f49 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h @@ -0,0 +1,114 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +#include "scalar.h" + +#include + +SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + return !(*a & 1); +} + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + if (offset < 32) + return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); + else + return 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + return secp256k1_scalar_get_bits(a, offset, count); +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; + return *r < *b; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + if (flag && bit < 32) + *r += (1 << bit); +#ifdef VERIFY + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; + int i; + *r = 0; + for (i = 0; i < 32; i++) { + *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; + } + /* just deny overflow, it basically always happens */ + if (overflow) *overflow = 0; +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + memset(bin, 0, 32); + bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return *a == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + if (*a == 0) { + *r = 0; + } else { + *r = EXHAUSTIVE_TEST_ORDER - *a; + } +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return *a == 1; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + return *a > EXHAUSTIVE_TEST_ORDER / 2; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + if (flag) secp256k1_scalar_negate(r, r); + return flag ? -1 : 1; +} + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = *r & ((1 << n) - 1); + *r >>= n; + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; +} + +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r1 = *a; + *r2 = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return *a == *b; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c new file mode 100644 index 0000000000..7d637bfad1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c @@ -0,0 +1,559 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" + +#include "util.h" +#include "num_impl.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_gen_impl.h" +#include "ecdsa_impl.h" +#include "eckey_impl.h" +#include "hash_impl.h" + +#define ARG_CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + secp256k1_callback_call(&ctx->illegal_callback, #cond); \ + return 0; \ + } \ +} while(0) + +static void default_illegal_callback_fn(const char* str, void* data) { + fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); + abort(); +} + +static const secp256k1_callback default_illegal_callback = { + default_illegal_callback_fn, + NULL +}; + +static void default_error_callback_fn(const char* str, void* data) { + fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); + abort(); +} + +static const secp256k1_callback default_error_callback = { + default_error_callback_fn, + NULL +}; + + +struct secp256k1_context_struct { + secp256k1_ecmult_context ecmult_ctx; + secp256k1_ecmult_gen_context ecmult_gen_ctx; + secp256k1_callback illegal_callback; + secp256k1_callback error_callback; +}; + +secp256k1_context* secp256k1_context_create(unsigned int flags) { + secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); + ret->illegal_callback = default_illegal_callback; + ret->error_callback = default_error_callback; + + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { + secp256k1_callback_call(&ret->illegal_callback, + "Invalid flags"); + free(ret); + return NULL; + } + + secp256k1_ecmult_context_init(&ret->ecmult_ctx); + secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); + + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { + secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); + } + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { + secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); + } + + return ret; +} + +secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { + secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); + ret->illegal_callback = ctx->illegal_callback; + ret->error_callback = ctx->error_callback; + secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); + secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); + return ret; +} + +void secp256k1_context_destroy(secp256k1_context* ctx) { + if (ctx != NULL) { + secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); + secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); + + free(ctx); + } +} + +void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + if (fun == NULL) { + fun = default_illegal_callback_fn; + } + ctx->illegal_callback.fn = fun; + ctx->illegal_callback.data = data; +} + +void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + if (fun == NULL) { + fun = default_error_callback_fn; + } + ctx->error_callback.fn = fun; + ctx->error_callback.data = data; +} + +static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { + if (sizeof(secp256k1_ge_storage) == 64) { + /* When the secp256k1_ge_storage type is exactly 64 byte, use its + * representation inside secp256k1_pubkey, as conversion is very fast. + * Note that secp256k1_pubkey_save must use the same representation. */ + secp256k1_ge_storage s; + memcpy(&s, &pubkey->data[0], 64); + secp256k1_ge_from_storage(ge, &s); + } else { + /* Otherwise, fall back to 32-byte big endian for X and Y. */ + secp256k1_fe x, y; + secp256k1_fe_set_b32(&x, pubkey->data); + secp256k1_fe_set_b32(&y, pubkey->data + 32); + secp256k1_ge_set_xy(ge, &x, &y); + } + ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); + return 1; +} + +static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { + if (sizeof(secp256k1_ge_storage) == 64) { + secp256k1_ge_storage s; + secp256k1_ge_to_storage(&s, ge); + memcpy(&pubkey->data[0], &s, 64); + } else { + VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); + secp256k1_fe_normalize_var(&ge->x); + secp256k1_fe_normalize_var(&ge->y); + secp256k1_fe_get_b32(pubkey->data, &ge->x); + secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); + } +} + +int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { + secp256k1_ge Q; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(input != NULL); + if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { + return 0; + } + secp256k1_pubkey_save(pubkey, &Q); + secp256k1_ge_clear(&Q); + return 1; +} + +int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { + secp256k1_ge Q; + size_t len; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); + len = *outputlen; + *outputlen = 0; + ARG_CHECK(output != NULL); + memset(output, 0, len); + ARG_CHECK(pubkey != NULL); + ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); + if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { + ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + if (ret) { + *outputlen = len; + } + } + return ret; +} + +static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { + (void)ctx; + if (sizeof(secp256k1_scalar) == 32) { + /* When the secp256k1_scalar type is exactly 32 byte, use its + * representation inside secp256k1_ecdsa_signature, as conversion is very fast. + * Note that secp256k1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); + } +} + +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { + if (sizeof(secp256k1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); + } +} + +int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input != NULL); + + if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { + secp256k1_ecdsa_signature_save(sig, &r, &s); + return 1; + } else { + memset(sig, 0, sizeof(*sig)); + return 0; + } +} + +int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { + secp256k1_scalar r, s; + int ret = 1; + int overflow = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + + secp256k1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + secp256k1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + secp256k1_ecdsa_signature_save(sig, &r, &s); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); +} + +int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + secp256k1_scalar_get_b32(&output64[0], &r); + secp256k1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { + secp256k1_scalar r, s; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sigin != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); + ret = secp256k1_scalar_is_high(&s); + if (sigout != NULL) { + if (ret) { + secp256k1_scalar_negate(&s, &s); + } + secp256k1_ecdsa_signature_save(sigout, &r, &s); + } + + return ret; +} + +int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { + secp256k1_ge q; + secp256k1_scalar r, s; + secp256k1_scalar m; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(pubkey != NULL); + + secp256k1_scalar_set_b32(&m, msg32, NULL); + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + return (!secp256k1_scalar_is_high(&s) && + secp256k1_pubkey_load(ctx, &q, pubkey) && + secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); +} + +static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + unsigned char keydata[112]; + int keylen = 64; + secp256k1_rfc6979_hmac_sha256_t rng; + unsigned int i; + /* We feed a byte array to the PRNG as input, consisting of: + * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. + * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. + * - optionally 16 extra bytes with the algorithm name. + * Because the arguments have distinct fixed lengths it is not possible for + * different argument mixtures to emulate each other and result in the same + * nonces. + */ + memcpy(keydata, key32, 32); + memcpy(keydata + 32, msg32, 32); + if (data != NULL) { + memcpy(keydata + 64, data, 32); + keylen = 96; + } + if (algo16 != NULL) { + memcpy(keydata + keylen, algo16, 16); + keylen += 16; + } + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); + memset(keydata, 0, sizeof(keydata)); + for (i = 0; i <= counter; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + return 1; +} + +const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; +const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; + +int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { + secp256k1_scalar r, s; + secp256k1_scalar sec, non, msg; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !secp256k1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + secp256k1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + if (!overflow && !secp256k1_scalar_is_zero(&non)) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + } + if (ret) { + secp256k1_ecdsa_signature_save(signature, &r, &s); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { + secp256k1_scalar sec; + int ret; + int overflow; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + ret = !overflow && !secp256k1_scalar_is_zero(&sec); + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { + secp256k1_gej pj; + secp256k1_ge p; + secp256k1_scalar sec; + int overflow; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); + if (ret) { + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); + secp256k1_ge_set_gej(&p, &pj); + secp256k1_pubkey_save(pubkey, &p); + } + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + secp256k1_scalar term; + secp256k1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&term, tweak, &overflow); + secp256k1_scalar_set_b32(&sec, seckey, NULL); + + ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); + memset(seckey, 0, 32); + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&term); + return ret; +} + +int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { + secp256k1_ge p; + secp256k1_scalar term; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&term, tweak, &overflow); + ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { + secp256k1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + secp256k1_scalar factor; + secp256k1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + secp256k1_scalar_set_b32(&sec, seckey, NULL); + ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); + memset(seckey, 0, 32); + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&factor); + return ret; +} + +int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { + secp256k1_ge p; + secp256k1_scalar factor; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { + secp256k1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + return 1; +} + +int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { + size_t i; + secp256k1_gej Qj; + secp256k1_ge Q; + + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(n >= 1); + ARG_CHECK(pubnonces != NULL); + + secp256k1_gej_set_infinity(&Qj); + + for (i = 0; i < n; i++) { + secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); + secp256k1_gej_add_ge(&Qj, &Qj, &Q); + } + if (secp256k1_gej_is_infinity(&Qj)) { + return 0; + } + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(pubnonce, &Q); + return 1; +} + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/main_impl.h" +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h new file mode 100644 index 0000000000..f8efa93c7c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h @@ -0,0 +1,38 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_H_ +#define _SECP256K1_TESTRAND_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +/* A non-cryptographic RNG used only for test infrastructure. */ + +/** Seed the pseudorandom number generator for testing. */ +SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16); + +/** Generate a pseudorandom number in the range [0..2**32-1]. */ +static uint32_t secp256k1_rand32(void); + +/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or + * more. */ +static uint32_t secp256k1_rand_bits(int bits); + +/** Generate a pseudorandom number in the range [0..range-1]. */ +static uint32_t secp256k1_rand_int(uint32_t range); + +/** Generate a pseudorandom 32-byte array. */ +static void secp256k1_rand256(unsigned char *b32); + +/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ +static void secp256k1_rand256_test(unsigned char *b32); + +/** Generate pseudorandom bytes with long sequences of zero and one bits. */ +static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h new file mode 100644 index 0000000000..15c7b9f12d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h @@ -0,0 +1,110 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_IMPL_H_ +#define _SECP256K1_TESTRAND_IMPL_H_ + +#include +#include + +#include "testrand.h" +#include "hash.h" + +static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; +static uint32_t secp256k1_test_rng_precomputed[8]; +static int secp256k1_test_rng_precomputed_used = 8; +static uint64_t secp256k1_test_rng_integer; +static int secp256k1_test_rng_integer_bits_left = 0; + +SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) { + secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); +} + +SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { + if (secp256k1_test_rng_precomputed_used == 8) { + secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); + secp256k1_test_rng_precomputed_used = 0; + } + return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; +} + +static uint32_t secp256k1_rand_bits(int bits) { + uint32_t ret; + if (secp256k1_test_rng_integer_bits_left < bits) { + secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left); + secp256k1_test_rng_integer_bits_left += 32; + } + ret = secp256k1_test_rng_integer; + secp256k1_test_rng_integer >>= bits; + secp256k1_test_rng_integer_bits_left -= bits; + ret &= ((~((uint32_t)0)) >> (32 - bits)); + return ret; +} + +static uint32_t secp256k1_rand_int(uint32_t range) { + /* We want a uniform integer between 0 and range-1, inclusive. + * B is the smallest number such that range <= 2**B. + * two mechanisms implemented here: + * - generate B bits numbers until one below range is found, and return it + * - find the largest multiple M of range that is <= 2**(B+A), generate B+A + * bits numbers until one below M is found, and return it modulo range + * The second mechanism consumes A more bits of entropy in every iteration, + * but may need fewer iterations due to M being closer to 2**(B+A) then + * range is to 2**B. The array below (indexed by B) contains a 0 when the + * first mechanism is to be used, and the number A otherwise. + */ + static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0}; + uint32_t trange, mult; + int bits = 0; + if (range <= 1) { + return 0; + } + trange = range - 1; + while (trange > 0) { + trange >>= 1; + bits++; + } + if (addbits[bits]) { + bits = bits + addbits[bits]; + mult = ((~((uint32_t)0)) >> (32 - bits)) / range; + trange = range * mult; + } else { + trange = range; + mult = 1; + } + while(1) { + uint32_t x = secp256k1_rand_bits(bits); + if (x < trange) { + return (mult == 1) ? x : (x % range); + } + } +} + +static void secp256k1_rand256(unsigned char *b32) { + secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); +} + +static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) { + size_t bits = 0; + memset(bytes, 0, len); + while (bits < len * 8) { + int now; + uint32_t val; + now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31; + val = secp256k1_rand_bits(1); + while (now > 0 && bits < len * 8) { + bytes[bits / 8] |= val << (bits % 8); + now--; + bits++; + } + } +} + +static void secp256k1_rand256_test(unsigned char *b32) { + secp256k1_rand_bytes_test(b32, 32); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c new file mode 100644 index 0000000000..9ae7d30281 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c @@ -0,0 +1,4525 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#include "secp256k1.c" +#include "include/secp256k1.h" +#include "testrand_impl.h" + +#ifdef ENABLE_OPENSSL_TESTS +#include "openssl/bn.h" +#include "openssl/ec.h" +#include "openssl/ecdsa.h" +#include "openssl/obj_mac.h" +#endif + +#include "contrib/lax_der_parsing.c" +#include "contrib/lax_der_privatekey_parsing.c" + +#if !defined(VG_CHECK) +# if defined(VALGRIND) +# include +# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y)) +# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y)) +# else +# define VG_UNDEF(x,y) +# define VG_CHECK(x,y) +# endif +#endif + +static int count = 64; +static secp256k1_context *ctx = NULL; + +static void counting_illegal_callback_fn(const char* str, void* data) { + /* Dummy callback function that just counts. */ + int32_t *p; + (void)str; + p = data; + (*p)++; +} + +static void uncounting_illegal_callback_fn(const char* str, void* data) { + /* Dummy callback function that just counts (backwards). */ + int32_t *p; + (void)str; + p = data; + (*p)--; +} + +void random_field_element_test(secp256k1_fe *fe) { + do { + unsigned char b32[32]; + secp256k1_rand256_test(b32); + if (secp256k1_fe_set_b32(fe, b32)) { + break; + } + } while(1); +} + +void random_field_element_magnitude(secp256k1_fe *fe) { + secp256k1_fe zero; + int n = secp256k1_rand_int(9); + secp256k1_fe_normalize(fe); + if (n == 0) { + return; + } + secp256k1_fe_clear(&zero); + secp256k1_fe_negate(&zero, &zero, 0); + secp256k1_fe_mul_int(&zero, n - 1); + secp256k1_fe_add(fe, &zero); + VERIFY_CHECK(fe->magnitude == n); +} + +void random_group_element_test(secp256k1_ge *ge) { + secp256k1_fe fe; + do { + random_field_element_test(&fe); + if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { + secp256k1_fe_normalize(&ge->y); + break; + } + } while(1); +} + +void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { + secp256k1_fe z2, z3; + do { + random_field_element_test(&gej->z); + if (!secp256k1_fe_is_zero(&gej->z)) { + break; + } + } while(1); + secp256k1_fe_sqr(&z2, &gej->z); + secp256k1_fe_mul(&z3, &z2, &gej->z); + secp256k1_fe_mul(&gej->x, &ge->x, &z2); + secp256k1_fe_mul(&gej->y, &ge->y, &z3); + gej->infinity = ge->infinity; +} + +void random_scalar_order_test(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_rand256_test(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +void random_scalar_order(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_rand256(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +void run_context_tests(void) { + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + unsigned char ctmp[32]; + int32_t ecount; + int32_t ecount2; + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + secp256k1_gej pubj; + secp256k1_ge pub; + secp256k1_scalar msg, key, nonce; + secp256k1_scalar sigr, sigs; + + ecount = 0; + ecount2 = 10; + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); + CHECK(vrfy->error_callback.fn != sign->error_callback.fn); + + /*** clone and destroy all of them to make sure cloning was complete ***/ + { + secp256k1_context *ctx_tmp; + + ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); + } + + /* Verify that the error callback makes it across the clone. */ + CHECK(vrfy->error_callback.fn != sign->error_callback.fn); + /* And that it resets back to default. */ + secp256k1_context_set_error_callback(sign, NULL, NULL); + CHECK(vrfy->error_callback.fn == sign->error_callback.fn); + + /*** attempt to use them ***/ + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); + secp256k1_ge_set_gej(&pub, &pubj); + + /* Verify context-type checking illegal-argument errors. */ + memset(ctmp, 1, 32); + CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); + CHECK(ecount == 1); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); + CHECK(ecount == 2); + VG_UNDEF(&sig, sizeof(sig)); + CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); + VG_CHECK(&sig, sizeof(sig)); + CHECK(ecount2 == 10); + CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); + CHECK(ecount2 == 11); + CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); + CHECK(ecount2 == 12); + CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); + CHECK(ecount2 == 13); + CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_context_randomize(sign, NULL) == 1); + CHECK(ecount2 == 13); + secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); + secp256k1_context_set_illegal_callback(sign, NULL, NULL); + + /* This shouldn't leak memory, due to already-set tests. */ + secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); + secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); + + /* obtain a working nonce */ + do { + random_scalar_order_test(&nonce); + } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + + /* try signing */ + CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + + /* try verifying */ + CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); + /* Defined as no-op. */ + secp256k1_context_destroy(NULL); +} + +/***** HASH TESTS *****/ + +void run_sha256_tests(void) { + static const char *inputs[8] = { + "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "For this sample, this 63-byte string will be used as input data", + "This is exactly 64 bytes long, not counting the terminating byte" + }; + static const unsigned char outputs[8][32] = { + {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, + {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, + {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, + {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, + {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, + {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, + {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, + {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} + }; + int i; + for (i = 0; i < 8; i++) { + unsigned char out[32]; + secp256k1_sha256_t hasher; + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + int split = secp256k1_rand_int(strlen(inputs[i])); + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_hmac_sha256_tests(void) { + static const char *keys[6] = { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x4a\x65\x66\x65", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + }; + static const char *inputs[6] = { + "\x48\x69\x20\x54\x68\x65\x72\x65", + "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", + "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" + }; + static const unsigned char outputs[6][32] = { + {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, + {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, + {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, + {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, + {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, + {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} + }; + int i; + for (i = 0; i < 6; i++) { + secp256k1_hmac_sha256_t hasher; + unsigned char out[32]; + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + int split = secp256k1_rand_int(strlen(inputs[i])); + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_rfc6979_hmac_sha256_tests(void) { + static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; + static const unsigned char out1[3][32] = { + {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, + {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, + {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} + }; + + static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; + static const unsigned char out2[3][32] = { + {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, + {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, + {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} + }; + + secp256k1_rfc6979_hmac_sha256_t rng; + unsigned char out[32]; + int i; + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out1[i], 32) == 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out1[i], 32) != 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out2[i], 32) == 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); +} + +/***** RANDOM TESTS *****/ + +void test_rand_bits(int rand32, int bits) { + /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to + * get a false negative chance below once in a billion */ + static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316}; + /* We try multiplying the results with various odd numbers, which shouldn't + * influence the uniform distribution modulo a power of 2. */ + static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011}; + /* We only select up to 6 bits from the output to analyse */ + unsigned int usebits = bits > 6 ? 6 : bits; + unsigned int maxshift = bits - usebits; + /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit + number, track all observed outcomes, one per bit in a uint64_t. */ + uint64_t x[6][27] = {{0}}; + unsigned int i, shift, m; + /* Multiply the output of all rand calls with the odd number m, which + should not change the uniformity of its distribution. */ + for (i = 0; i < rounds[usebits]; i++) { + uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); + CHECK((((uint64_t)r) >> bits) == 0); + for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { + uint32_t rm = r * mults[m]; + for (shift = 0; shift <= maxshift; shift++) { + x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1))); + } + } + } + for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { + for (shift = 0; shift <= maxshift; shift++) { + /* Test that the lower usebits bits of x[shift] are 1 */ + CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0); + } + } +} + +/* Subrange must be a whole divisor of range, and at most 64 */ +void test_rand_int(uint32_t range, uint32_t subrange) { + /* (1-1/subrange)^rounds < 1/10^9 */ + int rounds = (subrange * 2073) / 100; + int i; + uint64_t x = 0; + CHECK((range % subrange) == 0); + for (i = 0; i < rounds; i++) { + uint32_t r = secp256k1_rand_int(range); + CHECK(r < range); + r = r % subrange; + x |= (((uint64_t)1) << r); + } + /* Test that the lower subrange bits of x are 1. */ + CHECK(((~x) << (64 - subrange)) == 0); +} + +void run_rand_bits(void) { + size_t b; + test_rand_bits(1, 32); + for (b = 1; b <= 32; b++) { + test_rand_bits(0, b); + } +} + +void run_rand_int(void) { + static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432}; + static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64}; + unsigned int m, s; + for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) { + for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) { + test_rand_int(ms[m] * ss[s], ss[s]); + } + } +} + +/***** NUM TESTS *****/ + +#ifndef USE_NUM_NONE +void random_num_negate(secp256k1_num *num) { + if (secp256k1_rand_bits(1)) { + secp256k1_num_negate(num); + } +} + +void random_num_order_test(secp256k1_num *num) { + secp256k1_scalar sc; + random_scalar_order_test(&sc); + secp256k1_scalar_get_num(num, &sc); +} + +void random_num_order(secp256k1_num *num) { + secp256k1_scalar sc; + random_scalar_order(&sc); + secp256k1_scalar_get_num(num, &sc); +} + +void test_num_negate(void) { + secp256k1_num n1; + secp256k1_num n2; + random_num_order_test(&n1); /* n1 = R */ + random_num_negate(&n1); + secp256k1_num_copy(&n2, &n1); /* n2 = R */ + secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(!secp256k1_num_is_zero(&n1)); + secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); + secp256k1_num_negate(&n1); /* n1 = R */ + CHECK(secp256k1_num_eq(&n1, &n2)); +} + +void test_num_add_sub(void) { + int i; + secp256k1_scalar s; + secp256k1_num n1; + secp256k1_num n2; + secp256k1_num n1p2, n2p1, n1m2, n2m1; + random_num_order_test(&n1); /* n1 = R1 */ + if (secp256k1_rand_bits(1)) { + random_num_negate(&n1); + } + random_num_order_test(&n2); /* n2 = R2 */ + if (secp256k1_rand_bits(1)) { + random_num_negate(&n2); + } + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ + secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ + secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ + secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ + CHECK(secp256k1_num_eq(&n1p2, &n2p1)); + CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); + secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1m2)); + CHECK(!secp256k1_num_eq(&n2m1, &n1)); + secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1)); + CHECK(!secp256k1_num_eq(&n2p1, &n1)); + secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ + CHECK(secp256k1_num_eq(&n2p1, &n1)); + + /* check is_one */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&n1, &s); + CHECK(secp256k1_num_is_one(&n1)); + /* check that 2^n + 1 is never 1 */ + secp256k1_scalar_get_num(&n2, &s); + for (i = 0; i < 250; ++i) { + secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ + CHECK(!secp256k1_num_is_one(&n1p2)); + } +} + +void test_num_mod(void) { + int i; + secp256k1_scalar s; + secp256k1_num order, n; + + /* check that 0 mod anything is 0 */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_set_int(&s, 0); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that anything mod 1 is 0 */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that increasing the number past 2^256 does not break this */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&n, &s); + /* multiply by 2^8, which'll test this case with high probability */ + for (i = 0; i < 8; ++i) { + secp256k1_num_add(&n, &n, &n); + } + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); +} + +void test_num_jacobi(void) { + secp256k1_scalar sqr; + secp256k1_scalar small; + secp256k1_scalar five; /* five is not a quadratic residue */ + secp256k1_num order, n; + int i; + /* squares mod 5 are 1, 4 */ + const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; + + /* check some small values with 5 as the order */ + secp256k1_scalar_set_int(&five, 5); + secp256k1_scalar_get_num(&order, &five); + for (i = 0; i < 10; ++i) { + secp256k1_scalar_set_int(&small, i); + secp256k1_scalar_get_num(&n, &small); + CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); + } + + /** test large values with 5 as group order */ + secp256k1_scalar_get_num(&order, &five); + /* we first need a scalar which is not a multiple of 5 */ + do { + secp256k1_num fiven; + random_scalar_order_test(&sqr); + secp256k1_scalar_get_num(&fiven, &five); + secp256k1_scalar_get_num(&n, &sqr); + secp256k1_num_mod(&n, &fiven); + } while (secp256k1_num_is_zero(&n)); + /* next force it to be a residue. 2 is a nonresidue mod 5 so we can + * just multiply by two, i.e. add the number to itself */ + if (secp256k1_num_jacobi(&n, &order) == -1) { + secp256k1_num_add(&n, &n, &n); + } + + /* test residue */ + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_num_add(&n, &n, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + + /** test with secp group order as order */ + secp256k1_scalar_order_get_num(&order); + random_scalar_order_test(&sqr); + secp256k1_scalar_sqr(&sqr, &sqr); + /* test residue */ + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_scalar_mul(&sqr, &sqr, &five); + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + /* test multiple of the order*/ + CHECK(secp256k1_num_jacobi(&order, &order) == 0); + + /* check one less than the order */ + secp256k1_scalar_set_int(&small, 1); + secp256k1_scalar_get_num(&n, &small); + secp256k1_num_sub(&n, &order, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ +} + +void run_num_smalltests(void) { + int i; + for (i = 0; i < 100*count; i++) { + test_num_negate(); + test_num_add_sub(); + test_num_mod(); + test_num_jacobi(); + } +} +#endif + +/***** SCALAR TESTS *****/ + +void scalar_test(void) { + secp256k1_scalar s; + secp256k1_scalar s1; + secp256k1_scalar s2; +#ifndef USE_NUM_NONE + secp256k1_num snum, s1num, s2num; + secp256k1_num order, half_order; +#endif + unsigned char c[32]; + + /* Set 's' to a random scalar, with value 'snum'. */ + random_scalar_order_test(&s); + + /* Set 's1' to a random scalar, with value 's1num'. */ + random_scalar_order_test(&s1); + + /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ + random_scalar_order_test(&s2); + secp256k1_scalar_get_b32(c, &s2); + +#ifndef USE_NUM_NONE + secp256k1_scalar_get_num(&snum, &s); + secp256k1_scalar_get_num(&s1num, &s1); + secp256k1_scalar_get_num(&s2num, &s2); + + secp256k1_scalar_order_get_num(&order); + half_order = order; + secp256k1_num_shift(&half_order, 1); +#endif + + { + int i; + /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ + secp256k1_scalar n; + secp256k1_scalar_set_int(&n, 0); + for (i = 0; i < 256; i += 4) { + secp256k1_scalar t; + int j; + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + for (j = 0; j < 4; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); + } + CHECK(secp256k1_scalar_eq(&n, &s)); + } + + { + /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ + secp256k1_scalar n; + int i = 0; + secp256k1_scalar_set_int(&n, 0); + while (i < 256) { + secp256k1_scalar t; + int j; + int now = secp256k1_rand_int(15) + 1; + if (now + i > 256) { + now = 256 - i; + } + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); + for (j = 0; j < now; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); + i += now; + } + CHECK(secp256k1_scalar_eq(&n, &s)); + } + +#ifndef USE_NUM_NONE + { + /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ + secp256k1_num rnum; + secp256k1_num r2num; + secp256k1_scalar r; + secp256k1_num_add(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &order); + secp256k1_scalar_add(&r, &s, &s2); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + } + + { + /* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */ + secp256k1_scalar r; + secp256k1_num r2num; + secp256k1_num rnum; + secp256k1_num_mul(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &order); + secp256k1_scalar_mul(&r, &s, &s2); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + /* The result can only be zero if at least one of the factors was zero. */ + CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); + /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ + CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); + CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); + } + + { + secp256k1_scalar neg; + secp256k1_num negnum; + secp256k1_num negnum2; + /* Check that comparison with zero matches comparison with zero on the number. */ + CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); + /* Check that comparison with the half order is equal to testing for high scalar. */ + CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0)); + secp256k1_scalar_negate(&neg, &s); + secp256k1_num_sub(&negnum, &order, &snum); + secp256k1_num_mod(&negnum, &order); + /* Check that comparison with the half order is equal to testing for high scalar after negation. */ + CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0)); + /* Negating should change the high property, unless the value was already zero. */ + CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); + secp256k1_scalar_get_num(&negnum2, &neg); + /* Negating a scalar should be equal to (order - n) mod order on the number. */ + CHECK(secp256k1_num_eq(&negnum, &negnum2)); + secp256k1_scalar_add(&neg, &neg, &s); + /* Adding a number to its negation should result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + secp256k1_scalar_negate(&neg, &neg); + /* Negating zero should still result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + } + + { + /* Test secp256k1_scalar_mul_shift_var. */ + secp256k1_scalar r; + secp256k1_num one; + secp256k1_num rnum; + secp256k1_num rnum2; + unsigned char cone[1] = {0x01}; + unsigned int shift = 256 + secp256k1_rand_int(257); + secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); + secp256k1_num_mul(&rnum, &s1num, &s2num); + secp256k1_num_shift(&rnum, shift - 1); + secp256k1_num_set_bin(&one, cone, 1); + secp256k1_num_add(&rnum, &rnum, &one); + secp256k1_num_shift(&rnum, 1); + secp256k1_scalar_get_num(&rnum2, &r); + CHECK(secp256k1_num_eq(&rnum, &rnum2)); + } + + { + /* test secp256k1_scalar_shr_int */ + secp256k1_scalar r; + int i; + random_scalar_order_test(&r); + for (i = 0; i < 100; ++i) { + int low; + int shift = 1 + secp256k1_rand_int(15); + int expected = r.d[0] % (1 << shift); + low = secp256k1_scalar_shr_int(&r, shift); + CHECK(expected == low); + } + } +#endif + + { + /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ + if (!secp256k1_scalar_is_zero(&s)) { + secp256k1_scalar inv; +#ifndef USE_NUM_NONE + secp256k1_num invnum; + secp256k1_num invnum2; +#endif + secp256k1_scalar_inverse(&inv, &s); +#ifndef USE_NUM_NONE + secp256k1_num_mod_inverse(&invnum, &snum, &order); + secp256k1_scalar_get_num(&invnum2, &inv); + CHECK(secp256k1_num_eq(&invnum, &invnum2)); +#endif + secp256k1_scalar_mul(&inv, &inv, &s); + /* Multiplying a scalar with its inverse must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); + secp256k1_scalar_inverse(&inv, &inv); + /* Inverting one must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); +#ifndef USE_NUM_NONE + secp256k1_scalar_get_num(&invnum, &inv); + CHECK(secp256k1_num_is_one(&invnum)); +#endif + } + } + + { + /* Test commutativity of add. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + secp256k1_scalar r1, r2; + secp256k1_scalar b; + int i; + /* Test add_bit. */ + int bit = secp256k1_rand_bits(8); + secp256k1_scalar_set_int(&b, 1); + CHECK(secp256k1_scalar_is_one(&b)); + for (i = 0; i < bit; i++) { + secp256k1_scalar_add(&b, &b, &b); + } + r1 = s1; + r2 = s1; + if (!secp256k1_scalar_add(&r1, &r1, &b)) { + /* No overflow happened. */ + secp256k1_scalar_cadd_bit(&r2, bit, 1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + /* cadd is a noop when flag is zero */ + secp256k1_scalar_cadd_bit(&r2, bit, 0); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + } + + { + /* Test commutativity of mul. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of add. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r1, &r1, &s); + secp256k1_scalar_add(&r2, &s2, &s); + secp256k1_scalar_add(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of mul. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s2, &s); + secp256k1_scalar_mul(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test distributitivity of mul over add. */ + secp256k1_scalar r1, r2, t; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s1, &s); + secp256k1_scalar_mul(&t, &s2, &s); + secp256k1_scalar_add(&r2, &r2, &t); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test square. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_sqr(&r1, &s1); + secp256k1_scalar_mul(&r2, &s1, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test multiplicative identity. */ + secp256k1_scalar r1, v1; + secp256k1_scalar_set_int(&v1,1); + secp256k1_scalar_mul(&r1, &s1, &v1); + CHECK(secp256k1_scalar_eq(&r1, &s1)); + } + + { + /* Test additive identity. */ + secp256k1_scalar r1, v0; + secp256k1_scalar_set_int(&v0,0); + secp256k1_scalar_add(&r1, &s1, &v0); + CHECK(secp256k1_scalar_eq(&r1, &s1)); + } + + { + /* Test zero product property. */ + secp256k1_scalar r1, v0; + secp256k1_scalar_set_int(&v0,0); + secp256k1_scalar_mul(&r1, &s1, &v0); + CHECK(secp256k1_scalar_eq(&r1, &v0)); + } + +} + +void run_scalar_tests(void) { + int i; + for (i = 0; i < 128 * count; i++) { + scalar_test(); + } + + { + /* (-1)+1 should be zero. */ + secp256k1_scalar s, o; + secp256k1_scalar_set_int(&s, 1); + CHECK(secp256k1_scalar_is_one(&s)); + secp256k1_scalar_negate(&o, &s); + secp256k1_scalar_add(&o, &o, &s); + CHECK(secp256k1_scalar_is_zero(&o)); + secp256k1_scalar_negate(&o, &o); + CHECK(secp256k1_scalar_is_zero(&o)); + } + +#ifndef USE_NUM_NONE + { + /* A scalar with value of the curve order should be 0. */ + secp256k1_num order; + secp256k1_scalar zero; + unsigned char bin[32]; + int overflow = 0; + secp256k1_scalar_order_get_num(&order); + secp256k1_num_get_bin(bin, 32, &order); + secp256k1_scalar_set_b32(&zero, bin, &overflow); + CHECK(overflow == 1); + CHECK(secp256k1_scalar_is_zero(&zero)); + } +#endif + + { + /* Does check_overflow check catch all ones? */ + static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL + ); + CHECK(secp256k1_scalar_check_overflow(&overflowed)); + } + + { + /* Static test vectors. + * These were reduced from ~10^12 random vectors based on comparison-decision + * and edge-case coverage on 32-bit and 64-bit implementations. + * The responses were generated with Sage 5.9. + */ + secp256k1_scalar x; + secp256k1_scalar y; + secp256k1_scalar z; + secp256k1_scalar zz; + secp256k1_scalar one; + secp256k1_scalar r1; + secp256k1_scalar r2; +#if defined(USE_SCALAR_INV_NUM) + secp256k1_scalar zzv; +#endif + int overflow; + unsigned char chal[33][2][32] = { + {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, + {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, + {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, + 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, + {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, + {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, + 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, + {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, + {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, + {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, + {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, + {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, + {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, + {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, + {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, + {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, + 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, + {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, + 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, + {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, + {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, + {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} + }; + unsigned char res[33][2][32] = { + {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, + 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, + 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, + 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, + {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, + 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, + 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, + 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, + {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, + 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, + 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, + 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, + {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, + 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, + 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, + 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, + {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, + 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, + 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, + 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, + {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, + 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, + 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, + 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, + {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, + 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, + 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, + 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, + {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, + 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, + 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, + 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, + {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, + 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, + 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, + 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, + {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, + 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, + 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, + 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, + {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, + 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, + 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, + 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, + {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, + 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, + 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, + 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, + {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, + 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, + 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, + 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, + {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, + 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, + 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, + 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, + {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, + 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, + 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, + 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, + {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, + 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, + 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, + 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, + {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, + 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, + 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, + 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, + {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, + 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, + 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, + 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, + {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, + 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, + 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, + 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, + {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, + 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, + 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, + 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, + {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, + 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, + 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, + 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, + {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, + 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, + 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, + 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, + {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, + 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, + 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, + 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, + {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, + 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, + 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, + 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, + {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, + 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, + 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, + 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, + {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, + 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, + 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, + 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, + {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, + 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, + 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, + 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, + {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, + 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, + 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, + 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, + {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, + 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, + 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, + 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, + {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, + 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, + 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, + 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, + {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, + 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, + 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, + 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, + {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, + 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, + 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, + 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, + {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, + 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, + 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, + 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, + {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, + 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, + 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, + 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, + {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, + 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, + 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, + 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, + {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, + 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, + 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, + 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, + {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, + 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, + 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, + 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, + {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, + 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, + 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, + 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, + {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, + 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, + 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, + 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, + {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, + 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, + 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, + 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, + {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, + {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, + 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, + 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, + 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, + {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, + 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, + 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, + 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, + {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, + 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, + 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, + 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, + {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, + 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, + 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, + 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, + {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, + 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, + 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, + 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, + {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, + 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, + 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, + 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, + {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, + 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, + 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, + 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, + {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, + 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, + 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, + 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, + {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, + 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, + 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, + 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, + {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, + 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, + 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, + 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, + {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, + 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, + 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, + 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, + {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, + 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, + 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, + 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, + {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, + 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, + 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, + 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, + {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, + 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, + 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, + 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, + {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, + {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} + }; + secp256k1_scalar_set_int(&one, 1); + for (i = 0; i < 33; i++) { + secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); + CHECK(!overflow); + secp256k1_scalar_mul(&z, &x, &y); + CHECK(!secp256k1_scalar_check_overflow(&z)); + CHECK(secp256k1_scalar_eq(&r1, &z)); + if (!secp256k1_scalar_is_zero(&y)) { + secp256k1_scalar_inverse(&zz, &y); + CHECK(!secp256k1_scalar_check_overflow(&zz)); +#if defined(USE_SCALAR_INV_NUM) + secp256k1_scalar_inverse_var(&zzv, &y); + CHECK(secp256k1_scalar_eq(&zzv, &zz)); +#endif + secp256k1_scalar_mul(&z, &z, &zz); + CHECK(!secp256k1_scalar_check_overflow(&z)); + CHECK(secp256k1_scalar_eq(&x, &z)); + secp256k1_scalar_mul(&zz, &zz, &y); + CHECK(!secp256k1_scalar_check_overflow(&zz)); + CHECK(secp256k1_scalar_eq(&one, &zz)); + } + secp256k1_scalar_mul(&z, &x, &x); + CHECK(!secp256k1_scalar_check_overflow(&z)); + secp256k1_scalar_sqr(&zz, &x); + CHECK(!secp256k1_scalar_check_overflow(&zz)); + CHECK(secp256k1_scalar_eq(&zz, &z)); + CHECK(secp256k1_scalar_eq(&r2, &zz)); + } + } +} + +/***** FIELD TESTS *****/ + +void random_fe(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} + +void random_fe_test(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256_test(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} + +void random_fe_non_zero(secp256k1_fe *nz) { + int tries = 10; + while (--tries >= 0) { + random_fe(nz); + secp256k1_fe_normalize(nz); + if (!secp256k1_fe_is_zero(nz)) { + break; + } + } + /* Infinitesimal probability of spurious failure here */ + CHECK(tries >= 0); +} + +void random_fe_non_square(secp256k1_fe *ns) { + secp256k1_fe r; + random_fe_non_zero(ns); + if (secp256k1_fe_sqrt(&r, ns)) { + secp256k1_fe_negate(ns, ns, 1); + } +} + +int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe an = *a; + secp256k1_fe bn = *b; + secp256k1_fe_normalize_weak(&an); + secp256k1_fe_normalize_var(&bn); + return secp256k1_fe_equal_var(&an, &bn); +} + +int check_fe_inverse(const secp256k1_fe *a, const secp256k1_fe *ai) { + secp256k1_fe x; + secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_fe_mul(&x, a, ai); + return check_fe_equal(&x, &one); +} + +void run_field_convert(void) { + static const unsigned char b32[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 + }; + static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( + 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, + 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL + ); + static const secp256k1_fe fe = SECP256K1_FE_CONST( + 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, + 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL + ); + secp256k1_fe fe2; + unsigned char b322[32]; + secp256k1_fe_storage fes2; + /* Check conversions to fe. */ + CHECK(secp256k1_fe_set_b32(&fe2, b32)); + CHECK(secp256k1_fe_equal_var(&fe, &fe2)); + secp256k1_fe_from_storage(&fe2, &fes); + CHECK(secp256k1_fe_equal_var(&fe, &fe2)); + /* Check conversion from fe. */ + secp256k1_fe_get_b32(b322, &fe); + CHECK(memcmp(b322, b32, 32) == 0); + secp256k1_fe_to_storage(&fes2, &fe); + CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); +} + +int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe t = *b; +#ifdef VERIFY + t.magnitude = a->magnitude; + t.normalized = a->normalized; +#endif + return memcmp(a, &t, sizeof(secp256k1_fe)); +} + +void run_field_misc(void) { + secp256k1_fe x; + secp256k1_fe y; + secp256k1_fe z; + secp256k1_fe q; + secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); + int i, j; + for (i = 0; i < 5*count; i++) { + secp256k1_fe_storage xs, ys, zs; + random_fe(&x); + random_fe_non_zero(&y); + /* Test the fe equality and comparison operations. */ + CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); + CHECK(secp256k1_fe_equal_var(&x, &x)); + z = x; + secp256k1_fe_add(&z,&y); + /* Test fe conditional move; z is not normalized here. */ + q = x; + secp256k1_fe_cmov(&x, &z, 0); + VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); + secp256k1_fe_cmov(&x, &x, 1); + CHECK(fe_memcmp(&x, &z) != 0); + CHECK(fe_memcmp(&x, &q) == 0); + secp256k1_fe_cmov(&q, &z, 1); + VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); + CHECK(fe_memcmp(&q, &z) == 0); + secp256k1_fe_normalize_var(&x); + secp256k1_fe_normalize_var(&z); + CHECK(!secp256k1_fe_equal_var(&x, &z)); + secp256k1_fe_normalize_var(&q); + secp256k1_fe_cmov(&q, &z, (i&1)); + VERIFY_CHECK(q.normalized && q.magnitude == 1); + for (j = 0; j < 6; j++) { + secp256k1_fe_negate(&z, &z, j+1); + secp256k1_fe_normalize_var(&q); + secp256k1_fe_cmov(&q, &z, (j&1)); + VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); + } + secp256k1_fe_normalize_var(&z); + /* Test storage conversion and conditional moves. */ + secp256k1_fe_to_storage(&xs, &x); + secp256k1_fe_to_storage(&ys, &y); + secp256k1_fe_to_storage(&zs, &z); + secp256k1_fe_storage_cmov(&zs, &xs, 0); + secp256k1_fe_storage_cmov(&zs, &zs, 1); + CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); + secp256k1_fe_storage_cmov(&ys, &xs, 1); + CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); + secp256k1_fe_from_storage(&x, &xs); + secp256k1_fe_from_storage(&y, &ys); + secp256k1_fe_from_storage(&z, &zs); + /* Test that mul_int, mul, and add agree. */ + secp256k1_fe_add(&y, &x); + secp256k1_fe_add(&y, &x); + z = x; + secp256k1_fe_mul_int(&z, 3); + CHECK(check_fe_equal(&y, &z)); + secp256k1_fe_add(&y, &x); + secp256k1_fe_add(&z, &x); + CHECK(check_fe_equal(&z, &y)); + z = x; + secp256k1_fe_mul_int(&z, 5); + secp256k1_fe_mul(&q, &x, &fe5); + CHECK(check_fe_equal(&z, &q)); + secp256k1_fe_negate(&x, &x, 1); + secp256k1_fe_add(&z, &x); + secp256k1_fe_add(&q, &x); + CHECK(check_fe_equal(&y, &z)); + CHECK(check_fe_equal(&q, &y)); + } +} + +void run_field_inv(void) { + secp256k1_fe x, xi, xii; + int i; + for (i = 0; i < 10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_var(void) { + secp256k1_fe x, xi, xii; + int i; + for (i = 0; i < 10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv_var(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv_var(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_all_var(void) { + secp256k1_fe x[16], xi[16], xii[16]; + int i; + /* Check it's safe to call for 0 elements */ + secp256k1_fe_inv_all_var(xi, x, 0); + for (i = 0; i < count; i++) { + size_t j; + size_t len = secp256k1_rand_int(15) + 1; + for (j = 0; j < len; j++) { + random_fe_non_zero(&x[j]); + } + secp256k1_fe_inv_all_var(xi, x, len); + for (j = 0; j < len; j++) { + CHECK(check_fe_inverse(&x[j], &xi[j])); + } + secp256k1_fe_inv_all_var(xii, xi, len); + for (j = 0; j < len; j++) { + CHECK(check_fe_equal(&x[j], &xii[j])); + } + } +} + +void run_sqr(void) { + secp256k1_fe x, s; + + { + int i; + secp256k1_fe_set_int(&x, 1); + secp256k1_fe_negate(&x, &x, 1); + + for (i = 1; i <= 512; ++i) { + secp256k1_fe_mul_int(&x, 2); + secp256k1_fe_normalize(&x); + secp256k1_fe_sqr(&s, &x); + } + } +} + +void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { + secp256k1_fe r1, r2; + int v = secp256k1_fe_sqrt(&r1, a); + CHECK((v == 0) == (k == NULL)); + + if (k != NULL) { + /* Check that the returned root is +/- the given known answer */ + secp256k1_fe_negate(&r2, &r1, 1); + secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); + secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); + CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); + } +} + +void run_sqrt(void) { + secp256k1_fe ns, x, s, t; + int i; + + /* Check sqrt(0) is 0 */ + secp256k1_fe_set_int(&x, 0); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + + /* Check sqrt of small squares (and their negatives) */ + for (i = 1; i <= 100; i++) { + secp256k1_fe_set_int(&x, i); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + } + + /* Consistency checks for large random values */ + for (i = 0; i < 10; i++) { + int j; + random_fe_non_square(&ns); + for (j = 0; j < count; j++) { + random_fe(&x); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + secp256k1_fe_mul(&t, &s, &ns); + test_sqrt(&t, NULL); + } + } +} + +/***** GROUP TESTS *****/ + +void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); + CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); +} + +/* This compares jacobian points including their Z, not just their geometric meaning. */ +int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { + secp256k1_gej a2; + secp256k1_gej b2; + int ret = 1; + ret &= a->infinity == b->infinity; + if (ret && !a->infinity) { + a2 = *a; + b2 = *b; + secp256k1_fe_normalize(&a2.x); + secp256k1_fe_normalize(&a2.y); + secp256k1_fe_normalize(&a2.z); + secp256k1_fe_normalize(&b2.x); + secp256k1_fe_normalize(&b2.y); + secp256k1_fe_normalize(&b2.z); + ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; + ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; + ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; + } + return ret; +} + +void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { + secp256k1_fe z2s; + secp256k1_fe u1, u2, s1, s2; + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ + secp256k1_fe_sqr(&z2s, &b->z); + secp256k1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; secp256k1_fe_normalize_weak(&u2); + secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; secp256k1_fe_normalize_weak(&s2); + CHECK(secp256k1_fe_equal_var(&u1, &u2)); + CHECK(secp256k1_fe_equal_var(&s1, &s2)); +} + +void test_ge(void) { + int i, i1; +#ifdef USE_ENDOMORPHISM + int runs = 6; +#else + int runs = 4; +#endif + /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). + * The second in each pair of identical points uses a random Z coordinate in the Jacobian form. + * All magnitudes are randomized. + * All 17*17 combinations of points are added to each other, using all applicable methods. + * + * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. + */ + secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_fe zf; + secp256k1_fe zfi2, zfi3; + + secp256k1_gej_set_infinity(&gej[0]); + secp256k1_ge_clear(&ge[0]); + secp256k1_ge_set_gej_var(&ge[0], &gej[0]); + for (i = 0; i < runs; i++) { + int j; + secp256k1_ge g; + random_group_element_test(&g); +#ifdef USE_ENDOMORPHISM + if (i >= runs - 2) { + secp256k1_ge_mul_lambda(&g, &ge[1]); + } + if (i >= runs - 1) { + secp256k1_ge_mul_lambda(&g, &g); + } +#endif + ge[1 + 4 * i] = g; + ge[2 + 4 * i] = g; + secp256k1_ge_neg(&ge[3 + 4 * i], &g); + secp256k1_ge_neg(&ge[4 + 4 * i], &g); + secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); + random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); + secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); + random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); + for (j = 0; j < 4; j++) { + random_field_element_magnitude(&ge[1 + j + 4 * i].x); + random_field_element_magnitude(&ge[1 + j + 4 * i].y); + random_field_element_magnitude(&gej[1 + j + 4 * i].x); + random_field_element_magnitude(&gej[1 + j + 4 * i].y); + random_field_element_magnitude(&gej[1 + j + 4 * i].z); + } + } + + /* Compute z inverses. */ + { + secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + for (i = 0; i < 4 * runs + 1; i++) { + if (i == 0) { + /* The point at infinity does not have a meaningful z inverse. Any should do. */ + do { + random_field_element_test(&zs[i]); + } while(secp256k1_fe_is_zero(&zs[i])); + } else { + zs[i] = gej[i].z; + } + } + secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1); + free(zs); + } + + /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ + do { + random_field_element_test(&zf); + } while(secp256k1_fe_is_zero(&zf)); + random_field_element_magnitude(&zf); + secp256k1_fe_inv_var(&zfi3, &zf); + secp256k1_fe_sqr(&zfi2, &zfi3); + secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); + + for (i1 = 0; i1 < 1 + 4 * runs; i1++) { + int i2; + for (i2 = 0; i2 < 1 + 4 * runs; i2++) { + /* Compute reference result using gej + gej (var). */ + secp256k1_gej refj, resj; + secp256k1_ge ref; + secp256k1_fe zr; + secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); + /* Check Z ratio. */ + if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { + secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zrz, &refj.z)); + } + secp256k1_ge_set_gej_var(&ref, &refj); + + /* Test gej + ge with Z ratio result (var). */ + secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); + ge_equals_gej(&ref, &resj); + if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { + secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zrz, &resj.z)); + } + + /* Test gej + ge (var, with additional Z factor). */ + { + secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ + secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); + secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); + random_field_element_magnitude(&ge2_zfi.x); + random_field_element_magnitude(&ge2_zfi.y); + secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); + ge_equals_gej(&ref, &resj); + } + + /* Test gej + ge (const). */ + if (i2 != 0) { + /* secp256k1_gej_add_ge does not support its second argument being infinity. */ + secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); + ge_equals_gej(&ref, &resj); + } + + /* Test doubling (var). */ + if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { + secp256k1_fe zr2; + /* Normal doubling with Z ratio result. */ + secp256k1_gej_double_var(&resj, &gej[i1], &zr2); + ge_equals_gej(&ref, &resj); + /* Check Z ratio. */ + secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zr2, &resj.z)); + /* Normal doubling. */ + secp256k1_gej_double_var(&resj, &gej[i2], NULL); + ge_equals_gej(&ref, &resj); + } + + /* Test adding opposites. */ + if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { + CHECK(secp256k1_ge_is_infinity(&ref)); + } + + /* Test adding infinity. */ + if (i1 == 0) { + CHECK(secp256k1_ge_is_infinity(&ge[i1])); + CHECK(secp256k1_gej_is_infinity(&gej[i1])); + ge_equals_gej(&ref, &gej[i2]); + } + if (i2 == 0) { + CHECK(secp256k1_ge_is_infinity(&ge[i2])); + CHECK(secp256k1_gej_is_infinity(&gej[i2])); + ge_equals_gej(&ref, &gej[i1]); + } + } + } + + /* Test adding all points together in random order equals infinity. */ + { + secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; + secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); + for (i = 0; i < 4 * runs + 1; i++) { + gej_shuffled[i] = gej[i]; + } + for (i = 0; i < 4 * runs + 1; i++) { + int swap = i + secp256k1_rand_int(4 * runs + 1 - i); + if (swap != i) { + secp256k1_gej t = gej_shuffled[i]; + gej_shuffled[i] = gej_shuffled[swap]; + gej_shuffled[swap] = t; + } + } + for (i = 0; i < 4 * runs + 1; i++) { + secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); + } + CHECK(secp256k1_gej_is_infinity(&sum)); + free(gej_shuffled); + } + + /* Test batch gej -> ge conversion with and without known z ratios. */ + { + secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); + secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + for (i = 0; i < 4 * runs + 1; i++) { + /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ + if (i < 4 * runs) { + secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); + } + } + secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); + secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); + for (i = 0; i < 4 * runs + 1; i++) { + secp256k1_fe s; + random_fe_non_zero(&s); + secp256k1_gej_rescale(&gej[i], &s); + ge_equals_gej(&ge_set_table[i], &gej[i]); + ge_equals_gej(&ge_set_all[i], &gej[i]); + } + free(ge_set_table); + free(ge_set_all); + free(zr); + } + + free(ge); + free(gej); + free(zinv); +} + +void test_add_neg_y_diff_x(void) { + /* The point of this test is to check that we can add two points + * whose y-coordinates are negatives of each other but whose x + * coordinates differ. If the x-coordinates were the same, these + * points would be negatives of each other and their sum is + * infinity. This is cool because it "covers up" any degeneracy + * in the addition algorithm that would cause the xy coordinates + * of the sum to be wrong (since infinity has no xy coordinates). + * HOWEVER, if the x-coordinates are different, infinity is the + * wrong answer, and such degeneracies are exposed. This is the + * root of https://github.com/bitcoin-core/secp256k1/issues/257 + * which this test is a regression test for. + * + * These points were generated in sage as + * # secp256k1 params + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (7)]) + * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) + * N = FiniteField(G.order()) + * + * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F) + * x = polygen(N) + * lam = (1 - x^3).roots()[1][0] + * + * # random "bad pair" + * P = C.random_element() + * Q = -int(lam) * P + * print " P: %x %x" % P.xy() + * print " Q: %x %x" % Q.xy() + * print "P + Q: %x %x" % (P + Q).xy() + */ + secp256k1_gej aj = SECP256K1_GEJ_CONST( + 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, + 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, + 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, + 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d + ); + secp256k1_gej bj = SECP256K1_GEJ_CONST( + 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, + 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, + 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, + 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 + ); + secp256k1_gej sumj = SECP256K1_GEJ_CONST( + 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, + 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, + 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, + 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe + ); + secp256k1_ge b; + secp256k1_gej resj; + secp256k1_ge res; + secp256k1_ge_set_gej(&b, &bj); + + secp256k1_gej_add_var(&resj, &aj, &bj, NULL); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); + + secp256k1_gej_add_ge(&resj, &aj, &b); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); + + secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); +} + +void run_ge(void) { + int i; + for (i = 0; i < count * 32; i++) { + test_ge(); + } + test_add_neg_y_diff_x(); +} + +void test_ec_combine(void) { + secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_pubkey data[6]; + const secp256k1_pubkey* d[6]; + secp256k1_pubkey sd; + secp256k1_pubkey sd2; + secp256k1_gej Qj; + secp256k1_ge Q; + int i; + for (i = 1; i <= 6; i++) { + secp256k1_scalar s; + random_scalar_order_test(&s); + secp256k1_scalar_add(&sum, &sum, &s); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(&data[i - 1], &Q); + d[i - 1] = &data[i - 1]; + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(&sd, &Q); + CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); + CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); + } +} + +void run_ec_combine(void) { + int i; + for (i = 0; i < count * 8; i++) { + test_ec_combine(); + } +} + +void test_group_decompress(const secp256k1_fe* x) { + /* The input itself, normalized. */ + secp256k1_fe fex = *x; + secp256k1_fe fez; + /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ + secp256k1_ge ge_quad, ge_even, ge_odd; + secp256k1_gej gej_quad; + /* Return values of the above calls. */ + int res_quad, res_even, res_odd; + + secp256k1_fe_normalize_var(&fex); + + res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); + res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); + res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); + + CHECK(res_quad == res_even); + CHECK(res_quad == res_odd); + + if (res_quad) { + secp256k1_fe_normalize_var(&ge_quad.x); + secp256k1_fe_normalize_var(&ge_odd.x); + secp256k1_fe_normalize_var(&ge_even.x); + secp256k1_fe_normalize_var(&ge_quad.y); + secp256k1_fe_normalize_var(&ge_odd.y); + secp256k1_fe_normalize_var(&ge_even.y); + + /* No infinity allowed. */ + CHECK(!ge_quad.infinity); + CHECK(!ge_even.infinity); + CHECK(!ge_odd.infinity); + + /* Check that the x coordinates check out. */ + CHECK(secp256k1_fe_equal_var(&ge_quad.x, x)); + CHECK(secp256k1_fe_equal_var(&ge_even.x, x)); + CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); + + /* Check that the Y coordinate result in ge_quad is a square. */ + CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); + + /* Check odd/even Y in ge_odd, ge_even. */ + CHECK(secp256k1_fe_is_odd(&ge_odd.y)); + CHECK(!secp256k1_fe_is_odd(&ge_even.y)); + + /* Check secp256k1_gej_has_quad_y_var. */ + secp256k1_gej_set_ge(&gej_quad, &ge_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + } +} + +void run_group_decompress(void) { + int i; + for (i = 0; i < count * 4; i++) { + secp256k1_fe fe; + random_fe_test(&fe); + test_group_decompress(&fe); + } +} + +/***** ECMULT TESTS *****/ + +void run_ecmult_chain(void) { + /* random starting point A (on the curve) */ + secp256k1_gej a = SECP256K1_GEJ_CONST( + 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, + 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, + 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, + 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f + ); + /* two random initial factors xn and gn */ + secp256k1_scalar xn = SECP256K1_SCALAR_CONST( + 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, + 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 + ); + secp256k1_scalar gn = SECP256K1_SCALAR_CONST( + 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, + 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de + ); + /* two small multipliers to be applied to xn and gn in every iteration: */ + static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); + static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); + /* accumulators with the resulting coefficients to A and G */ + secp256k1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + /* actual points */ + secp256k1_gej x; + secp256k1_gej x2; + int i; + + /* the point being computed */ + x = a; + for (i = 0; i < 200*count; i++) { + /* in each iteration, compute X = xn*X + gn*G; */ + secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); + /* also compute ae and ge: the actual accumulated factors for A and G */ + /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ + secp256k1_scalar_mul(&ae, &ae, &xn); + secp256k1_scalar_mul(&ge, &ge, &xn); + secp256k1_scalar_add(&ge, &ge, &gn); + /* modify xn and gn */ + secp256k1_scalar_mul(&xn, &xn, &xf); + secp256k1_scalar_mul(&gn, &gn, &gf); + + /* verify */ + if (i == 19999) { + /* expected result after 19999 iterations */ + secp256k1_gej rp = SECP256K1_GEJ_CONST( + 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, + 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, + 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, + 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 + ); + + secp256k1_gej_neg(&rp, &rp); + secp256k1_gej_add_var(&rp, &rp, &x, NULL); + CHECK(secp256k1_gej_is_infinity(&rp)); + } + } + /* redo the computation, but directly with the resulting ae and ge coefficients: */ + secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); + secp256k1_gej_neg(&x2, &x2); + secp256k1_gej_add_var(&x2, &x2, &x, NULL); + CHECK(secp256k1_gej_is_infinity(&x2)); +} + +void test_point_times_order(const secp256k1_gej *point) { + /* X * (point + G) + (order-X) * (pointer + G) = 0 */ + secp256k1_scalar x; + secp256k1_scalar nx; + secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_gej res1, res2; + secp256k1_ge res3; + unsigned char pub[65]; + size_t psize = 65; + random_scalar_order_test(&x); + secp256k1_scalar_negate(&nx, &x); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ + secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ + secp256k1_gej_add_var(&res1, &res1, &res2, NULL); + CHECK(secp256k1_gej_is_infinity(&res1)); + CHECK(secp256k1_gej_is_valid_var(&res1) == 0); + secp256k1_ge_set_gej(&res3, &res1); + CHECK(secp256k1_ge_is_infinity(&res3)); + CHECK(secp256k1_ge_is_valid_var(&res3) == 0); + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); + psize = 65; + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); + /* check zero/one edge cases */ + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); + secp256k1_ge_set_gej(&res3, &res1); + CHECK(secp256k1_ge_is_infinity(&res3)); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); + secp256k1_ge_set_gej(&res3, &res1); + ge_equals_gej(&res3, point); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); + secp256k1_ge_set_gej(&res3, &res1); + ge_equals_ge(&res3, &secp256k1_ge_const_g); +} + +void run_point_times_order(void) { + int i; + secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); + static const secp256k1_fe xr = SECP256K1_FE_CONST( + 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, + 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 + ); + for (i = 0; i < 500; i++) { + secp256k1_ge p; + if (secp256k1_ge_set_xo_var(&p, &x, 1)) { + secp256k1_gej j; + CHECK(secp256k1_ge_is_valid_var(&p)); + secp256k1_gej_set_ge(&j, &p); + CHECK(secp256k1_gej_is_valid_var(&j)); + test_point_times_order(&j); + } + secp256k1_fe_sqr(&x, &x); + } + secp256k1_fe_normalize_var(&x); + CHECK(secp256k1_fe_equal_var(&x, &xr)); +} + +void ecmult_const_random_mult(void) { + /* random starting point A (on the curve) */ + secp256k1_ge a = SECP256K1_GE_CONST( + 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, + 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, + 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, + 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d + ); + /* random initial factor xn */ + secp256k1_scalar xn = SECP256K1_SCALAR_CONST( + 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, + 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b + ); + /* expected xn * A (from sage) */ + secp256k1_ge expected_b = SECP256K1_GE_CONST( + 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, + 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, + 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, + 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 + ); + secp256k1_gej b; + secp256k1_ecmult_const(&b, &a, &xn); + + CHECK(secp256k1_ge_is_valid_var(&a)); + ge_equals_gej(&expected_b, &b); +} + +void ecmult_const_commutativity(void) { + secp256k1_scalar a; + secp256k1_scalar b; + secp256k1_gej res1; + secp256k1_gej res2; + secp256k1_ge mid1; + secp256k1_ge mid2; + random_scalar_order_test(&a); + random_scalar_order_test(&b); + + secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); + secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); + secp256k1_ge_set_gej(&mid1, &res1); + secp256k1_ge_set_gej(&mid2, &res2); + secp256k1_ecmult_const(&res1, &mid1, &b); + secp256k1_ecmult_const(&res2, &mid2, &a); + secp256k1_ge_set_gej(&mid1, &res1); + secp256k1_ge_set_gej(&mid2, &res2); + ge_equals_ge(&mid1, &mid2); +} + +void ecmult_const_mult_zero_one(void) { + secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_scalar negone; + secp256k1_gej res1; + secp256k1_ge res2; + secp256k1_ge point; + secp256k1_scalar_negate(&negone, &one); + + random_group_element_test(&point); + secp256k1_ecmult_const(&res1, &point, &zero); + secp256k1_ge_set_gej(&res2, &res1); + CHECK(secp256k1_ge_is_infinity(&res2)); + secp256k1_ecmult_const(&res1, &point, &one); + secp256k1_ge_set_gej(&res2, &res1); + ge_equals_ge(&res2, &point); + secp256k1_ecmult_const(&res1, &point, &negone); + secp256k1_gej_neg(&res1, &res1); + secp256k1_ge_set_gej(&res2, &res1); + ge_equals_ge(&res2, &point); +} + +void ecmult_const_chain_multiply(void) { + /* Check known result (randomly generated test problem from sage) */ + const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( + 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, + 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b + ); + const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( + 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, + 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, + 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, + 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 + ); + secp256k1_gej point; + secp256k1_ge res; + int i; + + secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); + for (i = 0; i < 100; ++i) { + secp256k1_ge tmp; + secp256k1_ge_set_gej(&tmp, &point); + secp256k1_ecmult_const(&point, &tmp, &scalar); + } + secp256k1_ge_set_gej(&res, &point); + ge_equals_gej(&res, &expected_point); +} + +void run_ecmult_const_tests(void) { + ecmult_const_mult_zero_one(); + ecmult_const_random_mult(); + ecmult_const_commutativity(); + ecmult_const_chain_multiply(); +} + +void test_wnaf(const secp256k1_scalar *number, int w) { + secp256k1_scalar x, two, t; + int wnaf[256]; + int zeroes = -1; + int i; + int bits; + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&two, 2); + bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); + CHECK(bits <= 256); + for (i = bits-1; i >= 0; i--) { + int v = wnaf[i]; + secp256k1_scalar_mul(&x, &x, &two); + if (v) { + CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ + zeroes=0; + CHECK((v & 1) == 1); /* check non-zero elements are odd */ + CHECK(v <= (1 << (w-1)) - 1); /* check range below */ + CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ + } else { + CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ + zeroes++; + } + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); + } + CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ +} + +void test_constant_wnaf_negate(const secp256k1_scalar *number) { + secp256k1_scalar neg1 = *number; + secp256k1_scalar neg2 = *number; + int sign1 = 1; + int sign2 = 1; + + if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { + secp256k1_scalar_negate(&neg1, &neg1); + sign1 = -1; + } + sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); + CHECK(sign1 == sign2); + CHECK(secp256k1_scalar_eq(&neg1, &neg2)); +} + +void test_constant_wnaf(const secp256k1_scalar *number, int w) { + secp256k1_scalar x, shift; + int wnaf[256] = {0}; + int i; + int skew; + secp256k1_scalar num = *number; + + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&shift, 1 << w); + /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ +#ifdef USE_ENDOMORPHISM + for (i = 0; i < 16; ++i) { + secp256k1_scalar_shr_int(&num, 8); + } +#endif + skew = secp256k1_wnaf_const(wnaf, num, w); + + for (i = WNAF_SIZE(w); i >= 0; --i) { + secp256k1_scalar t; + int v = wnaf[i]; + CHECK(v != 0); /* check nonzero */ + CHECK(v & 1); /* check parity */ + CHECK(v > -(1 << w)); /* check range above */ + CHECK(v < (1 << w)); /* check range below */ + + secp256k1_scalar_mul(&x, &x, &shift); + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); + } + /* Skew num because when encoding numbers as odd we use an offset */ + secp256k1_scalar_cadd_bit(&num, skew == 2, 1); + CHECK(secp256k1_scalar_eq(&x, &num)); +} + +void run_wnaf(void) { + int i; + secp256k1_scalar n = {{0}}; + + /* Sanity check: 1 and 2 are the smallest odd and even numbers and should + * have easier-to-diagnose failure modes */ + n.d[0] = 1; + test_constant_wnaf(&n, 4); + n.d[0] = 2; + test_constant_wnaf(&n, 4); + /* Random tests */ + for (i = 0; i < count; i++) { + random_scalar_order(&n); + test_wnaf(&n, 4+(i%10)); + test_constant_wnaf_negate(&n); + test_constant_wnaf(&n, 4 + (i % 10)); + } + secp256k1_scalar_set_int(&n, 0); + CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); + CHECK(secp256k1_scalar_is_zero(&n)); + CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); + CHECK(secp256k1_scalar_is_zero(&n)); +} + +void test_ecmult_constants(void) { + /* Test ecmult_gen() for [0..36) and [order-36..0). */ + secp256k1_scalar x; + secp256k1_gej r; + secp256k1_ge ng; + int i; + int j; + secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); + for (i = 0; i < 36; i++ ) { + secp256k1_scalar_set_int(&x, i); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); + for (j = 0; j < i; j++) { + if (j == i - 1) { + ge_equals_gej(&secp256k1_ge_const_g, &r); + } + secp256k1_gej_add_ge(&r, &r, &ng); + } + CHECK(secp256k1_gej_is_infinity(&r)); + } + for (i = 1; i <= 36; i++ ) { + secp256k1_scalar_set_int(&x, i); + secp256k1_scalar_negate(&x, &x); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); + for (j = 0; j < i; j++) { + if (j == i - 1) { + ge_equals_gej(&ng, &r); + } + secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g); + } + CHECK(secp256k1_gej_is_infinity(&r)); + } +} + +void run_ecmult_constants(void) { + test_ecmult_constants(); +} + +void test_ecmult_gen_blind(void) { + /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ + secp256k1_scalar key; + secp256k1_scalar b; + unsigned char seed32[32]; + secp256k1_gej pgej; + secp256k1_gej pgej2; + secp256k1_gej i; + secp256k1_ge pge; + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); + secp256k1_rand256(seed32); + b = ctx->ecmult_gen_ctx.blind; + i = ctx->ecmult_gen_ctx.initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); + CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); + CHECK(!gej_xyz_equals_gej(&i, &ctx->ecmult_gen_ctx.initial)); + secp256k1_ge_set_gej(&pge, &pgej); + ge_equals_gej(&pge, &pgej2); +} + +void test_ecmult_gen_blind_reset(void) { + /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ + secp256k1_scalar b; + secp256k1_gej initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); + b = ctx->ecmult_gen_ctx.blind; + initial = ctx->ecmult_gen_ctx.initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); + CHECK(secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); + CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); +} + +void run_ecmult_gen_blind(void) { + int i; + test_ecmult_gen_blind_reset(); + for (i = 0; i < 10; i++) { + test_ecmult_gen_blind(); + } +} + +#ifdef USE_ENDOMORPHISM +/***** ENDOMORPHISH TESTS *****/ +void test_scalar_split(void) { + secp256k1_scalar full; + secp256k1_scalar s1, slam; + const unsigned char zero[32] = {0}; + unsigned char tmp[32]; + + random_scalar_order_test(&full); + secp256k1_scalar_split_lambda(&s1, &slam, &full); + + /* check that both are <= 128 bits in size */ + if (secp256k1_scalar_is_high(&s1)) { + secp256k1_scalar_negate(&s1, &s1); + } + if (secp256k1_scalar_is_high(&slam)) { + secp256k1_scalar_negate(&slam, &slam); + } + + secp256k1_scalar_get_b32(tmp, &s1); + CHECK(memcmp(zero, tmp, 16) == 0); + secp256k1_scalar_get_b32(tmp, &slam); + CHECK(memcmp(zero, tmp, 16) == 0); +} + +void run_endomorphism_tests(void) { + test_scalar_split(); +} +#endif + +void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { + unsigned char pubkeyc[65]; + secp256k1_pubkey pubkey; + secp256k1_ge ge; + size_t pubkeyclen; + int32_t ecount; + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { + /* Smaller sizes are tested exhaustively elsewhere. */ + int32_t i; + memcpy(&pubkeyc[1], input, 64); + VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen); + for (i = 0; i < 256; i++) { + /* Try all type bytes. */ + int xpass; + int ypass; + int ysign; + pubkeyc[0] = i; + /* What sign does this point have? */ + ysign = (input[63] & 1) + 2; + /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ + xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); + /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ + ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && + ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); + if (xpass || ypass) { + /* These cases must parse. */ + unsigned char pubkeyo[65]; + size_t outl; + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + ecount = 0; + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + outl = 65; + VG_UNDEF(pubkeyo, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + VG_CHECK(pubkeyo, outl); + CHECK(outl == 33); + CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); + CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); + if (ypass) { + /* This test isn't always done because we decode with alternative signs, so the y won't match. */ + CHECK(pubkeyo[0] == ysign); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + secp256k1_pubkey_save(&pubkey, &ge); + VG_CHECK(&pubkey, sizeof(pubkey)); + outl = 65; + VG_UNDEF(pubkeyo, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + VG_CHECK(pubkeyo, outl); + CHECK(outl == 65); + CHECK(pubkeyo[0] == 4); + CHECK(memcmp(&pubkeyo[1], input, 64) == 0); + } + CHECK(ecount == 0); + } else { + /* These cases must fail to parse. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + } + } + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); +} + +void run_ec_pubkey_parse_test(void) { +#define SECP256K1_EC_PARSE_TEST_NVALID (12) + const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { + { + /* Point with leading and trailing zeros in x and y serialization. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, + 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 + }, + { + /* Point with x equal to a 3rd root of unity.*/ + 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, + 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Point with largest x. (1/2) */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, + 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, + 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, + }, + { + /* Point with largest x. (2/2) */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, + 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, + 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, + }, + { + /* Point with smallest x. (1/2) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Point with smallest x. (2/2) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, + 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, + }, + { + /* Point with largest y. (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with largest y. (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with largest y. (3/3) */ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with smallest y. (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + { + /* Point with smallest y. (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + { + /* Point with smallest y. (3/3) */ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + } + }; +#define SECP256K1_EC_PARSE_TEST_NXVALID (4) + const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { + { + /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* x on curve, y is from y^2 = x^3 + 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 + } + }; +#define SECP256K1_EC_PARSE_TEST_NINVALID (7) + const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { + { + /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ + 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, + 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + { + /* Valid if x overflow ignored (x = 1 mod p). */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Valid if x overflow ignored (x = 1 mod p). */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, + 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, + }, + { + /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, + 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, + }, + { + /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, + 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, + }, + { + /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, + 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, + }, + { + /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, + 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 + } + }; + const unsigned char pubkeyc[66] = { + /* Serialization of G. */ + 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, + 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, + 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, + 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, + 0xB8, 0x00 + }; + unsigned char sout[65]; + unsigned char shortkey[2]; + secp256k1_ge ge; + secp256k1_pubkey pubkey; + size_t len; + int32_t i; + int32_t ecount; + int32_t ecount2; + ecount = 0; + /* Nothing should be reading this far into pubkeyc. */ + VG_UNDEF(&pubkeyc[65], 1); + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + /* Zero length claimed, fail, zeroize, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(shortkey, 2); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 0) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* Length one claimed, fail, zeroize, no illegal arg error. */ + for (i = 0; i < 256 ; i++) { + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + shortkey[0] = i; + VG_UNDEF(&shortkey[1], 1); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + /* Length two claimed, fail, zeroize, no illegal arg error. */ + for (i = 0; i < 65536 ; i++) { + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + shortkey[0] = i & 255; + shortkey[1] = i >> 8; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 33) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, pubkeyc, 65) == 0); + CHECK(ecount == 2); + /* NULL input string. Illegal arg and zeroize output. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, NULL, 65) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 1); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 2); + /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 64) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 66) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* Valid parse. */ + memset(&pubkey, 0, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + VG_UNDEF(&ge, sizeof(ge)); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); + VG_CHECK(&ge.x, sizeof(ge.x)); + VG_CHECK(&ge.y, sizeof(ge.y)); + VG_CHECK(&ge.infinity, sizeof(ge.infinity)); + ge_equals_ge(&secp256k1_ge_const_g, &ge); + CHECK(ecount == 0); + /* secp256k1_ec_pubkey_serialize illegal args. */ + ecount = 0; + len = 65; + CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(ecount == 1); + CHECK(len == 0); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(ecount == 2); + len = 65; + VG_UNDEF(sout, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0); + VG_CHECK(sout, 65); + CHECK(ecount == 3); + CHECK(len == 0); + len = 65; + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, ~0) == 0); + CHECK(ecount == 4); + CHECK(len == 0); + len = 65; + VG_UNDEF(sout, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + VG_CHECK(sout, 65); + CHECK(ecount == 4); + CHECK(len == 65); + /* Multiple illegal args. Should still set arg error only once. */ + ecount = 0; + ecount2 = 11; + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); + CHECK(ecount == 1); + /* Does the illegal arg callback actually change the behavior? */ + secp256k1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); + CHECK(ecount == 1); + CHECK(ecount2 == 10); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + /* Try a bunch of prefabbed points with all possible encodings. */ + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { + ec_pubkey_parse_pointtest(valid[i], 1, 1); + } + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { + ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); + } + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { + ec_pubkey_parse_pointtest(invalid[i], 0, 0); + } +} + +void run_eckey_edge_case_test(void) { + const unsigned char orderc[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 + }; + const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; + unsigned char ctmp[33]; + unsigned char ctmp2[33]; + secp256k1_pubkey pubkey; + secp256k1_pubkey pubkey2; + secp256k1_pubkey pubkey_one; + secp256k1_pubkey pubkey_negone; + const secp256k1_pubkey *pubkeys[3]; + size_t len; + int32_t ecount; + /* Group order is too large, reject. */ + CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* Maximum value is too large, reject. */ + memset(ctmp, 255, 32); + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* Zero is too small, reject. */ + memset(ctmp, 0, 32); + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* One must be accepted. */ + ctmp[31] = 0x01; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + pubkey_one = pubkey; + /* Group order + 1 is too large, reject. */ + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x42; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* -1 must be accepted. */ + ctmp[31] = 0x40; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + pubkey_negone = pubkey; + /* Tweak of zero leaves the value changed. */ + memset(ctmp2, 0, 32); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); + CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); + memcpy(&pubkey2, &pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Multiply tweak of zero zeroizes the output. */ + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Overflowing key tweak zeroizes. */ + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Private key tweaks results in a key of zero. */ + ctmp2[31] = 1; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); + CHECK(memcmp(zeros, ctmp2, 32) == 0); + ctmp2[31] = 1; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Tweak computation wraps and results in a key of 1. */ + ctmp2[31] = 2; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); + CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); + ctmp2[31] = 2; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + ctmp2[31] = 1; + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Tweak mul * 2 = 1+1. */ + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + ctmp2[31] = 2; + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Test argument errors. */ + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + CHECK(ecount == 0); + /* Zeroize pubkey on parse error. */ + memset(&pubkey, 0, 32); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + memset(&pubkey2, 0, 32); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); + CHECK(ecount == 2); + CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); + /* Plain argument errors. */ + ecount = 0; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); + CHECK(ecount == 1); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 4; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 4; + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 1; + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); + CHECK(ecount == 1); + memset(&pubkey, 1, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* secp256k1_ec_pubkey_combine tests. */ + ecount = 0; + pubkeys[0] = &pubkey_one; + VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); + VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); + VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 2); + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 3); + pubkeys[0] = &pubkey_negone; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + len = 33; + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); + CHECK(memcmp(ctmp, ctmp2, 33) == 0); + /* Result is infinity. */ + pubkeys[0] = &pubkey_one; + pubkeys[1] = &pubkey_negone; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 3); + /* Passes through infinity but comes out one. */ + pubkeys[2] = &pubkey_one; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + len = 33; + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); + CHECK(memcmp(ctmp, ctmp2, 33) == 0); + /* Adds to two. */ + pubkeys[1] = &pubkey_one; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); +} + +void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { + secp256k1_scalar nonce; + do { + random_scalar_order_test(&nonce); + } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); +} + +void test_ecdsa_sign_verify(void) { + secp256k1_gej pubj; + secp256k1_ge pub; + secp256k1_scalar one; + secp256k1_scalar msg, key; + secp256k1_scalar sigr, sigs; + int recid; + int getrec; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); + secp256k1_ge_set_gej(&pub, &pubj); + getrec = secp256k1_rand_bits(1); + random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); + if (getrec) { + CHECK(recid >= 0 && recid < 4); + } + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + secp256k1_scalar_set_int(&one, 1); + secp256k1_scalar_add(&msg, &msg, &one); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); +} + +void run_ecdsa_sign_verify(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_ecdsa_sign_verify(); + } +} + +/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ +static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void)msg32; + (void)key32; + (void)algo16; + memcpy(nonce32, data, 32); + return (counter == 0); +} + +static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + /* Dummy nonce generator that has a fatal error on the first counter value. */ + if (counter == 0) { + return 0; + } + return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); +} + +static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ + if (counter < 3) { + memset(nonce32, counter==0 ? 0 : 255, 32); + if (counter == 2) { + nonce32[31]--; + } + return 1; + } + if (counter < 5) { + static const unsigned char order[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 + }; + memcpy(nonce32, order, 32); + if (counter == 4) { + nonce32[31]++; + } + return 1; + } + /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ + /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ + if (counter > 5) { + return 0; + } + return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); +} + +int is_empty_signature(const secp256k1_ecdsa_signature *sig) { + static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; + return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; +} + +void test_ecdsa_end_to_end(void) { + unsigned char extra[32] = {0x00}; + unsigned char privkey[32]; + unsigned char message[32]; + unsigned char privkey2[32]; + secp256k1_ecdsa_signature signature[6]; + secp256k1_scalar r, s; + unsigned char sig[74]; + size_t siglen = 74; + unsigned char pubkeyc[65]; + size_t pubkeyclen = 65; + secp256k1_pubkey pubkey; + unsigned char seckey[300]; + size_t seckeylen = 300; + + /* Generate a random key and message. */ + { + secp256k1_scalar msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(privkey, &key); + secp256k1_scalar_get_b32(message, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Verify exporting and importing public key. */ + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); + memset(&pubkey, 0, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + + /* Verify private key import and export. */ + CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); + CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); + CHECK(memcmp(privkey, privkey2, 32) == 0); + + /* Optionally tweak the keys using addition. */ + if (secp256k1_rand_int(3) == 0) { + int ret1; + int ret2; + unsigned char rnd[32]; + secp256k1_pubkey pubkey2; + secp256k1_rand256_test(rnd); + ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); + ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) { + return; + } + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + } + + /* Optionally tweak the keys using multiplication. */ + if (secp256k1_rand_int(3) == 0) { + int ret1; + int ret2; + unsigned char rnd[32]; + secp256k1_pubkey pubkey2; + secp256k1_rand256_test(rnd); + ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); + ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) { + return; + } + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + } + + /* Sign. */ + CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &signature[2], message, privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); + CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); + CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); + /* Verify. */ + CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); + /* Test lower-S form, malleate, verify and fail, test again, malleate again */ + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); + secp256k1_scalar_negate(&s, &s); + secp256k1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); + CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); + secp256k1_scalar_negate(&s, &s); + secp256k1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); + CHECK(memcmp(&signature[5], &signature[0], 64) == 0); + + /* Serialize/parse DER and verify again */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + memset(&signature[0], 0, sizeof(signature[0])); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); + /* Serialize/destroy/parse DER and verify again. */ + siglen = 74; + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || + secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); +} + +void test_random_pubkeys(void) { + secp256k1_ge elem; + secp256k1_ge elem2; + unsigned char in[65]; + /* Generate some randomly sized pubkeys. */ + size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; + if (secp256k1_rand_bits(2) == 0) { + len = secp256k1_rand_bits(6); + } + if (len == 65) { + in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); + } else { + in[0] = secp256k1_rand_bits(1) ? 2 : 3; + } + if (secp256k1_rand_bits(3) == 0) { + in[0] = secp256k1_rand_bits(8); + } + if (len > 1) { + secp256k1_rand256(&in[1]); + } + if (len > 33) { + secp256k1_rand256(&in[33]); + } + if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { + unsigned char out[65]; + unsigned char firstb; + int res; + size_t size = len; + firstb = in[0]; + /* If the pubkey can be parsed, it should round-trip... */ + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); + CHECK(size == len); + CHECK(memcmp(&in[1], &out[1], len-1) == 0); + /* ... except for the type of hybrid inputs. */ + if ((in[0] != 6) && (in[0] != 7)) { + CHECK(in[0] == out[0]); + } + size = 65; + CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); + CHECK(size == 65); + CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); + ge_equals_ge(&elem,&elem2); + /* Check that the X9.62 hybrid type is checked. */ + in[0] = secp256k1_rand_bits(1) ? 6 : 7; + res = secp256k1_eckey_pubkey_parse(&elem2, in, size); + if (firstb == 2 || firstb == 3) { + if (in[0] == firstb + 4) { + CHECK(res); + } else { + CHECK(!res); + } + } + if (res) { + ge_equals_ge(&elem,&elem2); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); + CHECK(memcmp(&in[1], &out[1], 64) == 0); + } + } +} + +void run_random_pubkeys(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_random_pubkeys(); + } +} + +void run_ecdsa_end_to_end(void) { + int i; + for (i = 0; i < 64*count; i++) { + test_ecdsa_end_to_end(); + } +} + +int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { + static const unsigned char zeroes[32] = {0}; +#ifdef ENABLE_OPENSSL_TESTS + static const unsigned char max_scalar[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 + }; +#endif + + int ret = 0; + + secp256k1_ecdsa_signature sig_der; + unsigned char roundtrip_der[2048]; + unsigned char compact_der[64]; + size_t len_der = 2048; + int parsed_der = 0, valid_der = 0, roundtrips_der = 0; + + secp256k1_ecdsa_signature sig_der_lax; + unsigned char roundtrip_der_lax[2048]; + unsigned char compact_der_lax[64]; + size_t len_der_lax = 2048; + int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; + +#ifdef ENABLE_OPENSSL_TESTS + ECDSA_SIG *sig_openssl; + const unsigned char *sigptr; + unsigned char roundtrip_openssl[2048]; + int len_openssl = 2048; + int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0; +#endif + + parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); + if (parsed_der) { + ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; + valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); + } + if (valid_der) { + ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; + roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; + } + + parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); + if (parsed_der_lax) { + ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; + valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); + } + if (valid_der_lax) { + ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; + roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; + } + + if (certainly_der) { + ret |= (!parsed_der) << 2; + } + if (certainly_not_der) { + ret |= (parsed_der) << 17; + } + if (valid_der) { + ret |= (!roundtrips_der) << 3; + } + + if (valid_der) { + ret |= (!roundtrips_der_lax) << 12; + ret |= (len_der != len_der_lax) << 13; + ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14; + } + ret |= (roundtrips_der != roundtrips_der_lax) << 15; + if (parsed_der) { + ret |= (!parsed_der_lax) << 16; + } + +#ifdef ENABLE_OPENSSL_TESTS + sig_openssl = ECDSA_SIG_new(); + sigptr = sig; + parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); + if (parsed_openssl) { + valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; + if (valid_openssl) { + unsigned char tmp[32] = {0}; + BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); + valid_openssl = memcmp(tmp, max_scalar, 32) < 0; + } + if (valid_openssl) { + unsigned char tmp[32] = {0}; + BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); + valid_openssl = memcmp(tmp, max_scalar, 32) < 0; + } + } + len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); + if (len_openssl <= 2048) { + unsigned char *ptr = roundtrip_openssl; + CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); + roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); + } else { + len_openssl = 0; + } + ECDSA_SIG_free(sig_openssl); + + ret |= (parsed_der && !parsed_openssl) << 4; + ret |= (valid_der && !valid_openssl) << 5; + ret |= (roundtrips_openssl && !parsed_der) << 6; + ret |= (roundtrips_der != roundtrips_openssl) << 7; + if (roundtrips_openssl) { + ret |= (len_der != (size_t)len_openssl) << 8; + ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9; + } +#endif + return ret; +} + +static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { + size_t i; + for (i = 0; i < ptrlen; i++) { + int shift = ptrlen - 1 - i; + if (shift >= 4) { + ptr[i] = 0; + } else { + ptr[i] = (val >> shift) & 0xFF; + } + } +} + +static void damage_array(unsigned char *sig, size_t *len) { + int pos; + int action = secp256k1_rand_bits(3); + if (action < 1 && *len > 3) { + /* Delete a byte. */ + pos = secp256k1_rand_int(*len); + memmove(sig + pos, sig + pos + 1, *len - pos - 1); + (*len)--; + return; + } else if (action < 2 && *len < 2048) { + /* Insert a byte. */ + pos = secp256k1_rand_int(1 + *len); + memmove(sig + pos + 1, sig + pos, *len - pos); + sig[pos] = secp256k1_rand_bits(8); + (*len)++; + return; + } else if (action < 4) { + /* Modify a byte. */ + sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); + return; + } else { /* action < 8 */ + /* Modify a bit. */ + sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); + return; + } +} + +static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { + int der; + int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; + size_t tlen, elen, glen; + int indet; + int n; + + *len = 0; + der = secp256k1_rand_bits(2) == 0; + *certainly_der = der; + *certainly_not_der = 0; + indet = der ? 0 : secp256k1_rand_int(10) == 0; + + for (n = 0; n < 2; n++) { + /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ + nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); + /* The length of the number in bytes (the first byte of which will always be nonzero) */ + nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; + CHECK(nlen[n] <= 232); + /* The top bit of the number. */ + nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); + /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ + nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); + /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ + nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); + if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { + *certainly_not_der = 1; + } + CHECK(nlen[n] + nzlen[n] <= 300); + /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ + nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); + if (!der) { + /* nlenlen[n] max 127 bytes */ + int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + nlenlen[n] += add; + if (add != 0) { + *certainly_not_der = 1; + } + } + CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); + } + + /* The total length of the data to go, so far */ + tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; + CHECK(tlen <= 856); + + /* The length of the garbage inside the tuple. */ + elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; + if (elen != 0) { + *certainly_not_der = 1; + } + tlen += elen; + CHECK(tlen <= 980); + + /* The length of the garbage after the end of the tuple. */ + glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; + if (glen != 0) { + *certainly_not_der = 1; + } + CHECK(tlen + glen <= 990); + + /* Write the tuple header. */ + sig[(*len)++] = 0x30; + if (indet) { + /* Indeterminate length */ + sig[(*len)++] = 0x80; + *certainly_not_der = 1; + } else { + int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); + if (!der) { + int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + tlenlen += add; + if (add != 0) { + *certainly_not_der = 1; + } + } + if (tlenlen == 0) { + /* Short length notation */ + sig[(*len)++] = tlen; + } else { + /* Long length notation */ + sig[(*len)++] = 128 + tlenlen; + assign_big_endian(sig + *len, tlenlen, tlen); + *len += tlenlen; + } + tlen += tlenlen; + } + tlen += 2; + CHECK(tlen + glen <= 1119); + + for (n = 0; n < 2; n++) { + /* Write the integer header. */ + sig[(*len)++] = 0x02; + if (nlenlen[n] == 0) { + /* Short length notation */ + sig[(*len)++] = nlen[n] + nzlen[n]; + } else { + /* Long length notation. */ + sig[(*len)++] = 128 + nlenlen[n]; + assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); + *len += nlenlen[n]; + } + /* Write zero padding */ + while (nzlen[n] > 0) { + sig[(*len)++] = 0x00; + nzlen[n]--; + } + if (nlen[n] == 32 && !nlow[n]) { + /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ + int i; + for (i = 0; i < 16; i++) { + sig[(*len)++] = 0xFF; + } + nlen[n] -= 16; + } + /* Write first byte of number */ + if (nlen[n] > 0) { + sig[(*len)++] = nhbyte[n]; + nlen[n]--; + } + /* Generate remaining random bytes of number */ + secp256k1_rand_bytes_test(sig + *len, nlen[n]); + *len += nlen[n]; + nlen[n] = 0; + } + + /* Generate random garbage inside tuple. */ + secp256k1_rand_bytes_test(sig + *len, elen); + *len += elen; + + /* Generate end-of-contents bytes. */ + if (indet) { + sig[(*len)++] = 0; + sig[(*len)++] = 0; + tlen += 2; + } + CHECK(tlen + glen <= 1121); + + /* Generate random garbage outside tuple. */ + secp256k1_rand_bytes_test(sig + *len, glen); + *len += glen; + tlen += glen; + CHECK(tlen <= 1121); + CHECK(tlen == *len); +} + +void run_ecdsa_der_parse(void) { + int i,j; + for (i = 0; i < 200 * count; i++) { + unsigned char buffer[2048]; + size_t buflen = 0; + int certainly_der = 0; + int certainly_not_der = 0; + random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); + CHECK(buflen <= 2048); + for (j = 0; j < 16; j++) { + int ret = 0; + if (j > 0) { + damage_array(buffer, &buflen); + /* We don't know anything anymore about the DERness of the result */ + certainly_der = 0; + certainly_not_der = 0; + } + ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); + if (ret != 0) { + size_t k; + fprintf(stderr, "Failure %x on ", ret); + for (k = 0; k < buflen; k++) { + fprintf(stderr, "%02x ", buffer[k]); + } + fprintf(stderr, "\n"); + } + CHECK(ret == 0); + } + } +} + +/* Tests several edge cases. */ +void test_ecdsa_edge_cases(void) { + int t; + secp256k1_ecdsa_signature sig; + + /* Test the case where ECDSA recomputes a point that is infinity. */ + { + secp256k1_gej keyj; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_negate(&ss, &ss); + secp256k1_scalar_inverse(&ss, &ss); + secp256k1_scalar_set_int(&sr, 1); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); + secp256k1_ge_set_gej(&key, &keyj); + msg = ss; + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with r of zero fails. */ + { + const unsigned char pubkey_mods_zero[33] = { + 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x41 + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 0); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with s of zero fails. */ + { + const unsigned char pubkey[33] = { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01 + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 0); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 1); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with message 0 passes. */ + { + const unsigned char pubkey[33] = { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02 + }; + const unsigned char pubkey2[33] = { + 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x43 + }; + secp256k1_ge key; + secp256k1_ge key2; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 2); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 2); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_set_int(&ss, 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); + } + + /* Verify signature with message 1 passes. */ + { + const unsigned char pubkey[33] = { + 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, + 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, + 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, + 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, + 0x25 + }; + const unsigned char pubkey2[33] = { + 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, + 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, + 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, + 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, + 0x62 + }; + const unsigned char csr[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb + }; + secp256k1_ge key; + secp256k1_ge key2; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 1); + secp256k1_scalar_set_b32(&sr, csr, NULL); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_set_int(&ss, 2); + secp256k1_scalar_inverse_var(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); + } + + /* Verify signature with message -1 passes. */ + { + const unsigned char pubkey[33] = { + 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, + 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, + 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, + 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, + 0xf1 + }; + const unsigned char csr[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 1); + secp256k1_scalar_negate(&msg, &msg); + secp256k1_scalar_set_b32(&sr, csr, NULL); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + secp256k1_scalar_set_int(&ss, 3); + secp256k1_scalar_inverse_var(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Signature where s would be zero. */ + { + secp256k1_pubkey pubkey; + size_t siglen; + int32_t ecount; + unsigned char signature[72]; + static const unsigned char nonce[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }; + static const unsigned char nonce2[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 + }; + const unsigned char key[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }; + unsigned char msg[32] = { + 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, + 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, + 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, + 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, + }; + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); + msg[31] = 0xaa; + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); + CHECK(ecount == 6); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 7); + /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); + CHECK(ecount == 8); + siglen = 72; + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); + CHECK(ecount == 9); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); + CHECK(ecount == 10); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); + CHECK(ecount == 11); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); + CHECK(ecount == 11); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); + CHECK(ecount == 12); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); + CHECK(ecount == 13); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); + CHECK(ecount == 13); + siglen = 10; + /* Too little room for a signature does not fail via ARGCHECK. */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); + CHECK(ecount == 13); + ecount = 0; + CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); + CHECK(ecount == 5); + memset(signature, 255, 64); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); + CHECK(ecount == 5); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + } + + /* Nonce function corner cases. */ + for (t = 0; t < 2; t++) { + static const unsigned char zero[32] = {0x00}; + int i; + unsigned char key[32]; + unsigned char msg[32]; + secp256k1_ecdsa_signature sig2; + secp256k1_scalar sr[512], ss; + const unsigned char *extra; + extra = t == 0 ? NULL : zero; + memset(msg, 0, 32); + msg[31] = 1; + /* High key results in signature failure. */ + memset(key, 0xFF, 32); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* Zero key results in signature failure. */ + memset(key, 0, 32); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* Nonce function failure results in signature failure. */ + key[31] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_fail, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* The retry loop successfully makes its way to the first good value. */ + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_retry, extra) == 1); + CHECK(!is_empty_signature(&sig)); + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); + /* The default nonce function is deterministic. */ + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); + /* The default nonce function changes output with different messages. */ + for(i = 0; i < 256; i++) { + int j; + msg[0] = i; + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + for (j = 0; j < i; j++) { + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + } + } + msg[0] = 0; + msg[31] = 2; + /* The default nonce function changes output with different keys. */ + for(i = 256; i < 512; i++) { + int j; + key[0] = i - 256; + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + for (j = 0; j < i; j++) { + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + } + } + key[0] = 0; + } + + { + /* Check that optional nonce arguments do not have equivalent effect. */ + const unsigned char zeros[32] = {0}; + unsigned char nonce[32]; + unsigned char nonce2[32]; + unsigned char nonce3[32]; + unsigned char nonce4[32]; + VG_UNDEF(nonce,32); + VG_UNDEF(nonce2,32); + VG_UNDEF(nonce3,32); + VG_UNDEF(nonce4,32); + CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); + VG_CHECK(nonce,32); + CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); + VG_CHECK(nonce2,32); + CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); + VG_CHECK(nonce3,32); + CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); + VG_CHECK(nonce4,32); + CHECK(memcmp(nonce, nonce2, 32) != 0); + CHECK(memcmp(nonce, nonce3, 32) != 0); + CHECK(memcmp(nonce, nonce4, 32) != 0); + CHECK(memcmp(nonce2, nonce3, 32) != 0); + CHECK(memcmp(nonce2, nonce4, 32) != 0); + CHECK(memcmp(nonce3, nonce4, 32) != 0); + } + + + /* Privkey export where pubkey is the point at infinity. */ + { + unsigned char privkey[300]; + unsigned char seckey[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, + }; + size_t outlen = 300; + CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); + outlen = 300; + CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); + } +} + +void run_ecdsa_edge_cases(void) { + test_ecdsa_edge_cases(); +} + +#ifdef ENABLE_OPENSSL_TESTS +EC_KEY *get_openssl_key(const unsigned char *key32) { + unsigned char privkey[300]; + size_t privkeylen; + const unsigned char* pbegin = privkey; + int compr = secp256k1_rand_bits(1); + EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); + CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); + CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); + CHECK(EC_KEY_check_key(ec_key)); + return ec_key; +} + +void test_ecdsa_openssl(void) { + secp256k1_gej qj; + secp256k1_ge q; + secp256k1_scalar sigr, sigs; + secp256k1_scalar one; + secp256k1_scalar msg2; + secp256k1_scalar key, msg; + EC_KEY *ec_key; + unsigned int sigsize = 80; + size_t secp_sigsize = 80; + unsigned char message[32]; + unsigned char signature[80]; + unsigned char key32[32]; + secp256k1_rand256_test(message); + secp256k1_scalar_set_b32(&msg, message, NULL); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(key32, &key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); + secp256k1_ge_set_gej(&q, &qj); + ec_key = get_openssl_key(key32); + CHECK(ec_key != NULL); + CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); + CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); + secp256k1_scalar_set_int(&one, 1); + secp256k1_scalar_add(&msg2, &msg, &one); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); + + random_sign(&sigr, &sigs, &key, &msg, NULL); + CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); + CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); + + EC_KEY_free(ec_key); +} + +void run_ecdsa_openssl(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_ecdsa_openssl(); + } +} +#endif + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/tests_impl.h" +#endif + +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/tests_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/tests_impl.h" +#endif + +int main(int argc, char **argv) { + unsigned char seed16[16] = {0}; + unsigned char run32[32] = {0}; + /* find iteration count */ + if (argc > 1) { + count = strtol(argv[1], NULL, 0); + } + + /* find random seed */ + if (argc > 2) { + int pos = 0; + const char* ch = argv[2]; + while (pos < 16 && ch[0] != 0 && ch[1] != 0) { + unsigned short sh; + if (sscanf(ch, "%2hx", &sh)) { + seed16[pos] = sh; + } else { + break; + } + ch += 2; + pos++; + } + } else { + FILE *frand = fopen("/dev/urandom", "r"); + if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { + uint64_t t = time(NULL) * (uint64_t)1337; + seed16[0] ^= t; + seed16[1] ^= t >> 8; + seed16[2] ^= t >> 16; + seed16[3] ^= t >> 24; + seed16[4] ^= t >> 32; + seed16[5] ^= t >> 40; + seed16[6] ^= t >> 48; + seed16[7] ^= t >> 56; + } + fclose(frand); + } + secp256k1_rand_seed(seed16); + + printf("test count = %i\n", count); + printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); + + /* initialize */ + run_context_tests(); + ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + if (secp256k1_rand_bits(1)) { + secp256k1_rand256(run32); + CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); + } + + run_rand_bits(); + run_rand_int(); + + run_sha256_tests(); + run_hmac_sha256_tests(); + run_rfc6979_hmac_sha256_tests(); + +#ifndef USE_NUM_NONE + /* num tests */ + run_num_smalltests(); +#endif + + /* scalar tests */ + run_scalar_tests(); + + /* field tests */ + run_field_inv(); + run_field_inv_var(); + run_field_inv_all_var(); + run_field_misc(); + run_field_convert(); + run_sqr(); + run_sqrt(); + + /* group tests */ + run_ge(); + run_group_decompress(); + + /* ecmult tests */ + run_wnaf(); + run_point_times_order(); + run_ecmult_chain(); + run_ecmult_constants(); + run_ecmult_gen_blind(); + run_ecmult_const_tests(); + run_ec_combine(); + + /* endomorphism tests */ +#ifdef USE_ENDOMORPHISM + run_endomorphism_tests(); +#endif + + /* EC point parser test */ + run_ec_pubkey_parse_test(); + + /* EC key edge cases */ + run_eckey_edge_case_test(); + +#ifdef ENABLE_MODULE_ECDH + /* ecdh tests */ + run_ecdh_tests(); +#endif + + /* ecdsa tests */ + run_random_pubkeys(); + run_ecdsa_der_parse(); + run_ecdsa_sign_verify(); + run_ecdsa_end_to_end(); + run_ecdsa_edge_cases(); +#ifdef ENABLE_OPENSSL_TESTS + run_ecdsa_openssl(); +#endif + +#ifdef ENABLE_MODULE_SCHNORR + /* Schnorr tests */ + run_schnorr_tests(); +#endif + +#ifdef ENABLE_MODULE_RECOVERY + /* ECDSA pubkey recovery tests */ + run_recovery_tests(); +#endif + + secp256k1_rand256(run32); + printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); + + /* shutdown */ + secp256k1_context_destroy(ctx); + + printf("no problems found\n"); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c new file mode 100644 index 0000000000..b040bb0733 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c @@ -0,0 +1,470 @@ +/*********************************************************************** + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#undef USE_ECMULT_STATIC_PRECOMPUTATION + +#ifndef EXHAUSTIVE_TEST_ORDER +/* see group_impl.h for allowable values */ +#define EXHAUSTIVE_TEST_ORDER 13 +#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ +#endif + +#include "include/secp256k1.h" +#include "group.h" +#include "secp256k1.c" +#include "testrand_impl.h" + +#ifdef ENABLE_MODULE_RECOVERY +#include "src/modules/recovery/main_impl.h" +#include "include/secp256k1_recovery.h" +#endif + +/** stolen from tests.c */ +void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); + CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); +} + +void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { + secp256k1_fe z2s; + secp256k1_fe u1, u2, s1, s2; + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ + secp256k1_fe_sqr(&z2s, &b->z); + secp256k1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; secp256k1_fe_normalize_weak(&u2); + secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; secp256k1_fe_normalize_weak(&s2); + CHECK(secp256k1_fe_equal_var(&u1, &u2)); + CHECK(secp256k1_fe_equal_var(&s1, &s2)); +} + +void random_fe(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} +/** END stolen from tests.c */ + +int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, + const unsigned char *key32, const unsigned char *algo16, + void *data, unsigned int attempt) { + secp256k1_scalar s; + int *idata = data; + (void)msg32; + (void)key32; + (void)algo16; + /* Some nonces cannot be used because they'd cause s and/or r to be zero. + * The signing function has retry logic here that just re-calls the nonce + * function with an increased `attempt`. So if attempt > 0 this means we + * need to change the nonce to avoid an infinite loop. */ + if (attempt > 0) { + *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; + } + secp256k1_scalar_set_int(&s, *idata); + secp256k1_scalar_get_b32(nonce32, &s); + return 1; +} + +#ifdef USE_ENDOMORPHISM +void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { + int i; + for (i = 0; i < order; i++) { + secp256k1_ge res; + secp256k1_ge_mul_lambda(&res, &group[i]); + ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); + } +} +#endif + +void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j; + + /* Sanity-check (and check infinity functions) */ + CHECK(secp256k1_ge_is_infinity(&group[0])); + CHECK(secp256k1_gej_is_infinity(&groupj[0])); + for (i = 1; i < order; i++) { + CHECK(!secp256k1_ge_is_infinity(&group[i])); + CHECK(!secp256k1_gej_is_infinity(&groupj[i])); + } + + /* Check all addition formulae */ + for (j = 0; j < order; j++) { + secp256k1_fe fe_inv; + secp256k1_fe_inv(&fe_inv, &groupj[j].z); + for (i = 0; i < order; i++) { + secp256k1_ge zless_gej; + secp256k1_gej tmp; + /* add_var */ + secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_ge */ + if (j > 0) { + secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + /* add_ge_var */ + secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_zinv_var */ + zless_gej.infinity = groupj[j].infinity; + zless_gej.x = groupj[j].x; + zless_gej.y = groupj[j].y; + secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + } + + /* Check doubling */ + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + if (i > 0) { + secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + secp256k1_gej_double_var(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + + /* Check negation */ + for (i = 1; i < order; i++) { + secp256k1_ge tmp; + secp256k1_gej tmpj; + secp256k1_ge_neg(&tmp, &group[i]); + ge_equals_ge(&group[order - i], &tmp); + secp256k1_gej_neg(&tmpj, &groupj[i]); + ge_equals_gej(&group[order - i], &tmpj); + } +} + +void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j, r_log; + for (r_log = 1; r_log < order; r_log++) { + for (j = 0; j < order; j++) { + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + secp256k1_scalar na, ng; + secp256k1_scalar_set_int(&na, i); + secp256k1_scalar_set_int(&ng, j); + + secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); + ge_equals_gej(&group[(i * r_log + j) % order], &tmp); + + if (i > 0) { + secp256k1_ecmult_const(&tmp, &group[i], &ng); + ge_equals_gej(&group[(i * j) % order], &tmp); + } + } + } + } +} + +void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { + secp256k1_fe x; + unsigned char x_bin[32]; + k %= EXHAUSTIVE_TEST_ORDER; + x = group[k].x; + secp256k1_fe_normalize(&x); + secp256k1_fe_get_b32(x_bin, &x); + secp256k1_scalar_set_b32(r, x_bin, NULL); +} + +void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* Verify by calling verify */ + secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + secp256k1_scalar_get_b32(msg32, &msg_s); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} + +void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } + + /* We would like to verify zero-knowledge here by counting how often every + * possible (s, r) tuple appears, but because the group order is larger + * than the field order, when coercing the x-values to scalar values, some + * appear more often than others, so we are actually not zero-knowledge. + * (This effect also appears in the real code, but the difference is on the + * order of 1/2^128th the field order, so the deviation is not useful to a + * computationally bounded attacker.) + */ +} + +#ifdef ENABLE_MODULE_RECOVERY +void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_fe r_dot_y_normalized; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + int expected_recid; + int recid; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + /* Check directly */ + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + /* In computing the recid, there is an overflow condition that is disabled in + * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value + * will exceed the group order, and our signing code always holds out for r + * values that don't overflow, so with a proper overflow check the tests would + * loop indefinitely. */ + r_dot_y_normalized = group[k].y; + secp256k1_fe_normalize(&r_dot_y_normalized); + /* Also the recovery id is flipped depending if we hit the low-s branch */ + if ((k * s) % order == (i + r * j) % order) { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; + } else { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; + } + CHECK(recid == expected_recid); + + /* Convert to a standard sig then check */ + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } +} + +void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + /* This is essentially a copy of test_exhaustive_verify, with recovery added */ + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int recid = 0; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + secp256k1_scalar_get_b32(msg32, &msg_s); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* We would like to try recovering the pubkey and checking that it matches, + * but pubkey recovery is impossible in the exhaustive tests (the reason + * being that there are 12 nonzero r values, 12 nonzero points, and no + * overlap between the sets, so there are no valid signatures). */ + + /* Verify by converting to a standard signature and calling verify */ + secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} +#endif + +int main(void) { + int i; + secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; + secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; + + /* Build context */ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + /* TODO set z = 1, then do num_tests runs with random z values */ + + /* Generate the entire group */ + secp256k1_gej_set_infinity(&groupj[0]); + secp256k1_ge_set_gej(&group[0], &groupj[0]); + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + /* Set a different random z-value for each Jacobian point */ + secp256k1_fe z; + random_fe(&z); + + secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); + secp256k1_ge_set_gej(&group[i], &groupj[i]); + secp256k1_gej_rescale(&groupj[i], &z); + + /* Verify against ecmult_gen */ + { + secp256k1_scalar scalar_i; + secp256k1_gej generatedj; + secp256k1_ge generated; + + secp256k1_scalar_set_int(&scalar_i, i); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + secp256k1_ge_set_gej(&generated, &generatedj); + + CHECK(group[i].infinity == 0); + CHECK(generated.infinity == 0); + CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); + CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); + } + } + + /* Run the tests */ +#ifdef USE_ENDOMORPHISM + test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); +#endif + test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); + +#ifdef ENABLE_MODULE_RECOVERY + test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#endif + + secp256k1_context_destroy(ctx); + return 0; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h new file mode 100644 index 0000000000..4092a86c91 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h @@ -0,0 +1,113 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_UTIL_H_ +#define _SECP256K1_UTIL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include +#include + +typedef struct { + void (*fn)(const char *text, void* data); + const void* data; +} secp256k1_callback; + +static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { + cb->fn(text, (void*)cb->data); +} + +#ifdef DETERMINISTIC +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s\n", msg); \ + abort(); \ +} while(0); +#else +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ + abort(); \ +} while(0) +#endif + +#ifdef HAVE_BUILTIN_EXPECT +#define EXPECT(x,c) __builtin_expect((x),(c)) +#else +#define EXPECT(x,c) (x) +#endif + +#ifdef DETERMINISTIC +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed"); \ + } \ +} while(0) +#else +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed: " #cond); \ + } \ +} while(0) +#endif + +/* Like assert(), but when VERIFY is defined, and side-effect safe. */ +#if defined(COVERAGE) +#define VERIFY_CHECK(check) +#define VERIFY_SETUP(stmt) +#elif defined(VERIFY) +#define VERIFY_CHECK CHECK +#define VERIFY_SETUP(stmt) do { stmt; } while(0) +#else +#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) +#define VERIFY_SETUP(stmt) +#endif + +static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { + void *ret = malloc(size); + if (ret == NULL) { + secp256k1_callback_call(cb, "Out of memory"); + } + return ret; +} + +/* Macro for restrict, when available and not in a VERIFY build. */ +#if defined(SECP256K1_BUILD) && defined(VERIFY) +# define SECP256K1_RESTRICT +#else +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(3,0) +# define SECP256K1_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define SECP256K1_RESTRICT __restrict +# else +# define SECP256K1_RESTRICT +# endif +# else +# define SECP256K1_RESTRICT restrict +# endif +#endif + +#if defined(_WIN32) +# define I64FORMAT "I64d" +# define I64uFORMAT "I64u" +#else +# define I64FORMAT "lld" +# define I64uFORMAT "llu" +#endif + +#if defined(HAVE___INT128) +# if defined(__GNUC__) +# define SECP256K1_GNUC_EXT __extension__ +# else +# define SECP256K1_GNUC_EXT +# endif +SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; +#endif + +#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt b/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt new file mode 100644 index 0000000000..7acafd78c3 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt @@ -0,0 +1,16 @@ + +HIDAPI Authors: + +Alan Ott : + Original Author and Maintainer + Linux, Windows, and Mac implementations + +Ludovic Rousseau : + Formatting for Doxygen documentation + Bug fixes + Correctness fixes + + +For a comprehensive list of contributions, see the commit list at github: + http://github.com/signal11/hidapi/commits/master + diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt new file mode 100644 index 0000000000..538cdf95cf --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt @@ -0,0 +1,26 @@ +Copyright (c) 2010, Alan Ott, Signal 11 Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Signal 11 Software nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt new file mode 100644 index 0000000000..94a9ed024d --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt new file mode 100644 index 0000000000..e3f3380829 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt @@ -0,0 +1,9 @@ + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. diff --git a/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt b/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt new file mode 100644 index 0000000000..e1676d4c42 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/LICENSE.txt @@ -0,0 +1,13 @@ +HIDAPI can be used under one of three licenses. + +1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt +2. A BSD-Style License, in LICENSE-bsd.txt. +3. The more liberal original HIDAPI license. LICENSE-orig.txt + +The license chosen is at the discretion of the user of HIDAPI. For example: +1. An author of GPL software would likely use HIDAPI under the terms of the +GPL. + +2. An author of commercial closed-source software would likely use HIDAPI +under the terms of the BSD-style license or the original HIDAPI license. + diff --git a/vendor/github.com/karalabe/usb/hidapi/README.txt b/vendor/github.com/karalabe/usb/hidapi/README.txt new file mode 100644 index 0000000000..f19dae4ab7 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/README.txt @@ -0,0 +1,339 @@ + HIDAPI library for Windows, Linux, FreeBSD and Mac OS X + ========================================================= + +About +====== + +HIDAPI is a multi-platform library which allows an application to interface +with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac +OS X. HIDAPI can be either built as a shared library (.so or .dll) or +can be embedded directly into a target application by adding a single source +file (per platform) and a single header. + +HIDAPI has four back-ends: + * Windows (using hid.dll) + * Linux/hidraw (using the Kernel's hidraw driver) + * Linux/libusb (using libusb-1.0) + * FreeBSD (using libusb-1.0) + * Mac (using IOHidManager) + +On Linux, either the hidraw or the libusb back-end can be used. There are +tradeoffs, and the functionality supported is slightly different. + +Linux/hidraw (linux/hid.c): +This back-end uses the hidraw interface in the Linux kernel. While this +back-end will support both USB and Bluetooth, it has some limitations on +kernels prior to 2.6.39, including the inability to send or receive feature +reports. In addition, it will only communicate with devices which have +hidraw nodes associated with them. Keyboards, mice, and some other devices +which are blacklisted from having hidraw nodes will not work. Fortunately, +for nearly all the uses of hidraw, this is not a problem. + +Linux/FreeBSD/libusb (libusb/hid.c): +This back-end uses libusb-1.0 to communicate directly to a USB device. This +back-end will of course not work with Bluetooth devices. + +HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses +Fox Toolkit (http://www.fox-toolkit.org). It will build on every platform +which HIDAPI supports. Since it relies on a 3rd party library, building it +is optional but recommended because it is so useful when debugging hardware. + +What Does the API Look Like? +============================= +The API provides the the most commonly used HID functions including sending +and receiving of input, output, and feature reports. The sample program, +which communicates with a heavily hacked up version of the Microchip USB +Generic HID sample looks like this (with error checking removed for +simplicity): + +#ifdef WIN32 +#include +#endif +#include +#include +#include "hidapi.h" + +#define MAX_STR 255 + +int main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + wchar_t wstr[MAX_STR]; + hid_device *handle; + int i; + + // Initialize the hidapi library + res = hid_init(); + + // Open the device using the VID, PID, + // and optionally the Serial number. + handle = hid_open(0x4d8, 0x3f, NULL); + + // Read the Manufacturer String + res = hid_get_manufacturer_string(handle, wstr, MAX_STR); + wprintf(L"Manufacturer String: %s\n", wstr); + + // Read the Product String + res = hid_get_product_string(handle, wstr, MAX_STR); + wprintf(L"Product String: %s\n", wstr); + + // Read the Serial Number String + res = hid_get_serial_number_string(handle, wstr, MAX_STR); + wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr); + + // Read Indexed String 1 + res = hid_get_indexed_string(handle, 1, wstr, MAX_STR); + wprintf(L"Indexed String 1: %s\n", wstr); + + // Toggle LED (cmd 0x80). The first byte is the report number (0x0). + buf[0] = 0x0; + buf[1] = 0x80; + res = hid_write(handle, buf, 65); + + // Request state (cmd 0x81). The first byte is the report number (0x0). + buf[0] = 0x0; + buf[1] = 0x81; + res = hid_write(handle, buf, 65); + + // Read requested state + res = hid_read(handle, buf, 65); + + // Print out the returned buffer. + for (i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + // Finalize the hidapi library + res = hid_exit(); + + return 0; +} + +If you have your own simple test programs which communicate with standard +hardware development boards (such as those from Microchip, TI, Atmel, +FreeScale and others), please consider sending me something like the above +for inclusion into the HIDAPI source. This will help others who have the +same hardware as you do. + +License +======== +HIDAPI may be used by one of three licenses as outlined in LICENSE.txt. + +Download +========= +HIDAPI can be downloaded from github + git clone git://github.com/signal11/hidapi.git + +Build Instructions +=================== + +This section is long. Don't be put off by this. It's not long because it's +complicated to build HIDAPI; it's quite the opposite. This section is long +because of the flexibility of HIDAPI and the large number of ways in which +it can be built and used. You will likely pick a single build method. + +HIDAPI can be built in several different ways. If you elect to build a +shared library, you will need to build it from the HIDAPI source +distribution. If you choose instead to embed HIDAPI directly into your +application, you can skip the building and look at the provided platform +Makefiles for guidance. These platform Makefiles are located in linux/ +libusb/ mac/ and windows/ and are called Makefile-manual. In addition, +Visual Studio projects are provided. Even if you're going to embed HIDAPI +into your project, it is still beneficial to build the example programs. + + +Prerequisites: +--------------- + + Linux: + ------- + On Linux, you will need to install development packages for libudev, + libusb and optionally Fox-toolkit (for the test GUI). On + Debian/Ubuntu systems these can be installed by running: + sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev + + If you downloaded the source directly from the git repository (using + git clone), you'll need Autotools: + sudo apt-get install autotools-dev autoconf automake libtool + + FreeBSD: + --------- + On FreeBSD you will need to install GNU make, libiconv, and + optionally Fox-Toolkit (for the test GUI). This is done by running + the following: + pkg_add -r gmake libiconv fox16 + + If you downloaded the source directly from the git repository (using + git clone), you'll need Autotools: + pkg_add -r autotools + + Mac: + ----- + On Mac, you will need to install Fox-Toolkit if you wish to build + the Test GUI. There are two ways to do this, and each has a slight + complication. Which method you use depends on your use case. + + If you wish to build the Test GUI just for your own testing on your + own computer, then the easiest method is to install Fox-Toolkit + using ports: + sudo port install fox + + If you wish to build the TestGUI app bundle to redistribute to + others, you will need to install Fox-toolkit from source. This is + because the version of fox that gets installed using ports uses the + ports X11 libraries which are not compatible with the Apple X11 + libraries. If you install Fox with ports and then try to distribute + your built app bundle, it will simply fail to run on other systems. + To install Fox-Toolkit manually, download the source package from + http://www.fox-toolkit.org, extract it, and run the following from + within the extracted source: + ./configure && make && make install + + Windows: + --------- + On Windows, if you want to build the test GUI, you will need to get + the hidapi-externals.zip package from the download site. This + contains pre-built binaries for Fox-toolkit. Extract + hidapi-externals.zip just outside of hidapi, so that + hidapi-externals and hidapi are on the same level, as shown: + + Parent_Folder + | + +hidapi + +hidapi-externals + + Again, this step is not required if you do not wish to build the + test GUI. + + +Building HIDAPI into a shared library on Unix Platforms: +--------------------------------------------------------- + +On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using +Mingw or Cygwin, the easiest way to build a standard system-installed shared +library is to use the GNU Autotools build system. If you checked out the +source from the git repository, run the following: + + ./bootstrap + ./configure + make + make install <----- as root, or using sudo + +If you downloaded a source package (ie: if you did not run git clone), you +can skip the ./bootstrap step. + +./configure can take several arguments which control the build. The two most +likely to be used are: + --enable-testgui + Enable build of the Test GUI. This requires Fox toolkit to + be installed. Instructions for installing Fox-Toolkit on + each platform are in the Prerequisites section above. + + --prefix=/usr + Specify where you want the output headers and libraries to + be installed. The example above will put the headers in + /usr/include and the binaries in /usr/lib. The default is to + install into /usr/local which is fine on most systems. + +Building the manual way on Unix platforms: +------------------------------------------- + +Manual Makefiles are provided mostly to give the user and idea what it takes +to build a program which embeds HIDAPI directly inside of it. These should +really be used as examples only. If you want to build a system-wide shared +library, use the Autotools method described above. + + To build HIDAPI using the manual makefiles, change to the directory + of your platform and run make. For example, on Linux run: + cd linux/ + make -f Makefile-manual + + To build the Test GUI using the manual makefiles: + cd testgui/ + make -f Makefile-manual + +Building on Windows: +--------------------- + +To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file +in the windows/ directory. + +To build the Test GUI on windows using Visual Studio, build the .sln file in +the testgui/ directory. + +To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions +in the section titled "Building HIDAPI into a shared library on Unix +Platforms" above. Note that building the Test GUI with MinGW or Cygwin will +require the Windows procedure in the Prerequisites section above (ie: +hidapi-externals.zip). + +To build HIDAPI using MinGW using the Manual Makefiles, see the section +"Building the manual way on Unix platforms" above. + +HIDAPI can also be built using the Windows DDK (now also called the Windows +Driver Kit or WDK). This method was originally required for the HIDAPI build +but not anymore. However, some users still prefer this method. It is not as +well supported anymore but should still work. Patches are welcome if it does +not. To build using the DDK: + + 1. Install the Windows Driver Kit (WDK) from Microsoft. + 2. From the Start menu, in the Windows Driver Kits folder, select Build + Environments, then your operating system, then the x86 Free Build + Environment (or one that is appropriate for your system). + 3. From the console, change directory to the windows/ddk_build/ directory, + which is part of the HIDAPI distribution. + 4. Type build. + 5. You can find the output files (DLL and LIB) in a subdirectory created + by the build system which is appropriate for your environment. On + Windows XP, this directory is objfre_wxp_x86/i386. + +Cross Compiling +================ + +This section talks about cross compiling HIDAPI for Linux using autotools. +This is useful for using HIDAPI on embedded Linux targets. These +instructions assume the most raw kind of embedded Linux build, where all +prerequisites will need to be built first. This process will of course vary +based on your embedded Linux build system if you are using one, such as +OpenEmbedded or Buildroot. + +For the purpose of this section, it will be assumed that the following +environment variables are exported. + + $ export STAGING=$HOME/out + $ export HOST=arm-linux + +STAGING and HOST can be modified to suit your setup. + +Prerequisites +-------------- + +Note that the build of libudev is the very basic configuration. + +Build Libusb. From the libusb source directory, run: + ./configure --host=$HOST --prefix=$STAGING + make + make install + +Build libudev. From the libudev source directory, run: + ./configure --disable-gudev --disable-introspection --disable-hwdb \ + --host=$HOST --prefix=$STAGING + make + make install + +Building HIDAPI +---------------- + +Build HIDAPI: + + PKG_CONFIG_DIR= \ + PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \ + PKG_CONFIG_SYSROOT_DIR=$STAGING \ + ./configure --host=$HOST --prefix=$STAGING + + +Signal 11 Software - 2010-04-11 + 2010-07-28 + 2011-09-10 + 2012-05-01 + 2012-07-03 diff --git a/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h b/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h new file mode 100644 index 0000000000..166f3509ab --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h @@ -0,0 +1,390 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +#ifdef _WIN32 + #define HID_API_EXPORT __declspec(dllexport) + #define HID_API_CALL +#else + #define HID_API_EXPORT /**< API export macro */ + #define HID_API_CALL /**< API call macro */ +#endif + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +#ifdef __cplusplus +extern "C" { +#endif + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. Valid on both Linux implementations + in all cases, and valid on the Windows implementation + only if the device contains more than one interface. */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device, containing information about the HID devices + attached to the system, or NULL in the case of failure. Free + this linked list by calling hid_free_enumeration(). + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read within + the timeout period, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param device A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a string describing the last error which occurred. + + @ingroup API + @param device A device handle returned from hid_open(). + + @returns + This function returns a string containing the last error + which occurred or NULL if none has occurred. + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c b/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c new file mode 100644 index 0000000000..474dff41c1 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c @@ -0,0 +1,1512 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2010 + Libusb Version - 8/13/2010 + FreeBSD Version - 11/1/2011 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* C */ +#include +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* GNU / LibUSB */ +#include +#ifndef __ANDROID__ +#include +#endif + +#include "hidapi.h" + +#ifdef __ANDROID__ + +/* Barrier implementation because Android/Bionic don't have pthread_barrier. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DEBUG_PRINTF +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG(...) do {} while (0) +#endif + +#ifndef __FreeBSD__ +#define DETACH_KERNEL_DRIVER +#endif + +/* Uncomment to enable the retrieval of Usage and Usage Page in +hid_enumerate(). Warning, on platforms different from FreeBSD +this is very invasive as it requires the detach +and re-attach of the kernel driver. See comments inside hid_enumerate(). +libusb HIDAPI programs are encouraged to use the interface number +instead to differentiate between interfaces on a composite HID device. */ +/*#define INVASIVE_GET_USAGE*/ + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + + +struct hid_device_ { + /* Handle to the actual device. */ + libusb_device_handle *device_handle; + + /* Endpoint information */ + int input_endpoint; + int output_endpoint; + int input_ep_max_packet_size; + + /* The interface number of the HID */ + int interface; + + /* Indexes of Strings */ + int manufacturer_index; + int product_index; + int serial_index; + + /* Whether blocking reads are used */ + int blocking; /* boolean */ + + /* Read thread objects */ + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + int shutdown_thread; + int cancelled; + struct libusb_transfer *transfer; + + /* List of received input reports. */ + struct input_report *input_reports; +}; + +static libusb_context *usb_context = NULL; + +uint16_t get_usb_code_for_current_locale(void); +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->blocking = 1; + + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the device itself */ + free(dev); +} + +#if 0 +/*TODO: Implement this funciton on hidapi/libusb.. */ +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + +#ifdef INVASIVE_GET_USAGE +/* Get bytes from a HID Report Descriptor. + Only call with a num_bytes of 0, 1, 2, or 4. */ +static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) +{ + /* Return if there aren't enough bytes. */ + if (cur + num_bytes >= len) + return 0; + + if (num_bytes == 0) + return 0; + else if (num_bytes == 1) { + return rpt[cur+1]; + } + else if (num_bytes == 2) { + return (rpt[cur+2] * 256 + rpt[cur+1]); + } + else if (num_bytes == 4) { + return (rpt[cur+4] * 0x01000000 + + rpt[cur+3] * 0x00010000 + + rpt[cur+2] * 0x00000100 + + rpt[cur+1] * 0x00000001); + } + else + return 0; +} + +/* Retrieves the device's Usage Page and Usage from the report + descriptor. The algorithm is simple, as it just returns the first + Usage and Usage Page that it finds in the descriptor. + The return value is 0 on success and -1 on failure. */ +static int get_usage(uint8_t *report_descriptor, size_t size, + unsigned short *usage_page, unsigned short *usage) +{ + unsigned int i = 0; + int size_code; + int data_len, key_size; + int usage_found = 0, usage_page_found = 0; + + while (i < size) { + int key = report_descriptor[i]; + int key_cmd = key & 0xfc; + + //printf("key: %02hhx\n", key); + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } + else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + data_len = size_code; + break; + case 3: + data_len = 4; + break; + default: + /* Can't ever happen since size_code is & 0x3 */ + data_len = 0; + break; + }; + key_size = 1; + } + + if (key_cmd == 0x4) { + *usage_page = get_bytes(report_descriptor, size, data_len, i); + usage_page_found = 1; + //printf("Usage Page: %x\n", (uint32_t)*usage_page); + } + if (key_cmd == 0x8) { + *usage = get_bytes(report_descriptor, size, data_len, i); + usage_found = 1; + //printf("Usage: %x\n", (uint32_t)*usage); + } + + if (usage_page_found && usage_found) + return 0; /* success */ + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + return -1; /* failure */ +} +#endif /* INVASIVE_GET_USAGE */ + +#if defined(__FreeBSD__) && __FreeBSD__ < 10 +/* The libusb version included in FreeBSD < 10 doesn't have this function. In + mainline libusb, it's inlined in libusb.h. This function will bear a striking + resemblance to that one, because there's about one way to code it. + + Note that the data parameter is Unicode in UTF-16LE encoding. + Return value is the number of bytes in data, or LIBUSB_ERROR_*. + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev, + uint8_t descriptor_index, uint16_t lang_id, + unsigned char *data, int length) +{ + return libusb_control_transfer(dev, + LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ + LIBUSB_REQUEST_GET_DESCRIPTOR, + (LIBUSB_DT_STRING << 8) | descriptor_index, + lang_id, data, (uint16_t) length, 1000); +} + +#endif + + +/* Get the first language the device says it reports. This comes from + USB string #0. */ +static uint16_t get_first_language(libusb_device_handle *dev) +{ + uint16_t buf[32]; + int len; + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + 0x0, /* String ID */ + 0x0, /* Language */ + (unsigned char*)buf, + sizeof(buf)); + if (len < 4) + return 0x0; + + return buf[1]; /* First two bytes are len and descriptor type. */ +} + +static int is_language_supported(libusb_device_handle *dev, uint16_t lang) +{ + uint16_t buf[32]; + int len; + int i; + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + 0x0, /* String ID */ + 0x0, /* Language */ + (unsigned char*)buf, + sizeof(buf)); + if (len < 4) + return 0x0; + + + len /= 2; /* language IDs are two-bytes each. */ + /* Start at index 1 because there are two bytes of protocol data. */ + for (i = 1; i < len; i++) { + if (buf[i] == lang) + return 1; + } + + return 0; +} + + +/* This function returns a newly allocated wide string containing the USB + device string numbered by the index. The returned string must be freed + by using free(). */ +static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) +{ + char buf[512]; + int len; + wchar_t *str = NULL; + +#ifndef __ANDROID__ /* we don't use iconv on Android */ + wchar_t wbuf[256]; + /* iconv variables */ + iconv_t ic; + size_t inbytes; + size_t outbytes; + size_t res; +#ifdef __FreeBSD__ + const char *inptr; +#else + char *inptr; +#endif + char *outptr; +#endif + + /* Determine which language to use. */ + uint16_t lang; + lang = get_usb_code_for_current_locale(); + if (!is_language_supported(dev, lang)) + lang = get_first_language(dev); + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + idx, + lang, + (unsigned char*)buf, + sizeof(buf)); + if (len < 0) + return NULL; + +#ifdef __ANDROID__ + + /* Bionic does not have iconv support nor wcsdup() function, so it + has to be done manually. The following code will only work for + code points that can be represented as a single UTF-16 character, + and will incorrectly convert any code points which require more + than one UTF-16 character. + + Skip over the first character (2-bytes). */ + len -= 2; + str = malloc((len / 2 + 1) * sizeof(wchar_t)); + int i; + for (i = 0; i < len / 2; i++) { + str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8); + } + str[len / 2] = 0x00000000; + +#else + + /* buf does not need to be explicitly NULL-terminated because + it is only passed into iconv() which does not need it. */ + + /* Initialize iconv. */ + ic = iconv_open("WCHAR_T", "UTF-16LE"); + if (ic == (iconv_t)-1) { + LOG("iconv_open() failed\n"); + return NULL; + } + + /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). + Skip the first character (2-bytes). */ + inptr = buf+2; + inbytes = len-2; + outptr = (char*) wbuf; + outbytes = sizeof(wbuf); + res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); + if (res == (size_t)-1) { + LOG("iconv() failed\n"); + goto err; + } + + /* Write the terminating NULL. */ + wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; + if (outbytes >= sizeof(wbuf[0])) + *((wchar_t*)outptr) = 0x00000000; + + /* Allocate and copy the string. */ + str = wcsdup(wbuf); + +err: + iconv_close(ic); + +#endif + + return str; +} + +static char *make_path(libusb_device *dev, int interface_number) +{ + char str[64]; + snprintf(str, sizeof(str), "%04x:%04x:%02x", + libusb_get_bus_number(dev), + libusb_get_device_address(dev), + interface_number); + str[sizeof(str)-1] = '\0'; + + return strdup(str); +} + + +int HID_API_EXPORT hid_init(void) +{ + if (!usb_context) { + const char *locale; + + /* Init Libusb */ + if (libusb_init(&usb_context)) + return -1; + + /* Set the locale if it's not set. */ + locale = setlocale(LC_CTYPE, NULL); + if (!locale) + setlocale(LC_CTYPE, ""); + } + + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (usb_context) { + libusb_exit(usb_context); + usb_context = NULL; + } + + return 0; +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + libusb_device **devs; + libusb_device *dev; + libusb_device_handle *handle; + ssize_t num_devs; + int i = 0; + + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + if(hid_init() < 0) + return NULL; + + num_devs = libusb_get_device_list(usb_context, &devs); + if (num_devs < 0) + return NULL; + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + struct libusb_config_descriptor *conf_desc = NULL; + int j, k; + int interface_num = 0; + + int res = libusb_get_device_descriptor(dev, &desc); + unsigned short dev_vid = desc.idVendor; + unsigned short dev_pid = desc.idProduct; + + res = libusb_get_active_config_descriptor(dev, &conf_desc); + if (res < 0) + libusb_get_config_descriptor(dev, 0, &conf_desc); + if (conf_desc) { + for (j = 0; j < conf_desc->bNumInterfaces; j++) { + const struct libusb_interface *intf = &conf_desc->interface[j]; + for (k = 0; k < intf->num_altsetting; k++) { + const struct libusb_interface_descriptor *intf_desc; + intf_desc = &intf->altsetting[k]; + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { + interface_num = intf_desc->bInterfaceNumber; + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + + /* VID/PID match. Create the record. */ + tmp = calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Fill out the record */ + cur_dev->next = NULL; + cur_dev->path = make_path(dev, interface_num); + + res = libusb_open(dev, &handle); + + if (res >= 0) { + /* Serial Number */ + if (desc.iSerialNumber > 0) + cur_dev->serial_number = + get_usb_string(handle, desc.iSerialNumber); + + /* Manufacturer and Product strings */ + if (desc.iManufacturer > 0) + cur_dev->manufacturer_string = + get_usb_string(handle, desc.iManufacturer); + if (desc.iProduct > 0) + cur_dev->product_string = + get_usb_string(handle, desc.iProduct); + +#ifdef INVASIVE_GET_USAGE +{ + /* + This section is removed because it is too + invasive on the system. Getting a Usage Page + and Usage requires parsing the HID Report + descriptor. Getting a HID Report descriptor + involves claiming the interface. Claiming the + interface involves detaching the kernel driver. + Detaching the kernel driver is hard on the system + because it will unclaim interfaces (if another + app has them claimed) and the re-attachment of + the driver will sometimes change /dev entry names. + It is for these reasons that this section is + #if 0. For composite devices, use the interface + field in the hid_device_info struct to distinguish + between interfaces. */ + unsigned char data[256]; +#ifdef DETACH_KERNEL_DRIVER + int detached = 0; + /* Usage Page and Usage */ + res = libusb_kernel_driver_active(handle, interface_num); + if (res == 1) { + res = libusb_detach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); + else + detached = 1; + } +#endif + res = libusb_claim_interface(handle, interface_num); + if (res >= 0) { + /* Get the HID Report Descriptor. */ + res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); + if (res >= 0) { + unsigned short page=0, usage=0; + /* Parse the usage and usage page + out of the report descriptor. */ + get_usage(data, res, &page, &usage); + cur_dev->usage_page = page; + cur_dev->usage = usage; + } + else + LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); + + /* Release the interface */ + res = libusb_release_interface(handle, interface_num); + if (res < 0) + LOG("Can't release the interface.\n"); + } + else + LOG("Can't claim interface %d\n", res); +#ifdef DETACH_KERNEL_DRIVER + /* Re-attach kernel driver if necessary. */ + if (detached) { + res = libusb_attach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't re-attach kernel driver.\n"); + } +#endif +} +#endif /* INVASIVE_GET_USAGE */ + + libusb_close(handle); + } + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = desc.bcdDevice; + + /* Interface Number */ + cur_dev->interface_number = interface_num; + } + } + } /* altsettings */ + } /* interfaces */ + libusb_free_config_descriptor(conf_desc); + } + } + + libusb_free_device_list(devs, 1); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (cur_dev->serial_number && + wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void read_callback(struct libusb_transfer *transfer) +{ + hid_device *dev = transfer->user_data; + int res; + + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { + + struct input_report *rpt = malloc(sizeof(*rpt)); + rpt->data = malloc(transfer->actual_length); + memcpy(rpt->data, transfer->buffer, transfer->actual_length); + rpt->len = transfer->actual_length; + rpt->next = NULL; + + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + pthread_cond_signal(&dev->condition); + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + pthread_mutex_unlock(&dev->mutex); + } + else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { + dev->shutdown_thread = 1; + dev->cancelled = 1; + return; + } + else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { + dev->shutdown_thread = 1; + dev->cancelled = 1; + return; + } + else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { + //LOG("Timeout (normal)\n"); + } + else { + LOG("Unknown transfer code: %d\n", transfer->status); + } + + /* Re-submit the transfer object. */ + res = libusb_submit_transfer(transfer); + if (res != 0) { + LOG("Unable to submit URB. libusb error code: %d\n", res); + dev->shutdown_thread = 1; + dev->cancelled = 1; + } +} + + +static void *read_thread(void *param) +{ + hid_device *dev = param; + unsigned char *buf; + const size_t length = dev->input_ep_max_packet_size; + + /* Set up the transfer object. */ + buf = malloc(length); + dev->transfer = libusb_alloc_transfer(0); + libusb_fill_interrupt_transfer(dev->transfer, + dev->device_handle, + dev->input_endpoint, + buf, + length, + read_callback, + dev, + 5000/*timeout*/); + + /* Make the first submission. Further submissions are made + from inside read_callback() */ + libusb_submit_transfer(dev->transfer); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Handle all the events. */ + while (!dev->shutdown_thread) { + int res; + res = libusb_handle_events(usb_context); + if (res < 0) { + /* There was an error. */ + LOG("read_thread(): libusb reports error # %d\n", res); + + /* Break out of this loop only on fatal error.*/ + if (res != LIBUSB_ERROR_BUSY && + res != LIBUSB_ERROR_TIMEOUT && + res != LIBUSB_ERROR_OVERFLOW && + res != LIBUSB_ERROR_INTERRUPTED) { + break; + } + } + } + + /* Cancel any transfer that may be pending. This call will fail + if no transfers are pending, but that's OK. */ + libusb_cancel_transfer(dev->transfer); + + while (!dev->cancelled) + libusb_handle_events_completed(usb_context, &dev->cancelled); + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition actually will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* The dev->transfer->buffer and dev->transfer objects are cleaned up + in hid_close(). They are not cleaned up here because this thread + could end either due to a disconnect or due to a user + call to hid_close(). In both cases the objects can be safely + cleaned up after the call to pthread_join() (in hid_close()), but + since hid_close() calls libusb_cancel_transfer(), on these objects, + they can not be cleaned up here. */ + + return NULL; +} + + +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + + libusb_device **devs; + libusb_device *usb_dev; + int res; + int d = 0; + int good_open = 0; + + if(hid_init() < 0) + return NULL; + + dev = new_hid_device(); + + libusb_get_device_list(usb_context, &devs); + while ((usb_dev = devs[d++]) != NULL) { + struct libusb_device_descriptor desc; + struct libusb_config_descriptor *conf_desc = NULL; + int i,j,k; + libusb_get_device_descriptor(usb_dev, &desc); + + if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) + continue; + for (j = 0; j < conf_desc->bNumInterfaces; j++) { + const struct libusb_interface *intf = &conf_desc->interface[j]; + for (k = 0; k < intf->num_altsetting; k++) { + const struct libusb_interface_descriptor *intf_desc; + intf_desc = &intf->altsetting[k]; + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { + char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); + if (!strcmp(dev_path, path)) { + /* Matched Paths. Open this device */ + + /* OPEN HERE */ + res = libusb_open(usb_dev, &dev->device_handle); + if (res < 0) { + LOG("can't open device\n"); + free(dev_path); + break; + } + good_open = 1; +#ifdef DETACH_KERNEL_DRIVER + /* Detach the kernel driver, but only if the + device is managed by the kernel */ + if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { + res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); + if (res < 0) { + libusb_close(dev->device_handle); + LOG("Unable to detach Kernel Driver\n"); + free(dev_path); + good_open = 0; + break; + } + } +#endif + res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); + if (res < 0) { + LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); + free(dev_path); + libusb_close(dev->device_handle); + good_open = 0; + break; + } + + /* Store off the string descriptor indexes */ + dev->manufacturer_index = desc.iManufacturer; + dev->product_index = desc.iProduct; + dev->serial_index = desc.iSerialNumber; + + /* Store off the interface number */ + dev->interface = intf_desc->bInterfaceNumber; + + /* Find the INPUT and OUTPUT endpoints. An + OUTPUT endpoint is not required. */ + for (i = 0; i < intf_desc->bNumEndpoints; i++) { + const struct libusb_endpoint_descriptor *ep + = &intf_desc->endpoint[i]; + + /* Determine the type and direction of this + endpoint. */ + int is_interrupt = + (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) + == LIBUSB_TRANSFER_TYPE_INTERRUPT; + int is_output = + (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) + == LIBUSB_ENDPOINT_OUT; + int is_input = + (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) + == LIBUSB_ENDPOINT_IN; + + /* Decide whether to use it for input or output. */ + if (dev->input_endpoint == 0 && + is_interrupt && is_input) { + /* Use this endpoint for INPUT */ + dev->input_endpoint = ep->bEndpointAddress; + dev->input_ep_max_packet_size = ep->wMaxPacketSize; + } + if (dev->output_endpoint == 0 && + is_interrupt && is_output) { + /* Use this endpoint for OUTPUT */ + dev->output_endpoint = ep->bEndpointAddress; + } + } + + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + } + free(dev_path); + } + } + } + libusb_free_config_descriptor(conf_desc); + + } + + libusb_free_device_list(devs, 1); + + /* If we have a good handle, return it. */ + if (good_open) { + return dev; + } + else { + /* Unable to open any devices. */ + free_hid_device(dev); + return NULL; + } +} + + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + int res; + int report_number = data[0]; + int skipped_report_id = 0; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + + if (dev->output_endpoint <= 0) { + /* No interrupt out endpoint. Use the Control Endpoint */ + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID Set_Report*/, + (2/*HID output*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + if (skipped_report_id) + length++; + + return length; + } + else { + /* Use the interrupt out endpoint */ + int actual_length; + res = libusb_interrupt_transfer(dev->device_handle, + dev->output_endpoint, + (unsigned char*)data, + length, + &actual_length, 1000); + + if (res < 0) + return -1; + + if (skipped_report_id) + actual_length++; + + return actual_length; + } +} + +/* Helper function, to simplify hid_read(). + This should be called with dev->mutex locked. */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + if (len > 0) + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static void cleanup_mutex(void *param) +{ + hid_device *dev = param; + pthread_mutex_unlock(&dev->mutex); +} + + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + +#if 0 + int transferred; + int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); + LOG("transferred: %d\n", transferred); + return transferred; +#endif + + pthread_mutex_lock(&dev->mutex); + pthread_cleanup_push(&cleanup_mutex, dev); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been disconnected. + An error code of -1 should be returned. */ + bytes_read = -1; + goto ret; + } + + if (milliseconds == -1) { + /* Blocking */ + while (!dev->input_reports && !dev->shutdown_thread) { + pthread_cond_wait(&dev->condition, &dev->mutex); + } + if (dev->input_reports) { + bytes_read = return_data(dev, data, length); + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + while (!dev->input_reports && !dev->shutdown_thread) { + res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); + if (res == 0) { + if (dev->input_reports) { + bytes_read = return_data(dev, data, length); + break; + } + + /* If we're here, there was a spurious wake up + or the read thread was shutdown. Run the + loop again (ie: don't break). */ + } + else if (res == ETIMEDOUT) { + /* Timed out. */ + bytes_read = 0; + break; + } + else { + /* Error. */ + bytes_read = -1; + break; + } + } + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + pthread_mutex_unlock(&dev->mutex); + pthread_cleanup_pop(0); + + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + + return 0; +} + + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID set_report*/, + (3/*HID feature*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + /* Account for the report ID */ + if (skipped_report_id) + length++; + + return length; +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + /* Offset the return buffer by 1, so that the report ID + will remain in byte 0. */ + data++; + length--; + skipped_report_id = 1; + } + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, + 0x01/*HID get_report*/, + (3/*HID feature*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + if (skipped_report_id) + res++; + + return res; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + libusb_cancel_transfer(dev->transfer); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Clean up the Transfer objects allocated in read_thread(). */ + free(dev->transfer->buffer); + libusb_free_transfer(dev->transfer); + + /* release the interface */ + libusb_release_interface(dev->device_handle, dev->interface); + + /* Close the handle */ + libusb_close(dev->device_handle); + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + + free_hid_device(dev); +} + + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->product_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + wchar_t *str; + + str = get_usb_string(dev->device_handle, string_index); + if (str) { + wcsncpy(string, str, maxlen); + string[maxlen-1] = L'\0'; + free(str); + return 0; + } + else + return -1; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return NULL; +} + + +struct lang_map_entry { + const char *name; + const char *string_code; + uint16_t usb_code; +}; + +#define LANG(name,code,usb_code) { name, code, usb_code } +static struct lang_map_entry lang_map[] = { + LANG("Afrikaans", "af", 0x0436), + LANG("Albanian", "sq", 0x041C), + LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), + LANG("Arabic - Bahrain", "ar_bh", 0x3C01), + LANG("Arabic - Algeria", "ar_dz", 0x1401), + LANG("Arabic - Egypt", "ar_eg", 0x0C01), + LANG("Arabic - Iraq", "ar_iq", 0x0801), + LANG("Arabic - Jordan", "ar_jo", 0x2C01), + LANG("Arabic - Kuwait", "ar_kw", 0x3401), + LANG("Arabic - Lebanon", "ar_lb", 0x3001), + LANG("Arabic - Libya", "ar_ly", 0x1001), + LANG("Arabic - Morocco", "ar_ma", 0x1801), + LANG("Arabic - Oman", "ar_om", 0x2001), + LANG("Arabic - Qatar", "ar_qa", 0x4001), + LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), + LANG("Arabic - Syria", "ar_sy", 0x2801), + LANG("Arabic - Tunisia", "ar_tn", 0x1C01), + LANG("Arabic - Yemen", "ar_ye", 0x2401), + LANG("Armenian", "hy", 0x042B), + LANG("Azeri - Latin", "az_az", 0x042C), + LANG("Azeri - Cyrillic", "az_az", 0x082C), + LANG("Basque", "eu", 0x042D), + LANG("Belarusian", "be", 0x0423), + LANG("Bulgarian", "bg", 0x0402), + LANG("Catalan", "ca", 0x0403), + LANG("Chinese - China", "zh_cn", 0x0804), + LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), + LANG("Chinese - Macau SAR", "zh_mo", 0x1404), + LANG("Chinese - Singapore", "zh_sg", 0x1004), + LANG("Chinese - Taiwan", "zh_tw", 0x0404), + LANG("Croatian", "hr", 0x041A), + LANG("Czech", "cs", 0x0405), + LANG("Danish", "da", 0x0406), + LANG("Dutch - Netherlands", "nl_nl", 0x0413), + LANG("Dutch - Belgium", "nl_be", 0x0813), + LANG("English - Australia", "en_au", 0x0C09), + LANG("English - Belize", "en_bz", 0x2809), + LANG("English - Canada", "en_ca", 0x1009), + LANG("English - Caribbean", "en_cb", 0x2409), + LANG("English - Ireland", "en_ie", 0x1809), + LANG("English - Jamaica", "en_jm", 0x2009), + LANG("English - New Zealand", "en_nz", 0x1409), + LANG("English - Phillippines", "en_ph", 0x3409), + LANG("English - Southern Africa", "en_za", 0x1C09), + LANG("English - Trinidad", "en_tt", 0x2C09), + LANG("English - Great Britain", "en_gb", 0x0809), + LANG("English - United States", "en_us", 0x0409), + LANG("Estonian", "et", 0x0425), + LANG("Farsi", "fa", 0x0429), + LANG("Finnish", "fi", 0x040B), + LANG("Faroese", "fo", 0x0438), + LANG("French - France", "fr_fr", 0x040C), + LANG("French - Belgium", "fr_be", 0x080C), + LANG("French - Canada", "fr_ca", 0x0C0C), + LANG("French - Luxembourg", "fr_lu", 0x140C), + LANG("French - Switzerland", "fr_ch", 0x100C), + LANG("Gaelic - Ireland", "gd_ie", 0x083C), + LANG("Gaelic - Scotland", "gd", 0x043C), + LANG("German - Germany", "de_de", 0x0407), + LANG("German - Austria", "de_at", 0x0C07), + LANG("German - Liechtenstein", "de_li", 0x1407), + LANG("German - Luxembourg", "de_lu", 0x1007), + LANG("German - Switzerland", "de_ch", 0x0807), + LANG("Greek", "el", 0x0408), + LANG("Hebrew", "he", 0x040D), + LANG("Hindi", "hi", 0x0439), + LANG("Hungarian", "hu", 0x040E), + LANG("Icelandic", "is", 0x040F), + LANG("Indonesian", "id", 0x0421), + LANG("Italian - Italy", "it_it", 0x0410), + LANG("Italian - Switzerland", "it_ch", 0x0810), + LANG("Japanese", "ja", 0x0411), + LANG("Korean", "ko", 0x0412), + LANG("Latvian", "lv", 0x0426), + LANG("Lithuanian", "lt", 0x0427), + LANG("F.Y.R.O. Macedonia", "mk", 0x042F), + LANG("Malay - Malaysia", "ms_my", 0x043E), + LANG("Malay – Brunei", "ms_bn", 0x083E), + LANG("Maltese", "mt", 0x043A), + LANG("Marathi", "mr", 0x044E), + LANG("Norwegian - Bokml", "no_no", 0x0414), + LANG("Norwegian - Nynorsk", "no_no", 0x0814), + LANG("Polish", "pl", 0x0415), + LANG("Portuguese - Portugal", "pt_pt", 0x0816), + LANG("Portuguese - Brazil", "pt_br", 0x0416), + LANG("Raeto-Romance", "rm", 0x0417), + LANG("Romanian - Romania", "ro", 0x0418), + LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), + LANG("Russian", "ru", 0x0419), + LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), + LANG("Sanskrit", "sa", 0x044F), + LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), + LANG("Serbian - Latin", "sr_sp", 0x081A), + LANG("Setsuana", "tn", 0x0432), + LANG("Slovenian", "sl", 0x0424), + LANG("Slovak", "sk", 0x041B), + LANG("Sorbian", "sb", 0x042E), + LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), + LANG("Spanish - Argentina", "es_ar", 0x2C0A), + LANG("Spanish - Bolivia", "es_bo", 0x400A), + LANG("Spanish - Chile", "es_cl", 0x340A), + LANG("Spanish - Colombia", "es_co", 0x240A), + LANG("Spanish - Costa Rica", "es_cr", 0x140A), + LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), + LANG("Spanish - Ecuador", "es_ec", 0x300A), + LANG("Spanish - Guatemala", "es_gt", 0x100A), + LANG("Spanish - Honduras", "es_hn", 0x480A), + LANG("Spanish - Mexico", "es_mx", 0x080A), + LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), + LANG("Spanish - Panama", "es_pa", 0x180A), + LANG("Spanish - Peru", "es_pe", 0x280A), + LANG("Spanish - Puerto Rico", "es_pr", 0x500A), + LANG("Spanish - Paraguay", "es_py", 0x3C0A), + LANG("Spanish - El Salvador", "es_sv", 0x440A), + LANG("Spanish - Uruguay", "es_uy", 0x380A), + LANG("Spanish - Venezuela", "es_ve", 0x200A), + LANG("Southern Sotho", "st", 0x0430), + LANG("Swahili", "sw", 0x0441), + LANG("Swedish - Sweden", "sv_se", 0x041D), + LANG("Swedish - Finland", "sv_fi", 0x081D), + LANG("Tamil", "ta", 0x0449), + LANG("Tatar", "tt", 0X0444), + LANG("Thai", "th", 0x041E), + LANG("Turkish", "tr", 0x041F), + LANG("Tsonga", "ts", 0x0431), + LANG("Ukrainian", "uk", 0x0422), + LANG("Urdu", "ur", 0x0420), + LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), + LANG("Uzbek – Latin", "uz_uz", 0x0443), + LANG("Vietnamese", "vi", 0x042A), + LANG("Xhosa", "xh", 0x0434), + LANG("Yiddish", "yi", 0x043D), + LANG("Zulu", "zu", 0x0435), + LANG(NULL, NULL, 0x0), +}; + +uint16_t get_usb_code_for_current_locale(void) +{ + char *locale; + char search_string[64]; + char *ptr; + struct lang_map_entry *lang; + + /* Get the current locale. */ + locale = setlocale(0, NULL); + if (!locale) + return 0x0; + + /* Make a copy of the current locale string. */ + strncpy(search_string, locale, sizeof(search_string)); + search_string[sizeof(search_string)-1] = '\0'; + + /* Chop off the encoding part, and make it lower case. */ + ptr = search_string; + while (*ptr) { + *ptr = tolower(*ptr); + if (*ptr == '.') { + *ptr = '\0'; + break; + } + ptr++; + } + + /* Find the entry which matches the string code of our locale. */ + lang = lang_map; + while (lang->string_code) { + if (!strcmp(lang->string_code, search_string)) { + return lang->usb_code; + } + lang++; + } + + /* There was no match. Find with just the language only. */ + /* Chop off the variant. Chop it off at the '_'. */ + ptr = search_string; + while (*ptr) { + *ptr = tolower(*ptr); + if (*ptr == '_') { + *ptr = '\0'; + break; + } + ptr++; + } + +#if 0 /* TODO: Do we need this? */ + /* Find the entry which matches the string code of our language. */ + lang = lang_map; + while (lang->string_code) { + if (!strcmp(lang->string_code, search_string)) { + return lang->usb_code; + } + lang++; + } +#endif + + /* Found nothing. */ + return 0x0; +} + +#ifdef __cplusplus +} +#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/mac/hid.c b/vendor/github.com/karalabe/usb/hidapi/mac/hid.c new file mode 100644 index 0000000000..e0756a1588 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/mac/hid.c @@ -0,0 +1,1110 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 2010-07-03 + + Copyright 2010, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* See Apple Technical Note TN2187 for details on IOHidManager. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hidapi.h" + +/* Barrier implementation because Mac OSX doesn't have pthread_barrier. + It also doesn't have clock_gettime(). So much for POSIX and SUSv2. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + +struct hid_device_ { + IOHIDDeviceRef device_handle; + int blocking; + int uses_numbered_reports; + int disconnected; + CFStringRef run_loop_mode; + CFRunLoopRef run_loop; + CFRunLoopSourceRef source; + uint8_t *input_report_buf; + CFIndex max_input_report_len; + struct input_report *input_reports; + + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ + int shutdown_thread; +}; + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = NULL; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + dev->disconnected = 0; + dev->run_loop_mode = NULL; + dev->run_loop = NULL; + dev->source = NULL; + dev->input_report_buf = NULL; + dev->input_reports = NULL; + dev->shutdown_thread = 0; + + /* Thread objects */ + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + if (!dev) + return; + + /* Delete any input reports still left over. */ + struct input_report *rpt = dev->input_reports; + while (rpt) { + struct input_report *next = rpt->next; + free(rpt->data); + free(rpt); + rpt = next; + } + + /* Free the string and the report buffer. The check for NULL + is necessary here as CFRelease() doesn't handle NULL like + free() and others do. */ + if (dev->run_loop_mode) + CFRelease(dev->run_loop_mode); + if (dev->source) + CFRelease(dev->source); + free(dev->input_report_buf); + + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->shutdown_barrier); + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the structure itself. */ + free(dev); +} + +static IOHIDManagerRef hid_mgr = 0x0; + + +#if 0 +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + + +static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) +{ + CFTypeRef ref; + int32_t value; + + ref = IOHIDDeviceGetProperty(device, key); + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); + return value; + } + } + return 0; +} + +static unsigned short get_vendor_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); +} + +static unsigned short get_product_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDProductIDKey)); +} + +static int32_t get_max_report_length(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); +} + +static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) +{ + CFStringRef str; + + if (!len) + return 0; + + str = IOHIDDeviceGetProperty(device, prop); + + buf[0] = 0; + + if (str) { + CFIndex str_len = CFStringGetLength(str); + CFRange range; + CFIndex used_buf_len; + CFIndex chars_copied; + + len --; + + range.location = 0; + range.length = ((size_t)str_len > len)? len: (size_t)str_len; + chars_copied = CFStringGetBytes(str, + range, + kCFStringEncodingUTF32LE, + (char)'?', + FALSE, + (UInt8*)buf, + len * sizeof(wchar_t), + &used_buf_len); + + if (chars_copied == len) + buf[len] = 0; /* len is decremented above */ + else + buf[chars_copied] = 0; + + return 0; + } + else + return -1; + +} + +static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); +} + +static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); +} + +static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); +} + + +/* Implementation of wcsdup() for Mac. */ +static wchar_t *dup_wcs(const wchar_t *s) +{ + size_t len = wcslen(s); + wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); + wcscpy(ret, s); + + return ret; +} + +/* hidapi_IOHIDDeviceGetService() + * + * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by: + * - on OS X 10.6 and above, calling IOHIDDeviceGetService() + * - on OS X 10.5, extract it from the IOHIDDevice struct + */ +static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device) +{ + static void *iokit_framework = NULL; + static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL; + + /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists. + * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL + * and the fallback method will be used. + */ + if (iokit_framework == NULL) { + iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY); + + if (iokit_framework != NULL) + dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService"); + } + + if (dynamic_IOHIDDeviceGetService != NULL) { + /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */ + return dynamic_IOHIDDeviceGetService(device); + } + else + { + /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist. + * + * Be naughty and pull the service out of the IOHIDDevice. + * IOHIDDevice is an opaque struct not exposed to applications, but its + * layout is stable through all available versions of OS X. + * Tested and working on OS X 10.5.8 i386, x86_64, and ppc. + */ + struct IOHIDDevice_internal { + /* The first field of the IOHIDDevice struct is a + * CFRuntimeBase (which is a private CF struct). + * + * a, b, and c are the 3 fields that make up a CFRuntimeBase. + * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h + * + * The second field of the IOHIDDevice is the io_service_t we're looking for. + */ + uintptr_t a; + uint8_t b[4]; +#if __LP64__ + uint32_t c; +#endif + io_service_t service; + }; + struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device; + + return tmp->service; + } +} + +/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ +static int init_hid_manager(void) +{ + /* Initialize all the HID Manager Objects */ + hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_mgr) { + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + return 0; + } + + return -1; +} + +/* Initialize the IOHIDManager if necessary. This is the public function, and + it is safe to call this function repeatedly. Return 0 for success and -1 + for failure. */ +int HID_API_EXPORT hid_init(void) +{ + if (!hid_mgr) { + return init_hid_manager(); + } + + /* Already initialized. */ + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (hid_mgr) { + /* Close the HID manager. */ + IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); + CFRelease(hid_mgr); + hid_mgr = NULL; + } + + return 0; +} + +static void process_pending_events(void) { + SInt32 res; + do { + res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); + } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + CFIndex num_devices; + int i; + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* give the IOHIDManager a chance to update itself */ + process_pending_events(); + + /* Get a list of the Devices */ + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + /* Iterate over each device, making an entry for it. */ + for (i = 0; i < num_devices; i++) { + unsigned short dev_vid; + unsigned short dev_pid; + #define BUF_LEN 256 + wchar_t buf[BUF_LEN]; + + IOHIDDeviceRef dev = device_array[i]; + + if (!dev) { + continue; + } + dev_vid = get_vendor_id(dev); + dev_pid = get_product_id(dev); + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + io_object_t iokit_dev; + kern_return_t res; + io_string_t path; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); + cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); + + /* Fill out the record */ + cur_dev->next = NULL; + + /* Fill in the path (IOService plane) */ + iokit_dev = hidapi_IOHIDDeviceGetService(dev); + res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); + if (res == KERN_SUCCESS) + cur_dev->path = strdup(path); + else + cur_dev->path = strdup(""); + + /* Serial Number */ + get_serial_number(dev, buf, BUF_LEN); + cur_dev->serial_number = dup_wcs(buf); + + /* Manufacturer and Product strings */ + get_manufacturer_string(dev, buf, BUF_LEN); + cur_dev->manufacturer_string = dup_wcs(buf); + get_product_string(dev, buf, BUF_LEN); + cur_dev->product_string = dup_wcs(buf); + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); + + /* Interface Number (Unsupported on Mac)*/ + cur_dev->interface_number = -1; + } + } + + free(device_array); + CFRelease(device_set); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device * handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void hid_device_removal_callback(void *context, IOReturn result, + void *sender) +{ + /* Stop the Run Loop for this device. */ + hid_device *d = context; + + d->disconnected = 1; + CFRunLoopStop(d->run_loop); +} + +/* The Run Loop calls this function for each input report received. + This function puts the data into a linked list to be picked up by + hid_read(). */ +static void hid_report_callback(void *context, IOReturn result, void *sender, + IOHIDReportType report_type, uint32_t report_id, + uint8_t *report, CFIndex report_length) +{ + struct input_report *rpt; + hid_device *dev = context; + + /* Make a new Input Report object */ + rpt = calloc(1, sizeof(struct input_report)); + rpt->data = calloc(1, report_length); + memcpy(rpt->data, report, report_length); + rpt->len = report_length; + rpt->next = NULL; + + /* Lock this section */ + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + + /* Signal a waiting thread that there is data. */ + pthread_cond_signal(&dev->condition); + + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + +} + +/* This gets called when the read_thread's run loop gets signaled by + hid_close(), and serves to stop the read_thread's run loop. */ +static void perform_signal_callback(void *context) +{ + hid_device *dev = context; + CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ +} + +static void *read_thread(void *param) +{ + hid_device *dev = param; + SInt32 code; + + /* Move the device's run loop to this thread. */ + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); + + /* Create the RunLoopSource which is used to signal the + event loop to stop when hid_close() is called. */ + CFRunLoopSourceContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.version = 0; + ctx.info = dev; + ctx.perform = &perform_signal_callback; + dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); + + /* Store off the Run Loop so it can be stopped from hid_close() + and on device disconnection. */ + dev->run_loop = CFRunLoopGetCurrent(); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input + reports into the hid_report_callback(). */ + while (!dev->shutdown_thread && !dev->disconnected) { + code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); + /* Return if the device has been disconnected */ + if (code == kCFRunLoopRunFinished) { + dev->disconnected = 1; + break; + } + + + /* Break if The Run Loop returns Finished or Stopped. */ + if (code != kCFRunLoopRunTimedOut && + code != kCFRunLoopRunHandledSource) { + /* There was some kind of error. Setting + shutdown seems to make sense, but + there may be something else more appropriate */ + dev->shutdown_thread = 1; + break; + } + } + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition actually will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* Wait here until hid_close() is called and makes it past + the call to CFRunLoopWakeUp(). This thread still needs to + be valid when that function is called on the other thread. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + return NULL; +} + +/* hid_open_path() + * + * path must be a valid path to an IOHIDDevice in the IOService plane + * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver" + */ +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + io_registry_entry_t entry = MACH_PORT_NULL; + + dev = new_hid_device(); + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* Get the IORegistry entry for the given path */ + entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); + if (entry == MACH_PORT_NULL) { + /* Path wasn't valid (maybe device was removed?) */ + goto return_error; + } + + /* Create an IOHIDDevice for the entry */ + dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); + if (dev->device_handle == NULL) { + /* Error creating the HID device */ + goto return_error; + } + + /* Open the IOHIDDevice */ + IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + if (ret == kIOReturnSuccess) { + char str[32]; + + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); + + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + IOObjectRelease(entry); + return dev; + } + else { + goto return_error; + } + +return_error: + if (dev->device_handle != NULL) + CFRelease(dev->device_handle); + + if (entry != MACH_PORT_NULL) + IOObjectRelease(entry); + + free_hid_device(dev); + return NULL; +} + +static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) +{ + const unsigned char *data_to_send; + size_t length_to_send; + IOReturn res; + + /* Return if the device has been disconnected. */ + if (dev->disconnected) + return -1; + + if (data[0] == 0x0) { + /* Not using numbered Reports. + Don't send the report number. */ + data_to_send = data+1; + length_to_send = length-1; + } + else { + /* Using numbered Reports. + Send the Report Number */ + data_to_send = data; + length_to_send = length; + } + + if (!dev->disconnected) { + res = IOHIDDeviceSetReport(dev->device_handle, + type, + data[0], /* Report ID*/ + data_to_send, length_to_send); + + if (res == kIOReturnSuccess) { + return length; + } + else + return -1; + } + + return -1; +} + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeOutput, data, length); +} + +/* Helper function, so that this isn't duplicated in hid_read(). */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + while (!dev->input_reports) { + int res = pthread_cond_wait(cond, mutex); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; +} + +static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +{ + while (!dev->input_reports) { + int res = pthread_cond_timedwait(cond, mutex, abstime); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; + +} + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + + /* Lock the access to the report list. */ + pthread_mutex_lock(&dev->mutex); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + /* Return if the device has been disconnected. */ + if (dev->disconnected) { + bytes_read = -1; + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been closed (or there + has been an error. An error code of -1 should + be returned. */ + bytes_read = -1; + goto ret; + } + + /* There is no data. Go to sleep and wait for data. */ + + if (milliseconds == -1) { + /* Blocking */ + int res; + res = cond_wait(dev, &dev->condition, &dev->mutex); + if (res == 0) + bytes_read = return_data(dev, data, length); + else { + /* There was an error, or a device disconnection. */ + bytes_read = -1; + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + struct timeval tv; + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); + if (res == 0) + bytes_read = return_data(dev, data, length); + else if (res == ETIMEDOUT) + bytes_read = 0; + else + bytes_read = -1; + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* All Nonblocking operation is handled by the library. */ + dev->blocking = !nonblock; + + return 0; +} + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeFeature, data, length); +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + CFIndex len = length; + IOReturn res; + + /* Return if the device has been unplugged. */ + if (dev->disconnected) + return -1; + + res = IOHIDDeviceGetReport(dev->device_handle, + kIOHIDReportTypeFeature, + data[0], /* Report ID */ + data, &len); + if (res == kIOReturnSuccess) + return len; + else + return -1; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Disconnect the report callback before close. */ + if (!dev->disconnected) { + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + NULL, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); + IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + } + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + + /* Wake up the run thread's event loop so that the thread can exit. */ + CFRunLoopSourceSignal(dev->source); + CFRunLoopWakeUp(dev->run_loop); + + /* Notify the read thread that it can shut down now. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Close the OS handle to the device, but only if it's not + been unplugged. If it's been unplugged, then calling + IOHIDDeviceClose() will crash. */ + if (!dev->disconnected) { + IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + } + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + CFRelease(dev->device_handle); + + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_manufacturer_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_product_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_serial_number(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + /* TODO: */ + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + /* TODO: */ + + return NULL; +} + + + + + + + +#if 0 +static int32_t get_location_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); +} + +static int32_t get_usage(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); + return res; +} + +static int32_t get_usage_page(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); + return res; +} + +static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); +} + + +int main(void) +{ + IOHIDManagerRef mgr; + int i; + + mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerSetDeviceMatching(mgr, NULL); + IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); + + CFSetRef device_set = IOHIDManagerCopyDevices(mgr); + + CFIndex num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + for (i = 0; i < num_devices; i++) { + IOHIDDeviceRef dev = device_array[i]; + printf("Device: %p\n", dev); + printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); + + wchar_t serial[256], buf[256]; + char cbuf[256]; + get_serial_number(dev, serial, 256); + + + printf(" Serial: %ls\n", serial); + printf(" Loc: %ld\n", get_location_id(dev)); + get_transport(dev, buf, 256); + printf(" Trans: %ls\n", buf); + make_path(dev, cbuf, 256); + printf(" Path: %s\n", cbuf); + + } + + return 0; +} +#endif diff --git a/vendor/github.com/karalabe/usb/hidapi/windows/hid.c b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c new file mode 100644 index 0000000000..4e92cc8bc9 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c @@ -0,0 +1,944 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +#include + +#ifndef _NTDEF_ +typedef LONG NTSTATUS; +#endif + +#ifdef __MINGW32__ +#include +#include +#endif + +#ifdef __CYGWIN__ +#include +#define _wcsdup wcsdup +#endif + +/* The maximum number of characters that can be passed into the + HidD_Get*String() functions without it failing.*/ +#define MAX_STRING_WCHARS 0xFFF + +/*#define HIDAPI_USE_DDK*/ + +#ifdef __cplusplus +extern "C" { +#endif + #include + #include + #ifdef HIDAPI_USE_DDK + #include + #endif + + /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include +#include + + +#include "hidapi.h" + +#undef MIN +#define MIN(x,y) ((x) < (y)? (x): (y)) + +#ifdef _MSC_VER + /* Thanks Microsoft, but I know how to use strncpy(). */ + #pragma warning(disable:4996) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HIDAPI_USE_DDK + /* Since we're not building with the DDK, and the HID header + files aren't part of the SDK, we have to define all this + stuff here. In lookup_functions(), the function pointers + defined below are set. */ + typedef struct _HIDD_ATTRIBUTES{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + typedef USHORT USAGE; + typedef struct _HIDP_CAPS { + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT fields_not_used_by_hidapi[10]; + } HIDP_CAPS, *PHIDP_CAPS; + typedef void* PHIDP_PREPARSED_DATA; + #define HIDP_STATUS_SUCCESS 0x110000 + + typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); + typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); + typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); + typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); + + static HidD_GetAttributes_ HidD_GetAttributes; + static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; + static HidD_GetManufacturerString_ HidD_GetManufacturerString; + static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetFeature_ HidD_SetFeature; + static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetIndexedString_ HidD_GetIndexedString; + static HidD_GetPreparsedData_ HidD_GetPreparsedData; + static HidD_FreePreparsedData_ HidD_FreePreparsedData; + static HidP_GetCaps_ HidP_GetCaps; + static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; + + static HMODULE lib_handle = NULL; + static BOOLEAN initialized = FALSE; +#endif /* HIDAPI_USE_DDK */ + +struct hid_device_ { + HANDLE device_handle; + BOOL blocking; + USHORT output_report_length; + size_t input_report_length; + void *last_error_str; + DWORD last_error_num; + BOOL read_pending; + char *read_buf; + OVERLAPPED ol; +}; + +static hid_device *new_hid_device() +{ + hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + dev->device_handle = INVALID_HANDLE_VALUE; + dev->blocking = TRUE; + dev->output_report_length = 0; + dev->input_report_length = 0; + dev->last_error_str = NULL; + dev->last_error_num = 0; + dev->read_pending = FALSE; + dev->read_buf = NULL; + memset(&dev->ol, 0, sizeof(dev->ol)); + dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + CloseHandle(dev->ol.hEvent); + CloseHandle(dev->device_handle); + LocalFree(dev->last_error_str); + free(dev->read_buf); + free(dev); +} + +static void register_error(hid_device *device, const char *op) +{ + WCHAR *ptr, *msg; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPVOID)&msg, 0/*sz*/, + NULL); + + /* Get rid of the CR and LF that FormatMessage() sticks at the + end of the message. Thanks Microsoft! */ + ptr = msg; + while (*ptr) { + if (*ptr == '\r') { + *ptr = 0x0000; + break; + } + ptr++; + } + + /* Store the message off in the Device entry so that + the hid_error() function can pick it up. */ + LocalFree(device->last_error_str); + device->last_error_str = msg; +} + +#ifndef HIDAPI_USE_DDK +static int lookup_functions() +{ + lib_handle = LoadLibraryA("hid.dll"); + if (lib_handle) { +#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; + RESOLVE(HidD_GetAttributes); + RESOLVE(HidD_GetSerialNumberString); + RESOLVE(HidD_GetManufacturerString); + RESOLVE(HidD_GetProductString); + RESOLVE(HidD_SetFeature); + RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetIndexedString); + RESOLVE(HidD_GetPreparsedData); + RESOLVE(HidD_FreePreparsedData); + RESOLVE(HidP_GetCaps); + RESOLVE(HidD_SetNumInputBuffers); +#undef RESOLVE + } + else + return -1; + + return 0; +} +#endif + +static HANDLE open_device(const char *path, BOOL enumerate) +{ + HANDLE handle; + DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + + handle = CreateFileA(path, + desired_access, + share_mode, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ + 0); + + return handle; +} + +int HID_API_EXPORT hid_init(void) +{ +#ifndef HIDAPI_USE_DDK + if (!initialized) { + if (lookup_functions() < 0) { + hid_exit(); + return -1; + } + initialized = TRUE; + } +#endif + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ +#ifndef HIDAPI_USE_DDK + if (lib_handle) + FreeLibrary(lib_handle); + lib_handle = NULL; + initialized = FALSE; +#endif + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + BOOL res; + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + /* Windows objects for interacting with the driver. */ + GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + SP_DEVINFO_DATA devinfo_data; + SP_DEVICE_INTERFACE_DATA device_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; + HDEVINFO device_info_set = INVALID_HANDLE_VALUE; + int device_index = 0; + int i; + + if (hid_init() < 0) + return NULL; + + /* Initialize the Windows objects. */ + memset(&devinfo_data, 0x0, sizeof(devinfo_data)); + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + /* Get information for all the devices belonging to the HID class. */ + device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + /* Iterate over each device in the HID class, looking for the right one. */ + + for (;;) { + HANDLE write_handle = INVALID_HANDLE_VALUE; + DWORD required_size = 0; + HIDD_ATTRIBUTES attrib; + + res = SetupDiEnumDeviceInterfaces(device_info_set, + NULL, + &InterfaceClassGuid, + device_index, + &device_interface_data); + + if (!res) { + /* A return of FALSE from this function means that + there are no more devices. */ + break; + } + + /* Call with 0-sized detail size, and let the function + tell us how long the detail struct needs to be. The + size is put in &required_size. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + NULL, + 0, + &required_size, + NULL); + + /* Allocate a long enough structure for device_interface_detail_data. */ + device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); + device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + + /* Get the detailed data for this device. The detail data gives us + the device path for this device, which is then passed into + CreateFile() to get a handle to the device. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + device_interface_detail_data, + required_size, + NULL, + NULL); + + if (!res) { + /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); + Continue to the next device. */ + goto cont; + } + + /* Make sure this device is of Setup Class "HIDClass" and has a + driver bound to it. */ + for (i = 0; ; i++) { + char driver_name[256]; + + /* Populate devinfo_data. This function will return failure + when there are no more interfaces left. */ + res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); + if (!res) + goto cont; + + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (!res) + goto cont; + + if (strcmp(driver_name, "HIDClass") == 0) { + /* See if there's a driver bound. */ + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (res) + break; + } + } + + //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); + + /* Open a handle to the device */ + write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + + /* Check validity of write_handle. */ + if (write_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + goto cont_close; + } + + + /* Get the Vendor ID and Product ID for this device. */ + attrib.Size = sizeof(HIDD_ATTRIBUTES); + HidD_GetAttributes(write_handle, &attrib); + //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + /* Check the VID/PID to see if we should add this + device to the enumeration list. */ + if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && + (product_id == 0x0 || attrib.ProductID == product_id)) { + + #define WSTR_LEN 512 + const char *str; + struct hid_device_info *tmp; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + BOOLEAN res; + NTSTATUS nt_res; + wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ + size_t len; + + /* VID/PID match. Create the record. */ + tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + cur_dev->usage_page = caps.UsagePage; + cur_dev->usage = caps.Usage; + } + + HidD_FreePreparsedData(pp_data); + } + + /* Fill out the record */ + cur_dev->next = NULL; + str = device_interface_detail_data->DevicePath; + if (str) { + len = strlen(str); + cur_dev->path = (char*) calloc(len+1, sizeof(char)); + strncpy(cur_dev->path, str, sizeof(cur_dev->path)); + cur_dev->path[len] = '\0'; + } + else + cur_dev->path = NULL; + + /* Serial Number */ + res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->serial_number = _wcsdup(wstr); + } + + /* Manufacturer String */ + res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->manufacturer_string = _wcsdup(wstr); + } + + /* Product String */ + res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->product_string = _wcsdup(wstr); + } + + /* VID/PID */ + cur_dev->vendor_id = attrib.VendorID; + cur_dev->product_id = attrib.ProductID; + + /* Release Number */ + cur_dev->release_number = attrib.VersionNumber; + + /* Interface Number. It can sometimes be parsed out of the path + on Windows if a device has multiple interfaces. See + http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or + search for "Hardware IDs for HID Devices" at MSDN. If it's not + in the path, it's set to -1. */ + cur_dev->interface_number = -1; + if (cur_dev->path) { + char *interface_component = strstr(cur_dev->path, "&mi_"); + if (interface_component) { + char *hex_str = interface_component + 4; + char *endptr = NULL; + cur_dev->interface_number = strtol(hex_str, &endptr, 16); + if (endptr == hex_str) { + /* The parsing failed. Set interface_number to -1. */ + cur_dev->interface_number = -1; + } + } + } + } + +cont_close: + CloseHandle(write_handle); +cont: + /* We no longer need the detail data. It can be freed */ + free(device_interface_detail_data); + + device_index++; + + } + + /* Close the device information handle. */ + SetupDiDestroyDeviceInfoList(device_info_set); + + return root; + +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + /* TODO: Merge this with the Linux version. This function is platform-independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + hid_device *dev; + HIDP_CAPS caps; + PHIDP_PREPARSED_DATA pp_data = NULL; + BOOLEAN res; + NTSTATUS nt_res; + + if (hid_init() < 0) { + return NULL; + } + + dev = new_hid_device(); + + /* Open a handle to the device */ + dev->device_handle = open_device(path, FALSE); + + /* Check validity of write_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + register_error(dev, "CreateFile"); + goto err; + } + + /* Set the Input Report buffer size to 64 reports. */ + res = HidD_SetNumInputBuffers(dev->device_handle, 64); + if (!res) { + register_error(dev, "HidD_SetNumInputBuffers"); + goto err; + } + + /* Get the Input Report length for the device. */ + res = HidD_GetPreparsedData(dev->device_handle, &pp_data); + if (!res) { + register_error(dev, "HidD_GetPreparsedData"); + goto err; + } + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + register_error(dev, "HidP_GetCaps"); + goto err_pp_data; + } + dev->output_report_length = caps.OutputReportByteLength; + dev->input_report_length = caps.InputReportByteLength; + HidD_FreePreparsedData(pp_data); + + dev->read_buf = (char*) malloc(dev->input_report_length); + + return dev; + +err_pp_data: + HidD_FreePreparsedData(pp_data); +err: + free_hid_device(dev); + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + DWORD bytes_written; + BOOL res; + + OVERLAPPED ol; + unsigned char *buf; + memset(&ol, 0, sizeof(ol)); + + /* Make sure the right number of bytes are passed to WriteFile. Windows + expects the number of bytes which are in the _longest_ report (plus + one for the report number) bytes even if the data is a report + which is shorter than that. Windows gives us this value in + caps.OutputReportByteLength. If a user passes in fewer bytes than this, + create a temporary buffer which is the proper size. */ + if (length >= dev->output_report_length) { + /* The user passed the right number of bytes. Use the buffer as-is. */ + buf = (unsigned char *) data; + } else { + /* Create a temporary buffer and copy the user's data + into it, padding the rest with zeros. */ + buf = (unsigned char *) malloc(dev->output_report_length); + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length = dev->output_report_length; + } + + res = WriteFile(dev->device_handle, buf, length, NULL, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* WriteFile() failed. Return error. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + } + + /* Wait here until the write is done. This makes + hid_write() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + if (!res) { + /* The Write operation failed. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + +end_of_function: + if (buf != data) + free(buf); + + return bytes_written; +} + + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + DWORD bytes_read = 0; + size_t copy_len = 0; + BOOL res; + + /* Copy the handle for convenience. */ + HANDLE ev = dev->ol.hEvent; + + if (!dev->read_pending) { + /* Start an Overlapped I/O read. */ + dev->read_pending = TRUE; + memset(dev->read_buf, 0, dev->input_report_length); + ResetEvent(ev); + res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIo(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } + } + + if (milliseconds >= 0) { + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; + } + } + + /* Either WaitForSingleObject() told us that ReadFile has completed, or + we are in non-blocking mode. Get the number of bytes read. The actual + data has been copied to the data[] array which was passed to ReadFile(). */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + + /* Set pending back to false, even if GetOverlappedResult() returned error. */ + dev->read_pending = FALSE; + + if (res && bytes_read > 0) { + if (dev->read_buf[0] == 0x0) { + /* If report numbers aren't being used, but Windows sticks a report + number (0x0) on the beginning of the report anyway. To make this + work like the other platforms, and to make it work more like the + HID spec, we'll skip over this byte. */ + bytes_read--; + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf+1, copy_len); + } + else { + /* Copy the whole buffer, report number and all. */ + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); + } + } + +end_of_function: + if (!res) { + register_error(dev, "GetOverlappedResult"); + return -1; + } + + return copy_len; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; /* Success */ +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length); + if (!res) { + register_error(dev, "HidD_SetFeature"); + return -1; + } + + return length; +} + + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; +#if 0 + res = HidD_GetFeature(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetFeature"); + return -1; + } + return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_FEATURE, + data, length, + data, length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Feature Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Feature Report GetOverLappedResult"); + return -1; + } + + /* bytes_returned does not include the first byte which contains the + report ID. The data buffer actually contains one more byte than + bytes_returned. */ + bytes_returned++; + + return bytes_returned; +#endif +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + CancelIo(dev->device_handle); + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + if (!res) { + register_error(dev, "HidD_GetManufacturerString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + if (!res) { + register_error(dev, "HidD_GetProductString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + if (!res) { + register_error(dev, "HidD_GetSerialNumberString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + if (!res) { + register_error(dev, "HidD_GetIndexedString"); + return -1; + } + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return (wchar_t*)dev->last_error_str; +} + + +/*#define PICPGM*/ +/*#define S11*/ +#define P32 +#ifdef S11 + unsigned short VendorID = 0xa0a0; + unsigned short ProductID = 0x0001; +#endif + +#ifdef P32 + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x3f; +#endif + + +#ifdef PICPGM + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x0033; +#endif + + +#if 0 +int __cdecl main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + /* Set up the command buffer. */ + memset(buf,0x00,sizeof(buf)); + buf[0] = 0; + buf[1] = 0x81; + + + /* Open the device. */ + int handle = open(VendorID, ProductID, L"12345"); + if (handle < 0) + printf("unable to open device\n"); + + + /* Toggle LED (cmd 0x80) */ + buf[1] = 0x80; + res = write(handle, buf, 65); + if (res < 0) + printf("Unable to write()\n"); + + /* Request state (cmd 0x81) */ + buf[1] = 0x81; + write(handle, buf, 65); + if (res < 0) + printf("Unable to write() (2)\n"); + + /* Read requested state */ + read(handle, buf, 65); + if (res < 0) + printf("Unable to read()\n"); + + /* Print out the returned buffer. */ + for (int i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + return 0; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/AUTHORS b/vendor/github.com/karalabe/usb/libusb/AUTHORS new file mode 100644 index 0000000000..e90ad9bb2a --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/AUTHORS @@ -0,0 +1,119 @@ +Copyright © 2001 Johannes Erdfelt +Copyright © 2007-2009 Daniel Drake +Copyright © 2010-2012 Peter Stuge +Copyright © 2008-2016 Nathan Hjelm +Copyright © 2009-2013 Pete Batard +Copyright © 2009-2013 Ludovic Rousseau +Copyright © 2010-2012 Michael Plante +Copyright © 2011-2013 Hans de Goede +Copyright © 2012-2013 Martin Pieuchot +Copyright © 2012-2013 Toby Gray +Copyright © 2013-2018 Chris Dickens + +Other contributors: +Adrian Bunk +Akshay Jaggi +Alan Ott +Alan Stern +Alex Vatchenko +Andrew Fernandes +Andy Chunyu +Andy McFadden +Angus Gratton +Anil Nair +Anthony Clay +Antonio Ospite +Artem Egorkine +Aurelien Jarno +Bastien Nocera +Bei Zhang +Benjamin Dobell +Brent Rector +Carl Karsten +Christophe Zeitouny +Colin Walters +Dave Camarillo +David Engraf +David Moore +Davidlohr Bueso +Dmitry Fleytman +Doug Johnston +Evan Hunter +Federico Manzan +Felipe Balbi +Florian Albrechtskirchinger +Francesco Montorsi +Francisco Facioni +Gaurav Gupta +Graeme Gill +Gustavo Zacarias +Hans Ulrich Niedermann +Hector Martin +Hoi-Ho Chan +Ilya Konstantinov +Jakub Klama +James Hanko +Jeffrey Nichols +Johann Richard +John Sheu +Jonathon Jongsma +Joost Muller +Josh Gao +Joshua Blake +Justin Bischoff +KIMURA Masaru +Karsten Koenig +Konrad Rzepecki +Kuangye Guo +Lars Kanis +Lars Wirzenius +Lei Chen +Luca Longinotti +Marcus Meissner +Markus Heidelberg +Martin Ettl +Martin Koegler +Matthew Stapleton +Matthias Bolte +Michel Zou +Mike Frysinger +Mikhail Gusarov +Morgan Leborgne +Moritz Fischer +Ларионов Даниил +Nicholas Corgan +Omri Iluz +Orin Eman +Paul Fertser +Pekka Nikander +Rob Walker +Romain Vimont +Roman Kalashnikov +Sameeh Jubran +Sean McBride +Sebastian Pipping +Sergey Serb +Simon Haggett +Simon Newton +Stefan Agner +Stefan Tauner +Steinar H. Gunderson +Thomas Röfer +Tim Hutt +Tim Roberts +Tobias Klauser +Toby Peterson +Tormod Volden +Trygve Laugstøl +Uri Lublin +Vasily Khoruzhick +Vegard Storheil Eriksen +Venkatesh Shukla +Vianney le Clément de Saint-Marcq +Victor Toso +Vitali Lovich +William Skellenger +Xiaofan Chen +Zoltán Kovács +Роман Донченко +parafin diff --git a/vendor/github.com/karalabe/usb/libusb/COPYING b/vendor/github.com/karalabe/usb/libusb/COPYING new file mode 100644 index 0000000000..5ab7695ab8 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/config.h b/vendor/github.com/karalabe/usb/libusb/libusb/config.h new file mode 100644 index 0000000000..e004f03cd4 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/config.h @@ -0,0 +1,3 @@ +#ifndef CONFIG_H +#define CONFIG_H +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/core.c b/vendor/github.com/karalabe/usb/libusb/libusb/core.c new file mode 100644 index 0000000000..50f92f6b1b --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/core.c @@ -0,0 +1,2579 @@ +/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ +/* + * Core functions for libusb + * Copyright © 2012-2013 Nathan Hjelm + * Copyright © 2007-2008 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYSLOG_H +#include +#endif + +#ifdef __ANDROID__ +#include +#endif + +#include "libusbi.h" +#include "hotplug.h" + +struct libusb_context *usbi_default_context = NULL; +static const struct libusb_version libusb_version_internal = + { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, + LIBUSB_RC, "http://libusb.info" }; +static int default_context_refcnt = 0; +static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; +static struct timespec timestamp_origin = { 0, 0 }; + +usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER; +struct list_head active_contexts_list; + +/** + * \mainpage libusb-1.0 API Reference + * + * \section intro Introduction + * + * libusb is an open source library that allows you to communicate with USB + * devices from userspace. For more info, see the + * libusb homepage. + * + * This documentation is aimed at application developers wishing to + * communicate with USB peripherals from their own software. After reviewing + * this documentation, feedback and questions can be sent to the + * libusb-devel mailing list. + * + * This documentation assumes knowledge of how to operate USB devices from + * a software standpoint (descriptors, configurations, interfaces, endpoints, + * control/bulk/interrupt/isochronous transfers, etc). Full information + * can be found in the USB 3.0 + * Specification which is available for free download. You can probably + * find less verbose introductions by searching the web. + * + * \section API Application Programming Interface (API) + * + * See the \ref libusb_api page for a complete list of the libusb functions. + * + * \section features Library features + * + * - All transfer types supported (control/bulk/interrupt/isochronous) + * - 2 transfer interfaces: + * -# Synchronous (simple) + * -# Asynchronous (more complicated, but more powerful) + * - Thread safe (although the asynchronous interface means that you + * usually won't need to thread) + * - Lightweight with lean API + * - Compatible with libusb-0.1 through the libusb-compat-0.1 translation layer + * - Hotplug support (on some platforms). See \ref libusb_hotplug. + * + * \section gettingstarted Getting Started + * + * To begin reading the API documentation, start with the Modules page which + * links to the different categories of libusb's functionality. + * + * One decision you will have to make is whether to use the synchronous + * or the asynchronous data transfer interface. The \ref libusb_io documentation + * provides some insight into this topic. + * + * Some example programs can be found in the libusb source distribution under + * the "examples" subdirectory. The libusb homepage includes a list of + * real-life project examples which use libusb. + * + * \section errorhandling Error handling + * + * libusb functions typically return 0 on success or a negative error code + * on failure. These negative error codes relate to LIBUSB_ERROR constants + * which are listed on the \ref libusb_misc "miscellaneous" documentation page. + * + * \section msglog Debug message logging + * + * libusb uses stderr for all logging. By default, logging is set to NONE, + * which means that no output will be produced. However, unless the library + * has been compiled with logging disabled, then any application calls to + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the + * environmental variable LIBUSB_DEBUG outside of the application, can result + * in logging being produced. Your application should therefore not close + * stderr, but instead direct it to the null device if its output is + * undesirable. + * + * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be + * used to enable logging of certain messages. Under standard configuration, + * libusb doesn't really log much so you are advised to use this function + * to enable all error/warning/ informational messages. It will help debug + * problems with your software. + * + * The logged messages are unstructured. There is no one-to-one correspondence + * between messages being logged and success or failure return codes from + * libusb functions. There is no format to the messages, so you should not + * try to capture or parse them. They are not and will not be localized. + * These messages are not intended to being passed to your application user; + * instead, you should interpret the error codes returned from libusb functions + * and provide appropriate notification to the user. The messages are simply + * there to aid you as a programmer, and if you're confused because you're + * getting a strange error code from a libusb function, enabling message + * logging may give you a suitable explanation. + * + * The LIBUSB_DEBUG environment variable can be used to enable message logging + * at run-time. This environment variable should be set to a log level number, + * which is interpreted the same as the + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this + * environment variable is set, the message logging verbosity level is fixed + * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does + * nothing. + * + * libusb can be compiled without any logging functions, useful for embedded + * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) + * and the LIBUSB_DEBUG environment variable have no effects. + * + * libusb can also be compiled with verbose debugging messages always. When + * the library is compiled in this way, all messages of all verbosities are + * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and + * the LIBUSB_DEBUG environment variable have no effects. + * + * \section remarks Other remarks + * + * libusb does have imperfections. The \ref libusb_caveats "caveats" page attempts + * to document these. + */ + +/** + * \page libusb_caveats Caveats + * + * \section fork Fork considerations + * + * libusb is not designed to work across fork() calls. Depending on + * the platform, there may be resources in the parent process that are not + * available to the child (e.g. the hotplug monitor thread on Linux). In + * addition, since the parent and child will share libusb's internal file + * descriptors, using libusb in any way from the child could cause the parent + * process's \ref libusb_context to get into an inconsistent state. + * + * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means + * that it is safe to fork() and exec() without worrying about the child + * process needing to clean up state or having access to these file descriptors. + * Other platforms may not be so forgiving, so consider yourself warned! + * + * \section devresets Device resets + * + * The libusb_reset_device() function allows you to reset a device. If your + * program has to call such a function, it should obviously be aware that + * the reset will cause device state to change (e.g. register values may be + * reset). + * + * The problem is that any other program could reset the device your program + * is working with, at any time. libusb does not offer a mechanism to inform + * you when this has happened, so if someone else resets your device it will + * not be clear to your own program why the device state has changed. + * + * Ultimately, this is a limitation of writing drivers in userspace. + * Separation from the USB stack in the underlying kernel makes it difficult + * for the operating system to deliver such notifications to your program. + * The Linux kernel USB stack allows such reset notifications to be delivered + * to in-kernel USB drivers, but it is not clear how such notifications could + * be delivered to second-class drivers that live in userspace. + * + * \section blockonly Blocking-only functionality + * + * The functionality listed below is only available through synchronous, + * blocking functions. There are no asynchronous/non-blocking alternatives, + * and no clear ways of implementing these. + * + * - Configuration activation (libusb_set_configuration()) + * - Interface/alternate setting activation (libusb_set_interface_alt_setting()) + * - Releasing of interfaces (libusb_release_interface()) + * - Clearing of halt/stall condition (libusb_clear_halt()) + * - Device resets (libusb_reset_device()) + * + * \section configsel Configuration selection and handling + * + * When libusb presents a device handle to an application, there is a chance + * that the corresponding device may be in unconfigured state. For devices + * with multiple configurations, there is also a chance that the configuration + * currently selected is not the one that the application wants to use. + * + * The obvious solution is to add a call to libusb_set_configuration() early + * on during your device initialization routines, but there are caveats to + * be aware of: + * -# If the device is already in the desired configuration, calling + * libusb_set_configuration() using the same configuration value will cause + * a lightweight device reset. This may not be desirable behaviour. + * -# In the case where the desired configuration is already active, libusb + * may not even be able to perform a lightweight device reset. For example, + * take my USB keyboard with fingerprint reader: I'm interested in driving + * the fingerprint reader interface through libusb, but the kernel's + * USB-HID driver will almost always have claimed the keyboard interface. + * Because the kernel has claimed an interface, it is not even possible to + * perform the lightweight device reset, so libusb_set_configuration() will + * fail. (Luckily the device in question only has a single configuration.) + * -# libusb will be unable to set a configuration if other programs or + * drivers have claimed interfaces. In particular, this means that kernel + * drivers must be detached from all the interfaces before + * libusb_set_configuration() may succeed. + * + * One solution to some of the above problems is to consider the currently + * active configuration. If the configuration we want is already active, then + * we don't have to select any configuration: +\code +cfg = -1; +libusb_get_configuration(dev, &cfg); +if (cfg != desired) + libusb_set_configuration(dev, desired); +\endcode + * + * This is probably suitable for most scenarios, but is inherently racy: + * another application or driver may change the selected configuration + * after the libusb_get_configuration() call. + * + * Even in cases where libusb_set_configuration() succeeds, consider that other + * applications or drivers may change configuration after your application + * calls libusb_set_configuration(). + * + * One possible way to lock your device into a specific configuration is as + * follows: + * -# Set the desired configuration (or use the logic above to realise that + * it is already in the desired configuration) + * -# Claim the interface that you wish to use + * -# Check that the currently active configuration is the one that you want + * to use. + * + * The above method works because once an interface is claimed, no application + * or driver is able to select another configuration. + * + * \section earlycomp Early transfer completion + * + * NOTE: This section is currently Linux-centric. I am not sure if any of these + * considerations apply to Darwin or other platforms. + * + * When a transfer completes early (i.e. when less data is received/sent in + * any one packet than the transfer buffer allows for) then libusb is designed + * to terminate the transfer immediately, not transferring or receiving any + * more data unless other transfers have been queued by the user. + * + * On legacy platforms, libusb is unable to do this in all situations. After + * the incomplete packet occurs, "surplus" data may be transferred. For recent + * versions of libusb, this information is kept (the data length of the + * transfer is updated) and, for device-to-host transfers, any surplus data was + * added to the buffer. Still, this is not a nice solution because it loses the + * information about the end of the short packet, and the user probably wanted + * that surplus data to arrive in the next logical transfer. + * + * \section zlp Zero length packets + * + * - libusb is able to send a packet of zero length to an endpoint simply by + * submitting a transfer of zero length. + * - The \ref libusb_transfer_flags::LIBUSB_TRANSFER_ADD_ZERO_PACKET + * "LIBUSB_TRANSFER_ADD_ZERO_PACKET" flag is currently only supported on Linux. + */ + +/** + * \page libusb_contexts Contexts + * + * It is possible that libusb may be used simultaneously from two independent + * libraries linked into the same executable. For example, if your application + * has a plugin-like system which allows the user to dynamically load a range + * of modules into your program, it is feasible that two independently + * developed modules may both use libusb. + * + * libusb is written to allow for these multiple user scenarios. The two + * "instances" of libusb will not interfere: libusb_set_option() calls + * from one user will not affect the same settings for other users, other + * users can continue using libusb after one of them calls libusb_exit(), etc. + * + * This is made possible through libusb's context concept. When you + * call libusb_init(), you are (optionally) given a context. You can then pass + * this context pointer back into future libusb functions. + * + * In order to keep things simple for more simplistic applications, it is + * legal to pass NULL to all functions requiring a context pointer (as long as + * you're sure no other code will attempt to use libusb from the same process). + * When you pass NULL, the default context will be used. The default context + * is created the first time a process calls libusb_init() when no other + * context is alive. Contexts are destroyed during libusb_exit(). + * + * The default context is reference-counted and can be shared. That means that + * if libusb_init(NULL) is called twice within the same process, the two + * users end up sharing the same context. The deinitialization and freeing of + * the default context will only happen when the last user calls libusb_exit(). + * In other words, the default context is created and initialized when its + * reference count goes from 0 to 1, and is deinitialized and destroyed when + * its reference count goes from 1 to 0. + * + * You may be wondering why only a subset of libusb functions require a + * context pointer in their function definition. Internally, libusb stores + * context pointers in other objects (e.g. libusb_device instances) and hence + * can infer the context from those objects. + */ + + /** + * \page libusb_api Application Programming Interface + * + * This is the complete list of libusb functions, structures and + * enumerations in alphabetical order. + * + * \section Functions + * - libusb_alloc_streams() + * - libusb_alloc_transfer() + * - libusb_attach_kernel_driver() + * - libusb_bulk_transfer() + * - libusb_cancel_transfer() + * - libusb_claim_interface() + * - libusb_clear_halt() + * - libusb_close() + * - libusb_control_transfer() + * - libusb_control_transfer_get_data() + * - libusb_control_transfer_get_setup() + * - libusb_cpu_to_le16() + * - libusb_detach_kernel_driver() + * - libusb_dev_mem_alloc() + * - libusb_dev_mem_free() + * - libusb_error_name() + * - libusb_event_handler_active() + * - libusb_event_handling_ok() + * - libusb_exit() + * - libusb_fill_bulk_stream_transfer() + * - libusb_fill_bulk_transfer() + * - libusb_fill_control_setup() + * - libusb_fill_control_transfer() + * - libusb_fill_interrupt_transfer() + * - libusb_fill_iso_transfer() + * - libusb_free_bos_descriptor() + * - libusb_free_config_descriptor() + * - libusb_free_container_id_descriptor() + * - libusb_free_device_list() + * - libusb_free_pollfds() + * - libusb_free_ss_endpoint_companion_descriptor() + * - libusb_free_ss_usb_device_capability_descriptor() + * - libusb_free_streams() + * - libusb_free_transfer() + * - libusb_free_usb_2_0_extension_descriptor() + * - libusb_get_active_config_descriptor() + * - libusb_get_bos_descriptor() + * - libusb_get_bus_number() + * - libusb_get_config_descriptor() + * - libusb_get_config_descriptor_by_value() + * - libusb_get_configuration() + * - libusb_get_container_id_descriptor() + * - libusb_get_descriptor() + * - libusb_get_device() + * - libusb_get_device_address() + * - libusb_get_device_descriptor() + * - libusb_get_device_list() + * - libusb_get_device_speed() + * - libusb_get_iso_packet_buffer() + * - libusb_get_iso_packet_buffer_simple() + * - libusb_get_max_iso_packet_size() + * - libusb_get_max_packet_size() + * - libusb_get_next_timeout() + * - libusb_get_parent() + * - libusb_get_pollfds() + * - libusb_get_port_number() + * - libusb_get_port_numbers() + * - libusb_get_port_path() + * - libusb_get_ss_endpoint_companion_descriptor() + * - libusb_get_ss_usb_device_capability_descriptor() + * - libusb_get_string_descriptor() + * - libusb_get_string_descriptor_ascii() + * - libusb_get_usb_2_0_extension_descriptor() + * - libusb_get_version() + * - libusb_handle_events() + * - libusb_handle_events_completed() + * - libusb_handle_events_locked() + * - libusb_handle_events_timeout() + * - libusb_handle_events_timeout_completed() + * - libusb_has_capability() + * - libusb_hotplug_deregister_callback() + * - libusb_hotplug_register_callback() + * - libusb_init() + * - libusb_interrupt_event_handler() + * - libusb_interrupt_transfer() + * - libusb_kernel_driver_active() + * - libusb_lock_events() + * - libusb_lock_event_waiters() + * - libusb_open() + * - libusb_open_device_with_vid_pid() + * - libusb_pollfds_handle_timeouts() + * - libusb_ref_device() + * - libusb_release_interface() + * - libusb_reset_device() + * - libusb_set_auto_detach_kernel_driver() + * - libusb_set_configuration() + * - libusb_set_debug() + * - libusb_set_interface_alt_setting() + * - libusb_set_iso_packet_lengths() + * - libusb_set_option() + * - libusb_setlocale() + * - libusb_set_pollfd_notifiers() + * - libusb_strerror() + * - libusb_submit_transfer() + * - libusb_transfer_get_stream_id() + * - libusb_transfer_set_stream_id() + * - libusb_try_lock_events() + * - libusb_unlock_events() + * - libusb_unlock_event_waiters() + * - libusb_unref_device() + * - libusb_wait_for_event() + * + * \section Structures + * - libusb_bos_descriptor + * - libusb_bos_dev_capability_descriptor + * - libusb_config_descriptor + * - libusb_container_id_descriptor + * - \ref libusb_context + * - libusb_control_setup + * - \ref libusb_device + * - libusb_device_descriptor + * - \ref libusb_device_handle + * - libusb_endpoint_descriptor + * - libusb_interface + * - libusb_interface_descriptor + * - libusb_iso_packet_descriptor + * - libusb_pollfd + * - libusb_ss_endpoint_companion_descriptor + * - libusb_ss_usb_device_capability_descriptor + * - libusb_transfer + * - libusb_usb_2_0_extension_descriptor + * - libusb_version + * + * \section Enums + * - \ref libusb_bos_type + * - \ref libusb_capability + * - \ref libusb_class_code + * - \ref libusb_descriptor_type + * - \ref libusb_endpoint_direction + * - \ref libusb_error + * - \ref libusb_iso_sync_type + * - \ref libusb_iso_usage_type + * - \ref libusb_log_level + * - \ref libusb_option + * - \ref libusb_request_recipient + * - \ref libusb_request_type + * - \ref libusb_speed + * - \ref libusb_ss_usb_device_capability_attributes + * - \ref libusb_standard_request + * - \ref libusb_supported_speed + * - \ref libusb_transfer_flags + * - \ref libusb_transfer_status + * - \ref libusb_transfer_type + * - \ref libusb_usb_2_0_extension_attributes + */ + +/** + * @defgroup libusb_lib Library initialization/deinitialization + * This page details how to initialize and deinitialize libusb. Initialization + * must be performed before using any libusb functionality, and similarly you + * must not call any libusb functions after deinitialization. + */ + +/** + * @defgroup libusb_dev Device handling and enumeration + * The functionality documented below is designed to help with the following + * operations: + * - Enumerating the USB devices currently attached to the system + * - Choosing a device to operate from your software + * - Opening and closing the chosen device + * + * \section nutshell In a nutshell... + * + * The description below really makes things sound more complicated than they + * actually are. The following sequence of function calls will be suitable + * for almost all scenarios and does not require you to have such a deep + * understanding of the resource management issues: + * \code +// discover devices +libusb_device **list; +libusb_device *found = NULL; +ssize_t cnt = libusb_get_device_list(NULL, &list); +ssize_t i = 0; +int err = 0; +if (cnt < 0) + error(); + +for (i = 0; i < cnt; i++) { + libusb_device *device = list[i]; + if (is_interesting(device)) { + found = device; + break; + } +} + +if (found) { + libusb_device_handle *handle; + + err = libusb_open(found, &handle); + if (err) + error(); + // etc +} + +libusb_free_device_list(list, 1); +\endcode + * + * The two important points: + * - You asked libusb_free_device_list() to unreference the devices (2nd + * parameter) + * - You opened the device before freeing the list and unreferencing the + * devices + * + * If you ended up with a handle, you can now proceed to perform I/O on the + * device. + * + * \section devshandles Devices and device handles + * libusb has a concept of a USB device, represented by the + * \ref libusb_device opaque type. A device represents a USB device that + * is currently or was previously connected to the system. Using a reference + * to a device, you can determine certain information about the device (e.g. + * you can read the descriptor data). + * + * The libusb_get_device_list() function can be used to obtain a list of + * devices currently connected to the system. This is known as device + * discovery. + * + * Just because you have a reference to a device does not mean it is + * necessarily usable. The device may have been unplugged, you may not have + * permission to operate such device, or another program or driver may be + * using the device. + * + * When you've found a device that you'd like to operate, you must ask + * libusb to open the device using the libusb_open() function. Assuming + * success, libusb then returns you a device handle + * (a \ref libusb_device_handle pointer). All "real" I/O operations then + * operate on the handle rather than the original device pointer. + * + * \section devref Device discovery and reference counting + * + * Device discovery (i.e. calling libusb_get_device_list()) returns a + * freshly-allocated list of devices. The list itself must be freed when + * you are done with it. libusb also needs to know when it is OK to free + * the contents of the list - the devices themselves. + * + * To handle these issues, libusb provides you with two separate items: + * - A function to free the list itself + * - A reference counting system for the devices inside + * + * New devices presented by the libusb_get_device_list() function all have a + * reference count of 1. You can increase and decrease reference count using + * libusb_ref_device() and libusb_unref_device(). A device is destroyed when + * its reference count reaches 0. + * + * With the above information in mind, the process of opening a device can + * be viewed as follows: + * -# Discover devices using libusb_get_device_list(). + * -# Choose the device that you want to operate, and call libusb_open(). + * -# Unref all devices in the discovered device list. + * -# Free the discovered device list. + * + * The order is important - you must not unreference the device before + * attempting to open it, because unreferencing it may destroy the device. + * + * For convenience, the libusb_free_device_list() function includes a + * parameter to optionally unreference all the devices in the list before + * freeing the list itself. This combines steps 3 and 4 above. + * + * As an implementation detail, libusb_open() actually adds a reference to + * the device in question. This is because the device remains available + * through the handle via libusb_get_device(). The reference is deleted during + * libusb_close(). + */ + +/** @defgroup libusb_misc Miscellaneous */ + +/* we traverse usbfs without knowing how many devices we are going to find. + * so we create this discovered_devs model which is similar to a linked-list + * which grows when required. it can be freed once discovery has completed, + * eliminating the need for a list node in the libusb_device structure + * itself. */ +#define DISCOVERED_DEVICES_SIZE_STEP 8 + +static struct discovered_devs *discovered_devs_alloc(void) +{ + struct discovered_devs *ret = + malloc(sizeof(*ret) + (sizeof(void *) * DISCOVERED_DEVICES_SIZE_STEP)); + + if (ret) { + ret->len = 0; + ret->capacity = DISCOVERED_DEVICES_SIZE_STEP; + } + return ret; +} + +static void discovered_devs_free(struct discovered_devs *discdevs) +{ + size_t i; + + for (i = 0; i < discdevs->len; i++) + libusb_unref_device(discdevs->devices[i]); + + free(discdevs); +} + +/* append a device to the discovered devices collection. may realloc itself, + * returning new discdevs. returns NULL on realloc failure. */ +struct discovered_devs *discovered_devs_append( + struct discovered_devs *discdevs, struct libusb_device *dev) +{ + size_t len = discdevs->len; + size_t capacity; + struct discovered_devs *new_discdevs; + + /* if there is space, just append the device */ + if (len < discdevs->capacity) { + discdevs->devices[len] = libusb_ref_device(dev); + discdevs->len++; + return discdevs; + } + + /* exceeded capacity, need to grow */ + usbi_dbg("need to increase capacity"); + capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP; + /* can't use usbi_reallocf here because in failure cases it would + * free the existing discdevs without unreferencing its devices. */ + new_discdevs = realloc(discdevs, + sizeof(*discdevs) + (sizeof(void *) * capacity)); + if (!new_discdevs) { + discovered_devs_free(discdevs); + return NULL; + } + + discdevs = new_discdevs; + discdevs->capacity = capacity; + discdevs->devices[len] = libusb_ref_device(dev); + discdevs->len++; + + return discdevs; +} + +/* Allocate a new device with a specific session ID. The returned device has + * a reference count of 1. */ +struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, + unsigned long session_id) +{ + size_t priv_size = usbi_backend.device_priv_size; + struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size); + int r; + + if (!dev) + return NULL; + + r = usbi_mutex_init(&dev->lock); + if (r) { + free(dev); + return NULL; + } + + dev->ctx = ctx; + dev->refcnt = 1; + dev->session_data = session_id; + dev->speed = LIBUSB_SPEED_UNKNOWN; + + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + usbi_connect_device (dev); + } + + return dev; +} + +void usbi_connect_device(struct libusb_device *dev) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + + dev->attached = 1; + + usbi_mutex_lock(&dev->ctx->usb_devs_lock); + list_add(&dev->list, &dev->ctx->usb_devs); + usbi_mutex_unlock(&dev->ctx->usb_devs_lock); + + /* Signal that an event has occurred for this device if we support hotplug AND + * the hotplug message list is ready. This prevents an event from getting raised + * during initial enumeration. */ + if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { + usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED); + } +} + +void usbi_disconnect_device(struct libusb_device *dev) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + + usbi_mutex_lock(&dev->lock); + dev->attached = 0; + usbi_mutex_unlock(&dev->lock); + + usbi_mutex_lock(&ctx->usb_devs_lock); + list_del(&dev->list); + usbi_mutex_unlock(&ctx->usb_devs_lock); + + /* Signal that an event has occurred for this device if we support hotplug AND + * the hotplug message list is ready. This prevents an event from getting raised + * during initial enumeration. libusb_handle_events will take care of dereferencing + * the device. */ + if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { + usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT); + } +} + +/* Perform some final sanity checks on a newly discovered device. If this + * function fails (negative return code), the device should not be added + * to the discovered device list. */ +int usbi_sanitize_device(struct libusb_device *dev) +{ + int r; + uint8_t num_configurations; + + r = usbi_device_cache_descriptor(dev); + if (r < 0) + return r; + + num_configurations = dev->device_descriptor.bNumConfigurations; + if (num_configurations > USB_MAXCONFIG) { + usbi_err(DEVICE_CTX(dev), "too many configurations"); + return LIBUSB_ERROR_IO; + } else if (0 == num_configurations) + usbi_dbg("zero configurations, maybe an unauthorized device"); + + dev->num_configurations = num_configurations; + return 0; +} + +/* Examine libusb's internal list of known devices, looking for one with + * a specific session ID. Returns the matching device if it was found, and + * NULL otherwise. */ +struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, + unsigned long session_id) +{ + struct libusb_device *dev; + struct libusb_device *ret = NULL; + + usbi_mutex_lock(&ctx->usb_devs_lock); + list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) + if (dev->session_data == session_id) { + ret = libusb_ref_device(dev); + break; + } + usbi_mutex_unlock(&ctx->usb_devs_lock); + + return ret; +} + +/** @ingroup libusb_dev + * Returns a list of USB devices currently attached to the system. This is + * your entry point into finding a USB device to operate. + * + * You are expected to unreference all the devices when you are done with + * them, and then free the list with libusb_free_device_list(). Note that + * libusb_free_device_list() can unref all the devices for you. Be careful + * not to unreference a device you are about to open until after you have + * opened it. + * + * This return value of this function indicates the number of devices in + * the resultant list. The list is actually one element larger, as it is + * NULL-terminated. + * + * \param ctx the context to operate on, or NULL for the default context + * \param list output location for a list of devices. Must be later freed with + * libusb_free_device_list(). + * \returns the number of devices in the outputted list, or any + * \ref libusb_error according to errors encountered by the backend. + */ +ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, + libusb_device ***list) +{ + struct discovered_devs *discdevs = discovered_devs_alloc(); + struct libusb_device **ret; + int r = 0; + ssize_t i, len; + USBI_GET_CONTEXT(ctx); + usbi_dbg(""); + + if (!discdevs) + return LIBUSB_ERROR_NO_MEM; + + if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + /* backend provides hotplug support */ + struct libusb_device *dev; + + if (usbi_backend.hotplug_poll) + usbi_backend.hotplug_poll(); + + usbi_mutex_lock(&ctx->usb_devs_lock); + list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { + discdevs = discovered_devs_append(discdevs, dev); + + if (!discdevs) { + r = LIBUSB_ERROR_NO_MEM; + break; + } + } + usbi_mutex_unlock(&ctx->usb_devs_lock); + } else { + /* backend does not provide hotplug support */ + r = usbi_backend.get_device_list(ctx, &discdevs); + } + + if (r < 0) { + len = r; + goto out; + } + + /* convert discovered_devs into a list */ + len = discdevs->len; + ret = calloc(len + 1, sizeof(struct libusb_device *)); + if (!ret) { + len = LIBUSB_ERROR_NO_MEM; + goto out; + } + + ret[len] = NULL; + for (i = 0; i < len; i++) { + struct libusb_device *dev = discdevs->devices[i]; + ret[i] = libusb_ref_device(dev); + } + *list = ret; + +out: + if (discdevs) + discovered_devs_free(discdevs); + return len; +} + +/** \ingroup libusb_dev + * Frees a list of devices previously discovered using + * libusb_get_device_list(). If the unref_devices parameter is set, the + * reference count of each device in the list is decremented by 1. + * \param list the list to free + * \param unref_devices whether to unref the devices in the list + */ +void API_EXPORTED libusb_free_device_list(libusb_device **list, + int unref_devices) +{ + if (!list) + return; + + if (unref_devices) { + int i = 0; + struct libusb_device *dev; + + while ((dev = list[i++]) != NULL) + libusb_unref_device(dev); + } + free(list); +} + +/** \ingroup libusb_dev + * Get the number of the bus that a device is connected to. + * \param dev a device + * \returns the bus number + */ +uint8_t API_EXPORTED libusb_get_bus_number(libusb_device *dev) +{ + return dev->bus_number; +} + +/** \ingroup libusb_dev + * Get the number of the port that a device is connected to. + * Unless the OS does something funky, or you are hot-plugging USB extension cards, + * the port number returned by this call is usually guaranteed to be uniquely tied + * to a physical port, meaning that different devices plugged on the same physical + * port should return the same port number. + * + * But outside of this, there is no guarantee that the port number returned by this + * call will remain the same, or even match the order in which ports have been + * numbered by the HUB/HCD manufacturer. + * + * \param dev a device + * \returns the port number (0 if not available) + */ +uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) +{ + return dev->port_number; +} + +/** \ingroup libusb_dev + * Get the list of all port numbers from root for the specified device + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * \param dev a device + * \param port_numbers the array that should contain the port numbers + * \param port_numbers_len the maximum length of the array. As per the USB 3.0 + * specs, the current maximum limit for the depth is 7. + * \returns the number of elements filled + * \returns LIBUSB_ERROR_OVERFLOW if the array is too small + */ +int API_EXPORTED libusb_get_port_numbers(libusb_device *dev, + uint8_t* port_numbers, int port_numbers_len) +{ + int i = port_numbers_len; + struct libusb_context *ctx = DEVICE_CTX(dev); + + if (port_numbers_len <= 0) + return LIBUSB_ERROR_INVALID_PARAM; + + // HCDs can be listed as devices with port #0 + while((dev) && (dev->port_number != 0)) { + if (--i < 0) { + usbi_warn(ctx, "port numbers array is too small"); + return LIBUSB_ERROR_OVERFLOW; + } + port_numbers[i] = dev->port_number; + dev = dev->parent_dev; + } + if (i < port_numbers_len) + memmove(port_numbers, &port_numbers[i], port_numbers_len - i); + return port_numbers_len - i; +} + +/** \ingroup libusb_dev + * Deprecated please use libusb_get_port_numbers instead. + */ +int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, + uint8_t* port_numbers, uint8_t port_numbers_len) +{ + UNUSED(ctx); + + return libusb_get_port_numbers(dev, port_numbers, port_numbers_len); +} + +/** \ingroup libusb_dev + * Get the the parent from the specified device. + * \param dev a device + * \returns the device parent or NULL if not available + * You should issue a \ref libusb_get_device_list() before calling this + * function and make sure that you only access the parent before issuing + * \ref libusb_free_device_list(). The reason is that libusb currently does + * not maintain a permanent list of device instances, and therefore can + * only guarantee that parents are fully instantiated within a + * libusb_get_device_list() - libusb_free_device_list() block. + */ +DEFAULT_VISIBILITY +libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev) +{ + return dev->parent_dev; +} + +/** \ingroup libusb_dev + * Get the address of the device on the bus it is connected to. + * \param dev a device + * \returns the device address + */ +uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev) +{ + return dev->device_address; +} + +/** \ingroup libusb_dev + * Get the negotiated connection speed for a device. + * \param dev a device + * \returns a \ref libusb_speed code, where LIBUSB_SPEED_UNKNOWN means that + * the OS doesn't know or doesn't support returning the negotiated speed. + */ +int API_EXPORTED libusb_get_device_speed(libusb_device *dev) +{ + return dev->speed; +} + +static const struct libusb_endpoint_descriptor *find_endpoint( + struct libusb_config_descriptor *config, unsigned char endpoint) +{ + int iface_idx; + for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { + const struct libusb_interface *iface = &config->interface[iface_idx]; + int altsetting_idx; + + for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; + altsetting_idx++) { + const struct libusb_interface_descriptor *altsetting + = &iface->altsetting[altsetting_idx]; + int ep_idx; + + for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) { + const struct libusb_endpoint_descriptor *ep = + &altsetting->endpoint[ep_idx]; + if (ep->bEndpointAddress == endpoint) + return ep; + } + } + } + return NULL; +} + +/** \ingroup libusb_dev + * Convenience function to retrieve the wMaxPacketSize value for a particular + * endpoint in the active device configuration. + * + * This function was originally intended to be of assistance when setting up + * isochronous transfers, but a design mistake resulted in this function + * instead. It simply returns the wMaxPacketSize value without considering + * its contents. If you're dealing with isochronous transfers, you probably + * want libusb_get_max_iso_packet_size() instead. + * + * \param dev a device + * \param endpoint address of the endpoint in question + * \returns the wMaxPacketSize value + * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns LIBUSB_ERROR_OTHER on other failure + */ +int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, + unsigned char endpoint) +{ + struct libusb_config_descriptor *config; + const struct libusb_endpoint_descriptor *ep; + int r; + + r = libusb_get_active_config_descriptor(dev, &config); + if (r < 0) { + usbi_err(DEVICE_CTX(dev), + "could not retrieve active config descriptor"); + return LIBUSB_ERROR_OTHER; + } + + ep = find_endpoint(config, endpoint); + if (!ep) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + + r = ep->wMaxPacketSize; + +out: + libusb_free_config_descriptor(config); + return r; +} + +/** \ingroup libusb_dev + * Calculate the maximum packet size which a specific endpoint is capable is + * sending or receiving in the duration of 1 microframe + * + * Only the active configuration is examined. The calculation is based on the + * wMaxPacketSize field in the endpoint descriptor as described in section + * 9.6.6 in the USB 2.0 specifications. + * + * If acting on an isochronous or interrupt endpoint, this function will + * multiply the value found in bits 0:10 by the number of transactions per + * microframe (determined by bits 11:12). Otherwise, this function just + * returns the numeric value found in bits 0:10. + * + * This function is useful for setting up isochronous transfers, for example + * you might pass the return value from this function to + * libusb_set_iso_packet_lengths() in order to set the length field of every + * isochronous packet in a transfer. + * + * Since v1.0.3. + * + * \param dev a device + * \param endpoint address of the endpoint in question + * \returns the maximum packet size which can be sent/received on this endpoint + * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns LIBUSB_ERROR_OTHER on other failure + */ +int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, + unsigned char endpoint) +{ + struct libusb_config_descriptor *config; + const struct libusb_endpoint_descriptor *ep; + enum libusb_transfer_type ep_type; + uint16_t val; + int r; + + r = libusb_get_active_config_descriptor(dev, &config); + if (r < 0) { + usbi_err(DEVICE_CTX(dev), + "could not retrieve active config descriptor"); + return LIBUSB_ERROR_OTHER; + } + + ep = find_endpoint(config, endpoint); + if (!ep) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + + val = ep->wMaxPacketSize; + ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3); + + r = val & 0x07ff; + if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS + || ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) + r *= (1 + ((val >> 11) & 3)); + +out: + libusb_free_config_descriptor(config); + return r; +} + +/** \ingroup libusb_dev + * Increment the reference count of a device. + * \param dev the device to reference + * \returns the same device + */ +DEFAULT_VISIBILITY +libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev) +{ + usbi_mutex_lock(&dev->lock); + dev->refcnt++; + usbi_mutex_unlock(&dev->lock); + return dev; +} + +/** \ingroup libusb_dev + * Decrement the reference count of a device. If the decrement operation + * causes the reference count to reach zero, the device shall be destroyed. + * \param dev the device to unreference + */ +void API_EXPORTED libusb_unref_device(libusb_device *dev) +{ + int refcnt; + + if (!dev) + return; + + usbi_mutex_lock(&dev->lock); + refcnt = --dev->refcnt; + usbi_mutex_unlock(&dev->lock); + + if (refcnt == 0) { + usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address); + + libusb_unref_device(dev->parent_dev); + + if (usbi_backend.destroy_device) + usbi_backend.destroy_device(dev); + + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + /* backend does not support hotplug */ + usbi_disconnect_device(dev); + } + + usbi_mutex_destroy(&dev->lock); + free(dev); + } +} + +/* + * Signal the event pipe so that the event handling thread will be + * interrupted to process an internal event. + */ +int usbi_signal_event(struct libusb_context *ctx) +{ + unsigned char dummy = 1; + ssize_t r; + + /* write some data on event pipe to interrupt event handlers */ + r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy)); + if (r != sizeof(dummy)) { + usbi_warn(ctx, "internal signalling write failed"); + return LIBUSB_ERROR_IO; + } + + return 0; +} + +/* + * Clear the event pipe so that the event handling will no longer be + * interrupted. + */ +int usbi_clear_event(struct libusb_context *ctx) +{ + unsigned char dummy; + ssize_t r; + + /* read some data on event pipe to clear it */ + r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); + if (r != sizeof(dummy)) { + usbi_warn(ctx, "internal signalling read failed"); + return LIBUSB_ERROR_IO; + } + + return 0; +} + +/** \ingroup libusb_dev + * Open a device and obtain a device handle. A handle allows you to perform + * I/O on the device in question. + * + * Internally, this function adds a reference to the device and makes it + * available to you through libusb_get_device(). This reference is removed + * during libusb_close(). + * + * This is a non-blocking function; no requests are sent over the bus. + * + * \param dev the device to open + * \param dev_handle output location for the returned device handle pointer. Only + * populated when the return code is 0. + * \returns 0 on success + * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure + * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_open(libusb_device *dev, + libusb_device_handle **dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + struct libusb_device_handle *_dev_handle; + size_t priv_size = usbi_backend.device_handle_priv_size; + int r; + usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); + + if (!dev->attached) { + return LIBUSB_ERROR_NO_DEVICE; + } + + _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); + if (!_dev_handle) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_mutex_init(&_dev_handle->lock); + if (r) { + free(_dev_handle); + return LIBUSB_ERROR_OTHER; + } + + _dev_handle->dev = libusb_ref_device(dev); + _dev_handle->auto_detach_kernel_driver = 0; + _dev_handle->claimed_interfaces = 0; + memset(&_dev_handle->os_priv, 0, priv_size); + + r = usbi_backend.open(_dev_handle); + if (r < 0) { + usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); + libusb_unref_device(dev); + usbi_mutex_destroy(&_dev_handle->lock); + free(_dev_handle); + return r; + } + + usbi_mutex_lock(&ctx->open_devs_lock); + list_add(&_dev_handle->list, &ctx->open_devs); + usbi_mutex_unlock(&ctx->open_devs_lock); + *dev_handle = _dev_handle; + + return 0; +} + +/** \ingroup libusb_dev + * Convenience function for finding a device with a particular + * idVendor/idProduct combination. This function is intended + * for those scenarios where you are using libusb to knock up a quick test + * application - it allows you to avoid calling libusb_get_device_list() and + * worrying about traversing/freeing the list. + * + * This function has limitations and is hence not intended for use in real + * applications: if multiple devices have the same IDs it will only + * give you the first one, etc. + * + * \param ctx the context to operate on, or NULL for the default context + * \param vendor_id the idVendor value to search for + * \param product_id the idProduct value to search for + * \returns a device handle for the first found device, or NULL on error + * or if the device could not be found. */ +DEFAULT_VISIBILITY +libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) +{ + struct libusb_device **devs; + struct libusb_device *found = NULL; + struct libusb_device *dev; + struct libusb_device_handle *dev_handle = NULL; + size_t i = 0; + int r; + + if (libusb_get_device_list(ctx, &devs) < 0) + return NULL; + + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) + goto out; + if (desc.idVendor == vendor_id && desc.idProduct == product_id) { + found = dev; + break; + } + } + + if (found) { + r = libusb_open(found, &dev_handle); + if (r < 0) + dev_handle = NULL; + } + +out: + libusb_free_device_list(devs, 1); + return dev_handle; +} + +static void do_close(struct libusb_context *ctx, + struct libusb_device_handle *dev_handle) +{ + struct usbi_transfer *itransfer; + struct usbi_transfer *tmp; + + /* remove any transfers in flight that are for this device */ + usbi_mutex_lock(&ctx->flying_transfers_lock); + + /* safe iteration because transfers may be being deleted */ + list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) { + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + if (transfer->dev_handle != dev_handle) + continue; + + usbi_mutex_lock(&itransfer->lock); + if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { + usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); + + if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) + usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); + else + usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); + } + usbi_mutex_unlock(&itransfer->lock); + + /* remove from the list of in-flight transfers and make sure + * we don't accidentally use the device handle in the future + * (or that such accesses will be easily caught and identified as a crash) + */ + list_del(&itransfer->list); + transfer->dev_handle = NULL; + + /* it is up to the user to free up the actual transfer struct. this is + * just making sure that we don't attempt to process the transfer after + * the device handle is invalid + */ + usbi_dbg("Removed transfer %p from the in-flight list because device handle %p closed", + transfer, dev_handle); + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + usbi_mutex_lock(&ctx->open_devs_lock); + list_del(&dev_handle->list); + usbi_mutex_unlock(&ctx->open_devs_lock); + + usbi_backend.close(dev_handle); + libusb_unref_device(dev_handle->dev); + usbi_mutex_destroy(&dev_handle->lock); + free(dev_handle); +} + +/** \ingroup libusb_dev + * Close a device handle. Should be called on all open handles before your + * application exits. + * + * Internally, this function destroys the reference that was added by + * libusb_open() on the given device. + * + * This is a non-blocking function; no requests are sent over the bus. + * + * \param dev_handle the device handle to close + */ +void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx; + int handling_events; + int pending_events; + + if (!dev_handle) + return; + usbi_dbg(""); + + ctx = HANDLE_CTX(dev_handle); + handling_events = usbi_handling_events(ctx); + + /* Similarly to libusb_open(), we want to interrupt all event handlers + * at this point. More importantly, we want to perform the actual close of + * the device while holding the event handling lock (preventing any other + * thread from doing event handling) because we will be removing a file + * descriptor from the polling loop. If this is being called by the current + * event handler, we can bypass the interruption code because we already + * hold the event handling lock. */ + + if (!handling_events) { + /* Record that we are closing a device. + * Only signal an event if there are no prior pending events. */ + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + ctx->device_close++; + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + /* take event handling lock */ + libusb_lock_events(ctx); + } + + /* Close the device */ + do_close(ctx, dev_handle); + + if (!handling_events) { + /* We're done with closing this device. + * Clear the event pipe if there are no further pending events. */ + usbi_mutex_lock(&ctx->event_data_lock); + ctx->device_close--; + pending_events = usbi_pending_events(ctx); + if (!pending_events) + usbi_clear_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + /* Release event handling lock and wake up event waiters */ + libusb_unlock_events(ctx); + } +} + +/** \ingroup libusb_dev + * Get the underlying device for a device handle. This function does not modify + * the reference count of the returned device, so do not feel compelled to + * unreference it when you are done. + * \param dev_handle a device handle + * \returns the underlying device + */ +DEFAULT_VISIBILITY +libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) +{ + return dev_handle->dev; +} + +/** \ingroup libusb_dev + * Determine the bConfigurationValue of the currently active configuration. + * + * You could formulate your own control request to obtain this information, + * but this function has the advantage that it may be able to retrieve the + * information from operating system caches (no I/O involved). + * + * If the OS does not cache this information, then this function will block + * while a control transfer is submitted to retrieve the information. + * + * This function will return a value of 0 in the config output + * parameter if the device is in unconfigured state. + * + * \param dev_handle a device handle + * \param config output location for the bConfigurationValue of the active + * configuration (only valid for return code 0) + * \returns 0 on success + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, + int *config) +{ + int r = LIBUSB_ERROR_NOT_SUPPORTED; + + usbi_dbg(""); + if (usbi_backend.get_configuration) + r = usbi_backend.get_configuration(dev_handle, config); + + if (r == LIBUSB_ERROR_NOT_SUPPORTED) { + uint8_t tmp = 0; + usbi_dbg("falling back to control message"); + r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000); + if (r == 0) { + usbi_err(HANDLE_CTX(dev_handle), "zero bytes returned in ctrl transfer?"); + r = LIBUSB_ERROR_IO; + } else if (r == 1) { + r = 0; + *config = tmp; + } else { + usbi_dbg("control failed, error %d", r); + } + } + + if (r == 0) + usbi_dbg("active config %d", *config); + + return r; +} + +/** \ingroup libusb_dev + * Set the active configuration for a device. + * + * The operating system may or may not have already set an active + * configuration on the device. It is up to your application to ensure the + * correct configuration is selected before you attempt to claim interfaces + * and perform other operations. + * + * If you call this function on a device already configured with the selected + * configuration, then this function will act as a lightweight device reset: + * it will issue a SET_CONFIGURATION request using the current configuration, + * causing most USB-related device state to be reset (altsetting reset to zero, + * endpoint halts cleared, toggles reset). + * + * You cannot change/reset configuration if your application has claimed + * interfaces. It is advised to set the desired configuration before claiming + * interfaces. + * + * Alternatively you can call libusb_release_interface() first. Note if you + * do things this way you must ensure that auto_detach_kernel_driver for + * dev is 0, otherwise the kernel driver will be re-attached when you + * release the interface(s). + * + * You cannot change/reset configuration if other applications or drivers have + * claimed interfaces. + * + * A configuration value of -1 will put the device in unconfigured state. + * The USB specifications state that a configuration value of 0 does this, + * however buggy devices exist which actually have a configuration 0. + * + * You should always use this function rather than formulating your own + * SET_CONFIGURATION control request. This is because the underlying operating + * system needs to know when such changes happen. + * + * This is a blocking function. + * + * \param dev_handle a device handle + * \param configuration the bConfigurationValue of the configuration you + * wish to activate, or -1 if you wish to put the device in an unconfigured + * state + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist + * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + * \see libusb_set_auto_detach_kernel_driver() + */ +int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, + int configuration) +{ + usbi_dbg("configuration %d", configuration); + return usbi_backend.set_configuration(dev_handle, configuration); +} + +/** \ingroup libusb_dev + * Claim an interface on a given device handle. You must claim the interface + * you wish to use before you can perform I/O on any of its endpoints. + * + * It is legal to attempt to claim an already-claimed interface, in which + * case libusb just returns 0 without doing anything. + * + * If auto_detach_kernel_driver is set to 1 for dev, the kernel driver + * will be detached if necessary, on failure the detach error is returned. + * + * Claiming of interfaces is a purely logical operation; it does not cause + * any requests to be sent over the bus. Interface claiming is used to + * instruct the underlying operating system that your application wishes + * to take ownership of the interface. + * + * This is a non-blocking function. + * + * \param dev_handle a device handle + * \param interface_number the bInterfaceNumber of the interface you + * wish to claim + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist + * \returns LIBUSB_ERROR_BUSY if another program or driver has claimed the + * interface + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns a LIBUSB_ERROR code on other failure + * \see libusb_set_auto_detach_kernel_driver() + */ +int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, + int interface_number) +{ + int r = 0; + + usbi_dbg("interface %d", interface_number); + if (interface_number >= USB_MAXINTERFACES) + return LIBUSB_ERROR_INVALID_PARAM; + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_mutex_lock(&dev_handle->lock); + if (dev_handle->claimed_interfaces & (1 << interface_number)) + goto out; + + r = usbi_backend.claim_interface(dev_handle, interface_number); + if (r == 0) + dev_handle->claimed_interfaces |= 1 << interface_number; + +out: + usbi_mutex_unlock(&dev_handle->lock); + return r; +} + +/** \ingroup libusb_dev + * Release an interface previously claimed with libusb_claim_interface(). You + * should release all claimed interfaces before closing a device handle. + * + * This is a blocking function. A SET_INTERFACE control request will be sent + * to the device, resetting interface state to the first alternate setting. + * + * If auto_detach_kernel_driver is set to 1 for dev, the kernel + * driver will be re-attached after releasing the interface. + * + * \param dev_handle a device handle + * \param interface_number the bInterfaceNumber of the + * previously-claimed interface + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + * \see libusb_set_auto_detach_kernel_driver() + */ +int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, + int interface_number) +{ + int r; + + usbi_dbg("interface %d", interface_number); + if (interface_number >= USB_MAXINTERFACES) + return LIBUSB_ERROR_INVALID_PARAM; + + usbi_mutex_lock(&dev_handle->lock); + if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + + r = usbi_backend.release_interface(dev_handle, interface_number); + if (r == 0) + dev_handle->claimed_interfaces &= ~(1 << interface_number); + +out: + usbi_mutex_unlock(&dev_handle->lock); + return r; +} + +/** \ingroup libusb_dev + * Activate an alternate setting for an interface. The interface must have + * been previously claimed with libusb_claim_interface(). + * + * You should always use this function rather than formulating your own + * SET_INTERFACE control request. This is because the underlying operating + * system needs to know when such changes happen. + * + * This is a blocking function. + * + * \param dev_handle a device handle + * \param interface_number the bInterfaceNumber of the + * previously-claimed interface + * \param alternate_setting the bAlternateSetting of the alternate + * setting to activate + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the + * requested alternate setting does not exist + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, + int interface_number, int alternate_setting) +{ + usbi_dbg("interface %d altsetting %d", + interface_number, alternate_setting); + if (interface_number >= USB_MAXINTERFACES) + return LIBUSB_ERROR_INVALID_PARAM; + + usbi_mutex_lock(&dev_handle->lock); + if (!dev_handle->dev->attached) { + usbi_mutex_unlock(&dev_handle->lock); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { + usbi_mutex_unlock(&dev_handle->lock); + return LIBUSB_ERROR_NOT_FOUND; + } + usbi_mutex_unlock(&dev_handle->lock); + + return usbi_backend.set_interface_altsetting(dev_handle, interface_number, + alternate_setting); +} + +/** \ingroup libusb_dev + * Clear the halt/stall condition for an endpoint. Endpoints with halt status + * are unable to receive or transmit data until the halt condition is stalled. + * + * You should cancel all pending transfers before attempting to clear the halt + * condition. + * + * This is a blocking function. + * + * \param dev_handle a device handle + * \param endpoint the endpoint to clear halt status + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, + unsigned char endpoint) +{ + usbi_dbg("endpoint %x", endpoint); + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + return usbi_backend.clear_halt(dev_handle, endpoint); +} + +/** \ingroup libusb_dev + * Perform a USB port reset to reinitialize a device. The system will attempt + * to restore the previous configuration and alternate settings after the + * reset has completed. + * + * If the reset fails, the descriptors change, or the previous state cannot be + * restored, the device will appear to be disconnected and reconnected. This + * means that the device handle is no longer valid (you should close it) and + * rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates + * when this is the case. + * + * This is a blocking function which usually incurs a noticeable delay. + * + * \param dev_handle a handle of the device to reset + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the + * device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) +{ + usbi_dbg(""); + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + return usbi_backend.reset_device(dev_handle); +} + +/** \ingroup libusb_asyncio + * Allocate up to num_streams usb bulk streams on the specified endpoints. This + * function takes an array of endpoints rather then a single endpoint because + * some protocols require that endpoints are setup with similar stream ids. + * All endpoints passed in must belong to the same interface. + * + * Note this function may return less streams then requested. Also note that the + * same number of streams are allocated for each endpoint in the endpoint array. + * + * Stream id 0 is reserved, and should not be used to communicate with devices. + * If libusb_alloc_streams() returns with a value of N, you may use stream ids + * 1 to N. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param dev_handle a device handle + * \param num_streams number of streams to try to allocate + * \param endpoints array of endpoints to allocate streams on + * \param num_endpoints length of the endpoints array + * \returns number of streams allocated, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints) +{ + usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints); + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + if (usbi_backend.alloc_streams) + return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints, + num_endpoints); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_asyncio + * Free usb bulk streams allocated with libusb_alloc_streams(). + * + * Note streams are automatically free-ed when releasing an interface. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param dev_handle a device handle + * \param endpoints array of endpoints to free streams on + * \param num_endpoints length of the endpoints array + * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, + unsigned char *endpoints, int num_endpoints) +{ + usbi_dbg("eps %d", num_endpoints); + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + if (usbi_backend.free_streams) + return usbi_backend.free_streams(dev_handle, endpoints, + num_endpoints); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_asyncio + * Attempts to allocate a block of persistent DMA memory suitable for transfers + * against the given device. If successful, will return a block of memory + * that is suitable for use as "buffer" in \ref libusb_transfer against this + * device. Using this memory instead of regular memory means that the host + * controller can use DMA directly into the buffer to increase performance, and + * also that transfers can no longer fail due to kernel memory fragmentation. + * + * Note that this means you should not modify this memory (or even data on + * the same cache lines) when a transfer is in progress, although it is legal + * to have several transfers going on within the same memory block. + * + * Will return NULL on failure. Many systems do not support such zerocopy + * and will always return NULL. Memory allocated with this function must be + * freed with \ref libusb_dev_mem_free. Specifically, this means that the + * flag \ref LIBUSB_TRANSFER_FREE_BUFFER cannot be used to free memory allocated + * with this function. + * + * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 + * + * \param dev_handle a device handle + * \param length size of desired data buffer + * \returns a pointer to the newly allocated memory, or NULL on failure + */ +DEFAULT_VISIBILITY +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length) +{ + if (!dev_handle->dev->attached) + return NULL; + + if (usbi_backend.dev_mem_alloc) + return usbi_backend.dev_mem_alloc(dev_handle, length); + else + return NULL; +} + +/** \ingroup libusb_asyncio + * Free device memory allocated with libusb_dev_mem_alloc(). + * + * \param dev_handle a device handle + * \param buffer pointer to the previously allocated memory + * \param length size of previously allocated memory + * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length) +{ + if (usbi_backend.dev_mem_free) + return usbi_backend.dev_mem_free(dev_handle, buffer, length); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_dev + * Determine if a kernel driver is active on an interface. If a kernel driver + * is active, you cannot claim the interface, and libusb will be unable to + * perform I/O. + * + * This functionality is not available on Windows. + * + * \param dev_handle a device handle + * \param interface_number the interface to check + * \returns 0 if no kernel driver is active + * \returns 1 if a kernel driver is active + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * is not available + * \returns another LIBUSB_ERROR code on other failure + * \see libusb_detach_kernel_driver() + */ +int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, + int interface_number) +{ + usbi_dbg("interface %d", interface_number); + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + if (usbi_backend.kernel_driver_active) + return usbi_backend.kernel_driver_active(dev_handle, interface_number); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_dev + * Detach a kernel driver from an interface. If successful, you will then be + * able to claim the interface and perform I/O. + * + * This functionality is not available on Darwin or Windows. + * + * Note that libusb itself also talks to the device through a special kernel + * driver, if this driver is already attached to the device, this call will + * not detach it and return LIBUSB_ERROR_NOT_FOUND. + * + * \param dev_handle a device handle + * \param interface_number the interface to detach the driver from + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * is not available + * \returns another LIBUSB_ERROR code on other failure + * \see libusb_kernel_driver_active() + */ +int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number) +{ + usbi_dbg("interface %d", interface_number); + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + if (usbi_backend.detach_kernel_driver) + return usbi_backend.detach_kernel_driver(dev_handle, interface_number); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_dev + * Re-attach an interface's kernel driver, which was previously detached + * using libusb_detach_kernel_driver(). This call is only effective on + * Linux and returns LIBUSB_ERROR_NOT_SUPPORTED on all other platforms. + * + * This functionality is not available on Darwin or Windows. + * + * \param dev_handle a device handle + * \param interface_number the interface to attach the driver from + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * is not available + * \returns LIBUSB_ERROR_BUSY if the driver cannot be attached because the + * interface is claimed by a program or driver + * \returns another LIBUSB_ERROR code on other failure + * \see libusb_kernel_driver_active() + */ +int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number) +{ + usbi_dbg("interface %d", interface_number); + + if (!dev_handle->dev->attached) + return LIBUSB_ERROR_NO_DEVICE; + + if (usbi_backend.attach_kernel_driver) + return usbi_backend.attach_kernel_driver(dev_handle, interface_number); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +/** \ingroup libusb_dev + * Enable/disable libusb's automatic kernel driver detachment. When this is + * enabled libusb will automatically detach the kernel driver on an interface + * when claiming the interface, and attach it when releasing the interface. + * + * Automatic kernel driver detachment is disabled on newly opened device + * handles by default. + * + * On platforms which do not have LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER + * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will + * continue as if this function was never called. + * + * \param dev_handle a device handle + * \param enable whether to enable or disable auto kernel driver detachment + * + * \returns LIBUSB_SUCCESS on success + * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality + * is not available + * \see libusb_claim_interface() + * \see libusb_release_interface() + * \see libusb_set_configuration() + */ +int API_EXPORTED libusb_set_auto_detach_kernel_driver( + libusb_device_handle *dev_handle, int enable) +{ + if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) + return LIBUSB_ERROR_NOT_SUPPORTED; + + dev_handle->auto_detach_kernel_driver = enable; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_lib + * \deprecated Use libusb_set_option() instead using the + * \ref LIBUSB_OPTION_LOG_LEVEL option. + */ +void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) +{ +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + USBI_GET_CONTEXT(ctx); + if (!ctx->debug_fixed) { + level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + ctx->debug = (enum libusb_log_level)level; + } +#else + UNUSED(ctx); + UNUSED(level); +#endif +} + +/** \ingroup libusb_lib + * Set an option in the library. + * + * Use this function to configure a specific option within the library. + * + * Some options require one or more arguments to be provided. Consult each + * option's documentation for specific requirements. + * + * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106 + * + * \param ctx context on which to operate + * \param option which option to set + * \param ... any required arguments for the specified option + * + * \returns LIBUSB_SUCCESS on success + * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported + * on this platform + */ +int API_EXPORTED libusb_set_option(libusb_context *ctx, + enum libusb_option option, ...) +{ + int arg, r = LIBUSB_SUCCESS; + va_list ap; + + USBI_GET_CONTEXT(ctx); + + va_start(ap, option); + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: + arg = va_arg(ap, int); + if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) { + r = LIBUSB_ERROR_INVALID_PARAM; + break; + } +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + if (!ctx->debug_fixed) + ctx->debug = (enum libusb_log_level)arg; +#endif + break; + + /* Handle all backend-specific options here */ + case LIBUSB_OPTION_USE_USBDK: + if (usbi_backend.set_option) + r = usbi_backend.set_option(ctx, option, ap); + else + r = LIBUSB_ERROR_NOT_SUPPORTED; + break; + + default: + r = LIBUSB_ERROR_INVALID_PARAM; + } + va_end(ap); + + return r; +} + +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) +/* returns the log level as defined in the LIBUSB_DEBUG environment variable. + * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE. + * value is clamped to ensure it is within the valid range of possibilities. + */ +static enum libusb_log_level get_env_debug_level(void) +{ + const char *dbg = getenv("LIBUSB_DEBUG"); + enum libusb_log_level level; + if (dbg) { + int dbg_level = atoi(dbg); + dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + level = (enum libusb_log_level)dbg_level; + } else { + level = LIBUSB_LOG_LEVEL_NONE; + } + return level; +} +#endif + +/** \ingroup libusb_lib + * Initialize libusb. This function must be called before calling any other + * libusb function. + * + * If you do not provide an output location for a context pointer, a default + * context will be created. If there was already a default context, it will + * be reused (and nothing will be initialized/reinitialized). + * + * \param context Optional output location for context pointer. + * Only valid on return code 0. + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \see libusb_contexts + */ +int API_EXPORTED libusb_init(libusb_context **context) +{ + struct libusb_device *dev, *next; + size_t priv_size = usbi_backend.context_priv_size; + struct libusb_context *ctx; + static int first_init = 1; + int r = 0; + + usbi_mutex_static_lock(&default_context_lock); + + if (!timestamp_origin.tv_sec) { + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); + } + + if (!context && usbi_default_context) { + usbi_dbg("reusing default context"); + default_context_refcnt++; + usbi_mutex_static_unlock(&default_context_lock); + return 0; + } + + ctx = calloc(1, sizeof(*ctx) + priv_size); + if (!ctx) { + r = LIBUSB_ERROR_NO_MEM; + goto err_unlock; + } + +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + ctx->debug = get_env_debug_level(); + if (ctx->debug != LIBUSB_LOG_LEVEL_NONE) + ctx->debug_fixed = 1; +#endif + + /* default context should be initialized before calling usbi_dbg */ + if (!usbi_default_context) { + usbi_default_context = ctx; + default_context_refcnt++; + usbi_dbg("created default context"); + } + + usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor, + libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc); + + usbi_mutex_init(&ctx->usb_devs_lock); + usbi_mutex_init(&ctx->open_devs_lock); + usbi_mutex_init(&ctx->hotplug_cbs_lock); + list_init(&ctx->usb_devs); + list_init(&ctx->open_devs); + list_init(&ctx->hotplug_cbs); + ctx->next_hotplug_cb_handle = 1; + + usbi_mutex_static_lock(&active_contexts_lock); + if (first_init) { + first_init = 0; + list_init (&active_contexts_list); + } + list_add (&ctx->list, &active_contexts_list); + usbi_mutex_static_unlock(&active_contexts_lock); + + if (usbi_backend.init) { + r = usbi_backend.init(ctx); + if (r) + goto err_free_ctx; + } + + r = usbi_io_init(ctx); + if (r < 0) + goto err_backend_exit; + + usbi_mutex_static_unlock(&default_context_lock); + + if (context) + *context = ctx; + + return 0; + +err_backend_exit: + if (usbi_backend.exit) + usbi_backend.exit(ctx); +err_free_ctx: + if (ctx == usbi_default_context) { + usbi_default_context = NULL; + default_context_refcnt--; + } + + usbi_mutex_static_lock(&active_contexts_lock); + list_del (&ctx->list); + usbi_mutex_static_unlock(&active_contexts_lock); + + usbi_mutex_lock(&ctx->usb_devs_lock); + list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { + list_del(&dev->list); + libusb_unref_device(dev); + } + usbi_mutex_unlock(&ctx->usb_devs_lock); + + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_destroy(&ctx->hotplug_cbs_lock); + + free(ctx); +err_unlock: + usbi_mutex_static_unlock(&default_context_lock); + return r; +} + +/** \ingroup libusb_lib + * Deinitialize libusb. Should be called after closing all open devices and + * before your application terminates. + * \param ctx the context to deinitialize, or NULL for the default context + */ +void API_EXPORTED libusb_exit(struct libusb_context *ctx) +{ + struct libusb_device *dev, *next; + struct timeval tv = { 0, 0 }; + + usbi_dbg(""); + USBI_GET_CONTEXT(ctx); + + /* if working with default context, only actually do the deinitialization + * if we're the last user */ + usbi_mutex_static_lock(&default_context_lock); + if (ctx == usbi_default_context) { + if (--default_context_refcnt > 0) { + usbi_dbg("not destroying default context"); + usbi_mutex_static_unlock(&default_context_lock); + return; + } + usbi_dbg("destroying default context"); + usbi_default_context = NULL; + } + usbi_mutex_static_unlock(&default_context_lock); + + usbi_mutex_static_lock(&active_contexts_lock); + list_del (&ctx->list); + usbi_mutex_static_unlock(&active_contexts_lock); + + if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + usbi_hotplug_deregister(ctx, 1); + + /* + * Ensure any pending unplug events are read from the hotplug + * pipe. The usb_device-s hold in the events are no longer part + * of usb_devs, but the events still hold a reference! + * + * Note we don't do this if the application has left devices + * open (which implies a buggy app) to avoid packet completion + * handlers running when the app does not expect them to run. + */ + if (list_empty(&ctx->open_devs)) + libusb_handle_events_timeout(ctx, &tv); + + usbi_mutex_lock(&ctx->usb_devs_lock); + list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { + list_del(&dev->list); + libusb_unref_device(dev); + } + usbi_mutex_unlock(&ctx->usb_devs_lock); + } + + /* a few sanity checks. don't bother with locking because unless + * there is an application bug, nobody will be accessing these. */ + if (!list_empty(&ctx->usb_devs)) + usbi_warn(ctx, "some libusb_devices were leaked"); + if (!list_empty(&ctx->open_devs)) + usbi_warn(ctx, "application left some devices open"); + + usbi_io_exit(ctx); + if (usbi_backend.exit) + usbi_backend.exit(ctx); + + usbi_mutex_destroy(&ctx->open_devs_lock); + usbi_mutex_destroy(&ctx->usb_devs_lock); + usbi_mutex_destroy(&ctx->hotplug_cbs_lock); + free(ctx); +} + +/** \ingroup libusb_misc + * Check at runtime if the loaded library has a given capability. + * This call should be performed after \ref libusb_init(), to ensure the + * backend has updated its capability set. + * + * \param capability the \ref libusb_capability to check for + * \returns nonzero if the running library has the capability, 0 otherwise + */ +int API_EXPORTED libusb_has_capability(uint32_t capability) +{ + switch (capability) { + case LIBUSB_CAP_HAS_CAPABILITY: + return 1; + case LIBUSB_CAP_HAS_HOTPLUG: + return !(usbi_backend.get_device_list); + case LIBUSB_CAP_HAS_HID_ACCESS: + return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS); + case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: + return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); + } + return 0; +} + +#ifdef ENABLE_LOGGING + +/* this is defined in libusbi.h if needed */ +#ifdef LIBUSB_PRINTF_WIN32 +/* + * Prior to VS2015, Microsoft did not provide the snprintf() function and + * provided a vsnprintf() that did not guarantee NULL-terminated output. + * Microsoft did provide a _snprintf() function, but again it did not + * guarantee NULL-terminated output. + * + * The below implementations guarantee NULL-terminated output and are + * C99 compliant. + */ + +int usbi_snprintf(char *str, size_t size, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = usbi_vsnprintf(str, size, format, ap); + va_end(ap); + + return ret; +} + +int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + int ret; + + ret = _vsnprintf(str, size, format, ap); + if (ret < 0 || ret == (int)size) { + /* Output is truncated, ensure buffer is NULL-terminated and + * determine how many characters would have been written. */ + str[size - 1] = '\0'; + if (ret < 0) + ret = _vsnprintf(NULL, 0, format, ap); + } + + return ret; +} +#endif /* LIBUSB_PRINTF_WIN32 */ + +static void usbi_log_str(enum libusb_log_level level, const char *str) +{ +#if defined(USE_SYSTEM_LOGGING_FACILITY) +#if defined(OS_WINDOWS) + OutputDebugString(str); +#elif defined(OS_WINCE) + /* Windows CE only supports the Unicode version of OutputDebugString. */ + WCHAR wbuf[USBI_MAX_LOG_LEN]; + MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf)); + OutputDebugStringW(wbuf); +#elif defined(__ANDROID__) + int priority = ANDROID_LOG_UNKNOWN; + switch (level) { + case LIBUSB_LOG_LEVEL_NONE: return; + case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break; + case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; + case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; + case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break; + } + __android_log_write(priority, "libusb", str); +#elif defined(HAVE_SYSLOG_FUNC) + int syslog_level = LOG_INFO; + switch (level) { + case LIBUSB_LOG_LEVEL_NONE: return; + case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break; + case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; + case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; + case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break; + } + syslog(syslog_level, "%s", str); +#else /* All of gcc, Clang, XCode seem to use #warning */ +#warning System logging is not supported on this platform. Logging to stderr will be used instead. + fputs(str, stderr); +#endif +#else + fputs(str, stderr); +#endif /* USE_SYSTEM_LOGGING_FACILITY */ + UNUSED(level); +} + +void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, + const char *function, const char *format, va_list args) +{ + const char *prefix; + char buf[USBI_MAX_LOG_LEN]; + struct timespec now; + int global_debug, header_len, text_len; + static int has_debug_header_been_displayed = 0; + +#ifdef ENABLE_DEBUG_LOGGING + global_debug = 1; + UNUSED(ctx); +#else + enum libusb_log_level ctx_level = LIBUSB_LOG_LEVEL_NONE; + + USBI_GET_CONTEXT(ctx); + if (ctx) + ctx_level = ctx->debug; + else + ctx_level = get_env_debug_level(); + + if (ctx_level == LIBUSB_LOG_LEVEL_NONE) + return; + if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING) + return; + if (level == LIBUSB_LOG_LEVEL_INFO && ctx_level < LIBUSB_LOG_LEVEL_INFO) + return; + if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG) + return; + + global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); +#endif + + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &now); + if ((global_debug) && (!has_debug_header_been_displayed)) { + has_debug_header_been_displayed = 1; + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); + } + if (now.tv_nsec < timestamp_origin.tv_nsec) { + now.tv_sec--; + now.tv_nsec += 1000000000L; + } + now.tv_sec -= timestamp_origin.tv_sec; + now.tv_nsec -= timestamp_origin.tv_nsec; + + switch (level) { + case LIBUSB_LOG_LEVEL_NONE: + return; + case LIBUSB_LOG_LEVEL_ERROR: + prefix = "error"; + break; + case LIBUSB_LOG_LEVEL_WARNING: + prefix = "warning"; + break; + case LIBUSB_LOG_LEVEL_INFO: + prefix = "info"; + break; + case LIBUSB_LOG_LEVEL_DEBUG: + prefix = "debug"; + break; + default: + prefix = "unknown"; + break; + } + + if (global_debug) { + header_len = snprintf(buf, sizeof(buf), + "[%2d.%06d] [%08x] libusb: %s [%s] ", + (int)now.tv_sec, (int)(now.tv_nsec / 1000L), usbi_get_tid(), prefix, function); + } else { + header_len = snprintf(buf, sizeof(buf), + "libusb: %s [%s] ", prefix, function); + } + + if (header_len < 0 || header_len >= (int)sizeof(buf)) { + /* Somehow snprintf failed to write to the buffer, + * remove the header so something useful is output. */ + header_len = 0; + } + /* Make sure buffer is NUL terminated */ + buf[header_len] = '\0'; + text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len, + format, args); + if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { + /* Truncated log output. On some platforms a -1 return value means + * that the output was truncated. */ + text_len = sizeof(buf) - header_len; + } + if (header_len + text_len + sizeof(USBI_LOG_LINE_END) >= sizeof(buf)) { + /* Need to truncate the text slightly to fit on the terminator. */ + text_len -= (header_len + text_len + sizeof(USBI_LOG_LINE_END)) - sizeof(buf); + } + strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); + + usbi_log_str(level, buf); +} + +void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, + const char *function, const char *format, ...) +{ + va_list args; + + va_start (args, format); + usbi_log_v(ctx, level, function, format, args); + va_end (args); +} + +#endif /* ENABLE_LOGGING */ + +/** \ingroup libusb_misc + * Returns a constant NULL-terminated string with the ASCII name of a libusb + * error or transfer status code. The caller must not free() the returned + * string. + * + * \param error_code The \ref libusb_error or libusb_transfer_status code to + * return the name of. + * \returns The error name, or the string **UNKNOWN** if the value of + * error_code is not a known error / status code. + */ +DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_error_name(int error_code) +{ + switch (error_code) { + case LIBUSB_ERROR_IO: + return "LIBUSB_ERROR_IO"; + case LIBUSB_ERROR_INVALID_PARAM: + return "LIBUSB_ERROR_INVALID_PARAM"; + case LIBUSB_ERROR_ACCESS: + return "LIBUSB_ERROR_ACCESS"; + case LIBUSB_ERROR_NO_DEVICE: + return "LIBUSB_ERROR_NO_DEVICE"; + case LIBUSB_ERROR_NOT_FOUND: + return "LIBUSB_ERROR_NOT_FOUND"; + case LIBUSB_ERROR_BUSY: + return "LIBUSB_ERROR_BUSY"; + case LIBUSB_ERROR_TIMEOUT: + return "LIBUSB_ERROR_TIMEOUT"; + case LIBUSB_ERROR_OVERFLOW: + return "LIBUSB_ERROR_OVERFLOW"; + case LIBUSB_ERROR_PIPE: + return "LIBUSB_ERROR_PIPE"; + case LIBUSB_ERROR_INTERRUPTED: + return "LIBUSB_ERROR_INTERRUPTED"; + case LIBUSB_ERROR_NO_MEM: + return "LIBUSB_ERROR_NO_MEM"; + case LIBUSB_ERROR_NOT_SUPPORTED: + return "LIBUSB_ERROR_NOT_SUPPORTED"; + case LIBUSB_ERROR_OTHER: + return "LIBUSB_ERROR_OTHER"; + + case LIBUSB_TRANSFER_ERROR: + return "LIBUSB_TRANSFER_ERROR"; + case LIBUSB_TRANSFER_TIMED_OUT: + return "LIBUSB_TRANSFER_TIMED_OUT"; + case LIBUSB_TRANSFER_CANCELLED: + return "LIBUSB_TRANSFER_CANCELLED"; + case LIBUSB_TRANSFER_STALL: + return "LIBUSB_TRANSFER_STALL"; + case LIBUSB_TRANSFER_NO_DEVICE: + return "LIBUSB_TRANSFER_NO_DEVICE"; + case LIBUSB_TRANSFER_OVERFLOW: + return "LIBUSB_TRANSFER_OVERFLOW"; + + case 0: + return "LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED"; + default: + return "**UNKNOWN**"; + } +} + +/** \ingroup libusb_misc + * Returns a pointer to const struct libusb_version with the version + * (major, minor, micro, nano and rc) of the running library. + */ +DEFAULT_VISIBILITY +const struct libusb_version * LIBUSB_CALL libusb_get_version(void) +{ + return &libusb_version_internal; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c b/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c new file mode 100644 index 0000000000..74d6de557e --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c @@ -0,0 +1,1192 @@ +/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ +/* + * USB descriptor handling functions for libusb + * Copyright © 2007 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include + +#include "libusbi.h" + +#define DESC_HEADER_LENGTH 2 +#define DEVICE_DESC_LENGTH 18 +#define CONFIG_DESC_LENGTH 9 +#define INTERFACE_DESC_LENGTH 9 +#define ENDPOINT_DESC_LENGTH 7 +#define ENDPOINT_AUDIO_DESC_LENGTH 9 + +/** @defgroup libusb_desc USB descriptors + * This page details how to examine the various standard USB descriptors + * for detected devices + */ + +/* set host_endian if the w values are already in host endian format, + * as opposed to bus endian. */ +int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, + void *dest, int host_endian) +{ + const unsigned char *sp = source; + unsigned char *dp = dest; + uint16_t w; + const char *cp; + uint32_t d; + + for (cp = descriptor; *cp; cp++) { + switch (*cp) { + case 'b': /* 8-bit byte */ + *dp++ = *sp++; + break; + case 'w': /* 16-bit word, convert from little endian to CPU */ + dp += ((uintptr_t)dp & 1); /* Align to word boundary */ + + if (host_endian) { + memcpy(dp, sp, 2); + } else { + w = (sp[1] << 8) | sp[0]; + *((uint16_t *)dp) = w; + } + sp += 2; + dp += 2; + break; + case 'd': /* 32-bit word, convert from little endian to CPU */ + dp += ((uintptr_t)dp & 1); /* Align to word boundary */ + + if (host_endian) { + memcpy(dp, sp, 4); + } else { + d = (sp[3] << 24) | (sp[2] << 16) | + (sp[1] << 8) | sp[0]; + *((uint32_t *)dp) = d; + } + sp += 4; + dp += 4; + break; + case 'u': /* 16 byte UUID */ + memcpy(dp, sp, 16); + sp += 16; + dp += 16; + break; + } + } + + return (int) (sp - source); +} + +static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint) +{ + free((void *) endpoint->extra); +} + +static int parse_endpoint(struct libusb_context *ctx, + struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer, + int size, int host_endian) +{ + struct usb_descriptor_header header; + unsigned char *extra; + unsigned char *begin; + int parsed = 0; + int len; + + if (size < DESC_HEADER_LENGTH) { + usbi_err(ctx, "short endpoint descriptor read %d/%d", + size, DESC_HEADER_LENGTH); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(buffer, "bb", &header, 0); + if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) { + usbi_err(ctx, "unexpected descriptor %x (expected %x)", + header.bDescriptorType, LIBUSB_DT_ENDPOINT); + return parsed; + } + if (header.bLength > size) { + usbi_warn(ctx, "short endpoint descriptor read %d/%d", + size, header.bLength); + return parsed; + } + if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH) + usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian); + else if (header.bLength >= ENDPOINT_DESC_LENGTH) + usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian); + else { + usbi_err(ctx, "invalid endpoint bLength (%d)", header.bLength); + return LIBUSB_ERROR_IO; + } + + buffer += header.bLength; + size -= header.bLength; + parsed += header.bLength; + + /* Skip over the rest of the Class Specific or Vendor Specific */ + /* descriptors */ + begin = buffer; + while (size >= DESC_HEADER_LENGTH) { + usbi_parse_descriptor(buffer, "bb", &header, 0); + if (header.bLength < DESC_HEADER_LENGTH) { + usbi_err(ctx, "invalid extra ep desc len (%d)", + header.bLength); + return LIBUSB_ERROR_IO; + } else if (header.bLength > size) { + usbi_warn(ctx, "short extra ep desc read %d/%d", + size, header.bLength); + return parsed; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || + (header.bDescriptorType == LIBUSB_DT_INTERFACE) || + (header.bDescriptorType == LIBUSB_DT_CONFIG) || + (header.bDescriptorType == LIBUSB_DT_DEVICE)) + break; + + usbi_dbg("skipping descriptor %x", header.bDescriptorType); + buffer += header.bLength; + size -= header.bLength; + parsed += header.bLength; + } + + /* Copy any unknown descriptors into a storage area for drivers */ + /* to later parse */ + len = (int)(buffer - begin); + if (!len) { + endpoint->extra = NULL; + endpoint->extra_length = 0; + return parsed; + } + + extra = malloc(len); + endpoint->extra = extra; + if (!extra) { + endpoint->extra_length = 0; + return LIBUSB_ERROR_NO_MEM; + } + + memcpy(extra, begin, len); + endpoint->extra_length = len; + + return parsed; +} + +static void clear_interface(struct libusb_interface *usb_interface) +{ + int i; + int j; + + if (usb_interface->altsetting) { + for (i = 0; i < usb_interface->num_altsetting; i++) { + struct libusb_interface_descriptor *ifp = + (struct libusb_interface_descriptor *) + usb_interface->altsetting + i; + free((void *) ifp->extra); + if (ifp->endpoint) { + for (j = 0; j < ifp->bNumEndpoints; j++) + clear_endpoint((struct libusb_endpoint_descriptor *) + ifp->endpoint + j); + } + free((void *) ifp->endpoint); + } + } + free((void *) usb_interface->altsetting); + usb_interface->altsetting = NULL; +} + +static int parse_interface(libusb_context *ctx, + struct libusb_interface *usb_interface, unsigned char *buffer, int size, + int host_endian) +{ + int i; + int len; + int r; + int parsed = 0; + int interface_number = -1; + struct usb_descriptor_header header; + struct libusb_interface_descriptor *ifp; + unsigned char *begin; + + usb_interface->num_altsetting = 0; + + while (size >= INTERFACE_DESC_LENGTH) { + struct libusb_interface_descriptor *altsetting = + (struct libusb_interface_descriptor *) usb_interface->altsetting; + altsetting = usbi_reallocf(altsetting, + sizeof(struct libusb_interface_descriptor) * + (usb_interface->num_altsetting + 1)); + if (!altsetting) { + r = LIBUSB_ERROR_NO_MEM; + goto err; + } + usb_interface->altsetting = altsetting; + + ifp = altsetting + usb_interface->num_altsetting; + usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0); + if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) { + usbi_err(ctx, "unexpected descriptor %x (expected %x)", + ifp->bDescriptorType, LIBUSB_DT_INTERFACE); + return parsed; + } + if (ifp->bLength < INTERFACE_DESC_LENGTH) { + usbi_err(ctx, "invalid interface bLength (%d)", + ifp->bLength); + r = LIBUSB_ERROR_IO; + goto err; + } + if (ifp->bLength > size) { + usbi_warn(ctx, "short intf descriptor read %d/%d", + size, ifp->bLength); + return parsed; + } + if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { + usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints); + r = LIBUSB_ERROR_IO; + goto err; + } + + usb_interface->num_altsetting++; + ifp->extra = NULL; + ifp->extra_length = 0; + ifp->endpoint = NULL; + + if (interface_number == -1) + interface_number = ifp->bInterfaceNumber; + + /* Skip over the interface */ + buffer += ifp->bLength; + parsed += ifp->bLength; + size -= ifp->bLength; + + begin = buffer; + + /* Skip over any interface, class or vendor descriptors */ + while (size >= DESC_HEADER_LENGTH) { + usbi_parse_descriptor(buffer, "bb", &header, 0); + if (header.bLength < DESC_HEADER_LENGTH) { + usbi_err(ctx, + "invalid extra intf desc len (%d)", + header.bLength); + r = LIBUSB_ERROR_IO; + goto err; + } else if (header.bLength > size) { + usbi_warn(ctx, + "short extra intf desc read %d/%d", + size, header.bLength); + return parsed; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) || + (header.bDescriptorType == LIBUSB_DT_ENDPOINT) || + (header.bDescriptorType == LIBUSB_DT_CONFIG) || + (header.bDescriptorType == LIBUSB_DT_DEVICE)) + break; + + buffer += header.bLength; + parsed += header.bLength; + size -= header.bLength; + } + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + ifp->extra = malloc(len); + if (!ifp->extra) { + r = LIBUSB_ERROR_NO_MEM; + goto err; + } + memcpy((unsigned char *) ifp->extra, begin, len); + ifp->extra_length = len; + } + + if (ifp->bNumEndpoints > 0) { + struct libusb_endpoint_descriptor *endpoint; + endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor)); + ifp->endpoint = endpoint; + if (!endpoint) { + r = LIBUSB_ERROR_NO_MEM; + goto err; + } + + for (i = 0; i < ifp->bNumEndpoints; i++) { + r = parse_endpoint(ctx, endpoint + i, buffer, size, + host_endian); + if (r < 0) + goto err; + if (r == 0) { + ifp->bNumEndpoints = (uint8_t)i; + break; + } + + buffer += r; + parsed += r; + size -= r; + } + } + + /* We check to see if it's an alternate to this one */ + ifp = (struct libusb_interface_descriptor *) buffer; + if (size < LIBUSB_DT_INTERFACE_SIZE || + ifp->bDescriptorType != LIBUSB_DT_INTERFACE || + ifp->bInterfaceNumber != interface_number) + return parsed; + } + + return parsed; +err: + clear_interface(usb_interface); + return r; +} + +static void clear_configuration(struct libusb_config_descriptor *config) +{ + int i; + if (config->interface) { + for (i = 0; i < config->bNumInterfaces; i++) + clear_interface((struct libusb_interface *) + config->interface + i); + } + free((void *) config->interface); + free((void *) config->extra); +} + +static int parse_configuration(struct libusb_context *ctx, + struct libusb_config_descriptor *config, unsigned char *buffer, + int size, int host_endian) +{ + int i; + int r; + struct usb_descriptor_header header; + struct libusb_interface *usb_interface; + + if (size < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(ctx, "short config descriptor read %d/%d", + size, LIBUSB_DT_CONFIG_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian); + if (config->bDescriptorType != LIBUSB_DT_CONFIG) { + usbi_err(ctx, "unexpected descriptor %x (expected %x)", + config->bDescriptorType, LIBUSB_DT_CONFIG); + return LIBUSB_ERROR_IO; + } + if (config->bLength < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(ctx, "invalid config bLength (%d)", config->bLength); + return LIBUSB_ERROR_IO; + } + if (config->bLength > size) { + usbi_err(ctx, "short config descriptor read %d/%d", + size, config->bLength); + return LIBUSB_ERROR_IO; + } + if (config->bNumInterfaces > USB_MAXINTERFACES) { + usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces); + return LIBUSB_ERROR_IO; + } + + usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface)); + config->interface = usb_interface; + if (!usb_interface) + return LIBUSB_ERROR_NO_MEM; + + buffer += config->bLength; + size -= config->bLength; + + config->extra = NULL; + config->extra_length = 0; + + for (i = 0; i < config->bNumInterfaces; i++) { + int len; + unsigned char *begin; + + /* Skip over the rest of the Class Specific or Vendor */ + /* Specific descriptors */ + begin = buffer; + while (size >= DESC_HEADER_LENGTH) { + usbi_parse_descriptor(buffer, "bb", &header, 0); + + if (header.bLength < DESC_HEADER_LENGTH) { + usbi_err(ctx, + "invalid extra config desc len (%d)", + header.bLength); + r = LIBUSB_ERROR_IO; + goto err; + } else if (header.bLength > size) { + usbi_warn(ctx, + "short extra config desc read %d/%d", + size, header.bLength); + config->bNumInterfaces = (uint8_t)i; + return size; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || + (header.bDescriptorType == LIBUSB_DT_INTERFACE) || + (header.bDescriptorType == LIBUSB_DT_CONFIG) || + (header.bDescriptorType == LIBUSB_DT_DEVICE)) + break; + + usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType); + buffer += header.bLength; + size -= header.bLength; + } + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + /* FIXME: We should realloc and append here */ + if (!config->extra_length) { + config->extra = malloc(len); + if (!config->extra) { + r = LIBUSB_ERROR_NO_MEM; + goto err; + } + + memcpy((unsigned char *) config->extra, begin, len); + config->extra_length = len; + } + } + + r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian); + if (r < 0) + goto err; + if (r == 0) { + config->bNumInterfaces = (uint8_t)i; + break; + } + + buffer += r; + size -= r; + } + + return size; + +err: + clear_configuration(config); + return r; +} + +static int raw_desc_to_config(struct libusb_context *ctx, + unsigned char *buf, int size, int host_endian, + struct libusb_config_descriptor **config) +{ + struct libusb_config_descriptor *_config = malloc(sizeof(*_config)); + int r; + + if (!_config) + return LIBUSB_ERROR_NO_MEM; + + r = parse_configuration(ctx, _config, buf, size, host_endian); + if (r < 0) { + usbi_err(ctx, "parse_configuration failed with error %d", r); + free(_config); + return r; + } else if (r > 0) { + usbi_warn(ctx, "still %d bytes of descriptor data left", r); + } + + *config = _config; + return LIBUSB_SUCCESS; +} + +int usbi_device_cache_descriptor(libusb_device *dev) +{ + int r, host_endian = 0; + + r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, + &host_endian); + if (r < 0) + return r; + + if (!host_endian) { + dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB); + dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor); + dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct); + dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice); + } + + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Get the USB device descriptor for a given device. + * + * This is a non-blocking function; the device descriptor is cached in memory. + * + * Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this + * function always succeeds. + * + * \param dev the device + * \param desc output location for the descriptor data + * \returns 0 on success or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, + struct libusb_device_descriptor *desc) +{ + usbi_dbg(""); + memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor, + sizeof (dev->device_descriptor)); + return 0; +} + +/** \ingroup libusb_desc + * Get the USB configuration descriptor for the currently active configuration. + * This is a non-blocking function which does not involve any requests being + * sent to the device. + * + * \param dev a device + * \param config output location for the USB configuration descriptor. Only + * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() + * after use. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state + * \returns another LIBUSB_ERROR code on error + * \see libusb_get_config_descriptor + */ +int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, + struct libusb_config_descriptor **config) +{ + struct libusb_config_descriptor _config; + unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; + unsigned char *buf = NULL; + int host_endian = 0; + int r; + + r = usbi_backend.get_active_config_descriptor(dev, tmp, + LIBUSB_DT_CONFIG_SIZE, &host_endian); + if (r < 0) + return r; + if (r < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(dev->ctx, "short config descriptor read %d/%d", + r, LIBUSB_DT_CONFIG_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); + buf = malloc(_config.wTotalLength); + if (!buf) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_backend.get_active_config_descriptor(dev, buf, + _config.wTotalLength, &host_endian); + if (r >= 0) + r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); + + free(buf); + return r; +} + +/** \ingroup libusb_desc + * Get a USB configuration descriptor based on its index. + * This is a non-blocking function which does not involve any requests being + * sent to the device. + * + * \param dev a device + * \param config_index the index of the configuration you wish to retrieve + * \param config output location for the USB configuration descriptor. Only + * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() + * after use. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns another LIBUSB_ERROR code on error + * \see libusb_get_active_config_descriptor() + * \see libusb_get_config_descriptor_by_value() + */ +int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, + uint8_t config_index, struct libusb_config_descriptor **config) +{ + struct libusb_config_descriptor _config; + unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; + unsigned char *buf = NULL; + int host_endian = 0; + int r; + + usbi_dbg("index %d", config_index); + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_NOT_FOUND; + + r = usbi_backend.get_config_descriptor(dev, config_index, tmp, + LIBUSB_DT_CONFIG_SIZE, &host_endian); + if (r < 0) + return r; + if (r < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(dev->ctx, "short config descriptor read %d/%d", + r, LIBUSB_DT_CONFIG_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); + buf = malloc(_config.wTotalLength); + if (!buf) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_backend.get_config_descriptor(dev, config_index, buf, + _config.wTotalLength, &host_endian); + if (r >= 0) + r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); + + free(buf); + return r; +} + +/* iterate through all configurations, returning the index of the configuration + * matching a specific bConfigurationValue in the idx output parameter, or -1 + * if the config was not found. + * returns 0 on success or a LIBUSB_ERROR code + */ +int usbi_get_config_index_by_value(struct libusb_device *dev, + uint8_t bConfigurationValue, int *idx) +{ + uint8_t i; + + usbi_dbg("value %d", bConfigurationValue); + for (i = 0; i < dev->num_configurations; i++) { + unsigned char tmp[6]; + int host_endian; + int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp), + &host_endian); + if (r < 0) { + *idx = -1; + return r; + } + if (tmp[5] == bConfigurationValue) { + *idx = i; + return 0; + } + } + + *idx = -1; + return 0; +} + +/** \ingroup libusb_desc + * Get a USB configuration descriptor with a specific bConfigurationValue. + * This is a non-blocking function which does not involve any requests being + * sent to the device. + * + * \param dev a device + * \param bConfigurationValue the bConfigurationValue of the configuration you + * wish to retrieve + * \param config output location for the USB configuration descriptor. Only + * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() + * after use. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns another LIBUSB_ERROR code on error + * \see libusb_get_active_config_descriptor() + * \see libusb_get_config_descriptor() + */ +int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, + uint8_t bConfigurationValue, struct libusb_config_descriptor **config) +{ + int r, idx, host_endian; + unsigned char *buf = NULL; + + if (usbi_backend.get_config_descriptor_by_value) { + r = usbi_backend.get_config_descriptor_by_value(dev, + bConfigurationValue, &buf, &host_endian); + if (r < 0) + return r; + return raw_desc_to_config(dev->ctx, buf, r, host_endian, config); + } + + r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx); + if (r < 0) + return r; + else if (idx == -1) + return LIBUSB_ERROR_NOT_FOUND; + else + return libusb_get_config_descriptor(dev, (uint8_t) idx, config); +} + +/** \ingroup libusb_desc + * Free a configuration descriptor obtained from + * libusb_get_active_config_descriptor() or libusb_get_config_descriptor(). + * It is safe to call this function with a NULL config parameter, in which + * case the function simply returns. + * + * \param config the configuration descriptor to free + */ +void API_EXPORTED libusb_free_config_descriptor( + struct libusb_config_descriptor *config) +{ + if (!config) + return; + + clear_configuration(config); + free(config); +} + +/** \ingroup libusb_desc + * Get an endpoints superspeed endpoint companion descriptor (if any) + * + * \param ctx the context to operate on, or NULL for the default context + * \param endpoint endpoint descriptor from which to get the superspeed + * endpoint companion descriptor + * \param ep_comp output location for the superspeed endpoint companion + * descriptor. Only valid if 0 was returned. Must be freed with + * libusb_free_ss_endpoint_companion_descriptor() after use. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * \returns another LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor( + struct libusb_context *ctx, + const struct libusb_endpoint_descriptor *endpoint, + struct libusb_ss_endpoint_companion_descriptor **ep_comp) +{ + struct usb_descriptor_header header; + int size = endpoint->extra_length; + const unsigned char *buffer = endpoint->extra; + + *ep_comp = NULL; + + while (size >= DESC_HEADER_LENGTH) { + usbi_parse_descriptor(buffer, "bb", &header, 0); + if (header.bLength < 2 || header.bLength > size) { + usbi_err(ctx, "invalid descriptor length %d", + header.bLength); + return LIBUSB_ERROR_IO; + } + if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) { + buffer += header.bLength; + size -= header.bLength; + continue; + } + if (header.bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) { + usbi_err(ctx, "invalid ss-ep-comp-desc length %d", + header.bLength); + return LIBUSB_ERROR_IO; + } + *ep_comp = malloc(sizeof(**ep_comp)); + if (*ep_comp == NULL) + return LIBUSB_ERROR_NO_MEM; + usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0); + return LIBUSB_SUCCESS; + } + return LIBUSB_ERROR_NOT_FOUND; +} + +/** \ingroup libusb_desc + * Free a superspeed endpoint companion descriptor obtained from + * libusb_get_ss_endpoint_companion_descriptor(). + * It is safe to call this function with a NULL ep_comp parameter, in which + * case the function simply returns. + * + * \param ep_comp the superspeed endpoint companion descriptor to free + */ +void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor( + struct libusb_ss_endpoint_companion_descriptor *ep_comp) +{ + free(ep_comp); +} + +static int parse_bos(struct libusb_context *ctx, + struct libusb_bos_descriptor **bos, + unsigned char *buffer, int size, int host_endian) +{ + struct libusb_bos_descriptor bos_header, *_bos; + struct libusb_bos_dev_capability_descriptor dev_cap; + int i; + + if (size < LIBUSB_DT_BOS_SIZE) { + usbi_err(ctx, "short bos descriptor read %d/%d", + size, LIBUSB_DT_BOS_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian); + if (bos_header.bDescriptorType != LIBUSB_DT_BOS) { + usbi_err(ctx, "unexpected descriptor %x (expected %x)", + bos_header.bDescriptorType, LIBUSB_DT_BOS); + return LIBUSB_ERROR_IO; + } + if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) { + usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength); + return LIBUSB_ERROR_IO; + } + if (bos_header.bLength > size) { + usbi_err(ctx, "short bos descriptor read %d/%d", + size, bos_header.bLength); + return LIBUSB_ERROR_IO; + } + + _bos = calloc (1, + sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *)); + if (!_bos) + return LIBUSB_ERROR_NO_MEM; + + usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian); + buffer += bos_header.bLength; + size -= bos_header.bLength; + + /* Get the device capability descriptors */ + for (i = 0; i < bos_header.bNumDeviceCaps; i++) { + if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { + usbi_warn(ctx, "short dev-cap descriptor read %d/%d", + size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE); + break; + } + usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian); + if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) { + usbi_warn(ctx, "unexpected descriptor %x (expected %x)", + dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY); + break; + } + if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { + usbi_err(ctx, "invalid dev-cap bLength (%d)", + dev_cap.bLength); + libusb_free_bos_descriptor(_bos); + return LIBUSB_ERROR_IO; + } + if (dev_cap.bLength > size) { + usbi_warn(ctx, "short dev-cap descriptor read %d/%d", + size, dev_cap.bLength); + break; + } + + _bos->dev_capability[i] = malloc(dev_cap.bLength); + if (!_bos->dev_capability[i]) { + libusb_free_bos_descriptor(_bos); + return LIBUSB_ERROR_NO_MEM; + } + memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength); + buffer += dev_cap.bLength; + size -= dev_cap.bLength; + } + _bos->bNumDeviceCaps = (uint8_t)i; + *bos = _bos; + + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Get a Binary Object Store (BOS) descriptor + * This is a BLOCKING function, which will send requests to the device. + * + * \param dev_handle the handle of an open libusb device + * \param bos output location for the BOS descriptor. Only valid if 0 was returned. + * Must be freed with \ref libusb_free_bos_descriptor() after use. + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor + * \returns another LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, + struct libusb_bos_descriptor **bos) +{ + struct libusb_bos_descriptor _bos; + uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0}; + unsigned char *bos_data = NULL; + const int host_endian = 0; + int r; + + /* Read the BOS. This generates 2 requests on the bus, + * one for the header, and one for the full BOS */ + r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header, + LIBUSB_DT_BOS_SIZE); + if (r < 0) { + if (r != LIBUSB_ERROR_PIPE) + usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); + return r; + } + if (r < LIBUSB_DT_BOS_SIZE) { + usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d", + r, LIBUSB_DT_BOS_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian); + usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities", + _bos.wTotalLength, _bos.bNumDeviceCaps); + bos_data = calloc(_bos.wTotalLength, 1); + if (bos_data == NULL) + return LIBUSB_ERROR_NO_MEM; + + r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, + _bos.wTotalLength); + if (r >= 0) + r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian); + else + usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); + + free(bos_data); + return r; +} + +/** \ingroup libusb_desc + * Free a BOS descriptor obtained from libusb_get_bos_descriptor(). + * It is safe to call this function with a NULL bos parameter, in which + * case the function simply returns. + * + * \param bos the BOS descriptor to free + */ +void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) +{ + int i; + + if (!bos) + return; + + for (i = 0; i < bos->bNumDeviceCaps; i++) + free(bos->dev_capability[i]); + free(bos); +} + +/** \ingroup libusb_desc + * Get an USB 2.0 Extension descriptor + * + * \param ctx the context to operate on, or NULL for the default context + * \param dev_cap Device Capability descriptor with a bDevCapabilityType of + * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION + * LIBUSB_BT_USB_2_0_EXTENSION + * \param usb_2_0_extension output location for the USB 2.0 Extension + * descriptor. Only valid if 0 was returned. Must be freed with + * libusb_free_usb_2_0_extension_descriptor() after use. + * \returns 0 on success + * \returns a LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_usb_2_0_extension_descriptor( + struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) +{ + struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension; + const int host_endian = 0; + + if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) { + usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", + dev_cap->bDevCapabilityType, + LIBUSB_BT_USB_2_0_EXTENSION); + return LIBUSB_ERROR_INVALID_PARAM; + } + if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) { + usbi_err(ctx, "short dev-cap descriptor read %d/%d", + dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE); + return LIBUSB_ERROR_IO; + } + + _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension)); + if (!_usb_2_0_extension) + return LIBUSB_ERROR_NO_MEM; + + usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd", + _usb_2_0_extension, host_endian); + + *usb_2_0_extension = _usb_2_0_extension; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Free a USB 2.0 Extension descriptor obtained from + * libusb_get_usb_2_0_extension_descriptor(). + * It is safe to call this function with a NULL usb_2_0_extension parameter, + * in which case the function simply returns. + * + * \param usb_2_0_extension the USB 2.0 Extension descriptor to free + */ +void API_EXPORTED libusb_free_usb_2_0_extension_descriptor( + struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) +{ + free(usb_2_0_extension); +} + +/** \ingroup libusb_desc + * Get a SuperSpeed USB Device Capability descriptor + * + * \param ctx the context to operate on, or NULL for the default context + * \param dev_cap Device Capability descriptor with a bDevCapabilityType of + * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * \param ss_usb_device_cap output location for the SuperSpeed USB Device + * Capability descriptor. Only valid if 0 was returned. Must be freed with + * libusb_free_ss_usb_device_capability_descriptor() after use. + * \returns 0 on success + * \returns a LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( + struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap) +{ + struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap; + const int host_endian = 0; + + if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) { + usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", + dev_cap->bDevCapabilityType, + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY); + return LIBUSB_ERROR_INVALID_PARAM; + } + if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) { + usbi_err(ctx, "short dev-cap descriptor read %d/%d", + dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE); + return LIBUSB_ERROR_IO; + } + + _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap)); + if (!_ss_usb_device_cap) + return LIBUSB_ERROR_NO_MEM; + + usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw", + _ss_usb_device_cap, host_endian); + + *ss_usb_device_cap = _ss_usb_device_cap; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Free a SuperSpeed USB Device Capability descriptor obtained from + * libusb_get_ss_usb_device_capability_descriptor(). + * It is safe to call this function with a NULL ss_usb_device_cap + * parameter, in which case the function simply returns. + * + * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free + */ +void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( + struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap) +{ + free(ss_usb_device_cap); +} + +/** \ingroup libusb_desc + * Get a Container ID descriptor + * + * \param ctx the context to operate on, or NULL for the default context + * \param dev_cap Device Capability descriptor with a bDevCapabilityType of + * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID + * LIBUSB_BT_CONTAINER_ID + * \param container_id output location for the Container ID descriptor. + * Only valid if 0 was returned. Must be freed with + * libusb_free_container_id_descriptor() after use. + * \returns 0 on success + * \returns a LIBUSB_ERROR code on error + */ +int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_container_id_descriptor **container_id) +{ + struct libusb_container_id_descriptor *_container_id; + const int host_endian = 0; + + if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) { + usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", + dev_cap->bDevCapabilityType, + LIBUSB_BT_CONTAINER_ID); + return LIBUSB_ERROR_INVALID_PARAM; + } + if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) { + usbi_err(ctx, "short dev-cap descriptor read %d/%d", + dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE); + return LIBUSB_ERROR_IO; + } + + _container_id = malloc(sizeof(*_container_id)); + if (!_container_id) + return LIBUSB_ERROR_NO_MEM; + + usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu", + _container_id, host_endian); + + *container_id = _container_id; + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_desc + * Free a Container ID descriptor obtained from + * libusb_get_container_id_descriptor(). + * It is safe to call this function with a NULL container_id parameter, + * in which case the function simply returns. + * + * \param container_id the USB 2.0 Extension descriptor to free + */ +void API_EXPORTED libusb_free_container_id_descriptor( + struct libusb_container_id_descriptor *container_id) +{ + free(container_id); +} + +/** \ingroup libusb_desc + * Retrieve a string descriptor in C style ASCII. + * + * Wrapper around libusb_get_string_descriptor(). Uses the first language + * supported by the device. + * + * \param dev_handle a device handle + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for ASCII string descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, + uint8_t desc_index, unsigned char *data, int length) +{ + unsigned char tbuf[255]; /* Some devices choke on size > 255 */ + int r, si, di; + uint16_t langid; + + /* Asking for the zero'th index is special - it returns a string + * descriptor that contains all the language IDs supported by the + * device. Typically there aren't many - often only one. Language + * IDs are 16 bit numbers, and they start at the third byte in the + * descriptor. There's also no point in trying to read descriptor 0 + * with this function. See USB 2.0 specification section 9.6.7 for + * more information. + */ + + if (desc_index == 0) + return LIBUSB_ERROR_INVALID_PARAM; + + r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf)); + if (r < 0) + return r; + + if (r < 4) + return LIBUSB_ERROR_IO; + + langid = tbuf[2] | (tbuf[3] << 8); + + r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf, + sizeof(tbuf)); + if (r < 0) + return r; + + if (tbuf[1] != LIBUSB_DT_STRING) + return LIBUSB_ERROR_IO; + + if (tbuf[0] > r) + return LIBUSB_ERROR_IO; + + di = 0; + for (si = 2; si < tbuf[0]; si += 2) { + if (di >= (length - 1)) + break; + + if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */ + data[di++] = '?'; + else + data[di++] = tbuf[si]; + } + + data[di] = 0; + return di; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c new file mode 100644 index 0000000000..a4320bc42e --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c @@ -0,0 +1,373 @@ +/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ +/* + * Hotplug functions for libusb + * Copyright © 2012-2013 Nathan Hjelm + * Copyright © 2012-2013 Peter Stuge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include + +#include "libusbi.h" +#include "hotplug.h" + +/** + * @defgroup libusb_hotplug Device hotplug event notification + * This page details how to use the libusb hotplug interface, where available. + * + * Be mindful that not all platforms currently implement hotplug notification and + * that you should first call on \ref libusb_has_capability() with parameter + * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available. + * + * \page libusb_hotplug Device hotplug event notification + * + * \section hotplug_intro Introduction + * + * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support + * for hotplug events on some platforms (you should test if your platform + * supports hotplug notification by calling \ref libusb_has_capability() with + * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). + * + * This interface allows you to request notification for the arrival and departure + * of matching USB devices. + * + * To receive hotplug notification you register a callback by calling + * \ref libusb_hotplug_register_callback(). This function will optionally return + * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback(). + * + * A callback function must return an int (0 or 1) indicating whether the callback is + * expecting additional events. Returning 0 will rearm the callback and 1 will cause + * the callback to be deregistered. Note that when callbacks are called from + * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE + * flag, the callback return value is ignored, iow you cannot cause a callback + * to be deregistered by returning 1 when it is called from + * libusb_hotplug_register_callback(). + * + * Callbacks for a particular context are automatically deregistered by libusb_exit(). + * + * As of 1.0.16 there are two supported hotplug events: + * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use + * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available + * + * A hotplug event can listen for either or both of these events. + * + * Note: If you receive notification that a device has left and you have any + * a libusb_device_handles for the device it is up to you to call libusb_close() + * on each device handle to free up any remaining resources associated with the device. + * Once a device has left any libusb_device_handle associated with the device + * are invalid and will remain so even if the device comes back. + * + * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered + * safe to call any libusb function that takes a libusb_device. It also safe to + * open a device and submit asynchronous transfers. However, most other functions + * that take a libusb_device_handle are not safe to call. Examples of such + * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking + * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must + * be used outside of the context of the hotplug callback. + * + * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function + * is libusb_get_device_descriptor(). + * + * The following code provides an example of the usage of the hotplug interface: +\code +#include +#include +#include +#include + +static int count = 0; + +int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event, void *user_data) { + static libusb_device_handle *dev_handle = NULL; + struct libusb_device_descriptor desc; + int rc; + + (void)libusb_get_device_descriptor(dev, &desc); + + if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { + rc = libusb_open(dev, &dev_handle); + if (LIBUSB_SUCCESS != rc) { + printf("Could not open USB device\n"); + } + } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { + if (dev_handle) { + libusb_close(dev_handle); + dev_handle = NULL; + } + } else { + printf("Unhandled event %d\n", event); + } + count++; + + return 0; +} + +int main (void) { + libusb_hotplug_callback_handle callback_handle; + int rc; + + libusb_init(NULL); + + rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, + LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, + &callback_handle); + if (LIBUSB_SUCCESS != rc) { + printf("Error creating a hotplug callback\n"); + libusb_exit(NULL); + return EXIT_FAILURE; + } + + while (count < 2) { + libusb_handle_events_completed(NULL, NULL); + nanosleep(&(struct timespec){0, 10000000UL}, NULL); + } + + libusb_hotplug_deregister_callback(NULL, callback_handle); + libusb_exit(NULL); + + return 0; +} +\endcode + */ + +static int usbi_hotplug_match_cb(struct libusb_context *ctx, + struct libusb_device *dev, libusb_hotplug_event event, + struct libusb_hotplug_callback *hotplug_cb) +{ + if (!(hotplug_cb->flags & event)) { + return 0; + } + + if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) && + hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { + return 0; + } + + if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) && + hotplug_cb->product_id != dev->device_descriptor.idProduct) { + return 0; + } + + if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) && + hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { + return 0; + } + + return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data); +} + +void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event) +{ + struct libusb_hotplug_callback *hotplug_cb, *next; + int ret; + + usbi_mutex_lock(&ctx->hotplug_cbs_lock); + + list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) { + /* process deregistration in usbi_hotplug_deregister() */ + continue; + } + + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); + ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb); + usbi_mutex_lock(&ctx->hotplug_cbs_lock); + + if (ret) { + list_del(&hotplug_cb->list); + free(hotplug_cb); + } + } + + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); +} + +void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event) +{ + int pending_events; + struct libusb_hotplug_message *message = calloc(1, sizeof(*message)); + + if (!message) { + usbi_err(ctx, "error allocating hotplug message"); + return; + } + + message->event = event; + message->device = dev; + + /* Take the event data lock and add this message to the list. + * Only signal an event if there are no prior pending events. */ + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + list_add_tail(&message->list, &ctx->hotplug_msgs); + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); +} + +int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, + libusb_hotplug_event events, libusb_hotplug_flag flags, + int vendor_id, int product_id, int dev_class, + libusb_hotplug_callback_fn cb_fn, void *user_data, + libusb_hotplug_callback_handle *callback_handle) +{ + struct libusb_hotplug_callback *new_callback; + + /* check for sane values */ + if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) || + (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) || + (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || + (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || + (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || + !cb_fn) { + return LIBUSB_ERROR_INVALID_PARAM; + } + + /* check for hotplug support */ + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + USBI_GET_CONTEXT(ctx); + + new_callback = calloc(1, sizeof(*new_callback)); + if (!new_callback) { + return LIBUSB_ERROR_NO_MEM; + } + + new_callback->flags = (uint8_t)events; + if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) { + new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID; + new_callback->vendor_id = (uint16_t)vendor_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) { + new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID; + new_callback->product_id = (uint16_t)product_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) { + new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID; + new_callback->dev_class = (uint8_t)dev_class; + } + new_callback->cb = cb_fn; + new_callback->user_data = user_data; + + usbi_mutex_lock(&ctx->hotplug_cbs_lock); + + /* protect the handle by the context hotplug lock */ + new_callback->handle = ctx->next_hotplug_cb_handle++; + + /* handle the unlikely case of overflow */ + if (ctx->next_hotplug_cb_handle < 0) + ctx->next_hotplug_cb_handle = 1; + + list_add(&new_callback->list, &ctx->hotplug_cbs); + + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); + + usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle); + + if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) { + ssize_t i, len; + struct libusb_device **devs; + + len = libusb_get_device_list(ctx, &devs); + if (len < 0) { + libusb_hotplug_deregister_callback(ctx, + new_callback->handle); + return (int)len; + } + + for (i = 0; i < len; i++) { + usbi_hotplug_match_cb(ctx, devs[i], + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, + new_callback); + } + + libusb_free_device_list(devs, 1); + } + + + if (callback_handle) + *callback_handle = new_callback->handle; + + return LIBUSB_SUCCESS; +} + +void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle) +{ + struct libusb_hotplug_callback *hotplug_cb; + int deregistered = 0; + + /* check for hotplug support */ + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + return; + } + + USBI_GET_CONTEXT(ctx); + + usbi_dbg("deregister hotplug cb %d", callback_handle); + + usbi_mutex_lock(&ctx->hotplug_cbs_lock); + list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (callback_handle == hotplug_cb->handle) { + /* Mark this callback for deregistration */ + hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE; + deregistered = 1; + } + } + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); + + if (deregistered) { + int pending_events; + + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + } +} + +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced) +{ + struct libusb_hotplug_callback *hotplug_cb, *next; + + usbi_mutex_lock(&ctx->hotplug_cbs_lock); + list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) { + usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb, + hotplug_cb->handle); + list_del(&hotplug_cb->list); + free(hotplug_cb); + } + } + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h new file mode 100644 index 0000000000..dbadbcb93d --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ +/* + * Hotplug support for libusb + * Copyright © 2012-2013 Nathan Hjelm + * Copyright © 2012-2013 Peter Stuge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef USBI_HOTPLUG_H +#define USBI_HOTPLUG_H + +#include "libusbi.h" + +enum usbi_hotplug_flags { + /* This callback is interested in device arrivals */ + USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, + + /* This callback is interested in device removals */ + USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + + /* IMPORTANT: The values for the below entries must start *after* + * the highest value of the above entries!!! + */ + + /* The vendor_id field is valid for matching */ + USBI_HOTPLUG_VENDOR_ID_VALID = (1 << 3), + + /* The product_id field is valid for matching */ + USBI_HOTPLUG_PRODUCT_ID_VALID = (1 << 4), + + /* The dev_class field is valid for matching */ + USBI_HOTPLUG_DEV_CLASS_VALID = (1 << 5), + + /* This callback has been unregistered and needs to be freed */ + USBI_HOTPLUG_NEEDS_FREE = (1 << 6), +}; + +/** \ingroup hotplug + * The hotplug callback structure. The user populates this structure with + * libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback() + * to receive notification of hotplug events. + */ +struct libusb_hotplug_callback { + /** Flags that control how this callback behaves */ + uint8_t flags; + + /** Vendor ID to match (if flags says this is valid) */ + uint16_t vendor_id; + + /** Product ID to match (if flags says this is valid) */ + uint16_t product_id; + + /** Device class to match (if flags says this is valid) */ + uint8_t dev_class; + + /** Callback function to invoke for matching event/device */ + libusb_hotplug_callback_fn cb; + + /** Handle for this callback (used to match on deregister) */ + libusb_hotplug_callback_handle handle; + + /** User data that will be passed to the callback function */ + void *user_data; + + /** List this callback is registered in (ctx->hotplug_cbs) */ + struct list_head list; +}; + +struct libusb_hotplug_message { + /** The hotplug event that occurred */ + libusb_hotplug_event event; + + /** The device for which this hotplug event occurred */ + struct libusb_device *device; + + /** List this message is contained in (ctx->hotplug_msgs) */ + struct list_head list; +}; + +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced); +void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event); +void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event); + +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/io.c b/vendor/github.com/karalabe/usb/libusb/libusb/io.c new file mode 100644 index 0000000000..a03bfaae1a --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/io.c @@ -0,0 +1,2822 @@ +/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ +/* + * I/O functions for libusb + * Copyright © 2007-2009 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef USBI_TIMERFD_AVAILABLE +#include +#endif + +#include "libusbi.h" +#include "hotplug.h" + +/** + * \page libusb_io Synchronous and asynchronous device I/O + * + * \section io_intro Introduction + * + * If you're using libusb in your application, you're probably wanting to + * perform I/O with devices - you want to perform USB data transfers. + * + * libusb offers two separate interfaces for device I/O. This page aims to + * introduce the two in order to help you decide which one is more suitable + * for your application. You can also choose to use both interfaces in your + * application by considering each transfer on a case-by-case basis. + * + * Once you have read through the following discussion, you should consult the + * detailed API documentation pages for the details: + * - \ref libusb_syncio + * - \ref libusb_asyncio + * + * \section theory Transfers at a logical level + * + * At a logical level, USB transfers typically happen in two parts. For + * example, when reading data from a endpoint: + * -# A request for data is sent to the device + * -# Some time later, the incoming data is received by the host + * + * or when writing data to an endpoint: + * + * -# The data is sent to the device + * -# Some time later, the host receives acknowledgement from the device that + * the data has been transferred. + * + * There may be an indefinite delay between the two steps. Consider a + * fictional USB input device with a button that the user can press. In order + * to determine when the button is pressed, you would likely submit a request + * to read data on a bulk or interrupt endpoint and wait for data to arrive. + * Data will arrive when the button is pressed by the user, which is + * potentially hours later. + * + * libusb offers both a synchronous and an asynchronous interface to performing + * USB transfers. The main difference is that the synchronous interface + * combines both steps indicated above into a single function call, whereas + * the asynchronous interface separates them. + * + * \section sync The synchronous interface + * + * The synchronous I/O interface allows you to perform a USB transfer with + * a single function call. When the function call returns, the transfer has + * completed and you can parse the results. + * + * If you have used the libusb-0.1 before, this I/O style will seem familar to + * you. libusb-0.1 only offered a synchronous interface. + * + * In our input device example, to read button presses you might write code + * in the following style: +\code +unsigned char data[4]; +int actual_length; +int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); +if (r == 0 && actual_length == sizeof(data)) { + // results of the transaction can now be found in the data buffer + // parse them here and report button press +} else { + error(); +} +\endcode + * + * The main advantage of this model is simplicity: you did everything with + * a single simple function call. + * + * However, this interface has its limitations. Your application will sleep + * inside libusb_bulk_transfer() until the transaction has completed. If it + * takes the user 3 hours to press the button, your application will be + * sleeping for that long. Execution will be tied up inside the library - + * the entire thread will be useless for that duration. + * + * Another issue is that by tieing up the thread with that single transaction + * there is no possibility of performing I/O with multiple endpoints and/or + * multiple devices simultaneously, unless you resort to creating one thread + * per transaction. + * + * Additionally, there is no opportunity to cancel the transfer after the + * request has been submitted. + * + * For details on how to use the synchronous API, see the + * \ref libusb_syncio "synchronous I/O API documentation" pages. + * + * \section async The asynchronous interface + * + * Asynchronous I/O is the most significant new feature in libusb-1.0. + * Although it is a more complex interface, it solves all the issues detailed + * above. + * + * Instead of providing which functions that block until the I/O has complete, + * libusb's asynchronous interface presents non-blocking functions which + * begin a transfer and then return immediately. Your application passes a + * callback function pointer to this non-blocking function, which libusb will + * call with the results of the transaction when it has completed. + * + * Transfers which have been submitted through the non-blocking functions + * can be cancelled with a separate function call. + * + * The non-blocking nature of this interface allows you to be simultaneously + * performing I/O to multiple endpoints on multiple devices, without having + * to use threads. + * + * This added flexibility does come with some complications though: + * - In the interest of being a lightweight library, libusb does not create + * threads and can only operate when your application is calling into it. Your + * application must call into libusb from it's main loop when events are ready + * to be handled, or you must use some other scheme to allow libusb to + * undertake whatever work needs to be done. + * - libusb also needs to be called into at certain fixed points in time in + * order to accurately handle transfer timeouts. + * - Memory handling becomes more complex. You cannot use stack memory unless + * the function with that stack is guaranteed not to return until the transfer + * callback has finished executing. + * - You generally lose some linearity from your code flow because submitting + * the transfer request is done in a separate function from where the transfer + * results are handled. This becomes particularly obvious when you want to + * submit a second transfer based on the results of an earlier transfer. + * + * Internally, libusb's synchronous interface is expressed in terms of function + * calls to the asynchronous interface. + * + * For details on how to use the asynchronous API, see the + * \ref libusb_asyncio "asynchronous I/O API" documentation pages. + */ + + +/** + * \page libusb_packetoverflow Packets and overflows + * + * \section packets Packet abstraction + * + * The USB specifications describe how data is transmitted in packets, with + * constraints on packet size defined by endpoint descriptors. The host must + * not send data payloads larger than the endpoint's maximum packet size. + * + * libusb and the underlying OS abstract out the packet concept, allowing you + * to request transfers of any size. Internally, the request will be divided + * up into correctly-sized packets. You do not have to be concerned with + * packet sizes, but there is one exception when considering overflows. + * + * \section overflow Bulk/interrupt transfer overflows + * + * When requesting data on a bulk endpoint, libusb requires you to supply a + * buffer and the maximum number of bytes of data that libusb can put in that + * buffer. However, the size of the buffer is not communicated to the device - + * the device is just asked to send any amount of data. + * + * There is no problem if the device sends an amount of data that is less than + * or equal to the buffer size. libusb reports this condition to you through + * the \ref libusb_transfer::actual_length "libusb_transfer.actual_length" + * field. + * + * Problems may occur if the device attempts to send more data than can fit in + * the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but + * other behaviour is largely undefined: actual_length may or may not be + * accurate, the chunk of data that can fit in the buffer (before overflow) + * may or may not have been transferred. + * + * Overflows are nasty, but can be avoided. Even though you were told to + * ignore packets above, think about the lower level details: each transfer is + * split into packets (typically small, with a maximum size of 512 bytes). + * Overflows can only happen if the final packet in an incoming data transfer + * is smaller than the actual packet that the device wants to transfer. + * Therefore, you will never see an overflow if your transfer buffer size is a + * multiple of the endpoint's packet size: the final packet will either + * fill up completely or will be only partially filled. + */ + +/** + * @defgroup libusb_asyncio Asynchronous device I/O + * + * This page details libusb's asynchronous (non-blocking) API for USB device + * I/O. This interface is very powerful but is also quite complex - you will + * need to read this page carefully to understand the necessary considerations + * and issues surrounding use of this interface. Simplistic applications + * may wish to consider the \ref libusb_syncio "synchronous I/O API" instead. + * + * The asynchronous interface is built around the idea of separating transfer + * submission and handling of transfer completion (the synchronous model + * combines both of these into one). There may be a long delay between + * submission and completion, however the asynchronous submission function + * is non-blocking so will return control to your application during that + * potentially long delay. + * + * \section asyncabstraction Transfer abstraction + * + * For the asynchronous I/O, libusb implements the concept of a generic + * transfer entity for all types of I/O (control, bulk, interrupt, + * isochronous). The generic transfer object must be treated slightly + * differently depending on which type of I/O you are performing with it. + * + * This is represented by the public libusb_transfer structure type. + * + * \section asynctrf Asynchronous transfers + * + * We can view asynchronous I/O as a 5 step process: + * -# Allocation: allocate a libusb_transfer + * -# Filling: populate the libusb_transfer instance with information + * about the transfer you wish to perform + * -# Submission: ask libusb to submit the transfer + * -# Completion handling: examine transfer results in the + * libusb_transfer structure + * -# Deallocation: clean up resources + * + * + * \subsection asyncalloc Allocation + * + * This step involves allocating memory for a USB transfer. This is the + * generic transfer object mentioned above. At this stage, the transfer + * is "blank" with no details about what type of I/O it will be used for. + * + * Allocation is done with the libusb_alloc_transfer() function. You must use + * this function rather than allocating your own transfers. + * + * \subsection asyncfill Filling + * + * This step is where you take a previously allocated transfer and fill it + * with information to determine the message type and direction, data buffer, + * callback function, etc. + * + * You can either fill the required fields yourself or you can use the + * helper functions: libusb_fill_control_transfer(), libusb_fill_bulk_transfer() + * and libusb_fill_interrupt_transfer(). + * + * \subsection asyncsubmit Submission + * + * When you have allocated a transfer and filled it, you can submit it using + * libusb_submit_transfer(). This function returns immediately but can be + * regarded as firing off the I/O request in the background. + * + * \subsection asynccomplete Completion handling + * + * After a transfer has been submitted, one of four things can happen to it: + * + * - The transfer completes (i.e. some data was transferred) + * - The transfer has a timeout and the timeout expires before all data is + * transferred + * - The transfer fails due to an error + * - The transfer is cancelled + * + * Each of these will cause the user-specified transfer callback function to + * be invoked. It is up to the callback function to determine which of the + * above actually happened and to act accordingly. + * + * The user-specified callback is passed a pointer to the libusb_transfer + * structure which was used to setup and submit the transfer. At completion + * time, libusb has populated this structure with results of the transfer: + * success or failure reason, number of bytes of data transferred, etc. See + * the libusb_transfer structure documentation for more information. + * + * Important Note: The user-specified callback is called from an event + * handling context. It is therefore important that no calls are made into + * libusb that will attempt to perform any event handling. Examples of such + * functions are any listed in the \ref libusb_syncio "synchronous API" and any of + * the blocking functions that retrieve \ref libusb_desc "USB descriptors". + * + * \subsection Deallocation + * + * When a transfer has completed (i.e. the callback function has been invoked), + * you are advised to free the transfer (unless you wish to resubmit it, see + * below). Transfers are deallocated with libusb_free_transfer(). + * + * It is undefined behaviour to free a transfer which has not completed. + * + * \section asyncresubmit Resubmission + * + * You may be wondering why allocation, filling, and submission are all + * separated above where they could reasonably be combined into a single + * operation. + * + * The reason for separation is to allow you to resubmit transfers without + * having to allocate new ones every time. This is especially useful for + * common situations dealing with interrupt endpoints - you allocate one + * transfer, fill and submit it, and when it returns with results you just + * resubmit it for the next interrupt. + * + * \section asynccancel Cancellation + * + * Another advantage of using the asynchronous interface is that you have + * the ability to cancel transfers which have not yet completed. This is + * done by calling the libusb_cancel_transfer() function. + * + * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the + * cancellation actually completes, the transfer's callback function will + * be invoked, and the callback function should check the transfer status to + * determine that it was cancelled. + * + * Freeing the transfer after it has been cancelled but before cancellation + * has completed will result in undefined behaviour. + * + * When a transfer is cancelled, some of the data may have been transferred. + * libusb will communicate this to you in the transfer callback. Do not assume + * that no data was transferred. + * + * \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints + * + * If your device does not have predictable transfer sizes (or it misbehaves), + * your application may submit a request for data on an IN endpoint which is + * smaller than the data that the device wishes to send. In some circumstances + * this will cause an overflow, which is a nasty condition to deal with. See + * the \ref libusb_packetoverflow page for discussion. + * + * \section asyncctrl Considerations for control transfers + * + * The libusb_transfer structure is generic and hence does not + * include specific fields for the control-specific setup packet structure. + * + * In order to perform a control transfer, you must place the 8-byte setup + * packet at the start of the data buffer. To simplify this, you could + * cast the buffer pointer to type struct libusb_control_setup, or you can + * use the helper function libusb_fill_control_setup(). + * + * The wLength field placed in the setup packet must be the length you would + * expect to be sent in the setup packet: the length of the payload that + * follows (or the expected maximum number of bytes to receive). However, + * the length field of the libusb_transfer object must be the length of + * the data buffer - i.e. it should be wLength plus the size of + * the setup packet (LIBUSB_CONTROL_SETUP_SIZE). + * + * If you use the helper functions, this is simplified for you: + * -# Allocate a buffer of size LIBUSB_CONTROL_SETUP_SIZE plus the size of the + * data you are sending/requesting. + * -# Call libusb_fill_control_setup() on the data buffer, using the transfer + * request size as the wLength value (i.e. do not include the extra space you + * allocated for the control setup). + * -# If this is a host-to-device transfer, place the data to be transferred + * in the data buffer, starting at offset LIBUSB_CONTROL_SETUP_SIZE. + * -# Call libusb_fill_control_transfer() to associate the data buffer with + * the transfer (and to set the remaining details such as callback and timeout). + * - Note that there is no parameter to set the length field of the transfer. + * The length is automatically inferred from the wLength field of the setup + * packet. + * -# Submit the transfer. + * + * The multi-byte control setup fields (wValue, wIndex and wLength) must + * be given in little-endian byte order (the endianness of the USB bus). + * Endianness conversion is transparently handled by + * libusb_fill_control_setup() which is documented to accept host-endian + * values. + * + * Further considerations are needed when handling transfer completion in + * your callback function: + * - As you might expect, the setup packet will still be sitting at the start + * of the data buffer. + * - If this was a device-to-host transfer, the received data will be sitting + * at offset LIBUSB_CONTROL_SETUP_SIZE into the buffer. + * - The actual_length field of the transfer structure is relative to the + * wLength of the setup packet, rather than the size of the data buffer. So, + * if your wLength was 4, your transfer's length was 12, then you + * should expect an actual_length of 4 to indicate that the data was + * transferred in entirity. + * + * To simplify parsing of setup packets and obtaining the data from the + * correct offset, you may wish to use the libusb_control_transfer_get_data() + * and libusb_control_transfer_get_setup() functions within your transfer + * callback. + * + * Even though control endpoints do not halt, a completed control transfer + * may have a LIBUSB_TRANSFER_STALL status code. This indicates the control + * request was not supported. + * + * \section asyncintr Considerations for interrupt transfers + * + * All interrupt transfers are performed using the polling interval presented + * by the bInterval value of the endpoint descriptor. + * + * \section asynciso Considerations for isochronous transfers + * + * Isochronous transfers are more complicated than transfers to + * non-isochronous endpoints. + * + * To perform I/O to an isochronous endpoint, allocate the transfer by calling + * libusb_alloc_transfer() with an appropriate number of isochronous packets. + * + * During filling, set \ref libusb_transfer::type "type" to + * \ref libusb_transfer_type::LIBUSB_TRANSFER_TYPE_ISOCHRONOUS + * "LIBUSB_TRANSFER_TYPE_ISOCHRONOUS", and set + * \ref libusb_transfer::num_iso_packets "num_iso_packets" to a value less than + * or equal to the number of packets you requested during allocation. + * libusb_alloc_transfer() does not set either of these fields for you, given + * that you might not even use the transfer on an isochronous endpoint. + * + * Next, populate the length field for the first num_iso_packets entries in + * the \ref libusb_transfer::iso_packet_desc "iso_packet_desc" array. Section + * 5.6.3 of the USB2 specifications describe how the maximum isochronous + * packet length is determined by the wMaxPacketSize field in the endpoint + * descriptor. + * Two functions can help you here: + * + * - libusb_get_max_iso_packet_size() is an easy way to determine the max + * packet size for an isochronous endpoint. Note that the maximum packet + * size is actually the maximum number of bytes that can be transmitted in + * a single microframe, therefore this function multiplies the maximum number + * of bytes per transaction by the number of transaction opportunities per + * microframe. + * - libusb_set_iso_packet_lengths() assigns the same length to all packets + * within a transfer, which is usually what you want. + * + * For outgoing transfers, you'll obviously fill the buffer and populate the + * packet descriptors in hope that all the data gets transferred. For incoming + * transfers, you must ensure the buffer has sufficient capacity for + * the situation where all packets transfer the full amount of requested data. + * + * Completion handling requires some extra consideration. The + * \ref libusb_transfer::actual_length "actual_length" field of the transfer + * is meaningless and should not be examined; instead you must refer to the + * \ref libusb_iso_packet_descriptor::actual_length "actual_length" field of + * each individual packet. + * + * The \ref libusb_transfer::status "status" field of the transfer is also a + * little misleading: + * - If the packets were submitted and the isochronous data microframes + * completed normally, status will have value + * \ref libusb_transfer_status::LIBUSB_TRANSFER_COMPLETED + * "LIBUSB_TRANSFER_COMPLETED". Note that bus errors and software-incurred + * delays are not counted as transfer errors; the transfer.status field may + * indicate COMPLETED even if some or all of the packets failed. Refer to + * the \ref libusb_iso_packet_descriptor::status "status" field of each + * individual packet to determine packet failures. + * - The status field will have value + * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR + * "LIBUSB_TRANSFER_ERROR" only when serious errors were encountered. + * - Other transfer status codes occur with normal behaviour. + * + * The data for each packet will be found at an offset into the buffer that + * can be calculated as if each prior packet completed in full. The + * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple() + * functions may help you here. + * + * Note: Some operating systems (e.g. Linux) may impose limits on the + * length of individual isochronous packets and/or the total length of the + * isochronous transfer. Such limits can be difficult for libusb to detect, + * so the library will simply try and submit the transfer as set up by you. + * If the transfer fails to submit because it is too large, + * libusb_submit_transfer() will return + * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM". + * + * \section asyncmem Memory caveats + * + * In most circumstances, it is not safe to use stack memory for transfer + * buffers. This is because the function that fired off the asynchronous + * transfer may return before libusb has finished using the buffer, and when + * the function returns it's stack gets destroyed. This is true for both + * host-to-device and device-to-host transfers. + * + * The only case in which it is safe to use stack memory is where you can + * guarantee that the function owning the stack space for the buffer does not + * return until after the transfer's callback function has completed. In every + * other case, you need to use heap memory instead. + * + * \section asyncflags Fine control + * + * Through using this asynchronous interface, you may find yourself repeating + * a few simple operations many times. You can apply a bitwise OR of certain + * flags to a transfer to simplify certain things: + * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_SHORT_NOT_OK + * "LIBUSB_TRANSFER_SHORT_NOT_OK" results in transfers which transferred + * less than the requested amount of data being marked with status + * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR "LIBUSB_TRANSFER_ERROR" + * (they would normally be regarded as COMPLETED) + * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER + * "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusb to free the transfer + * buffer when freeing the transfer. + * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_TRANSFER + * "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusb to automatically free the + * transfer after the transfer callback returns. + * + * \section asyncevent Event handling + * + * An asynchronous model requires that libusb perform work at various + * points in time - namely processing the results of previously-submitted + * transfers and invoking the user-supplied callback function. + * + * This gives rise to the libusb_handle_events() function which your + * application must call into when libusb has work do to. This gives libusb + * the opportunity to reap pending transfers, invoke callbacks, etc. + * + * There are 2 different approaches to dealing with libusb_handle_events: + * + * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated + * thread. + * -# Integrate libusb with your application's main event loop. libusb + * exposes a set of file descriptors which allow you to do this. + * + * The first approach has the big advantage that it will also work on Windows + * were libusb' poll API for select / poll integration is not available. So + * if you want to support Windows and use the async API, you must use this + * approach, see the \ref eventthread "Using an event handling thread" section + * below for details. + * + * If you prefer a single threaded approach with a single central event loop, + * see the \ref libusb_poll "polling and timing" section for how to integrate libusb + * into your application's main event loop. + * + * \section eventthread Using an event handling thread + * + * Lets begin with stating the obvious: If you're going to use a separate + * thread for libusb event handling, your callback functions MUST be + * threadsafe. + * + * Other then that doing event handling from a separate thread, is mostly + * simple. You can use an event thread function as follows: +\code +void *event_thread_func(void *ctx) +{ + while (event_thread_run) + libusb_handle_events(ctx); + + return NULL; +} +\endcode + * + * There is one caveat though, stopping this thread requires setting the + * event_thread_run variable to 0, and after that libusb_handle_events() needs + * to return control to event_thread_func. But unless some event happens, + * libusb_handle_events() will not return. + * + * There are 2 different ways of dealing with this, depending on if your + * application uses libusb' \ref libusb_hotplug "hotplug" support or not. + * + * Applications which do not use hotplug support, should not start the event + * thread until after their first call to libusb_open(), and should stop the + * thread when closing the last open device as follows: +\code +void my_close_handle(libusb_device_handle *dev_handle) +{ + if (open_devs == 1) + event_thread_run = 0; + + libusb_close(dev_handle); // This wakes up libusb_handle_events() + + if (open_devs == 1) + pthread_join(event_thread); + + open_devs--; +} +\endcode + * + * Applications using hotplug support should start the thread at program init, + * after having successfully called libusb_hotplug_register_callback(), and + * should stop the thread at program exit as follows: +\code +void my_libusb_exit(void) +{ + event_thread_run = 0; + libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events() + pthread_join(event_thread); + libusb_exit(ctx); +} +\endcode + */ + +/** + * @defgroup libusb_poll Polling and timing + * + * This page documents libusb's functions for polling events and timing. + * These functions are only necessary for users of the + * \ref libusb_asyncio "asynchronous API". If you are only using the simpler + * \ref libusb_syncio "synchronous API" then you do not need to ever call these + * functions. + * + * The justification for the functionality described here has already been + * discussed in the \ref asyncevent "event handling" section of the + * asynchronous API documentation. In summary, libusb does not create internal + * threads for event processing and hence relies on your application calling + * into libusb at certain points in time so that pending events can be handled. + * + * Your main loop is probably already calling poll() or select() or a + * variant on a set of file descriptors for other event sources (e.g. keyboard + * button presses, mouse movements, network sockets, etc). You then add + * libusb's file descriptors to your poll()/select() calls, and when activity + * is detected on such descriptors you know it is time to call + * libusb_handle_events(). + * + * There is one final event handling complication. libusb supports + * asynchronous transfers which time out after a specified time period. + * + * On some platforms a timerfd is used, so the timeout handling is just another + * fd, on other platforms this requires that libusb is called into at or after + * the timeout to handle it. So, in addition to considering libusb's file + * descriptors in your main event loop, you must also consider that libusb + * sometimes needs to be called into at fixed points in time even when there + * is no file descriptor activity, see \ref polltime details. + * + * In order to know precisely when libusb needs to be called into, libusb + * offers you a set of pollable file descriptors and information about when + * the next timeout expires. + * + * If you are using the asynchronous I/O API, you must take one of the two + * following options, otherwise your I/O will not complete. + * + * \section pollsimple The simple option + * + * If your application revolves solely around libusb and does not need to + * handle other event sources, you can have a program structure as follows: +\code +// initialize libusb +// find and open device +// maybe fire off some initial async I/O + +while (user_has_not_requested_exit) + libusb_handle_events(ctx); + +// clean up and exit +\endcode + * + * With such a simple main loop, you do not have to worry about managing + * sets of file descriptors or handling timeouts. libusb_handle_events() will + * handle those details internally. + * + * \section libusb_pollmain The more advanced option + * + * \note This functionality is currently only available on Unix-like platforms. + * On Windows, libusb_get_pollfds() simply returns NULL. Applications which + * want to support Windows are advised to use an \ref eventthread + * "event handling thread" instead. + * + * In more advanced applications, you will already have a main loop which + * is monitoring other event sources: network sockets, X11 events, mouse + * movements, etc. Through exposing a set of file descriptors, libusb is + * designed to cleanly integrate into such main loops. + * + * In addition to polling file descriptors for the other event sources, you + * take a set of file descriptors from libusb and monitor those too. When you + * detect activity on libusb's file descriptors, you call + * libusb_handle_events_timeout() in non-blocking mode. + * + * What's more, libusb may also need to handle events at specific moments in + * time. No file descriptor activity is generated at these times, so your + * own application needs to be continually aware of when the next one of these + * moments occurs (through calling libusb_get_next_timeout()), and then it + * needs to call libusb_handle_events_timeout() in non-blocking mode when + * these moments occur. This means that you need to adjust your + * poll()/select() timeout accordingly. + * + * libusb provides you with a set of file descriptors to poll and expects you + * to poll all of them, treating them as a single entity. The meaning of each + * file descriptor in the set is an internal implementation detail, + * platform-dependent and may vary from release to release. Don't try and + * interpret the meaning of the file descriptors, just do as libusb indicates, + * polling all of them at once. + * + * In pseudo-code, you want something that looks like: +\code +// initialise libusb + +libusb_get_pollfds(ctx) +while (user has not requested application exit) { + libusb_get_next_timeout(ctx); + poll(on libusb file descriptors plus any other event sources of interest, + using a timeout no larger than the value libusb just suggested) + if (poll() indicated activity on libusb file descriptors) + libusb_handle_events_timeout(ctx, &zero_tv); + if (time has elapsed to or beyond the libusb timeout) + libusb_handle_events_timeout(ctx, &zero_tv); + // handle events from other sources here +} + +// clean up and exit +\endcode + * + * \subsection polltime Notes on time-based events + * + * The above complication with having to track time and call into libusb at + * specific moments is a bit of a headache. For maximum compatibility, you do + * need to write your main loop as above, but you may decide that you can + * restrict the supported platforms of your application and get away with + * a more simplistic scheme. + * + * These time-based event complications are \b not required on the following + * platforms: + * - Darwin + * - Linux, provided that the following version requirements are satisfied: + * - Linux v2.6.27 or newer, compiled with timerfd support + * - glibc v2.9 or newer + * - libusb v1.0.5 or newer + * + * Under these configurations, libusb_get_next_timeout() will \em always return + * 0, so your main loop can be simplified to: +\code +// initialise libusb + +libusb_get_pollfds(ctx) +while (user has not requested application exit) { + poll(on libusb file descriptors plus any other event sources of interest, + using any timeout that you like) + if (poll() indicated activity on libusb file descriptors) + libusb_handle_events_timeout(ctx, &zero_tv); + // handle events from other sources here +} + +// clean up and exit +\endcode + * + * Do remember that if you simplify your main loop to the above, you will + * lose compatibility with some platforms (including legacy Linux platforms, + * and any future platforms supported by libusb which may have time-based + * event requirements). The resultant problems will likely appear as + * strange bugs in your application. + * + * You can use the libusb_pollfds_handle_timeouts() function to do a runtime + * check to see if it is safe to ignore the time-based event complications. + * If your application has taken the shortcut of ignoring libusb's next timeout + * in your main loop, then you are advised to check the return value of + * libusb_pollfds_handle_timeouts() during application startup, and to abort + * if the platform does suffer from these timing complications. + * + * \subsection fdsetchange Changes in the file descriptor set + * + * The set of file descriptors that libusb uses as event sources may change + * during the life of your application. Rather than having to repeatedly + * call libusb_get_pollfds(), you can set up notification functions for when + * the file descriptor set changes using libusb_set_pollfd_notifiers(). + * + * \subsection mtissues Multi-threaded considerations + * + * Unfortunately, the situation is complicated further when multiple threads + * come into play. If two threads are monitoring the same file descriptors, + * the fact that only one thread will be woken up when an event occurs causes + * some headaches. + * + * The events lock, event waiters lock, and libusb_handle_events_locked() + * entities are added to solve these problems. You do not need to be concerned + * with these entities otherwise. + * + * See the extra documentation: \ref libusb_mtasync + */ + +/** \page libusb_mtasync Multi-threaded applications and asynchronous I/O + * + * libusb is a thread-safe library, but extra considerations must be applied + * to applications which interact with libusb from multiple threads. + * + * The underlying issue that must be addressed is that all libusb I/O + * revolves around monitoring file descriptors through the poll()/select() + * system calls. This is directly exposed at the + * \ref libusb_asyncio "asynchronous interface" but it is important to note that the + * \ref libusb_syncio "synchronous interface" is implemented on top of the + * asynchonrous interface, therefore the same considerations apply. + * + * The issue is that if two or more threads are concurrently calling poll() + * or select() on libusb's file descriptors then only one of those threads + * will be woken up when an event arrives. The others will be completely + * oblivious that anything has happened. + * + * Consider the following pseudo-code, which submits an asynchronous transfer + * then waits for its completion. This style is one way you could implement a + * synchronous interface on top of the asynchronous interface (and libusb + * does something similar, albeit more advanced due to the complications + * explained on this page). + * +\code +void cb(struct libusb_transfer *transfer) +{ + int *completed = transfer->user_data; + *completed = 1; +} + +void myfunc() { + struct libusb_transfer *transfer; + unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2))); + int completed = 0; + + transfer = libusb_alloc_transfer(0); + libusb_fill_control_setup(buffer, + LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x04, 0x01, 0, 0); + libusb_fill_control_transfer(transfer, dev, buffer, cb, &completed, 1000); + libusb_submit_transfer(transfer); + + while (!completed) { + poll(libusb file descriptors, 120*1000); + if (poll indicates activity) + libusb_handle_events_timeout(ctx, &zero_tv); + } + printf("completed!"); + // other code here +} +\endcode + * + * Here we are serializing completion of an asynchronous event + * against a condition - the condition being completion of a specific transfer. + * The poll() loop has a long timeout to minimize CPU usage during situations + * when nothing is happening (it could reasonably be unlimited). + * + * If this is the only thread that is polling libusb's file descriptors, there + * is no problem: there is no danger that another thread will swallow up the + * event that we are interested in. On the other hand, if there is another + * thread polling the same descriptors, there is a chance that it will receive + * the event that we were interested in. In this situation, myfunc() + * will only realise that the transfer has completed on the next iteration of + * the loop, up to 120 seconds later. Clearly a two-minute delay is + * undesirable, and don't even think about using short timeouts to circumvent + * this issue! + * + * The solution here is to ensure that no two threads are ever polling the + * file descriptors at the same time. A naive implementation of this would + * impact the capabilities of the library, so libusb offers the scheme + * documented below to ensure no loss of functionality. + * + * Before we go any further, it is worth mentioning that all libusb-wrapped + * event handling procedures fully adhere to the scheme documented below. + * This includes libusb_handle_events() and its variants, and all the + * synchronous I/O functions - libusb hides this headache from you. + * + * \section Using libusb_handle_events() from multiple threads + * + * Even when only using libusb_handle_events() and synchronous I/O functions, + * you can still have a race condition. You might be tempted to solve the + * above with libusb_handle_events() like so: + * +\code + libusb_submit_transfer(transfer); + + while (!completed) { + libusb_handle_events(ctx); + } + printf("completed!"); +\endcode + * + * This however has a race between the checking of completed and + * libusb_handle_events() acquiring the events lock, so another thread + * could have completed the transfer, resulting in this thread hanging + * until either a timeout or another event occurs. See also commit + * 6696512aade99bb15d6792af90ae329af270eba6 which fixes this in the + * synchronous API implementation of libusb. + * + * Fixing this race requires checking the variable completed only after + * taking the event lock, which defeats the concept of just calling + * libusb_handle_events() without worrying about locking. This is why + * libusb-1.0.9 introduces the new libusb_handle_events_timeout_completed() + * and libusb_handle_events_completed() functions, which handles doing the + * completion check for you after they have acquired the lock: + * +\code + libusb_submit_transfer(transfer); + + while (!completed) { + libusb_handle_events_completed(ctx, &completed); + } + printf("completed!"); +\endcode + * + * This nicely fixes the race in our example. Note that if all you want to + * do is submit a single transfer and wait for its completion, then using + * one of the synchronous I/O functions is much easier. + * + * \section eventlock The events lock + * + * The problem is when we consider the fact that libusb exposes file + * descriptors to allow for you to integrate asynchronous USB I/O into + * existing main loops, effectively allowing you to do some work behind + * libusb's back. If you do take libusb's file descriptors and pass them to + * poll()/select() yourself, you need to be aware of the associated issues. + * + * The first concept to be introduced is the events lock. The events lock + * is used to serialize threads that want to handle events, such that only + * one thread is handling events at any one time. + * + * You must take the events lock before polling libusb file descriptors, + * using libusb_lock_events(). You must release the lock as soon as you have + * aborted your poll()/select() loop, using libusb_unlock_events(). + * + * \section threadwait Letting other threads do the work for you + * + * Although the events lock is a critical part of the solution, it is not + * enough on it's own. You might wonder if the following is sufficient... +\code + libusb_lock_events(ctx); + while (!completed) { + poll(libusb file descriptors, 120*1000); + if (poll indicates activity) + libusb_handle_events_timeout(ctx, &zero_tv); + } + libusb_unlock_events(ctx); +\endcode + * ...and the answer is that it is not. This is because the transfer in the + * code shown above may take a long time (say 30 seconds) to complete, and + * the lock is not released until the transfer is completed. + * + * Another thread with similar code that wants to do event handling may be + * working with a transfer that completes after a few milliseconds. Despite + * having such a quick completion time, the other thread cannot check that + * status of its transfer until the code above has finished (30 seconds later) + * due to contention on the lock. + * + * To solve this, libusb offers you a mechanism to determine when another + * thread is handling events. It also offers a mechanism to block your thread + * until the event handling thread has completed an event (and this mechanism + * does not involve polling of file descriptors). + * + * After determining that another thread is currently handling events, you + * obtain the event waiters lock using libusb_lock_event_waiters(). + * You then re-check that some other thread is still handling events, and if + * so, you call libusb_wait_for_event(). + * + * libusb_wait_for_event() puts your application to sleep until an event + * occurs, or until a thread releases the events lock. When either of these + * things happen, your thread is woken up, and should re-check the condition + * it was waiting on. It should also re-check that another thread is handling + * events, and if not, it should start handling events itself. + * + * This looks like the following, as pseudo-code: +\code +retry: +if (libusb_try_lock_events(ctx) == 0) { + // we obtained the event lock: do our own event handling + while (!completed) { + if (!libusb_event_handling_ok(ctx)) { + libusb_unlock_events(ctx); + goto retry; + } + poll(libusb file descriptors, 120*1000); + if (poll indicates activity) + libusb_handle_events_locked(ctx, 0); + } + libusb_unlock_events(ctx); +} else { + // another thread is doing event handling. wait for it to signal us that + // an event has completed + libusb_lock_event_waiters(ctx); + + while (!completed) { + // now that we have the event waiters lock, double check that another + // thread is still handling events for us. (it may have ceased handling + // events in the time it took us to reach this point) + if (!libusb_event_handler_active(ctx)) { + // whoever was handling events is no longer doing so, try again + libusb_unlock_event_waiters(ctx); + goto retry; + } + + libusb_wait_for_event(ctx, NULL); + } + libusb_unlock_event_waiters(ctx); +} +printf("completed!\n"); +\endcode + * + * A naive look at the above code may suggest that this can only support + * one event waiter (hence a total of 2 competing threads, the other doing + * event handling), because the event waiter seems to have taken the event + * waiters lock while waiting for an event. However, the system does support + * multiple event waiters, because libusb_wait_for_event() actually drops + * the lock while waiting, and reaquires it before continuing. + * + * We have now implemented code which can dynamically handle situations where + * nobody is handling events (so we should do it ourselves), and it can also + * handle situations where another thread is doing event handling (so we can + * piggyback onto them). It is also equipped to handle a combination of + * the two, for example, another thread is doing event handling, but for + * whatever reason it stops doing so before our condition is met, so we take + * over the event handling. + * + * Four functions were introduced in the above pseudo-code. Their importance + * should be apparent from the code shown above. + * -# libusb_try_lock_events() is a non-blocking function which attempts + * to acquire the events lock but returns a failure code if it is contended. + * -# libusb_event_handling_ok() checks that libusb is still happy for your + * thread to be performing event handling. Sometimes, libusb needs to + * interrupt the event handler, and this is how you can check if you have + * been interrupted. If this function returns 0, the correct behaviour is + * for you to give up the event handling lock, and then to repeat the cycle. + * The following libusb_try_lock_events() will fail, so you will become an + * events waiter. For more information on this, read \ref fullstory below. + * -# libusb_handle_events_locked() is a variant of + * libusb_handle_events_timeout() that you can call while holding the + * events lock. libusb_handle_events_timeout() itself implements similar + * logic to the above, so be sure not to call it when you are + * "working behind libusb's back", as is the case here. + * -# libusb_event_handler_active() determines if someone is currently + * holding the events lock + * + * You might be wondering why there is no function to wake up all threads + * blocked on libusb_wait_for_event(). This is because libusb can do this + * internally: it will wake up all such threads when someone calls + * libusb_unlock_events() or when a transfer completes (at the point after its + * callback has returned). + * + * \subsection fullstory The full story + * + * The above explanation should be enough to get you going, but if you're + * really thinking through the issues then you may be left with some more + * questions regarding libusb's internals. If you're curious, read on, and if + * not, skip to the next section to avoid confusing yourself! + * + * The immediate question that may spring to mind is: what if one thread + * modifies the set of file descriptors that need to be polled while another + * thread is doing event handling? + * + * There are 2 situations in which this may happen. + * -# libusb_open() will add another file descriptor to the poll set, + * therefore it is desirable to interrupt the event handler so that it + * restarts, picking up the new descriptor. + * -# libusb_close() will remove a file descriptor from the poll set. There + * are all kinds of race conditions that could arise here, so it is + * important that nobody is doing event handling at this time. + * + * libusb handles these issues internally, so application developers do not + * have to stop their event handlers while opening/closing devices. Here's how + * it works, focusing on the libusb_close() situation first: + * + * -# During initialization, libusb opens an internal pipe, and it adds the read + * end of this pipe to the set of file descriptors to be polled. + * -# During libusb_close(), libusb writes some dummy data on this event pipe. + * This immediately interrupts the event handler. libusb also records + * internally that it is trying to interrupt event handlers for this + * high-priority event. + * -# At this point, some of the functions described above start behaving + * differently: + * - libusb_event_handling_ok() starts returning 1, indicating that it is NOT + * OK for event handling to continue. + * - libusb_try_lock_events() starts returning 1, indicating that another + * thread holds the event handling lock, even if the lock is uncontended. + * - libusb_event_handler_active() starts returning 1, indicating that + * another thread is doing event handling, even if that is not true. + * -# The above changes in behaviour result in the event handler stopping and + * giving up the events lock very quickly, giving the high-priority + * libusb_close() operation a "free ride" to acquire the events lock. All + * threads that are competing to do event handling become event waiters. + * -# With the events lock held inside libusb_close(), libusb can safely remove + * a file descriptor from the poll set, in the safety of knowledge that + * nobody is polling those descriptors or trying to access the poll set. + * -# After obtaining the events lock, the close operation completes very + * quickly (usually a matter of milliseconds) and then immediately releases + * the events lock. + * -# At the same time, the behaviour of libusb_event_handling_ok() and friends + * reverts to the original, documented behaviour. + * -# The release of the events lock causes the threads that are waiting for + * events to be woken up and to start competing to become event handlers + * again. One of them will succeed; it will then re-obtain the list of poll + * descriptors, and USB I/O will then continue as normal. + * + * libusb_open() is similar, and is actually a more simplistic case. Upon a + * call to libusb_open(): + * + * -# The device is opened and a file descriptor is added to the poll set. + * -# libusb sends some dummy data on the event pipe, and records that it + * is trying to modify the poll descriptor set. + * -# The event handler is interrupted, and the same behaviour change as for + * libusb_close() takes effect, causing all event handling threads to become + * event waiters. + * -# The libusb_open() implementation takes its free ride to the events lock. + * -# Happy that it has successfully paused the events handler, libusb_open() + * releases the events lock. + * -# The event waiter threads are all woken up and compete to become event + * handlers again. The one that succeeds will obtain the list of poll + * descriptors again, which will include the addition of the new device. + * + * \subsection concl Closing remarks + * + * The above may seem a little complicated, but hopefully I have made it clear + * why such complications are necessary. Also, do not forget that this only + * applies to applications that take libusb's file descriptors and integrate + * them into their own polling loops. + * + * You may decide that it is OK for your multi-threaded application to ignore + * some of the rules and locks detailed above, because you don't think that + * two threads can ever be polling the descriptors at the same time. If that + * is the case, then that's good news for you because you don't have to worry. + * But be careful here; remember that the synchronous I/O functions do event + * handling internally. If you have one thread doing event handling in a loop + * (without implementing the rules and locking semantics documented above) + * and another trying to send a synchronous USB transfer, you will end up with + * two threads monitoring the same descriptors, and the above-described + * undesirable behaviour occurring. The solution is for your polling thread to + * play by the rules; the synchronous I/O functions do so, and this will result + * in them getting along in perfect harmony. + * + * If you do have a dedicated thread doing event handling, it is perfectly + * legal for it to take the event handling lock for long periods of time. Any + * synchronous I/O functions you call from other threads will transparently + * fall back to the "event waiters" mechanism detailed above. The only + * consideration that your event handling thread must apply is the one related + * to libusb_event_handling_ok(): you must call this before every poll(), and + * give up the events lock if instructed. + */ + +int usbi_io_init(struct libusb_context *ctx) +{ + int r; + + usbi_mutex_init(&ctx->flying_transfers_lock); + usbi_mutex_init(&ctx->events_lock); + usbi_mutex_init(&ctx->event_waiters_lock); + usbi_cond_init(&ctx->event_waiters_cond); + usbi_mutex_init(&ctx->event_data_lock); + usbi_tls_key_create(&ctx->event_handling_key); + list_init(&ctx->flying_transfers); + list_init(&ctx->ipollfds); + list_init(&ctx->hotplug_msgs); + list_init(&ctx->completed_transfers); + + /* FIXME should use an eventfd on kernels that support it */ + r = usbi_pipe(ctx->event_pipe); + if (r < 0) { + r = LIBUSB_ERROR_OTHER; + goto err; + } + + r = usbi_add_pollfd(ctx, ctx->event_pipe[0], POLLIN); + if (r < 0) + goto err_close_pipe; + +#ifdef USBI_TIMERFD_AVAILABLE + ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(), + TFD_NONBLOCK | TFD_CLOEXEC); + if (ctx->timerfd >= 0) { + usbi_dbg("using timerfd for timeouts"); + r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); + if (r < 0) + goto err_close_timerfd; + } else { + usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); + ctx->timerfd = -1; + } +#endif + + return 0; + +#ifdef USBI_TIMERFD_AVAILABLE +err_close_timerfd: + close(ctx->timerfd); + usbi_remove_pollfd(ctx, ctx->event_pipe[0]); +#endif +err_close_pipe: + usbi_close(ctx->event_pipe[0]); + usbi_close(ctx->event_pipe[1]); +err: + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); + usbi_mutex_destroy(&ctx->event_data_lock); + usbi_tls_key_delete(ctx->event_handling_key); + return r; +} + +void usbi_io_exit(struct libusb_context *ctx) +{ + usbi_remove_pollfd(ctx, ctx->event_pipe[0]); + usbi_close(ctx->event_pipe[0]); + usbi_close(ctx->event_pipe[1]); +#ifdef USBI_TIMERFD_AVAILABLE + if (usbi_using_timerfd(ctx)) { + usbi_remove_pollfd(ctx, ctx->timerfd); + close(ctx->timerfd); + } +#endif + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); + usbi_mutex_destroy(&ctx->event_data_lock); + usbi_tls_key_delete(ctx->event_handling_key); + if (ctx->pollfds) + free(ctx->pollfds); +} + +static int calculate_timeout(struct usbi_transfer *transfer) +{ + int r; + struct timespec current_time; + unsigned int timeout = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; + + if (!timeout) { + timerclear(&transfer->timeout); + return 0; + } + + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); + if (r < 0) { + usbi_err(ITRANSFER_CTX(transfer), + "failed to read monotonic clock, errno=%d", errno); + return r; + } + + current_time.tv_sec += timeout / 1000; + current_time.tv_nsec += (timeout % 1000) * 1000000; + + while (current_time.tv_nsec >= 1000000000) { + current_time.tv_nsec -= 1000000000; + current_time.tv_sec++; + } + + TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time); + return 0; +} + +/** \ingroup libusb_asyncio + * Allocate a libusb transfer with a specified number of isochronous packet + * descriptors. The returned transfer is pre-initialized for you. When the new + * transfer is no longer needed, it should be freed with + * libusb_free_transfer(). + * + * Transfers intended for non-isochronous endpoints (e.g. control, bulk, + * interrupt) should specify an iso_packets count of zero. + * + * For transfers intended for isochronous endpoints, specify an appropriate + * number of packet descriptors to be allocated as part of the transfer. + * The returned transfer is not specially initialized for isochronous I/O; + * you are still required to set the + * \ref libusb_transfer::num_iso_packets "num_iso_packets" and + * \ref libusb_transfer::type "type" fields accordingly. + * + * It is safe to allocate a transfer with some isochronous packets and then + * use it on a non-isochronous endpoint. If you do this, ensure that at time + * of submission, num_iso_packets is 0 and that type is set appropriately. + * + * \param iso_packets number of isochronous packet descriptors to allocate + * \returns a newly allocated transfer, or NULL on error + */ +DEFAULT_VISIBILITY +struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( + int iso_packets) +{ + struct libusb_transfer *transfer; + size_t os_alloc_size = usbi_backend.transfer_priv_size; + size_t alloc_size = sizeof(struct usbi_transfer) + + sizeof(struct libusb_transfer) + + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) + + os_alloc_size; + struct usbi_transfer *itransfer = calloc(1, alloc_size); + if (!itransfer) + return NULL; + + itransfer->num_iso_packets = iso_packets; + usbi_mutex_init(&itransfer->lock); + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + usbi_dbg("transfer %p", transfer); + return transfer; +} + +/** \ingroup libusb_asyncio + * Free a transfer structure. This should be called for all transfers + * allocated with libusb_alloc_transfer(). + * + * If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER + * "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is + * non-NULL, this function will also free the transfer buffer using the + * standard system memory allocator (e.g. free()). + * + * It is legal to call this function with a NULL transfer. In this case, + * the function will simply return safely. + * + * It is not legal to free an active transfer (one which has been submitted + * and has not yet completed). + * + * \param transfer the transfer to free + */ +void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) +{ + struct usbi_transfer *itransfer; + if (!transfer) + return; + + usbi_dbg("transfer %p", transfer); + if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) + free(transfer->buffer); + + itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + usbi_mutex_destroy(&itransfer->lock); + free(itransfer); +} + +#ifdef USBI_TIMERFD_AVAILABLE +static int disarm_timerfd(struct libusb_context *ctx) +{ + const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } }; + int r; + + usbi_dbg(""); + r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL); + if (r < 0) + return LIBUSB_ERROR_OTHER; + else + return 0; +} + +/* iterates through the flying transfers, and rearms the timerfd based on the + * next upcoming timeout. + * must be called with flying_list locked. + * returns 0 on success or a LIBUSB_ERROR code on failure. + */ +static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) +{ + struct usbi_transfer *transfer; + + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + struct timeval *cur_tv = &transfer->timeout; + + /* if we've reached transfers of infinite timeout, then we have no + * arming to do */ + if (!timerisset(cur_tv)) + goto disarm; + + /* act on first transfer that has not already been handled */ + if (!(transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) { + int r; + const struct itimerspec it = { {0, 0}, + { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; + usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); + r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); + if (r < 0) + return LIBUSB_ERROR_OTHER; + return 0; + } + } + +disarm: + return disarm_timerfd(ctx); +} +#else +static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) +{ + UNUSED(ctx); + return 0; +} +#endif + +/* add a transfer to the (timeout-sorted) active transfers list. + * This function will return non 0 if fails to update the timer, + * in which case the transfer is *not* on the flying_transfers list. */ +static int add_to_flying_list(struct usbi_transfer *transfer) +{ + struct usbi_transfer *cur; + struct timeval *timeout = &transfer->timeout; + struct libusb_context *ctx = ITRANSFER_CTX(transfer); + int r; + int first = 1; + + r = calculate_timeout(transfer); + if (r) + return r; + + /* if we have no other flying transfers, start the list with this one */ + if (list_empty(&ctx->flying_transfers)) { + list_add(&transfer->list, &ctx->flying_transfers); + goto out; + } + + /* if we have infinite timeout, append to end of list */ + if (!timerisset(timeout)) { + list_add_tail(&transfer->list, &ctx->flying_transfers); + /* first is irrelevant in this case */ + goto out; + } + + /* otherwise, find appropriate place in list */ + list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) { + /* find first timeout that occurs after the transfer in question */ + struct timeval *cur_tv = &cur->timeout; + + if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) || + (cur_tv->tv_sec == timeout->tv_sec && + cur_tv->tv_usec > timeout->tv_usec)) { + list_add_tail(&transfer->list, &cur->list); + goto out; + } + first = 0; + } + /* first is 0 at this stage (list not empty) */ + + /* otherwise we need to be inserted at the end */ + list_add_tail(&transfer->list, &ctx->flying_transfers); +out: +#ifdef USBI_TIMERFD_AVAILABLE + if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) { + /* if this transfer has the lowest timeout of all active transfers, + * rearm the timerfd with this transfer's timeout */ + const struct itimerspec it = { {0, 0}, + { timeout->tv_sec, timeout->tv_usec * 1000 } }; + usbi_dbg("arm timerfd for timeout in %dms (first in line)", + USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); + r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); + if (r < 0) { + usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno); + r = LIBUSB_ERROR_OTHER; + } + } +#else + UNUSED(first); +#endif + + if (r) + list_del(&transfer->list); + + return r; +} + +/* remove a transfer from the active transfers list. + * This function will *always* remove the transfer from the + * flying_transfers list. It will return a LIBUSB_ERROR code + * if it fails to update the timer for the next timeout. */ +static int remove_from_flying_list(struct usbi_transfer *transfer) +{ + struct libusb_context *ctx = ITRANSFER_CTX(transfer); + int rearm_timerfd; + int r = 0; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + rearm_timerfd = (timerisset(&transfer->timeout) && + list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == transfer); + list_del(&transfer->list); + if (usbi_using_timerfd(ctx) && rearm_timerfd) + r = arm_timerfd_for_next_timeout(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + return r; +} + +/** \ingroup libusb_asyncio + * Submit a transfer. This function will fire off the USB transfer and then + * return immediately. + * + * \param transfer the transfer to submit + * \returns 0 on success + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported + * by the operating system. + * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * the operating system and/or hardware can support + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) +{ + struct usbi_transfer *itransfer = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + int r; + + usbi_dbg("transfer %p", transfer); + + /* + * Important note on locking, this function takes / releases locks + * in the following order: + * take flying_transfers_lock + * take itransfer->lock + * clear transfer + * add to flying_transfers list + * release flying_transfers_lock + * submit transfer + * release itransfer->lock + * if submit failed: + * take flying_transfers_lock + * remove from flying_transfers list + * release flying_transfers_lock + * + * Note that it takes locks in the order a-b and then releases them + * in the same order a-b. This is somewhat unusual but not wrong, + * release order is not important as long as *all* locks are released + * before re-acquiring any locks. + * + * This means that the ordering of first releasing itransfer->lock + * and then re-acquiring the flying_transfers_list on error is + * important and must not be changed! + * + * This is done this way because when we take both locks we must always + * take flying_transfers_lock first to avoid ab-ba style deadlocks with + * the timeout handling and usbi_handle_disconnect paths. + * + * And we cannot release itransfer->lock before the submission is + * complete otherwise timeout handling for transfers with short + * timeouts may run before submission. + */ + usbi_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&itransfer->lock); + if (itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) { + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&itransfer->lock); + return LIBUSB_ERROR_BUSY; + } + itransfer->transferred = 0; + itransfer->state_flags = 0; + itransfer->timeout_flags = 0; + r = add_to_flying_list(itransfer); + if (r) { + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&itransfer->lock); + return r; + } + /* + * We must release the flying transfers lock here, because with + * some backends the submit_transfer method is synchroneous. + */ + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + r = usbi_backend.submit_transfer(itransfer); + if (r == LIBUSB_SUCCESS) { + itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; + /* keep a reference to this device */ + libusb_ref_device(transfer->dev_handle->dev); + } + usbi_mutex_unlock(&itransfer->lock); + + if (r != LIBUSB_SUCCESS) + remove_from_flying_list(itransfer); + + return r; +} + +/** \ingroup libusb_asyncio + * Asynchronously cancel a previously submitted transfer. + * This function returns immediately, but this does not indicate cancellation + * is complete. Your callback function will be invoked at some later time + * with a transfer status of + * \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED + * "LIBUSB_TRANSFER_CANCELLED." + * + * \param transfer the transfer to cancel + * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, + * already complete, or already cancelled. + * \returns a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) +{ + struct usbi_transfer *itransfer = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + int r; + + usbi_dbg("transfer %p", transfer ); + usbi_mutex_lock(&itransfer->lock); + if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) + || (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + r = usbi_backend.cancel_transfer(itransfer); + if (r < 0) { + if (r != LIBUSB_ERROR_NOT_FOUND && + r != LIBUSB_ERROR_NO_DEVICE) + usbi_err(TRANSFER_CTX(transfer), + "cancel transfer failed error %d", r); + else + usbi_dbg("cancel transfer failed error %d", r); + + if (r == LIBUSB_ERROR_NO_DEVICE) + itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; + } + + itransfer->state_flags |= USBI_TRANSFER_CANCELLING; + +out: + usbi_mutex_unlock(&itransfer->lock); + return r; +} + +/** \ingroup libusb_asyncio + * Set a transfers bulk stream id. Note users are advised to use + * libusb_fill_bulk_stream_transfer() instead of calling this function + * directly. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param transfer the transfer to set the stream id for + * \param stream_id the stream id to set + * \see libusb_alloc_streams() + */ +void API_EXPORTED libusb_transfer_set_stream_id( + struct libusb_transfer *transfer, uint32_t stream_id) +{ + struct usbi_transfer *itransfer = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + + itransfer->stream_id = stream_id; +} + +/** \ingroup libusb_asyncio + * Get a transfers bulk stream id. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param transfer the transfer to get the stream id for + * \returns the stream id for the transfer + */ +uint32_t API_EXPORTED libusb_transfer_get_stream_id( + struct libusb_transfer *transfer) +{ + struct usbi_transfer *itransfer = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + + return itransfer->stream_id; +} + +/* Handle completion of a transfer (completion might be an error condition). + * This will invoke the user-supplied callback function, which may end up + * freeing the transfer. Therefore you cannot use the transfer structure + * after calling this function, and you should free all backend-specific + * data before calling it. + * Do not call this function with the usbi_transfer lock held. User-specified + * callback functions may attempt to directly resubmit the transfer, which + * will attempt to take the lock. */ +int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, + enum libusb_transfer_status status) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_device_handle *dev_handle = transfer->dev_handle; + uint8_t flags; + int r; + + r = remove_from_flying_list(itransfer); + if (r < 0) + usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno); + + usbi_mutex_lock(&itransfer->lock); + itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT; + usbi_mutex_unlock(&itransfer->lock); + + if (status == LIBUSB_TRANSFER_COMPLETED + && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { + int rqlen = transfer->length; + if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) + rqlen -= LIBUSB_CONTROL_SETUP_SIZE; + if (rqlen != itransfer->transferred) { + usbi_dbg("interpreting short transfer as error"); + status = LIBUSB_TRANSFER_ERROR; + } + } + + flags = transfer->flags; + transfer->status = status; + transfer->actual_length = itransfer->transferred; + usbi_dbg("transfer %p has callback %p", transfer, transfer->callback); + if (transfer->callback) + transfer->callback(transfer); + /* transfer might have been freed by the above call, do not use from + * this point. */ + if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) + libusb_free_transfer(transfer); + libusb_unref_device(dev_handle->dev); + return r; +} + +/* Similar to usbi_handle_transfer_completion() but exclusively for transfers + * that were asynchronously cancelled. The same concerns w.r.t. freeing of + * transfers exist here. + * Do not call this function with the usbi_transfer lock held. User-specified + * callback functions may attempt to directly resubmit the transfer, which + * will attempt to take the lock. */ +int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) +{ + struct libusb_context *ctx = ITRANSFER_CTX(transfer); + uint8_t timed_out; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT; + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + /* if the URB was cancelled due to timeout, report timeout to the user */ + if (timed_out) { + usbi_dbg("detected timeout cancellation"); + return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); + } + + /* otherwise its a normal async cancel */ + return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED); +} + +/* Add a completed transfer to the completed_transfers list of the + * context and signal the event. The backend's handle_transfer_completion() + * function will be called the next time an event handler runs. */ +void usbi_signal_transfer_completion(struct usbi_transfer *transfer) +{ + struct libusb_context *ctx = ITRANSFER_CTX(transfer); + int pending_events; + + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + list_add_tail(&transfer->completed_list, &ctx->completed_transfers); + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); +} + +/** \ingroup libusb_poll + * Attempt to acquire the event handling lock. This lock is used to ensure that + * only one thread is monitoring libusb event sources at any one time. + * + * You only need to use this lock if you are developing an application + * which calls poll() or select() on libusb's file descriptors directly. + * If you stick to libusb's event handling loop functions (e.g. + * libusb_handle_events()) then you do not need to be concerned with this + * locking. + * + * While holding this lock, you are trusted to actually be handling events. + * If you are no longer handling events, you must call libusb_unlock_events() + * as soon as possible. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 0 if the lock was obtained successfully + * \returns 1 if the lock was not obtained (i.e. another thread holds the lock) + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) +{ + int r; + unsigned int ru; + USBI_GET_CONTEXT(ctx); + + /* is someone else waiting to close a device? if so, don't let this thread + * start event handling */ + usbi_mutex_lock(&ctx->event_data_lock); + ru = ctx->device_close; + usbi_mutex_unlock(&ctx->event_data_lock); + if (ru) { + usbi_dbg("someone else is closing a device"); + return 1; + } + + r = usbi_mutex_trylock(&ctx->events_lock); + if (r) + return 1; + + ctx->event_handler_active = 1; + return 0; +} + +/** \ingroup libusb_poll + * Acquire the event handling lock, blocking until successful acquisition if + * it is contended. This lock is used to ensure that only one thread is + * monitoring libusb event sources at any one time. + * + * You only need to use this lock if you are developing an application + * which calls poll() or select() on libusb's file descriptors directly. + * If you stick to libusb's event handling loop functions (e.g. + * libusb_handle_events()) then you do not need to be concerned with this + * locking. + * + * While holding this lock, you are trusted to actually be handling events. + * If you are no longer handling events, you must call libusb_unlock_events() + * as soon as possible. + * + * \param ctx the context to operate on, or NULL for the default context + * \ref libusb_mtasync + */ +void API_EXPORTED libusb_lock_events(libusb_context *ctx) +{ + USBI_GET_CONTEXT(ctx); + usbi_mutex_lock(&ctx->events_lock); + ctx->event_handler_active = 1; +} + +/** \ingroup libusb_poll + * Release the lock previously acquired with libusb_try_lock_events() or + * libusb_lock_events(). Releasing this lock will wake up any threads blocked + * on libusb_wait_for_event(). + * + * \param ctx the context to operate on, or NULL for the default context + * \ref libusb_mtasync + */ +void API_EXPORTED libusb_unlock_events(libusb_context *ctx) +{ + USBI_GET_CONTEXT(ctx); + ctx->event_handler_active = 0; + usbi_mutex_unlock(&ctx->events_lock); + + /* FIXME: perhaps we should be a bit more efficient by not broadcasting + * the availability of the events lock when we are modifying pollfds + * (check ctx->device_close)? */ + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); +} + +/** \ingroup libusb_poll + * Determine if it is still OK for this thread to be doing event handling. + * + * Sometimes, libusb needs to temporarily pause all event handlers, and this + * is the function you should use before polling file descriptors to see if + * this is the case. + * + * If this function instructs your thread to give up the events lock, you + * should just continue the usual logic that is documented in \ref libusb_mtasync. + * On the next iteration, your thread will fail to obtain the events lock, + * and will hence become an event waiter. + * + * This function should be called while the events lock is held: you don't + * need to worry about the results of this function if your thread is not + * the current event handler. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 1 if event handling can start or continue + * \returns 0 if this thread must give up the events lock + * \ref fullstory "Multi-threaded I/O: the full story" + */ +int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx) +{ + unsigned int r; + USBI_GET_CONTEXT(ctx); + + /* is someone else waiting to close a device? if so, don't let this thread + * continue event handling */ + usbi_mutex_lock(&ctx->event_data_lock); + r = ctx->device_close; + usbi_mutex_unlock(&ctx->event_data_lock); + if (r) { + usbi_dbg("someone else is closing a device"); + return 0; + } + + return 1; +} + + +/** \ingroup libusb_poll + * Determine if an active thread is handling events (i.e. if anyone is holding + * the event handling lock). + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 1 if a thread is handling events + * \returns 0 if there are no threads currently handling events + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) +{ + unsigned int r; + USBI_GET_CONTEXT(ctx); + + /* is someone else waiting to close a device? if so, don't let this thread + * start event handling -- indicate that event handling is happening */ + usbi_mutex_lock(&ctx->event_data_lock); + r = ctx->device_close; + usbi_mutex_unlock(&ctx->event_data_lock); + if (r) { + usbi_dbg("someone else is closing a device"); + return 1; + } + + return ctx->event_handler_active; +} + +/** \ingroup libusb_poll + * Interrupt any active thread that is handling events. This is mainly useful + * for interrupting a dedicated event handling thread when an application + * wishes to call libusb_exit(). + * + * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 + * + * \param ctx the context to operate on, or NULL for the default context + * \ref libusb_mtasync + */ +void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) +{ + int pending_events; + USBI_GET_CONTEXT(ctx); + + usbi_dbg(""); + usbi_mutex_lock(&ctx->event_data_lock); + + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_USER_INTERRUPT; + if (!pending_events) + usbi_signal_event(ctx); + + usbi_mutex_unlock(&ctx->event_data_lock); +} + +/** \ingroup libusb_poll + * Acquire the event waiters lock. This lock is designed to be obtained under + * the situation where you want to be aware when events are completed, but + * some other thread is event handling so calling libusb_handle_events() is not + * allowed. + * + * You then obtain this lock, re-check that another thread is still handling + * events, then call libusb_wait_for_event(). + * + * You only need to use this lock if you are developing an application + * which calls poll() or select() on libusb's file descriptors directly, + * and may potentially be handling events from 2 threads simultaenously. + * If you stick to libusb's event handling loop functions (e.g. + * libusb_handle_events()) then you do not need to be concerned with this + * locking. + * + * \param ctx the context to operate on, or NULL for the default context + * \ref libusb_mtasync + */ +void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) +{ + USBI_GET_CONTEXT(ctx); + usbi_mutex_lock(&ctx->event_waiters_lock); +} + +/** \ingroup libusb_poll + * Release the event waiters lock. + * \param ctx the context to operate on, or NULL for the default context + * \ref libusb_mtasync + */ +void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) +{ + USBI_GET_CONTEXT(ctx); + usbi_mutex_unlock(&ctx->event_waiters_lock); +} + +/** \ingroup libusb_poll + * Wait for another thread to signal completion of an event. Must be called + * with the event waiters lock held, see libusb_lock_event_waiters(). + * + * This function will block until any of the following conditions are met: + * -# The timeout expires + * -# A transfer completes + * -# A thread releases the event handling lock through libusb_unlock_events() + * + * Condition 1 is obvious. Condition 2 unblocks your thread after + * the callback for the transfer has completed. Condition 3 is important + * because it means that the thread that was previously handling events is no + * longer doing so, so if any events are to complete, another thread needs to + * step up and start event handling. + * + * This function releases the event waiters lock before putting your thread + * to sleep, and reacquires the lock as it is being woken up. + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv maximum timeout for this blocking function. A NULL value + * indicates unlimited timeout. + * \returns 0 after a transfer completes or another thread stops event handling + * \returns 1 if the timeout expired + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) +{ + int r; + + USBI_GET_CONTEXT(ctx); + if (tv == NULL) { + usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); + return 0; + } + + r = usbi_cond_timedwait(&ctx->event_waiters_cond, + &ctx->event_waiters_lock, tv); + + if (r < 0) + return r; + else + return (r == ETIMEDOUT); +} + +static void handle_timeout(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int r; + + itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED; + r = libusb_cancel_transfer(transfer); + if (r == LIBUSB_SUCCESS) + itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; + else + usbi_warn(TRANSFER_CTX(transfer), + "async cancel failed %d errno=%d", r, errno); +} + +static int handle_timeouts_locked(struct libusb_context *ctx) +{ + int r; + struct timespec systime_ts; + struct timeval systime; + struct usbi_transfer *transfer; + + if (list_empty(&ctx->flying_transfers)) + return 0; + + /* get current time */ + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); + if (r < 0) + return r; + + TIMESPEC_TO_TIMEVAL(&systime, &systime_ts); + + /* iterate through flying transfers list, finding all transfers that + * have expired timeouts */ + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + struct timeval *cur_tv = &transfer->timeout; + + /* if we've reached transfers of infinite timeout, we're all done */ + if (!timerisset(cur_tv)) + return 0; + + /* ignore timeouts we've already handled */ + if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) + continue; + + /* if transfer has non-expired timeout, nothing more to do */ + if ((cur_tv->tv_sec > systime.tv_sec) || + (cur_tv->tv_sec == systime.tv_sec && + cur_tv->tv_usec > systime.tv_usec)) + return 0; + + /* otherwise, we've got an expired timeout to handle */ + handle_timeout(transfer); + } + return 0; +} + +static int handle_timeouts(struct libusb_context *ctx) +{ + int r; + USBI_GET_CONTEXT(ctx); + usbi_mutex_lock(&ctx->flying_transfers_lock); + r = handle_timeouts_locked(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + return r; +} + +#ifdef USBI_TIMERFD_AVAILABLE +static int handle_timerfd_trigger(struct libusb_context *ctx) +{ + int r; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + + /* process the timeout that just happened */ + r = handle_timeouts_locked(ctx); + if (r < 0) + goto out; + + /* arm for next timeout*/ + r = arm_timerfd_for_next_timeout(ctx); + +out: + usbi_mutex_unlock(&ctx->flying_transfers_lock); + return r; +} +#endif + +/* do the actual event handling. assumes that no other thread is concurrently + * doing the same thing. */ +static int handle_events(struct libusb_context *ctx, struct timeval *tv) +{ + int r; + struct usbi_pollfd *ipollfd; + POLL_NFDS_TYPE nfds = 0; + POLL_NFDS_TYPE internal_nfds; + struct pollfd *fds = NULL; + int i = -1; + int timeout_ms; + + /* prevent attempts to recursively handle events (e.g. calling into + * libusb_handle_events() from within a hotplug or transfer callback) */ + if (usbi_handling_events(ctx)) + return LIBUSB_ERROR_BUSY; + usbi_start_event_handling(ctx); + + /* there are certain fds that libusb uses internally, currently: + * + * 1) event pipe + * 2) timerfd + * + * the backend will never need to attempt to handle events on these fds, so + * we determine how many fds are in use internally for this context and when + * handle_events() is called in the backend, the pollfd list and count will + * be adjusted to skip over these internal fds */ + if (usbi_using_timerfd(ctx)) + internal_nfds = 2; + else + internal_nfds = 1; + + /* only reallocate the poll fds when the list of poll fds has been modified + * since the last poll, otherwise reuse them to save the additional overhead */ + usbi_mutex_lock(&ctx->event_data_lock); + if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) { + usbi_dbg("poll fds modified, reallocating"); + + if (ctx->pollfds) { + free(ctx->pollfds); + ctx->pollfds = NULL; + } + + /* sanity check - it is invalid for a context to have fewer than the + * required internal fds (memory corruption?) */ + assert(ctx->pollfds_cnt >= internal_nfds); + + ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds)); + if (!ctx->pollfds) { + usbi_mutex_unlock(&ctx->event_data_lock); + r = LIBUSB_ERROR_NO_MEM; + goto done; + } + + list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) { + struct libusb_pollfd *pollfd = &ipollfd->pollfd; + i++; + ctx->pollfds[i].fd = pollfd->fd; + ctx->pollfds[i].events = pollfd->events; + } + + /* reset the flag now that we have the updated list */ + ctx->event_flags &= ~USBI_EVENT_POLLFDS_MODIFIED; + + /* if no further pending events, clear the event pipe so that we do + * not immediately return from poll */ + if (!usbi_pending_events(ctx)) + usbi_clear_event(ctx); + } + fds = ctx->pollfds; + nfds = ctx->pollfds_cnt; + usbi_mutex_unlock(&ctx->event_data_lock); + + timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); + + /* round up to next millisecond */ + if (tv->tv_usec % 1000) + timeout_ms++; + + usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); + r = usbi_poll(fds, nfds, timeout_ms); + usbi_dbg("poll() returned %d", r); + if (r == 0) { + r = handle_timeouts(ctx); + goto done; + } else if (r == -1 && errno == EINTR) { + r = LIBUSB_ERROR_INTERRUPTED; + goto done; + } else if (r < 0) { + usbi_err(ctx, "poll failed %d err=%d", r, errno); + r = LIBUSB_ERROR_IO; + goto done; + } + + /* fds[0] is always the event pipe */ + if (fds[0].revents) { + struct list_head hotplug_msgs; + struct usbi_transfer *itransfer; + int hotplug_cb_deregistered = 0; + int ret = 0; + + list_init(&hotplug_msgs); + + usbi_dbg("caught a fish on the event pipe"); + + /* take the the event data lock while processing events */ + usbi_mutex_lock(&ctx->event_data_lock); + + /* check if someone added a new poll fd */ + if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) + usbi_dbg("someone updated the poll fds"); + + if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) { + usbi_dbg("someone purposely interrupted"); + ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; + } + + if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) { + usbi_dbg("someone unregistered a hotplug cb"); + ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + hotplug_cb_deregistered = 1; + } + + /* check if someone is closing a device */ + if (ctx->device_close) + usbi_dbg("someone is closing a device"); + + /* check for any pending hotplug messages */ + if (!list_empty(&ctx->hotplug_msgs)) { + usbi_dbg("hotplug message received"); + list_cut(&hotplug_msgs, &ctx->hotplug_msgs); + } + + /* complete any pending transfers */ + while (ret == 0 && !list_empty(&ctx->completed_transfers)) { + itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); + list_del(&itransfer->completed_list); + usbi_mutex_unlock(&ctx->event_data_lock); + ret = usbi_backend.handle_transfer_completion(itransfer); + if (ret) + usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); + usbi_mutex_lock(&ctx->event_data_lock); + } + + /* if no further pending events, clear the event pipe */ + if (!usbi_pending_events(ctx)) + usbi_clear_event(ctx); + + usbi_mutex_unlock(&ctx->event_data_lock); + + if (hotplug_cb_deregistered) + usbi_hotplug_deregister(ctx, 0); + + /* process the hotplug messages, if any */ + while (!list_empty(&hotplug_msgs)) { + struct libusb_hotplug_message *message = + list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list); + + usbi_hotplug_match(ctx, message->device, message->event); + + /* the device left, dereference the device */ + if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) + libusb_unref_device(message->device); + + list_del(&message->list); + free(message); + } + + if (ret) { + /* return error code */ + r = ret; + goto done; + } + + if (0 == --r) + goto done; + } + +#ifdef USBI_TIMERFD_AVAILABLE + /* on timerfd configurations, fds[1] is the timerfd */ + if (usbi_using_timerfd(ctx) && fds[1].revents) { + /* timerfd indicates that a timeout has expired */ + int ret; + usbi_dbg("timerfd triggered"); + + ret = handle_timerfd_trigger(ctx); + if (ret < 0) { + /* return error code */ + r = ret; + goto done; + } + + if (0 == --r) + goto done; + } +#endif + + r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); + if (r) + usbi_err(ctx, "backend handle_events failed with error %d", r); + +done: + usbi_end_event_handling(ctx); + return r; +} + +/* returns the smallest of: + * 1. timeout of next URB + * 2. user-supplied timeout + * returns 1 if there is an already-expired timeout, otherwise returns 0 + * and populates out + */ +static int get_next_timeout(libusb_context *ctx, struct timeval *tv, + struct timeval *out) +{ + struct timeval timeout; + int r = libusb_get_next_timeout(ctx, &timeout); + if (r) { + /* timeout already expired? */ + if (!timerisset(&timeout)) + return 1; + + /* choose the smallest of next URB timeout or user specified timeout */ + if (timercmp(&timeout, tv, <)) + *out = timeout; + else + *out = *tv; + } else { + *out = *tv; + } + return 0; +} + +/** \ingroup libusb_poll + * Handle any pending events. + * + * libusb determines "pending events" by checking if any timeouts have expired + * and by checking the set of file descriptors for activity. + * + * If a zero timeval is passed, this function will handle any already-pending + * events and then immediately return in non-blocking style. + * + * If a non-zero timeval is passed and no events are currently pending, this + * function will block waiting for events to handle up until the specified + * timeout. If an event arrives or a signal is raised, this function will + * return early. + * + * If the parameter completed is not NULL then after obtaining the event + * handling lock this function will return immediately if the integer + * pointed to is not 0. This allows for race free waiting for the completion + * of a specific transfer. + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv the maximum time to block waiting for events, or an all zero + * timeval struct for non-blocking mode + * \param completed pointer to completion integer to check, or NULL + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, + struct timeval *tv, int *completed) +{ + int r; + struct timeval poll_timeout; + + USBI_GET_CONTEXT(ctx); + r = get_next_timeout(ctx, tv, &poll_timeout); + if (r) { + /* timeout already expired */ + return handle_timeouts(ctx); + } + +retry: + if (libusb_try_lock_events(ctx) == 0) { + if (completed == NULL || !*completed) { + /* we obtained the event lock: do our own event handling */ + usbi_dbg("doing our own event handling"); + r = handle_events(ctx, &poll_timeout); + } + libusb_unlock_events(ctx); + return r; + } + + /* another thread is doing event handling. wait for thread events that + * notify event completion. */ + libusb_lock_event_waiters(ctx); + + if (completed && *completed) + goto already_done; + + if (!libusb_event_handler_active(ctx)) { + /* we hit a race: whoever was event handling earlier finished in the + * time it took us to reach this point. try the cycle again. */ + libusb_unlock_event_waiters(ctx); + usbi_dbg("event handler was active but went away, retrying"); + goto retry; + } + + usbi_dbg("another thread is doing event handling"); + r = libusb_wait_for_event(ctx, &poll_timeout); + +already_done: + libusb_unlock_event_waiters(ctx); + + if (r < 0) + return r; + else if (r == 1) + return handle_timeouts(ctx); + else + return 0; +} + +/** \ingroup libusb_poll + * Handle any pending events + * + * Like libusb_handle_events_timeout_completed(), but without the completed + * parameter, calling this function is equivalent to calling + * libusb_handle_events_timeout_completed() with a NULL completed parameter. + * + * This function is kept primarily for backwards compatibility. + * All new code should call libusb_handle_events_completed() or + * libusb_handle_events_timeout_completed() to avoid race conditions. + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv the maximum time to block waiting for events, or an all zero + * timeval struct for non-blocking mode + * \returns 0 on success, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv) +{ + return libusb_handle_events_timeout_completed(ctx, tv, NULL); +} + +/** \ingroup libusb_poll + * Handle any pending events in blocking mode. There is currently a timeout + * hardcoded at 60 seconds but we plan to make it unlimited in future. For + * finer control over whether this function is blocking or non-blocking, or + * for control over the timeout, use libusb_handle_events_timeout_completed() + * instead. + * + * This function is kept primarily for backwards compatibility. + * All new code should call libusb_handle_events_completed() or + * libusb_handle_events_timeout_completed() to avoid race conditions. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 0 on success, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_handle_events(libusb_context *ctx) +{ + struct timeval tv; + tv.tv_sec = 60; + tv.tv_usec = 0; + return libusb_handle_events_timeout_completed(ctx, &tv, NULL); +} + +/** \ingroup libusb_poll + * Handle any pending events in blocking mode. + * + * Like libusb_handle_events(), with the addition of a completed parameter + * to allow for race free waiting for the completion of a specific transfer. + * + * See libusb_handle_events_timeout_completed() for details on the completed + * parameter. + * + * \param ctx the context to operate on, or NULL for the default context + * \param completed pointer to completion integer to check, or NULL + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, + int *completed) +{ + struct timeval tv; + tv.tv_sec = 60; + tv.tv_usec = 0; + return libusb_handle_events_timeout_completed(ctx, &tv, completed); +} + +/** \ingroup libusb_poll + * Handle any pending events by polling file descriptors, without checking if + * any other threads are already doing so. Must be called with the event lock + * held, see libusb_lock_events(). + * + * This function is designed to be called under the situation where you have + * taken the event lock and are calling poll()/select() directly on libusb's + * file descriptors (as opposed to using libusb_handle_events() or similar). + * You detect events on libusb's descriptors, so you then call this function + * with a zero timeout value (while still holding the event lock). + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv the maximum time to block waiting for events, or zero for + * non-blocking mode + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \ref libusb_mtasync + */ +int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, + struct timeval *tv) +{ + int r; + struct timeval poll_timeout; + + USBI_GET_CONTEXT(ctx); + r = get_next_timeout(ctx, tv, &poll_timeout); + if (r) { + /* timeout already expired */ + return handle_timeouts(ctx); + } + + return handle_events(ctx, &poll_timeout); +} + +/** \ingroup libusb_poll + * Determines whether your application must apply special timing considerations + * when monitoring libusb's file descriptors. + * + * This function is only useful for applications which retrieve and poll + * libusb's file descriptors in their own main loop (\ref libusb_pollmain). + * + * Ordinarily, libusb's event handler needs to be called into at specific + * moments in time (in addition to times when there is activity on the file + * descriptor set). The usual approach is to use libusb_get_next_timeout() + * to learn about when the next timeout occurs, and to adjust your + * poll()/select() timeout accordingly so that you can make a call into the + * library at that time. + * + * Some platforms supported by libusb do not come with this baggage - any + * events relevant to timing will be represented by activity on the file + * descriptor set, and libusb_get_next_timeout() will always return 0. + * This function allows you to detect whether you are running on such a + * platform. + * + * Since v1.0.5. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 0 if you must call into libusb at times determined by + * libusb_get_next_timeout(), or 1 if all timeout events are handled internally + * or through regular activity on the file descriptors. + * \ref libusb_pollmain "Polling libusb file descriptors for event handling" + */ +int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) +{ +#if defined(USBI_TIMERFD_AVAILABLE) + USBI_GET_CONTEXT(ctx); + return usbi_using_timerfd(ctx); +#else + UNUSED(ctx); + return 0; +#endif +} + +/** \ingroup libusb_poll + * Determine the next internal timeout that libusb needs to handle. You only + * need to use this function if you are calling poll() or select() or similar + * on libusb's file descriptors yourself - you do not need to use it if you + * are calling libusb_handle_events() or a variant directly. + * + * You should call this function in your main loop in order to determine how + * long to wait for select() or poll() to return results. libusb needs to be + * called into at this timeout, so you should use it as an upper bound on + * your select() or poll() call. + * + * When the timeout has expired, call into libusb_handle_events_timeout() + * (perhaps in non-blocking mode) so that libusb can handle the timeout. + * + * This function may return 1 (success) and an all-zero timeval. If this is + * the case, it indicates that libusb has a timeout that has already expired + * so you should call libusb_handle_events_timeout() or similar immediately. + * A return code of 0 indicates that there are no pending timeouts. + * + * On some platforms, this function will always returns 0 (no pending + * timeouts). See \ref polltime. + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv output location for a relative time against the current + * clock in which libusb must be called into in order to process timeout events + * \returns 0 if there are no pending timeouts, 1 if a timeout was returned, + * or LIBUSB_ERROR_OTHER on failure + */ +int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, + struct timeval *tv) +{ + struct usbi_transfer *transfer; + struct timespec cur_ts; + struct timeval cur_tv; + struct timeval next_timeout = { 0, 0 }; + int r; + + USBI_GET_CONTEXT(ctx); + if (usbi_using_timerfd(ctx)) + return 0; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + if (list_empty(&ctx->flying_transfers)) { + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_dbg("no URBs, no timeout!"); + return 0; + } + + /* find next transfer which hasn't already been processed as timed out */ + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) + continue; + + /* if we've reached transfers of infinte timeout, we're done looking */ + if (!timerisset(&transfer->timeout)) + break; + + next_timeout = transfer->timeout; + break; + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (!timerisset(&next_timeout)) { + usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); + return 0; + } + + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); + if (r < 0) { + usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); + return 0; + } + TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); + + if (!timercmp(&cur_tv, &next_timeout, <)) { + usbi_dbg("first timeout already expired"); + timerclear(tv); + } else { + timersub(&next_timeout, &cur_tv, tv); + usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec); + } + + return 1; +} + +/** \ingroup libusb_poll + * Register notification functions for file descriptor additions/removals. + * These functions will be invoked for every new or removed file descriptor + * that libusb uses as an event source. + * + * To remove notifiers, pass NULL values for the function pointers. + * + * Note that file descriptors may have been added even before you register + * these notifiers (e.g. at libusb_init() time). + * + * Additionally, note that the removal notifier may be called during + * libusb_exit() (e.g. when it is closing file descriptors that were opened + * and added to the poll set at libusb_init() time). If you don't want this, + * remove the notifiers immediately before calling libusb_exit(). + * + * \param ctx the context to operate on, or NULL for the default context + * \param added_cb pointer to function for addition notifications + * \param removed_cb pointer to function for removal notifications + * \param user_data User data to be passed back to callbacks (useful for + * passing context information) + */ +void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, + libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, + void *user_data) +{ + USBI_GET_CONTEXT(ctx); + ctx->fd_added_cb = added_cb; + ctx->fd_removed_cb = removed_cb; + ctx->fd_cb_user_data = user_data; +} + +/* + * Interrupt the iteration of the event handling thread, so that it picks + * up the fd change. Callers of this function must hold the event_data_lock. + */ +static void usbi_fd_notification(struct libusb_context *ctx) +{ + int pending_events; + + /* Record that there is a new poll fd. + * Only signal an event if there are no prior pending events. */ + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_POLLFDS_MODIFIED; + if (!pending_events) + usbi_signal_event(ctx); +} + +/* Add a file descriptor to the list of file descriptors to be monitored. + * events should be specified as a bitmask of events passed to poll(), e.g. + * POLLIN and/or POLLOUT. */ +int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) +{ + struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd)); + if (!ipollfd) + return LIBUSB_ERROR_NO_MEM; + + usbi_dbg("add fd %d events %d", fd, events); + ipollfd->pollfd.fd = fd; + ipollfd->pollfd.events = events; + usbi_mutex_lock(&ctx->event_data_lock); + list_add_tail(&ipollfd->list, &ctx->ipollfds); + ctx->pollfds_cnt++; + usbi_fd_notification(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + if (ctx->fd_added_cb) + ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); + return 0; +} + +/* Remove a file descriptor from the list of file descriptors to be polled. */ +void usbi_remove_pollfd(struct libusb_context *ctx, int fd) +{ + struct usbi_pollfd *ipollfd; + int found = 0; + + usbi_dbg("remove fd %d", fd); + usbi_mutex_lock(&ctx->event_data_lock); + list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) + if (ipollfd->pollfd.fd == fd) { + found = 1; + break; + } + + if (!found) { + usbi_dbg("couldn't find fd %d to remove", fd); + usbi_mutex_unlock(&ctx->event_data_lock); + return; + } + + list_del(&ipollfd->list); + ctx->pollfds_cnt--; + usbi_fd_notification(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + free(ipollfd); + if (ctx->fd_removed_cb) + ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); +} + +/** \ingroup libusb_poll + * Retrieve a list of file descriptors that should be polled by your main loop + * as libusb event sources. + * + * The returned list is NULL-terminated and should be freed with libusb_free_pollfds() + * when done. The actual list contents must not be touched. + * + * As file descriptors are a Unix-specific concept, this function is not + * available on Windows and will always return NULL. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns a NULL-terminated list of libusb_pollfd structures + * \returns NULL on error + * \returns NULL on platforms where the functionality is not available + */ +DEFAULT_VISIBILITY +const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( + libusb_context *ctx) +{ +#ifndef OS_WINDOWS + struct libusb_pollfd **ret = NULL; + struct usbi_pollfd *ipollfd; + size_t i = 0; + USBI_GET_CONTEXT(ctx); + + usbi_mutex_lock(&ctx->event_data_lock); + + ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *)); + if (!ret) + goto out; + + list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) + ret[i++] = (struct libusb_pollfd *) ipollfd; + ret[ctx->pollfds_cnt] = NULL; + +out: + usbi_mutex_unlock(&ctx->event_data_lock); + return (const struct libusb_pollfd **) ret; +#else + usbi_err(ctx, "external polling of libusb's internal descriptors "\ + "is not yet supported on Windows platforms"); + return NULL; +#endif +} + +/** \ingroup libusb_poll + * Free a list of libusb_pollfd structures. This should be called for all + * pollfd lists allocated with libusb_get_pollfds(). + * + * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104 + * + * It is legal to call this function with a NULL pollfd list. In this case, + * the function will simply return safely. + * + * \param pollfds the list of libusb_pollfd structures to free + */ +void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) +{ + if (!pollfds) + return; + + free((void *)pollfds); +} + +/* Backends may call this from handle_events to report disconnection of a + * device. This function ensures transfers get cancelled appropriately. + * Callers of this function must hold the events_lock. + */ +void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) +{ + struct usbi_transfer *cur; + struct usbi_transfer *to_cancel; + + usbi_dbg("device %d.%d", + dev_handle->dev->bus_number, dev_handle->dev->device_address); + + /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE + * status code. + * + * when we find a transfer for this device on the list, there are two + * possible scenarios: + * 1. the transfer is currently in-flight, in which case we terminate the + * transfer here + * 2. the transfer has been added to the flying transfer list by + * libusb_submit_transfer, has failed to submit and + * libusb_submit_transfer is waiting for us to release the + * flying_transfers_lock to remove it, so we ignore it + */ + + while (1) { + to_cancel = NULL; + usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); + list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer) + if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { + usbi_mutex_lock(&cur->lock); + if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT) + to_cancel = cur; + usbi_mutex_unlock(&cur->lock); + + if (to_cancel) + break; + } + usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); + + if (!to_cancel) + break; + + usbi_dbg("cancelling transfer %p from disconnect", + USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); + + usbi_mutex_lock(&to_cancel->lock); + usbi_backend.clear_transfer_priv(to_cancel); + usbi_mutex_unlock(&to_cancel->lock); + usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); + } + +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h new file mode 100644 index 0000000000..430136b2e2 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h @@ -0,0 +1,2039 @@ +/* + * Public libusb header file + * Copyright © 2001 Johannes Erdfelt + * Copyright © 2007-2008 Daniel Drake + * Copyright © 2012 Pete Batard + * Copyright © 2012 Nathan Hjelm + * For more information, please visit: http://libusb.info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_H +#define LIBUSB_H + +#ifdef _MSC_VER +/* on MS environments, the inline keyword is available in C++ only */ +#if !defined(__cplusplus) +#define inline __inline +#endif +/* ssize_t is also not available (copy/paste from MinGW) */ +#ifndef _SSIZE_T_DEFINED +#define _SSIZE_T_DEFINED +#undef ssize_t +#ifdef _WIN64 + typedef __int64 ssize_t; +#else + typedef int ssize_t; +#endif /* _WIN64 */ +#endif /* _SSIZE_T_DEFINED */ +#endif /* _MSC_VER */ + +/* stdint.h is not available on older MSVC */ +#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H)) +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +#else +#include +#endif + +#if !defined(_WIN32_WCE) +#include +#endif + +#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) +#include +#endif + +#include +#include + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#else +#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif + +/* 'interface' might be defined as a macro on Windows, so we need to + * undefine it so as not to break the current libusb API, because + * libusb_config_descriptor has an 'interface' member + * As this can be problematic if you include windows.h after libusb.h + * in your sources, we force windows.h to be included first. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +#include +#if defined(interface) +#undef interface +#endif +#if !defined(__CYGWIN__) +#include +#endif +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define LIBUSB_DEPRECATED_FOR(f) \ + __attribute__((deprecated("Use " #f " instead"))) +#elif __GNUC__ >= 3 +#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated)) +#else +#define LIBUSB_DEPRECATED_FOR(f) +#endif /* __GNUC__ */ + +/** \def LIBUSB_CALL + * \ingroup libusb_misc + * libusb's Windows calling convention. + * + * Under Windows, the selection of available compilers and configurations + * means that, unlike other platforms, there is not one true calling + * convention (calling convention: the manner in which parameters are + * passed to functions in the generated assembly code). + * + * Matching the Windows API itself, libusb uses the WINAPI convention (which + * translates to the stdcall convention) and guarantees that the + * library is compiled in this way. The public header file also includes + * appropriate annotations so that your own software will use the right + * convention, even if another convention is being used by default within + * your codebase. + * + * The one consideration that you must apply in your software is to mark + * all functions which you use as libusb callbacks with this LIBUSB_CALL + * annotation, so that they too get compiled for the correct calling + * convention. + * + * On non-Windows operating systems, this macro is defined as nothing. This + * means that you can apply it to your code without worrying about + * cross-platform compatibility. + */ +/* LIBUSB_CALL must be defined on both definition and declaration of libusb + * functions. You'd think that declaration would be enough, but cygwin will + * complain about conflicting types unless both are marked this way. + * The placement of this macro is important too; it must appear after the + * return type, before the function name. See internal documentation for + * API_EXPORTED. + */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +#define LIBUSB_CALL WINAPI +#else +#define LIBUSB_CALL +#endif + +/** \def LIBUSB_API_VERSION + * \ingroup libusb_misc + * libusb's API version. + * + * Since version 1.0.13, to help with feature detection, libusb defines + * a LIBUSB_API_VERSION macro that gets increased every time there is a + * significant change to the API, such as the introduction of a new call, + * the definition of a new macro/enum member, or any other element that + * libusb applications may want to detect at compilation time. + * + * The macro is typically used in an application as follows: + * \code + * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) + * // Use one of the newer features from the libusb API + * #endif + * \endcode + * + * Internally, LIBUSB_API_VERSION is defined as follows: + * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) + */ +#define LIBUSB_API_VERSION 0x01000106 + +/* The following is kept for compatibility, but will be deprecated in the future */ +#define LIBUSBX_API_VERSION LIBUSB_API_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup libusb_misc + * Convert a 16-bit value from host-endian to little-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the host-endian value to convert + * \returns the value in little-endian byte order + */ +static inline uint16_t libusb_cpu_to_le16(const uint16_t x) +{ + union { + uint8_t b8[2]; + uint16_t b16; + } _tmp; + _tmp.b8[1] = (uint8_t) (x >> 8); + _tmp.b8[0] = (uint8_t) (x & 0xff); + return _tmp.b16; +} + +/** \def libusb_le16_to_cpu + * \ingroup libusb_misc + * Convert a 16-bit value from little-endian to host-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the little-endian value to convert + * \returns the value in host-endian byte order + */ +#define libusb_le16_to_cpu libusb_cpu_to_le16 + +/* standard USB stuff */ + +/** \ingroup libusb_desc + * Device and/or Interface Class codes */ +enum libusb_class_code { + /** In the context of a \ref libusb_device_descriptor "device descriptor", + * this bDeviceClass value indicates that each interface specifies its + * own class information and all interfaces operate independently. + */ + LIBUSB_CLASS_PER_INTERFACE = 0, + + /** Audio class */ + LIBUSB_CLASS_AUDIO = 1, + + /** Communications class */ + LIBUSB_CLASS_COMM = 2, + + /** Human Interface Device class */ + LIBUSB_CLASS_HID = 3, + + /** Physical */ + LIBUSB_CLASS_PHYSICAL = 5, + + /** Printer class */ + LIBUSB_CLASS_PRINTER = 7, + + /** Image class */ + LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ + LIBUSB_CLASS_IMAGE = 6, + + /** Mass storage class */ + LIBUSB_CLASS_MASS_STORAGE = 8, + + /** Hub class */ + LIBUSB_CLASS_HUB = 9, + + /** Data class */ + LIBUSB_CLASS_DATA = 10, + + /** Smart Card */ + LIBUSB_CLASS_SMART_CARD = 0x0b, + + /** Content Security */ + LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, + + /** Video */ + LIBUSB_CLASS_VIDEO = 0x0e, + + /** Personal Healthcare */ + LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, + + /** Diagnostic Device */ + LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, + + /** Wireless class */ + LIBUSB_CLASS_WIRELESS = 0xe0, + + /** Application class */ + LIBUSB_CLASS_APPLICATION = 0xfe, + + /** Class is vendor-specific */ + LIBUSB_CLASS_VENDOR_SPEC = 0xff +}; + +/** \ingroup libusb_desc + * Descriptor types as defined by the USB specification. */ +enum libusb_descriptor_type { + /** Device descriptor. See libusb_device_descriptor. */ + LIBUSB_DT_DEVICE = 0x01, + + /** Configuration descriptor. See libusb_config_descriptor. */ + LIBUSB_DT_CONFIG = 0x02, + + /** String descriptor */ + LIBUSB_DT_STRING = 0x03, + + /** Interface descriptor. See libusb_interface_descriptor. */ + LIBUSB_DT_INTERFACE = 0x04, + + /** Endpoint descriptor. See libusb_endpoint_descriptor. */ + LIBUSB_DT_ENDPOINT = 0x05, + + /** BOS descriptor */ + LIBUSB_DT_BOS = 0x0f, + + /** Device Capability descriptor */ + LIBUSB_DT_DEVICE_CAPABILITY = 0x10, + + /** HID descriptor */ + LIBUSB_DT_HID = 0x21, + + /** HID report descriptor */ + LIBUSB_DT_REPORT = 0x22, + + /** Physical descriptor */ + LIBUSB_DT_PHYSICAL = 0x23, + + /** Hub descriptor */ + LIBUSB_DT_HUB = 0x29, + + /** SuperSpeed Hub descriptor */ + LIBUSB_DT_SUPERSPEED_HUB = 0x2a, + + /** SuperSpeed Endpoint Companion descriptor */ + LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30 +}; + +/* Descriptor sizes per descriptor type */ +#define LIBUSB_DT_DEVICE_SIZE 18 +#define LIBUSB_DT_CONFIG_SIZE 9 +#define LIBUSB_DT_INTERFACE_SIZE 9 +#define LIBUSB_DT_ENDPOINT_SIZE 7 +#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define LIBUSB_DT_HUB_NONVAR_SIZE 7 +#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 +#define LIBUSB_DT_BOS_SIZE 5 +#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3 + +/* BOS descriptor sizes */ +#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 +#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 +#define LIBUSB_BT_CONTAINER_ID_SIZE 20 + +/* We unwrap the BOS => define its max size */ +#define LIBUSB_DT_BOS_MAX_SIZE ((LIBUSB_DT_BOS_SIZE) +\ + (LIBUSB_BT_USB_2_0_EXTENSION_SIZE) +\ + (LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) +\ + (LIBUSB_BT_CONTAINER_ID_SIZE)) + +#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ +#define LIBUSB_ENDPOINT_DIR_MASK 0x80 + +/** \ingroup libusb_desc + * Endpoint direction. Values for bit 7 of the + * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. + */ +enum libusb_endpoint_direction { + /** In: device-to-host */ + LIBUSB_ENDPOINT_IN = 0x80, + + /** Out: host-to-device */ + LIBUSB_ENDPOINT_OUT = 0x00 +}; + +#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ + +/** \ingroup libusb_desc + * Endpoint transfer type. Values for bits 0:1 of the + * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. + */ +enum libusb_transfer_type { + /** Control endpoint */ + LIBUSB_TRANSFER_TYPE_CONTROL = 0, + + /** Isochronous endpoint */ + LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, + + /** Bulk endpoint */ + LIBUSB_TRANSFER_TYPE_BULK = 2, + + /** Interrupt endpoint */ + LIBUSB_TRANSFER_TYPE_INTERRUPT = 3, + + /** Stream endpoint */ + LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, +}; + +/** \ingroup libusb_misc + * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ +enum libusb_standard_request { + /** Request status of the specific recipient */ + LIBUSB_REQUEST_GET_STATUS = 0x00, + + /** Clear or disable a specific feature */ + LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, + + /* 0x02 is reserved */ + + /** Set or enable a specific feature */ + LIBUSB_REQUEST_SET_FEATURE = 0x03, + + /* 0x04 is reserved */ + + /** Set device address for all future accesses */ + LIBUSB_REQUEST_SET_ADDRESS = 0x05, + + /** Get the specified descriptor */ + LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, + + /** Used to update existing descriptors or add new descriptors */ + LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, + + /** Get the current device configuration value */ + LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, + + /** Set device configuration */ + LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, + + /** Return the selected alternate setting for the specified interface */ + LIBUSB_REQUEST_GET_INTERFACE = 0x0A, + + /** Select an alternate interface for the specified interface */ + LIBUSB_REQUEST_SET_INTERFACE = 0x0B, + + /** Set then report an endpoint's synchronization frame */ + LIBUSB_REQUEST_SYNCH_FRAME = 0x0C, + + /** Sets both the U1 and U2 Exit Latency */ + LIBUSB_REQUEST_SET_SEL = 0x30, + + /** Delay from the time a host transmits a packet to the time it is + * received by the device. */ + LIBUSB_SET_ISOCH_DELAY = 0x31, +}; + +/** \ingroup libusb_misc + * Request type bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. */ +enum libusb_request_type { + /** Standard */ + LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), + + /** Class */ + LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), + + /** Vendor */ + LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), + + /** Reserved */ + LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) +}; + +/** \ingroup libusb_misc + * Recipient bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. Values 4 through 31 are reserved. */ +enum libusb_request_recipient { + /** Device */ + LIBUSB_RECIPIENT_DEVICE = 0x00, + + /** Interface */ + LIBUSB_RECIPIENT_INTERFACE = 0x01, + + /** Endpoint */ + LIBUSB_RECIPIENT_ENDPOINT = 0x02, + + /** Other */ + LIBUSB_RECIPIENT_OTHER = 0x03, +}; + +#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C + +/** \ingroup libusb_desc + * Synchronization type for isochronous endpoints. Values for bits 2:3 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_sync_type { + /** No synchronization */ + LIBUSB_ISO_SYNC_TYPE_NONE = 0, + + /** Asynchronous */ + LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, + + /** Adaptive */ + LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, + + /** Synchronous */ + LIBUSB_ISO_SYNC_TYPE_SYNC = 3 +}; + +#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 + +/** \ingroup libusb_desc + * Usage type for isochronous endpoints. Values for bits 4:5 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_usage_type { + /** Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_DATA = 0, + + /** Feedback endpoint */ + LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, + + /** Implicit feedback Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB device descriptor. This + * descriptor is documented in section 9.6.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_device_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this + * context. */ + uint8_t bDescriptorType; + + /** USB specification release number in binary-coded decimal. A value of + * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ + uint16_t bcdUSB; + + /** USB-IF class code for the device. See \ref libusb_class_code. */ + uint8_t bDeviceClass; + + /** USB-IF subclass code for the device, qualified by the bDeviceClass + * value */ + uint8_t bDeviceSubClass; + + /** USB-IF protocol code for the device, qualified by the bDeviceClass and + * bDeviceSubClass values */ + uint8_t bDeviceProtocol; + + /** Maximum packet size for endpoint 0 */ + uint8_t bMaxPacketSize0; + + /** USB-IF vendor ID */ + uint16_t idVendor; + + /** USB-IF product ID */ + uint16_t idProduct; + + /** Device release number in binary-coded decimal */ + uint16_t bcdDevice; + + /** Index of string descriptor describing manufacturer */ + uint8_t iManufacturer; + + /** Index of string descriptor describing product */ + uint8_t iProduct; + + /** Index of string descriptor containing device serial number */ + uint8_t iSerialNumber; + + /** Number of possible configurations */ + uint8_t bNumConfigurations; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB endpoint descriptor. This + * descriptor is documented in section 9.6.6 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_endpoint_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in + * this context. */ + uint8_t bDescriptorType; + + /** The address of the endpoint described by this descriptor. Bits 0:3 are + * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, + * see \ref libusb_endpoint_direction. + */ + uint8_t bEndpointAddress; + + /** Attributes which apply to the endpoint when it is configured using + * the bConfigurationValue. Bits 0:1 determine the transfer type and + * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for + * isochronous endpoints and correspond to \ref libusb_iso_sync_type. + * Bits 4:5 are also only used for isochronous endpoints and correspond to + * \ref libusb_iso_usage_type. Bits 6:7 are reserved. + */ + uint8_t bmAttributes; + + /** Maximum packet size this endpoint is capable of sending/receiving. */ + uint16_t wMaxPacketSize; + + /** Interval for polling endpoint for data transfers. */ + uint8_t bInterval; + + /** For audio devices only: the rate at which synchronization feedback + * is provided. */ + uint8_t bRefresh; + + /** For audio devices only: the address if the synch endpoint */ + uint8_t bSynchAddress; + + /** Extra descriptors. If libusb encounters unknown endpoint descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB interface descriptor. This + * descriptor is documented in section 9.6.5 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_interface_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE + * in this context. */ + uint8_t bDescriptorType; + + /** Number of this interface */ + uint8_t bInterfaceNumber; + + /** Value used to select this alternate setting for this interface */ + uint8_t bAlternateSetting; + + /** Number of endpoints used by this interface (excluding the control + * endpoint). */ + uint8_t bNumEndpoints; + + /** USB-IF class code for this interface. See \ref libusb_class_code. */ + uint8_t bInterfaceClass; + + /** USB-IF subclass code for this interface, qualified by the + * bInterfaceClass value */ + uint8_t bInterfaceSubClass; + + /** USB-IF protocol code for this interface, qualified by the + * bInterfaceClass and bInterfaceSubClass values */ + uint8_t bInterfaceProtocol; + + /** Index of string descriptor describing this interface */ + uint8_t iInterface; + + /** Array of endpoint descriptors. This length of this array is determined + * by the bNumEndpoints field. */ + const struct libusb_endpoint_descriptor *endpoint; + + /** Extra descriptors. If libusb encounters unknown interface descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A collection of alternate settings for a particular USB interface. + */ +struct libusb_interface { + /** Array of interface descriptors. The length of this array is determined + * by the num_altsetting field. */ + const struct libusb_interface_descriptor *altsetting; + + /** The number of alternate settings that belong to this interface */ + int num_altsetting; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB configuration descriptor. This + * descriptor is documented in section 9.6.3 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_config_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG + * in this context. */ + uint8_t bDescriptorType; + + /** Total length of data returned for this configuration */ + uint16_t wTotalLength; + + /** Number of interfaces supported by this configuration */ + uint8_t bNumInterfaces; + + /** Identifier value for this configuration */ + uint8_t bConfigurationValue; + + /** Index of string descriptor describing this configuration */ + uint8_t iConfiguration; + + /** Configuration characteristics */ + uint8_t bmAttributes; + + /** Maximum power consumption of the USB device from this bus in this + * configuration when the device is fully operation. Expressed in units + * of 2 mA when the device is operating in high-speed mode and in units + * of 8 mA when the device is operating in super-speed mode. */ + uint8_t MaxPower; + + /** Array of interfaces supported by this configuration. The length of + * this array is determined by the bNumInterfaces field. */ + const struct libusb_interface *interface; + + /** Extra descriptors. If libusb encounters unknown configuration + * descriptors, it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the superspeed endpoint companion + * descriptor. This descriptor is documented in section 9.6.7 of + * the USB 3.0 specification. All multiple-byte fields are represented in + * host-endian format. + */ +struct libusb_ss_endpoint_companion_descriptor { + + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in + * this context. */ + uint8_t bDescriptorType; + + + /** The maximum number of packets the endpoint can send or + * receive as part of a burst. */ + uint8_t bMaxBurst; + + /** In bulk EP: bits 4:0 represents the maximum number of + * streams the EP supports. In isochronous EP: bits 1:0 + * represents the Mult - a zero based value that determines + * the maximum number of packets within a service interval */ + uint8_t bmAttributes; + + /** The total number of bytes this EP will transfer every + * service interval. valid only for periodic EPs. */ + uint16_t wBytesPerInterval; +}; + +/** \ingroup libusb_desc + * A generic representation of a BOS Device Capability descriptor. It is + * advised to check bDevCapabilityType and call the matching + * libusb_get_*_descriptor function to get a structure fully matching the type. + */ +struct libusb_bos_dev_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + /** Device Capability type */ + uint8_t bDevCapabilityType; + /** Device Capability data (bLength - 3 bytes) */ + uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the Binary Device Object Store (BOS) descriptor. + * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_bos_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS + * in this context. */ + uint8_t bDescriptorType; + + /** Length of this descriptor and all of its sub descriptors */ + uint16_t wTotalLength; + + /** The number of separate device capability descriptors in + * the BOS */ + uint8_t bNumDeviceCaps; + + /** bNumDeviceCap Device Capability Descriptors */ + struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the USB 2.0 Extension descriptor + * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_usb_2_0_extension_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION + * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_usb_2_0_extension_attributes. */ + uint32_t bmAttributes; +}; + +/** \ingroup libusb_desc + * A structure representing the SuperSpeed USB Device Capability descriptor + * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_ss_usb_device_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_ss_usb_device_capability_attributes. */ + uint8_t bmAttributes; + + /** Bitmap encoding of the speed supported by this device when + * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ + uint16_t wSpeedSupported; + + /** The lowest speed at which all the functionality supported + * by the device is available to the user. For example if the + * device supports all its functionality when connected at + * full speed and above then it sets this value to 1. */ + uint8_t bFunctionalitySupport; + + /** U1 Device Exit Latency. */ + uint8_t bU1DevExitLat; + + /** U2 Device Exit Latency. */ + uint16_t bU2DevExitLat; +}; + +/** \ingroup libusb_desc + * A structure representing the Container ID descriptor. + * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. + * All multiple-byte fields, except UUIDs, are represented in host-endian format. + */ +struct libusb_container_id_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID + * LIBUSB_BT_CONTAINER_ID in this context. */ + uint8_t bDevCapabilityType; + + /** Reserved field */ + uint8_t bReserved; + + /** 128 bit UUID */ + uint8_t ContainerID[16]; +}; + +/** \ingroup libusb_asyncio + * Setup packet for control transfers. */ +struct libusb_control_setup { + /** Request type. Bits 0:4 determine recipient, see + * \ref libusb_request_recipient. Bits 5:6 determine type, see + * \ref libusb_request_type. Bit 7 determines data transfer direction, see + * \ref libusb_endpoint_direction. + */ + uint8_t bmRequestType; + + /** Request. If the type bits of bmRequestType are equal to + * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD + * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to + * \ref libusb_standard_request. For other cases, use of this field is + * application-specific. */ + uint8_t bRequest; + + /** Value. Varies according to request */ + uint16_t wValue; + + /** Index. Varies according to request, typically used to pass an index + * or offset */ + uint16_t wIndex; + + /** Number of bytes to transfer */ + uint16_t wLength; +}; + +#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) + +/* libusb */ + +struct libusb_context; +struct libusb_device; +struct libusb_device_handle; + +/** \ingroup libusb_lib + * Structure providing the version of the libusb runtime + */ +struct libusb_version { + /** Library major version. */ + const uint16_t major; + + /** Library minor version. */ + const uint16_t minor; + + /** Library micro version. */ + const uint16_t micro; + + /** Library nano version. */ + const uint16_t nano; + + /** Library release candidate suffix string, e.g. "-rc4". */ + const char *rc; + + /** For ABI compatibility only. */ + const char* describe; +}; + +/** \ingroup libusb_lib + * Structure representing a libusb session. The concept of individual libusb + * sessions allows for your program to use two libraries (or dynamically + * load two modules) which both independently use libusb. This will prevent + * interference between the individual libusb users - for example + * libusb_set_option() will not affect the other user of the library, and + * libusb_exit() will not destroy resources that the other user is still + * using. + * + * Sessions are created by libusb_init() and destroyed through libusb_exit(). + * If your application is guaranteed to only ever include a single libusb + * user (i.e. you), you do not have to worry about contexts: pass NULL in + * every function call where a context is required. The default context + * will be used. + * + * For more information, see \ref libusb_contexts. + */ +typedef struct libusb_context libusb_context; + +/** \ingroup libusb_dev + * Structure representing a USB device detected on the system. This is an + * opaque type for which you are only ever provided with a pointer, usually + * originating from libusb_get_device_list(). + * + * Certain operations can be performed on a device, but in order to do any + * I/O you will have to first obtain a device handle using libusb_open(). + * + * Devices are reference counted with libusb_ref_device() and + * libusb_unref_device(), and are freed when the reference count reaches 0. + * New devices presented by libusb_get_device_list() have a reference count of + * 1, and libusb_free_device_list() can optionally decrease the reference count + * on all devices in the list. libusb_open() adds another reference which is + * later destroyed by libusb_close(). + */ +typedef struct libusb_device libusb_device; + + +/** \ingroup libusb_dev + * Structure representing a handle on a USB device. This is an opaque type for + * which you are only ever provided with a pointer, usually originating from + * libusb_open(). + * + * A device handle is used to perform I/O and other operations. When finished + * with a device handle, you should call libusb_close(). + */ +typedef struct libusb_device_handle libusb_device_handle; + +/** \ingroup libusb_dev + * Speed codes. Indicates the speed at which the device is operating. + */ +enum libusb_speed { + /** The OS doesn't report or know the device speed. */ + LIBUSB_SPEED_UNKNOWN = 0, + + /** The device is operating at low speed (1.5MBit/s). */ + LIBUSB_SPEED_LOW = 1, + + /** The device is operating at full speed (12MBit/s). */ + LIBUSB_SPEED_FULL = 2, + + /** The device is operating at high speed (480MBit/s). */ + LIBUSB_SPEED_HIGH = 3, + + /** The device is operating at super speed (5000MBit/s). */ + LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5, +}; + +/** \ingroup libusb_dev + * Supported speeds (wSpeedSupported) bitfield. Indicates what + * speeds the device supports. + */ +enum libusb_supported_speed { + /** Low speed operation supported (1.5MBit/s). */ + LIBUSB_LOW_SPEED_OPERATION = 1, + + /** Full speed operation supported (12MBit/s). */ + LIBUSB_FULL_SPEED_OPERATION = 2, + + /** High speed operation supported (480MBit/s). */ + LIBUSB_HIGH_SPEED_OPERATION = 4, + + /** Superspeed operation supported (5000MBit/s). */ + LIBUSB_SUPER_SPEED_OPERATION = 8, +}; + +/** \ingroup libusb_dev + * Masks for the bits of the + * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field + * of the USB 2.0 Extension descriptor. + */ +enum libusb_usb_2_0_extension_attributes { + /** Supports Link Power Management (LPM) */ + LIBUSB_BM_LPM_SUPPORT = 2, +}; + +/** \ingroup libusb_dev + * Masks for the bits of the + * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field + * field of the SuperSpeed USB Device Capability descriptor. + */ +enum libusb_ss_usb_device_capability_attributes { + /** Supports Latency Tolerance Messages (LTM) */ + LIBUSB_BM_LTM_SUPPORT = 2, +}; + +/** \ingroup libusb_dev + * USB capability types + */ +enum libusb_bos_type { + /** Wireless USB device capability */ + LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1, + + /** USB 2.0 extensions */ + LIBUSB_BT_USB_2_0_EXTENSION = 2, + + /** SuperSpeed USB device capability */ + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3, + + /** Container ID type */ + LIBUSB_BT_CONTAINER_ID = 4, +}; + +/** \ingroup libusb_misc + * Error codes. Most libusb functions return 0 on success or one of these + * codes on failure. + * You can call libusb_error_name() to retrieve a string representation of an + * error code or libusb_strerror() to get an end-user suitable description of + * an error code. + */ +enum libusb_error { + /** Success (no error) */ + LIBUSB_SUCCESS = 0, + + /** Input/output error */ + LIBUSB_ERROR_IO = -1, + + /** Invalid parameter */ + LIBUSB_ERROR_INVALID_PARAM = -2, + + /** Access denied (insufficient permissions) */ + LIBUSB_ERROR_ACCESS = -3, + + /** No such device (it may have been disconnected) */ + LIBUSB_ERROR_NO_DEVICE = -4, + + /** Entity not found */ + LIBUSB_ERROR_NOT_FOUND = -5, + + /** Resource busy */ + LIBUSB_ERROR_BUSY = -6, + + /** Operation timed out */ + LIBUSB_ERROR_TIMEOUT = -7, + + /** Overflow */ + LIBUSB_ERROR_OVERFLOW = -8, + + /** Pipe error */ + LIBUSB_ERROR_PIPE = -9, + + /** System call interrupted (perhaps due to signal) */ + LIBUSB_ERROR_INTERRUPTED = -10, + + /** Insufficient memory */ + LIBUSB_ERROR_NO_MEM = -11, + + /** Operation not supported or unimplemented on this platform */ + LIBUSB_ERROR_NOT_SUPPORTED = -12, + + /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the + message strings in strerror.c when adding new error codes here. */ + + /** Other error */ + LIBUSB_ERROR_OTHER = -99, +}; + +/* Total number of error codes in enum libusb_error */ +#define LIBUSB_ERROR_COUNT 14 + +/** \ingroup libusb_asyncio + * Transfer status codes */ +enum libusb_transfer_status { + /** Transfer completed without error. Note that this does not indicate + * that the entire amount of requested data was transferred. */ + LIBUSB_TRANSFER_COMPLETED, + + /** Transfer failed */ + LIBUSB_TRANSFER_ERROR, + + /** Transfer timed out */ + LIBUSB_TRANSFER_TIMED_OUT, + + /** Transfer was cancelled */ + LIBUSB_TRANSFER_CANCELLED, + + /** For bulk/interrupt endpoints: halt condition detected (endpoint + * stalled). For control endpoints: control request not supported. */ + LIBUSB_TRANSFER_STALL, + + /** Device was disconnected */ + LIBUSB_TRANSFER_NO_DEVICE, + + /** Device sent more data than requested */ + LIBUSB_TRANSFER_OVERFLOW, + + /* NB! Remember to update libusb_error_name() + when adding new status codes here. */ +}; + +/** \ingroup libusb_asyncio + * libusb_transfer.flags values */ +enum libusb_transfer_flags { + /** Report short frames as errors */ + LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, + + /** Automatically free() transfer buffer during libusb_free_transfer(). + * Note that buffers allocated with libusb_dev_mem_alloc() should not + * be attempted freed in this way, since free() is not an appropriate + * way to release such memory. */ + LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, + + /** Automatically call libusb_free_transfer() after callback returns. + * If this flag is set, it is illegal to call libusb_free_transfer() + * from your transfer callback, as this will result in a double-free + * when this flag is acted upon. */ + LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, + + /** Terminate transfers that are a multiple of the endpoint's + * wMaxPacketSize with an extra zero length packet. This is useful + * when a device protocol mandates that each logical request is + * terminated by an incomplete packet (i.e. the logical requests are + * not separated by other means). + * + * This flag only affects host-to-device transfers to bulk and interrupt + * endpoints. In other situations, it is ignored. + * + * This flag only affects transfers with a length that is a multiple of + * the endpoint's wMaxPacketSize. On transfers of other lengths, this + * flag has no effect. Therefore, if you are working with a device that + * needs a ZLP whenever the end of the logical request falls on a packet + * boundary, then it is sensible to set this flag on every + * transfer (you do not have to worry about only setting it on transfers + * that end on the boundary). + * + * This flag is currently only supported on Linux. + * On other systems, libusb_submit_transfer() will return + * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. + * + * Available since libusb-1.0.9. + */ + LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, +}; + +/** \ingroup libusb_asyncio + * Isochronous packet descriptor. */ +struct libusb_iso_packet_descriptor { + /** Length of data to request in this packet */ + unsigned int length; + + /** Amount of data that was actually transferred */ + unsigned int actual_length; + + /** Status code for this packet */ + enum libusb_transfer_status status; +}; + +struct libusb_transfer; + +/** \ingroup libusb_asyncio + * Asynchronous transfer callback function type. When submitting asynchronous + * transfers, you pass a pointer to a callback function of this type via the + * \ref libusb_transfer::callback "callback" member of the libusb_transfer + * structure. libusb will call this function later, when the transfer has + * completed or failed. See \ref libusb_asyncio for more information. + * \param transfer The libusb_transfer struct the callback function is being + * notified about. + */ +typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * The generic USB transfer structure. The user populates this structure and + * then submits it in order to request a transfer. After the transfer has + * completed, the library populates the transfer with the results and passes + * it back to the user. + */ +struct libusb_transfer { + /** Handle of the device that this transfer will be submitted to */ + libusb_device_handle *dev_handle; + + /** A bitwise OR combination of \ref libusb_transfer_flags. */ + uint8_t flags; + + /** Address of the endpoint where this transfer will be sent. */ + unsigned char endpoint; + + /** Type of the endpoint from \ref libusb_transfer_type */ + unsigned char type; + + /** Timeout for this transfer in milliseconds. A value of 0 indicates no + * timeout. */ + unsigned int timeout; + + /** The status of the transfer. Read-only, and only for use within + * transfer callback function. + * + * If this is an isochronous transfer, this field may read COMPLETED even + * if there were errors in the frames. Use the + * \ref libusb_iso_packet_descriptor::status "status" field in each packet + * to determine if errors occurred. */ + enum libusb_transfer_status status; + + /** Length of the data buffer */ + int length; + + /** Actual length of data that was transferred. Read-only, and only for + * use within transfer callback function. Not valid for isochronous + * endpoint transfers. */ + int actual_length; + + /** Callback function. This will be invoked when the transfer completes, + * fails, or is cancelled. */ + libusb_transfer_cb_fn callback; + + /** User context data to pass to the callback function. */ + void *user_data; + + /** Data buffer */ + unsigned char *buffer; + + /** Number of isochronous packets. Only used for I/O with isochronous + * endpoints. */ + int num_iso_packets; + + /** Isochronous packet descriptors, for isochronous transfers only. */ + struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_misc + * Capabilities supported by an instance of libusb on the current running + * platform. Test if the loaded library supports a given capability by calling + * \ref libusb_has_capability(). + */ +enum libusb_capability { + /** The libusb_has_capability() API is available. */ + LIBUSB_CAP_HAS_CAPABILITY = 0x0000, + /** Hotplug support is available on this platform. */ + LIBUSB_CAP_HAS_HOTPLUG = 0x0001, + /** The library can access HID devices without requiring user intervention. + * Note that before being able to actually access an HID device, you may + * still have to call additional libusb functions such as + * \ref libusb_detach_kernel_driver(). */ + LIBUSB_CAP_HAS_HID_ACCESS = 0x0100, + /** The library supports detaching of the default USB driver, using + * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ + LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 +}; + +/** \ingroup libusb_lib + * Log message levels. + * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) + * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr + * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr + * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr + * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr + */ +enum libusb_log_level { + LIBUSB_LOG_LEVEL_NONE = 0, + LIBUSB_LOG_LEVEL_ERROR = 1, + LIBUSB_LOG_LEVEL_WARNING = 2, + LIBUSB_LOG_LEVEL_INFO = 3, + LIBUSB_LOG_LEVEL_DEBUG = 4, +}; + +int LIBUSB_CALL libusb_init(libusb_context **ctx); +void LIBUSB_CALL libusb_exit(libusb_context *ctx); +LIBUSB_DEPRECATED_FOR(libusb_set_option) +void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +const struct libusb_version * LIBUSB_CALL libusb_get_version(void); +int LIBUSB_CALL libusb_has_capability(uint32_t capability); +const char * LIBUSB_CALL libusb_error_name(int errcode); +int LIBUSB_CALL libusb_setlocale(const char *locale); +const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode); + +ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, + libusb_device ***list); +void LIBUSB_CALL libusb_free_device_list(libusb_device **list, + int unref_devices); +libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); +void LIBUSB_CALL libusb_unref_device(libusb_device *dev); + +int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, + int *config); +int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, + struct libusb_device_descriptor *desc); +int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, + struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, + uint8_t config_index, struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, + uint8_t bConfigurationValue, struct libusb_config_descriptor **config); +void LIBUSB_CALL libusb_free_config_descriptor( + struct libusb_config_descriptor *config); +int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( + struct libusb_context *ctx, + const struct libusb_endpoint_descriptor *endpoint, + struct libusb_ss_endpoint_companion_descriptor **ep_comp); +void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( + struct libusb_ss_endpoint_companion_descriptor *ep_comp); +int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, + struct libusb_bos_descriptor **bos); +void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); +int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( + struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension); +void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor( + struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension); +int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor( + struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap); +void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor( + struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap); +int LIBUSB_CALL libusb_get_container_id_descriptor(struct libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_container_id_descriptor **container_id); +void LIBUSB_CALL libusb_free_container_id_descriptor( + struct libusb_container_id_descriptor *container_id); +uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); +int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len); +LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers) +int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length); +libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); +int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); +int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, + unsigned char endpoint); +int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, + unsigned char endpoint); + +int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); +void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); +libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, + int configuration); +int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, + int interface_number); + +libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); + +int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, + int interface_number, int alternate_setting); +int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, + unsigned char endpoint); +int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints); +int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, + unsigned char *endpoints, int num_endpoints); + +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length); +int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length); + +int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( + libusb_device_handle *dev_handle, int enable); + +/* async I/O */ + +/** \ingroup libusb_asyncio + * Get the data section of a control transfer. This convenience function is here + * to remind you that the data does not start until 8 bytes into the actual + * buffer, as the setup packet comes first. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns pointer to the first byte of the data section + */ +static inline unsigned char *libusb_control_transfer_get_data( + struct libusb_transfer *transfer) +{ + return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; +} + +/** \ingroup libusb_asyncio + * Get the control setup packet of a control transfer. This convenience + * function is here to remind you that the control setup occupies the first + * 8 bytes of the transfer data buffer. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns a casted pointer to the start of the transfer data buffer + */ +static inline struct libusb_control_setup *libusb_control_transfer_get_setup( + struct libusb_transfer *transfer) +{ + return (struct libusb_control_setup *)(void *) transfer->buffer; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the setup packet (first 8 bytes of the data + * buffer) for a control transfer. The wIndex, wValue and wLength values should + * be given in host-endian byte order. + * + * \param buffer buffer to output the setup packet into + * This pointer must be aligned to at least 2 bytes boundary. + * \param bmRequestType see the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field of + * \ref libusb_control_setup + * \param bRequest see the + * \ref libusb_control_setup::bRequest "bRequest" field of + * \ref libusb_control_setup + * \param wValue see the + * \ref libusb_control_setup::wValue "wValue" field of + * \ref libusb_control_setup + * \param wIndex see the + * \ref libusb_control_setup::wIndex "wIndex" field of + * \ref libusb_control_setup + * \param wLength see the + * \ref libusb_control_setup::wLength "wLength" field of + * \ref libusb_control_setup + */ +static inline void libusb_fill_control_setup(unsigned char *buffer, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint16_t wLength) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; + setup->bmRequestType = bmRequestType; + setup->bRequest = bRequest; + setup->wValue = libusb_cpu_to_le16(wValue); + setup->wIndex = libusb_cpu_to_le16(wIndex); + setup->wLength = libusb_cpu_to_le16(wLength); +} + +struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); +int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); +int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_transfer_set_stream_id( + struct libusb_transfer *transfer, uint32_t stream_id); +uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( + struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a control transfer. + * + * If you pass a transfer buffer to this function, the first 8 bytes will + * be interpreted as a control setup packet, and the wLength field will be + * used to automatically populate the \ref libusb_transfer::length "length" + * field of the transfer. Therefore the recommended approach is: + * -# Allocate a suitably sized data buffer (including space for control setup) + * -# Call libusb_fill_control_setup() + * -# If this is a host-to-device transfer with a data stage, put the data + * in place after the setup packet + * -# Call this function + * -# Call libusb_submit_transfer() + * + * It is also legal to pass a NULL buffer to this function, in which case this + * function will not attempt to populate the length field. Remember that you + * must then populate the buffer and length fields later. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param buffer data buffer. If provided, this function will interpret the + * first 8 bytes as a setup packet and infer the transfer length from that. + * This pointer must be aligned to at least 2 bytes boundary. + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_control_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, + unsigned int timeout) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; + transfer->dev_handle = dev_handle; + transfer->endpoint = 0; + transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; + transfer->timeout = timeout; + transfer->buffer = buffer; + if (setup) + transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE + + libusb_le16_to_cpu(setup->wLength)); + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_BULK; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer using bulk streams. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param stream_id bulk stream id for this transfer + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_stream_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, uint32_t stream_id, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, + length, callback, user_data, timeout); + transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; + libusb_transfer_set_stream_id(transfer, stream_id); +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an interrupt transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_interrupt_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an isochronous transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param num_iso_packets the number of isochronous packets + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, int num_iso_packets, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->num_iso_packets = num_iso_packets; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Convenience function to set the length of all packets in an isochronous + * transfer, based on the num_iso_packets field in the transfer structure. + * + * \param transfer a transfer + * \param length the length to set in each isochronous packet descriptor + * \see libusb_get_max_packet_size() + */ +static inline void libusb_set_iso_packet_lengths( + struct libusb_transfer *transfer, unsigned int length) +{ + int i; + for (i = 0; i < transfer->num_iso_packets; i++) + transfer->iso_packet_desc[i].length = length; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer. + * + * This is a thorough function which loops through all preceding packets, + * accumulating their lengths to find the position of the specified packet. + * Typically you will assign equal lengths to each packet in the transfer, + * and hence the above method is sub-optimal. You may wish to use + * libusb_get_iso_packet_buffer_simple() instead. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer_simple() + */ +static inline unsigned char *libusb_get_iso_packet_buffer( + struct libusb_transfer *transfer, unsigned int packet) +{ + int i; + size_t offset = 0; + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + for (i = 0; i < _packet; i++) + offset += transfer->iso_packet_desc[i].length; + + return transfer->buffer + offset; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer, for transfers where each + * packet is of identical size. + * + * This function relies on the assumption that every packet within the transfer + * is of identical size to the first packet. Calculating the location of + * the packet buffer is then just a simple calculation: + * buffer + (packet_size * packet) + * + * Do not use this function on transfers other than those that have identical + * packet lengths for each packet. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer() + */ +static inline unsigned char *libusb_get_iso_packet_buffer_simple( + struct libusb_transfer *transfer, unsigned int packet) +{ + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet); +} + +/* sync I/O */ + +int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, + uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout); + +int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +/** \ingroup libusb_desc + * Retrieve a descriptor from the default control pipe. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. + * + * \param dev_handle a device handle + * \param desc_type the descriptor type, see \ref libusb_descriptor_type + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), + 0, data, (uint16_t) length, 1000); +} + +/** \ingroup libusb_desc + * Retrieve a descriptor from a device. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. The string returned is Unicode, as + * detailed in the USB specifications. + * + * \param dev_handle a device handle + * \param desc_index the index of the descriptor to retrieve + * \param langid the language ID for the string descriptor + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + * \see libusb_get_string_descriptor_ascii() + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_index, uint16_t langid, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), + langid, data, (uint16_t) length, 1000); +} + +int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, + uint8_t desc_index, unsigned char *data, int length); + +/* polling and timeouts */ + +int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); +void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); +int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); + +int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, + struct timeval *tv, int *completed); +int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); +int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); +int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); +int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, + struct timeval *tv); + +/** \ingroup libusb_poll + * File descriptor for polling + */ +struct libusb_pollfd { + /** Numeric file descriptor */ + int fd; + + /** Event flags to poll for from . POLLIN indicates that you + * should monitor this file descriptor for becoming ready to read from, + * and POLLOUT indicates that you should monitor this file descriptor for + * nonblocking write readiness. */ + short events; +}; + +/** \ingroup libusb_poll + * Callback function, invoked when a new file descriptor should be added + * to the set of file descriptors monitored for events. + * \param fd the new file descriptor + * \param events events to monitor for, see \ref libusb_pollfd for a + * description + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, + void *user_data); + +/** \ingroup libusb_poll + * Callback function, invoked when a file descriptor should be removed from + * the set of file descriptors being monitored for events. After returning + * from this callback, do not use that file descriptor again. + * \param fd the file descriptor to stop monitoring + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); + +const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( + libusb_context *ctx); +void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds); +void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, + libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, + void *user_data); + +/** \ingroup libusb_hotplug + * Callback handle. + * + * Callbacks handles are generated by libusb_hotplug_register_callback() + * and can be used to deregister callbacks. Callback handles are unique + * per libusb_context and it is safe to call libusb_hotplug_deregister_callback() + * on an already deregisted callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * For more information, see \ref libusb_hotplug. + */ +typedef int libusb_hotplug_callback_handle; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Flags for hotplug events */ +typedef enum { + /** Default value when not using any flags. */ + LIBUSB_HOTPLUG_NO_FLAGS = 0, + + /** Arm the callback and fire it for all matching currently attached devices. */ + LIBUSB_HOTPLUG_ENUMERATE = 1<<0, +} libusb_hotplug_flag; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Hotplug events */ +typedef enum { + /** A device has been plugged in and is ready to use */ + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01, + + /** A device has left and is no longer available. + * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. + * It is safe to call libusb_get_device_descriptor on a device that has left */ + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, +} libusb_hotplug_event; + +/** \ingroup libusb_hotplug + * Wildcard matching for hotplug events */ +#define LIBUSB_HOTPLUG_MATCH_ANY -1 + +/** \ingroup libusb_hotplug + * Hotplug callback function type. When requesting hotplug event notifications, + * you pass a pointer to a callback function of this type. + * + * This callback may be called by an internal event thread and as such it is + * recommended the callback do minimal processing before returning. + * + * libusb will call this function later, when a matching event had happened on + * a matching device. See \ref libusb_hotplug for more information. + * + * It is safe to call either libusb_hotplug_register_callback() or + * libusb_hotplug_deregister_callback() from within a callback function. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param ctx context of this notification + * \param device libusb_device this event occurred on + * \param event event that occurred + * \param user_data user data provided when this callback was registered + * \returns bool whether this callback is finished processing events. + * returning 1 will cause this callback to be deregistered + */ +typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, + libusb_device *device, + libusb_hotplug_event event, + void *user_data); + +/** \ingroup libusb_hotplug + * Register a hotplug callback function + * + * Register a callback with the libusb_context. The callback will fire + * when a matching event occurs on a matching device. The callback is + * armed until either it is deregistered with libusb_hotplug_deregister_callback() + * or the supplied callback returns 1 to indicate it is finished processing events. + * + * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be + * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices + * already plugged into the machine. Note that libusb modifies its internal + * device list from a separate thread, while calling hotplug callbacks from + * libusb_handle_events(), so it is possible for a device to already be present + * on, or removed from, its internal device list, while the hotplug callbacks + * still need to be dispatched. This means that when using \ref + * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival + * of the same device, once from libusb_hotplug_register_callback() and once + * from libusb_handle_events(); and/or your callback may be called for the + * removal of a device for which an arrived call was never made. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context to register this callback with + * \param[in] events bitwise or of events that will trigger this callback. See \ref + * libusb_hotplug_event + * \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag + * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] cb_fn the function to be invoked on a matching event/device + * \param[in] user_data user data to pass to the callback function + * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) + * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure + */ +int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, + libusb_hotplug_event events, + libusb_hotplug_flag flags, + int vendor_id, int product_id, + int dev_class, + libusb_hotplug_callback_fn cb_fn, + void *user_data, + libusb_hotplug_callback_handle *callback_handle); + +/** \ingroup libusb_hotplug + * Deregisters a hotplug callback. + * + * Deregister a callback from a libusb_context. This function is safe to call from within + * a hotplug callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context this callback is registered with + * \param[in] callback_handle the handle of the callback to deregister + */ +void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); + +/** \ingroup libusb_lib + * Available option values for libusb_set_option(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + LIBUSB_OPTION_USE_USBDK, +}; + +int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h new file mode 100644 index 0000000000..31d6ce98d4 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h @@ -0,0 +1,1165 @@ +/* + * Internal header for libusb + * Copyright © 2007-2009 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSBI_H +#define LIBUSBI_H + +#include + +#include + +#include +#include +#include +#include +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_MISSING_H +#include +#endif + +#include "libusb.h" +#include "version.h" + +/* Attribute to ensure that a structure member is aligned to a natural + * pointer alignment. Used for os_priv member. */ +#if defined(_MSC_VER) +#if defined(_WIN64) +#define PTR_ALIGNED __declspec(align(8)) +#else +#define PTR_ALIGNED __declspec(align(4)) +#endif +#elif defined(__GNUC__) +#define PTR_ALIGNED __attribute__((aligned(sizeof(void *)))) +#else +#define PTR_ALIGNED +#endif + +/* Inside the libusb code, mark all public functions as follows: + * return_type API_EXPORTED function_name(params) { ... } + * But if the function returns a pointer, mark it as follows: + * DEFAULT_VISIBILITY return_type * LIBUSB_CALL function_name(params) { ... } + * In the libusb public header, mark all declarations as: + * return_type LIBUSB_CALL function_name(params); + */ +#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEVICE_DESC_LENGTH 18 + +#define USB_MAXENDPOINTS 32 +#define USB_MAXINTERFACES 32 +#define USB_MAXCONFIG 8 + +/* Backend specific capabilities */ +#define USBI_CAP_HAS_HID_ACCESS 0x00010000 +#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 + +/* Maximum number of bytes in a log line */ +#define USBI_MAX_LOG_LEN 1024 +/* Terminator for log lines */ +#define USBI_LOG_LINE_END "\n" + +/* The following is used to silence warnings for unused variables */ +#define UNUSED(var) do { (void)(var); } while(0) + +#if !defined(ARRAYSIZE) +#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0])) +#endif + +struct list_head { + struct list_head *prev, *next; +}; + +/* Get an entry from the list + * ptr - the address of this list_head element in "type" + * type - the data type that contains "member" + * member - the list_head element in "type" + */ +#define list_entry(ptr, type, member) \ + ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/* Get each entry from a list + * pos - A structure pointer has a "member" element + * head - list head + * member - the list_head element in "pos" + * type - the type of the first parameter + */ +#define list_for_each_entry(pos, head, member, type) \ + for (pos = list_entry((head)->next, type, member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, type, member)) + +#define list_for_each_entry_safe(pos, n, head, member, type) \ + for (pos = list_entry((head)->next, type, member), \ + n = list_entry(pos->member.next, type, member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, type, member)) + +#define list_empty(entry) ((entry)->next == (entry)) + +static inline void list_init(struct list_head *entry) +{ + entry->prev = entry->next = entry; +} + +static inline void list_add(struct list_head *entry, struct list_head *head) +{ + entry->next = head->next; + entry->prev = head; + + head->next->prev = entry; + head->next = entry; +} + +static inline void list_add_tail(struct list_head *entry, + struct list_head *head) +{ + entry->next = head; + entry->prev = head->prev; + + head->prev->next = entry; + head->prev = entry; +} + +static inline void list_del(struct list_head *entry) +{ + entry->next->prev = entry->prev; + entry->prev->next = entry->next; + entry->next = entry->prev = NULL; +} + +static inline void list_cut(struct list_head *list, struct list_head *head) +{ + if (list_empty(head)) + return; + + list->next = head->next; + list->next->prev = list; + list->prev = head->prev; + list->prev->next = list; + + list_init(head); +} + +static inline void *usbi_reallocf(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + if (!ret) + free(ptr); + return ret; +} + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *mptr = (ptr); \ + (type *)( (char *)mptr - offsetof(type,member) );}) + +#ifndef CLAMP +#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0) + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +#define TIMEVAL_TV_SEC_TYPE long +#else +#define TIMEVAL_TV_SEC_TYPE time_t +#endif + +/* Some platforms don't have this define */ +#ifndef TIMESPEC_TO_TIMEVAL +#define TIMESPEC_TO_TIMEVAL(tv, ts) \ + do { \ + (tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) +#endif + +#ifdef ENABLE_LOGGING + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf usbi_snprintf +#define vsnprintf usbi_vsnprintf +int usbi_snprintf(char *dst, size_t size, const char *format, ...); +int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); +#define LIBUSB_PRINTF_WIN32 +#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */ + +void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, + const char *function, const char *format, ...); + +void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, + const char *function, const char *format, va_list args); + +#if !defined(_MSC_VER) || (_MSC_VER >= 1400) + +#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) + +#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) +#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) +#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) +#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) + +#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ + +#define LOG_BODY(ctxt, level) \ +{ \ + va_list args; \ + va_start(args, format); \ + usbi_log_v(ctxt, level, "", format, args); \ + va_end(args); \ +} + +static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) +static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) +static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) +static inline void usbi_dbg(const char *format, ...) + LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) + +#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ + +#else /* ENABLE_LOGGING */ + +#define usbi_err(ctx, ...) do { (void)ctx; } while (0) +#define usbi_warn(ctx, ...) do { (void)ctx; } while (0) +#define usbi_info(ctx, ...) do { (void)ctx; } while (0) +#define usbi_dbg(...) do {} while (0) + +#endif /* ENABLE_LOGGING */ + +#define USBI_GET_CONTEXT(ctx) \ + do { \ + if (!(ctx)) \ + (ctx) = usbi_default_context; \ + } while(0) + +#define DEVICE_CTX(dev) ((dev)->ctx) +#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) +#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) +#define ITRANSFER_CTX(transfer) \ + (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) + +#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) +#define IS_EPOUT(ep) (!IS_EPIN(ep)) +#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) +#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) + +/* Internal abstraction for thread synchronization */ +#if defined(THREADS_POSIX) +#include "os/threads_posix.h" +#elif defined(OS_WINDOWS) || defined(OS_WINCE) +#include "os/threads_windows.h" +#endif + +extern struct libusb_context *usbi_default_context; + +/* Forward declaration for use in context (fully defined inside poll abstraction) */ +struct pollfd; + +struct libusb_context { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + enum libusb_log_level debug; + int debug_fixed; +#endif + + /* internal event pipe, used for signalling occurrence of an internal event. */ + int event_pipe[2]; + + struct list_head usb_devs; + usbi_mutex_t usb_devs_lock; + + /* A list of open handles. Backends are free to traverse this if required. + */ + struct list_head open_devs; + usbi_mutex_t open_devs_lock; + + /* A list of registered hotplug callbacks */ + struct list_head hotplug_cbs; + libusb_hotplug_callback_handle next_hotplug_cb_handle; + usbi_mutex_t hotplug_cbs_lock; + + /* this is a list of in-flight transfer handles, sorted by timeout + * expiration. URBs to timeout the soonest are placed at the beginning of + * the list, URBs that will time out later are placed after, and urbs with + * infinite timeout are always placed at the very end. */ + struct list_head flying_transfers; + /* Note paths taking both this and usbi_transfer->lock must always + * take this lock first */ + usbi_mutex_t flying_transfers_lock; + + /* user callbacks for pollfd changes */ + libusb_pollfd_added_cb fd_added_cb; + libusb_pollfd_removed_cb fd_removed_cb; + void *fd_cb_user_data; + + /* ensures that only one thread is handling events at any one time */ + usbi_mutex_t events_lock; + + /* used to see if there is an active thread doing event handling */ + int event_handler_active; + + /* A thread-local storage key to track which thread is performing event + * handling */ + usbi_tls_key_t event_handling_key; + + /* used to wait for event completion in threads other than the one that is + * event handling */ + usbi_mutex_t event_waiters_lock; + usbi_cond_t event_waiters_cond; + + /* A lock to protect internal context event data. */ + usbi_mutex_t event_data_lock; + + /* A bitmask of flags that are set to indicate specific events that need to + * be handled. Protected by event_data_lock. */ + unsigned int event_flags; + + /* A counter that is set when we want to interrupt and prevent event handling, + * in order to safely close a device. Protected by event_data_lock. */ + unsigned int device_close; + + /* list and count of poll fds and an array of poll fd structures that is + * (re)allocated as necessary prior to polling. Protected by event_data_lock. */ + struct list_head ipollfds; + struct pollfd *pollfds; + POLL_NFDS_TYPE pollfds_cnt; + + /* A list of pending hotplug messages. Protected by event_data_lock. */ + struct list_head hotplug_msgs; + + /* A list of pending completed transfers. Protected by event_data_lock. */ + struct list_head completed_transfers; + +#ifdef USBI_TIMERFD_AVAILABLE + /* used for timeout handling, if supported by OS. + * this timerfd is maintained to trigger on the next pending timeout */ + int timerfd; +#endif + + struct list_head list; + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; +}; + +enum usbi_event_flags { + /* The list of pollfds has been modified */ + USBI_EVENT_POLLFDS_MODIFIED = 1 << 0, + + /* The user has interrupted the event handler */ + USBI_EVENT_USER_INTERRUPT = 1 << 1, + + /* A hotplug callback deregistration is pending */ + USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1 << 2, +}; + +/* Macros for managing event handling state */ +#define usbi_handling_events(ctx) \ + (usbi_tls_key_get((ctx)->event_handling_key) != NULL) + +#define usbi_start_event_handling(ctx) \ + usbi_tls_key_set((ctx)->event_handling_key, ctx) + +#define usbi_end_event_handling(ctx) \ + usbi_tls_key_set((ctx)->event_handling_key, NULL) + +/* Update the following macro if new event sources are added */ +#define usbi_pending_events(ctx) \ + ((ctx)->event_flags || (ctx)->device_close \ + || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers)) + +#ifdef USBI_TIMERFD_AVAILABLE +#define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) +#else +#define usbi_using_timerfd(ctx) (0) +#endif + +struct libusb_device { + /* lock protects refcnt, everything else is finalized at initialization + * time */ + usbi_mutex_t lock; + int refcnt; + + struct libusb_context *ctx; + + uint8_t bus_number; + uint8_t port_number; + struct libusb_device* parent_dev; + uint8_t device_address; + uint8_t num_configurations; + enum libusb_speed speed; + + struct list_head list; + unsigned long session_data; + + struct libusb_device_descriptor device_descriptor; + int attached; + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; +}; + +struct libusb_device_handle { + /* lock protects claimed_interfaces */ + usbi_mutex_t lock; + unsigned long claimed_interfaces; + + struct list_head list; + struct libusb_device *dev; + int auto_detach_kernel_driver; + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; +}; + +enum { + USBI_CLOCK_MONOTONIC, + USBI_CLOCK_REALTIME +}; + +/* in-memory transfer layout: + * + * 1. struct usbi_transfer + * 2. struct libusb_transfer (which includes iso packets) [variable size] + * 3. os private data [variable size] + * + * from a libusb_transfer, you can get the usbi_transfer by rewinding the + * appropriate number of bytes. + * the usbi_transfer includes the number of allocated packets, so you can + * determine the size of the transfer and hence the start and length of the + * OS-private data. + */ + +struct usbi_transfer { + int num_iso_packets; + struct list_head list; + struct list_head completed_list; + struct timeval timeout; + int transferred; + uint32_t stream_id; + uint8_t state_flags; /* Protected by usbi_transfer->lock */ + uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */ + + /* this lock is held during libusb_submit_transfer() and + * libusb_cancel_transfer() (allowing the OS backend to prevent duplicate + * cancellation, submission-during-cancellation, etc). the OS backend + * should also take this lock in the handle_events path, to prevent the user + * cancelling the transfer from another thread while you are processing + * its completion (presumably there would be races within your OS backend + * if this were possible). + * Note paths taking both this and the flying_transfers_lock must + * always take the flying_transfers_lock first */ + usbi_mutex_t lock; +}; + +enum usbi_transfer_state_flags { + /* Transfer successfully submitted by backend */ + USBI_TRANSFER_IN_FLIGHT = 1 << 0, + + /* Cancellation was requested via libusb_cancel_transfer() */ + USBI_TRANSFER_CANCELLING = 1 << 1, + + /* Operation on the transfer failed because the device disappeared */ + USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2, +}; + +enum usbi_transfer_timeout_flags { + /* Set by backend submit_transfer() if the OS handles timeout */ + USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0, + + /* The transfer timeout has been handled */ + USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, + + /* The transfer timeout was successfully processed */ + USBI_TRANSFER_TIMED_OUT = 1 << 2, +}; + +#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ + ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ + + sizeof(struct usbi_transfer))) +#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ + ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ + - sizeof(struct usbi_transfer))) + +static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) +{ + return ((unsigned char *)transfer) + sizeof(struct usbi_transfer) + + sizeof(struct libusb_transfer) + + (transfer->num_iso_packets + * sizeof(struct libusb_iso_packet_descriptor)); +} + +/* bus structures */ + +/* All standard descriptors have these 2 fields in common */ +struct usb_descriptor_header { + uint8_t bLength; + uint8_t bDescriptorType; +}; + +/* shared data and functions */ + +int usbi_io_init(struct libusb_context *ctx); +void usbi_io_exit(struct libusb_context *ctx); + +struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, + unsigned long session_id); +struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, + unsigned long session_id); +int usbi_sanitize_device(struct libusb_device *dev); +void usbi_handle_disconnect(struct libusb_device_handle *dev_handle); + +int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, + enum libusb_transfer_status status); +int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); +void usbi_signal_transfer_completion(struct usbi_transfer *transfer); + +int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, + void *dest, int host_endian); +int usbi_device_cache_descriptor(libusb_device *dev); +int usbi_get_config_index_by_value(struct libusb_device *dev, + uint8_t bConfigurationValue, int *idx); + +void usbi_connect_device (struct libusb_device *dev); +void usbi_disconnect_device (struct libusb_device *dev); + +int usbi_signal_event(struct libusb_context *ctx); +int usbi_clear_event(struct libusb_context *ctx); + +/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ +#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ + defined(OS_HAIKU) || defined(OS_SUNOS) +#include +#include "os/poll_posix.h" +#elif defined(OS_WINDOWS) || defined(OS_WINCE) +#include "os/poll_windows.h" +#endif + +struct usbi_pollfd { + /* must come first */ + struct libusb_pollfd pollfd; + + struct list_head list; +}; + +int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); +void usbi_remove_pollfd(struct libusb_context *ctx, int fd); + +/* device discovery */ + +/* we traverse usbfs without knowing how many devices we are going to find. + * so we create this discovered_devs model which is similar to a linked-list + * which grows when required. it can be freed once discovery has completed, + * eliminating the need for a list node in the libusb_device structure + * itself. */ +struct discovered_devs { + size_t len; + size_t capacity; + struct libusb_device *devices[ZERO_SIZED_ARRAY]; +}; + +struct discovered_devs *discovered_devs_append( + struct discovered_devs *discdevs, struct libusb_device *dev); + +/* OS abstraction */ + +/* This is the interface that OS backends need to implement. + * All fields are mandatory, except ones explicitly noted as optional. */ +struct usbi_os_backend { + /* A human-readable name for your backend, e.g. "Linux usbfs" */ + const char *name; + + /* Binary mask for backend specific capabilities */ + uint32_t caps; + + /* Perform initialization of your backend. You might use this function + * to determine specific capabilities of the system, allocate required + * data structures for later, etc. + * + * This function is called when a libusb user initializes the library + * prior to use. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*init)(struct libusb_context *ctx); + + /* Deinitialization. Optional. This function should destroy anything + * that was set up by init. + * + * This function is called when the user deinitializes the library. + */ + void (*exit)(struct libusb_context *ctx); + + /* Set a backend-specific option. Optional. + * + * This function is called when the user calls libusb_set_option() and + * the option is not handled by the core library. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*set_option)(struct libusb_context *ctx, enum libusb_option option, + va_list args); + + /* Enumerate all the USB devices on the system, returning them in a list + * of discovered devices. + * + * Your implementation should enumerate all devices on the system, + * regardless of whether they have been seen before or not. + * + * When you have found a device, compute a session ID for it. The session + * ID should uniquely represent that particular device for that particular + * connection session since boot (i.e. if you disconnect and reconnect a + * device immediately after, it should be assigned a different session ID). + * If your OS cannot provide a unique session ID as described above, + * presenting a session ID of (bus_number << 8 | device_address) should + * be sufficient. Bus numbers and device addresses wrap and get reused, + * but that is an unlikely case. + * + * After computing a session ID for a device, call + * usbi_get_device_by_session_id(). This function checks if libusb already + * knows about the device, and if so, it provides you with a reference + * to a libusb_device structure for it. + * + * If usbi_get_device_by_session_id() returns NULL, it is time to allocate + * a new device structure for the device. Call usbi_alloc_device() to + * obtain a new libusb_device structure with reference count 1. Populate + * the bus_number and device_address attributes of the new device, and + * perform any other internal backend initialization you need to do. At + * this point, you should be ready to provide device descriptors and so + * on through the get_*_descriptor functions. Finally, call + * usbi_sanitize_device() to perform some final sanity checks on the + * device. Assuming all of the above succeeded, we can now continue. + * If any of the above failed, remember to unreference the device that + * was returned by usbi_alloc_device(). + * + * At this stage we have a populated libusb_device structure (either one + * that was found earlier, or one that we have just allocated and + * populated). This can now be added to the discovered devices list + * using discovered_devs_append(). Note that discovered_devs_append() + * may reallocate the list, returning a new location for it, and also + * note that reallocation can fail. Your backend should handle these + * error conditions appropriately. + * + * This function should not generate any bus I/O and should not block. + * If I/O is required (e.g. reading the active configuration value), it is + * OK to ignore these suggestions :) + * + * This function is executed when the user wishes to retrieve a list + * of USB devices connected to the system. + * + * If the backend has hotplug support, this function is not used! + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*get_device_list)(struct libusb_context *ctx, + struct discovered_devs **discdevs); + + /* Apps which were written before hotplug support, may listen for + * hotplug events on their own and call libusb_get_device_list on + * device addition. In this case libusb_get_device_list will likely + * return a list without the new device in there, as the hotplug + * event thread will still be busy enumerating the device, which may + * take a while, or may not even have seen the event yet. + * + * To avoid this libusb_get_device_list will call this optional + * function for backends with hotplug support before copying + * ctx->usb_devs to the user. In this function the backend should + * ensure any pending hotplug events are fully processed before + * returning. + * + * Optional, should be implemented by backends with hotplug support. + */ + void (*hotplug_poll)(void); + + /* Open a device for I/O and other USB operations. The device handle + * is preallocated for you, you can retrieve the device in question + * through handle->dev. + * + * Your backend should allocate any internal resources required for I/O + * and other operations so that those operations can happen (hopefully) + * without hiccup. This is also a good place to inform libusb that it + * should monitor certain file descriptors related to this device - + * see the usbi_add_pollfd() function. + * + * This function should not generate any bus I/O and should not block. + * + * This function is called when the user attempts to obtain a device + * handle for a device. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since + * discovery + * - another LIBUSB_ERROR code on other failure + * + * Do not worry about freeing the handle on failed open, the upper layers + * do this for you. + */ + int (*open)(struct libusb_device_handle *dev_handle); + + /* Close a device such that the handle cannot be used again. Your backend + * should destroy any resources that were allocated in the open path. + * This may also be a good place to call usbi_remove_pollfd() to inform + * libusb of any file descriptors associated with this device that should + * no longer be monitored. + * + * This function is called when the user closes a device handle. + */ + void (*close)(struct libusb_device_handle *dev_handle); + + /* Retrieve the device descriptor from a device. + * + * The descriptor should be retrieved from memory, NOT via bus I/O to the + * device. This means that you may have to cache it in a private structure + * during get_device_list enumeration. Alternatively, you may be able + * to retrieve it from a kernel interface (some Linux setups can do this) + * still without generating bus I/O. + * + * This function is expected to write DEVICE_DESC_LENGTH (18) bytes into + * buffer, which is guaranteed to be big enough. + * + * This function is called when sanity-checking a device before adding + * it to the list of discovered devices, and also when the user requests + * to read the device descriptor. + * + * This function is expected to return the descriptor in bus-endian format + * (LE). If it returns the multi-byte values in host-endian format, + * set the host_endian output parameter to "1". + * + * Return 0 on success or a LIBUSB_ERROR code on failure. + */ + int (*get_device_descriptor)(struct libusb_device *device, + unsigned char *buffer, int *host_endian); + + /* Get the ACTIVE configuration descriptor for a device. + * + * The descriptor should be retrieved from memory, NOT via bus I/O to the + * device. This means that you may have to cache it in a private structure + * during get_device_list enumeration. You may also have to keep track + * of which configuration is active when the user changes it. + * + * This function is expected to write len bytes of data into buffer, which + * is guaranteed to be big enough. If you can only do a partial write, + * return an error code. + * + * This function is expected to return the descriptor in bus-endian format + * (LE). If it returns the multi-byte values in host-endian format, + * set the host_endian output parameter to "1". + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state + * - another LIBUSB_ERROR code on other failure + */ + int (*get_active_config_descriptor)(struct libusb_device *device, + unsigned char *buffer, size_t len, int *host_endian); + + /* Get a specific configuration descriptor for a device. + * + * The descriptor should be retrieved from memory, NOT via bus I/O to the + * device. This means that you may have to cache it in a private structure + * during get_device_list enumeration. + * + * The requested descriptor is expressed as a zero-based index (i.e. 0 + * indicates that we are requesting the first descriptor). The index does + * not (necessarily) equal the bConfigurationValue of the configuration + * being requested. + * + * This function is expected to write len bytes of data into buffer, which + * is guaranteed to be big enough. If you can only do a partial write, + * return an error code. + * + * This function is expected to return the descriptor in bus-endian format + * (LE). If it returns the multi-byte values in host-endian format, + * set the host_endian output parameter to "1". + * + * Return the length read on success or a LIBUSB_ERROR code on failure. + */ + int (*get_config_descriptor)(struct libusb_device *device, + uint8_t config_index, unsigned char *buffer, size_t len, + int *host_endian); + + /* Like get_config_descriptor but then by bConfigurationValue instead + * of by index. + * + * Optional, if not present the core will call get_config_descriptor + * for all configs until it finds the desired bConfigurationValue. + * + * Returns a pointer to the raw-descriptor in *buffer, this memory + * is valid as long as device is valid. + * + * Returns the length of the returned raw-descriptor on success, + * or a LIBUSB_ERROR code on failure. + */ + int (*get_config_descriptor_by_value)(struct libusb_device *device, + uint8_t bConfigurationValue, unsigned char **buffer, + int *host_endian); + + /* Get the bConfigurationValue for the active configuration for a device. + * Optional. This should only be implemented if you can retrieve it from + * cache (don't generate I/O). + * + * If you cannot retrieve this from cache, either do not implement this + * function, or return LIBUSB_ERROR_NOT_SUPPORTED. This will cause + * libusb to retrieve the information through a standard control transfer. + * + * This function must be non-blocking. + * Return: + * - 0 on success + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - LIBUSB_ERROR_NOT_SUPPORTED if the value cannot be retrieved without + * blocking + * - another LIBUSB_ERROR code on other failure. + */ + int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); + + /* Set the active configuration for a device. + * + * A configuration value of -1 should put the device in unconfigured state. + * + * This function can block. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if the configuration does not exist + * - LIBUSB_ERROR_BUSY if interfaces are currently claimed (and hence + * configuration cannot be changed) + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure. + */ + int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); + + /* Claim an interface. When claimed, the application can then perform + * I/O to an interface's endpoints. + * + * This function should not generate any bus I/O and should not block. + * Interface claiming is a logical operation that simply ensures that + * no other drivers/applications are using the interface, and after + * claiming, no other drivers/applications can use the interface because + * we now "own" it. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if the interface does not exist + * - LIBUSB_ERROR_BUSY if the interface is in use by another driver/app + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); + + /* Release a previously claimed interface. + * + * This function should also generate a SET_INTERFACE control request, + * resetting the alternate setting of that interface to 0. It's OK for + * this function to block as a result. + * + * You will only ever be asked to release an interface which was + * successfully claimed earlier. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); + + /* Set the alternate setting for an interface. + * + * You will only ever be asked to set the alternate setting for an + * interface which was successfully claimed earlier. + * + * It's OK for this function to block. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if the alternate setting does not exist + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting); + + /* Clear a halt/stall condition on an endpoint. + * + * It's OK for this function to block. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*clear_halt)(struct libusb_device_handle *dev_handle, + unsigned char endpoint); + + /* Perform a USB port reset to reinitialize a device. + * + * If possible, the device handle should still be usable after the reset + * completes, assuming that the device descriptors did not change during + * reset and all previous interface state can be restored. + * + * If something changes, or you cannot easily locate/verify the resetted + * device, return LIBUSB_ERROR_NOT_FOUND. This prompts the application + * to close the old handle and re-enumerate the device. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the device + * has been disconnected since it was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*reset_device)(struct libusb_device_handle *dev_handle); + + /* Alloc num_streams usb3 bulk streams on the passed in endpoints */ + int (*alloc_streams)(struct libusb_device_handle *dev_handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints); + + /* Free usb3 bulk streams allocated with alloc_streams */ + int (*free_streams)(struct libusb_device_handle *dev_handle, + unsigned char *endpoints, int num_endpoints); + + /* Allocate persistent DMA memory for the given device, suitable for + * zerocopy. May return NULL on failure. Optional to implement. + */ + unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle, + size_t len); + + /* Free memory allocated by dev_mem_alloc. */ + int (*dev_mem_free)(struct libusb_device_handle *handle, + unsigned char *buffer, size_t len); + + /* Determine if a kernel driver is active on an interface. Optional. + * + * The presence of a kernel driver on an interface indicates that any + * calls to claim_interface would fail with the LIBUSB_ERROR_BUSY code. + * + * Return: + * - 0 if no driver is active + * - 1 if a driver is active + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*kernel_driver_active)(struct libusb_device_handle *dev_handle, + int interface_number); + + /* Detach a kernel driver from an interface. Optional. + * + * After detaching a kernel driver, the interface should be available + * for claim. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - another LIBUSB_ERROR code on other failure + */ + int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle, + int interface_number); + + /* Attach a kernel driver to an interface. Optional. + * + * Reattach a kernel driver to the device. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active + * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it + * was opened + * - LIBUSB_ERROR_BUSY if a program or driver has claimed the interface, + * preventing reattachment + * - another LIBUSB_ERROR code on other failure + */ + int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle, + int interface_number); + + /* Destroy a device. Optional. + * + * This function is called when the last reference to a device is + * destroyed. It should free any resources allocated in the get_device_list + * path. + */ + void (*destroy_device)(struct libusb_device *dev); + + /* Submit a transfer. Your implementation should take the transfer, + * morph it into whatever form your platform requires, and submit it + * asynchronously. + * + * This function must not block. + * + * This function gets called with the flying_transfers_lock locked! + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * - another LIBUSB_ERROR code on other failure + */ + int (*submit_transfer)(struct usbi_transfer *itransfer); + + /* Cancel a previously submitted transfer. + * + * This function must not block. The transfer cancellation must complete + * later, resulting in a call to usbi_handle_transfer_cancellation() + * from the context of handle_events. + */ + int (*cancel_transfer)(struct usbi_transfer *itransfer); + + /* Clear a transfer as if it has completed or cancelled, but do not + * report any completion/cancellation to the library. You should free + * all private data from the transfer as if you were just about to report + * completion or cancellation. + * + * This function might seem a bit out of place. It is used when libusb + * detects a disconnected device - it calls this function for all pending + * transfers before reporting completion (with the disconnect code) to + * the user. Maybe we can improve upon this internal interface in future. + */ + void (*clear_transfer_priv)(struct usbi_transfer *itransfer); + + /* Handle any pending events on file descriptors. Optional. + * + * Provide this function when file descriptors directly indicate device + * or transfer activity. If your backend does not have such file descriptors, + * implement the handle_transfer_completion function below. + * + * This involves monitoring any active transfers and processing their + * completion or cancellation. + * + * The function is passed an array of pollfd structures (size nfds) + * as a result of the poll() system call. The num_ready parameter + * indicates the number of file descriptors that have reported events + * (i.e. the poll() return value). This should be enough information + * for you to determine which actions need to be taken on the currently + * active transfers. + * + * For any cancelled transfers, call usbi_handle_transfer_cancellation(). + * For completed transfers, call usbi_handle_transfer_completion(). + * For control/bulk/interrupt transfers, populate the "transferred" + * element of the appropriate usbi_transfer structure before calling the + * above functions. For isochronous transfers, populate the status and + * transferred fields of the iso packet descriptors of the transfer. + * + * This function should also be able to detect disconnection of the + * device, reporting that situation with usbi_handle_disconnect(). + * + * When processing an event related to a transfer, you probably want to + * take usbi_transfer.lock to prevent races. See the documentation for + * the usbi_transfer structure. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*handle_events)(struct libusb_context *ctx, + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); + + /* Handle transfer completion. Optional. + * + * Provide this function when there are no file descriptors available + * that directly indicate device or transfer activity. If your backend does + * have such file descriptors, implement the handle_events function above. + * + * Your backend must tell the library when a transfer has completed by + * calling usbi_signal_transfer_completion(). You should store any private + * information about the transfer and its completion status in the transfer's + * private backend data. + * + * During event handling, this function will be called on each transfer for + * which usbi_signal_transfer_completion() was called. + * + * For any cancelled transfers, call usbi_handle_transfer_cancellation(). + * For completed transfers, call usbi_handle_transfer_completion(). + * For control/bulk/interrupt transfers, populate the "transferred" + * element of the appropriate usbi_transfer structure before calling the + * above functions. For isochronous transfers, populate the status and + * transferred fields of the iso packet descriptors of the transfer. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*handle_transfer_completion)(struct usbi_transfer *itransfer); + + /* Get time from specified clock. At least two clocks must be implemented + by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. + + Description of clocks: + USBI_CLOCK_REALTIME : clock returns time since system epoch. + USBI_CLOCK_MONOTONIC: clock returns time since unspecified start + time (usually boot). + */ + int (*clock_gettime)(int clkid, struct timespec *tp); + +#ifdef USBI_TIMERFD_AVAILABLE + /* clock ID of the clock that should be used for timerfd */ + clockid_t (*get_timerfd_clockid)(void); +#endif + + /* Number of bytes to reserve for per-context private backend data. + * This private data area is accessible through the "os_priv" field of + * struct libusb_context. */ + size_t context_priv_size; + + /* Number of bytes to reserve for per-device private backend data. + * This private data area is accessible through the "os_priv" field of + * struct libusb_device. */ + size_t device_priv_size; + + /* Number of bytes to reserve for per-handle private backend data. + * This private data area is accessible through the "os_priv" field of + * struct libusb_device. */ + size_t device_handle_priv_size; + + /* Number of bytes to reserve for per-transfer private backend data. + * This private data area is accessible by calling + * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance. + */ + size_t transfer_priv_size; +}; + +extern const struct usbi_os_backend usbi_backend; + +extern struct list_head active_contexts_list; +extern usbi_mutex_static_t active_contexts_lock; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c new file mode 100644 index 0000000000..35ea1c321e --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c @@ -0,0 +1,2142 @@ +/* -*- Mode: C; indent-tabs-mode:nil -*- */ +/* + * darwin backend for libusb 1.0 + * Copyright © 2008-2017 Nathan Hjelm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector + * function. Its use is also conditionalized to only older deployment targets. */ +#define OBJC_SILENCE_GC_DEPRECATIONS 1 + +#include +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + #include +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 +/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */ +#include +#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y) + +_Atomic int32_t initCount = ATOMIC_VAR_INIT(0); +#else +/* use darwin atomics if the target is older than 10.12 */ +#include + +/* OSAtomicAdd32Barrier returns the new value */ +#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y) + +static volatile int32_t initCount = 0; + +#endif + +/* On 10.12 and later, use newly available clock_*() functions */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 +#define OSX_USE_CLOCK_GETTIME 1 +#else +#define OSX_USE_CLOCK_GETTIME 0 +#endif + +#include "darwin_usb.h" + +/* async event thread */ +static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; + +static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT; + +#if !OSX_USE_CLOCK_GETTIME +static clock_serv_t clock_realtime; +static clock_serv_t clock_monotonic; +#endif + +static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ +static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ + +static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; +static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; +static const char *darwin_device_class = kIOUSBDeviceClassName; + +#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) + +/* async event thread */ +static pthread_t libusb_darwin_at; + +static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian); +static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface); +static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface); +static int darwin_reset_device(struct libusb_device_handle *dev_handle); +static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0); + +static int darwin_scan_devices(struct libusb_context *ctx); +static int process_new_device (struct libusb_context *ctx, io_service_t service); + +#if defined(ENABLE_LOGGING) +static const char *darwin_error_str (int result) { + static char string_buffer[50]; + switch (result) { + case kIOReturnSuccess: + return "no error"; + case kIOReturnNotOpen: + return "device not opened for exclusive access"; + case kIOReturnNoDevice: + return "no connection to an IOService"; + case kIOUSBNoAsyncPortErr: + return "no async port has been opened for interface"; + case kIOReturnExclusiveAccess: + return "another process has device opened for exclusive access"; + case kIOUSBPipeStalled: + return "pipe is stalled"; + case kIOReturnError: + return "could not establish a connection to the Darwin kernel"; + case kIOUSBTransactionTimeout: + return "transaction timed out"; + case kIOReturnBadArgument: + return "invalid argument"; + case kIOReturnAborted: + return "transaction aborted"; + case kIOReturnNotResponding: + return "device not responding"; + case kIOReturnOverrun: + return "data overrun"; + case kIOReturnCannotWire: + return "physical memory can not be wired down"; + case kIOReturnNoResources: + return "out of resources"; + case kIOUSBHighSpeedSplitError: + return "high speed split error"; + default: + snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result); + return string_buffer; + } +} +#endif + +static int darwin_to_libusb (int result) { + switch (result) { + case kIOReturnUnderrun: + case kIOReturnSuccess: + return LIBUSB_SUCCESS; + case kIOReturnNotOpen: + case kIOReturnNoDevice: + return LIBUSB_ERROR_NO_DEVICE; + case kIOReturnExclusiveAccess: + return LIBUSB_ERROR_ACCESS; + case kIOUSBPipeStalled: + return LIBUSB_ERROR_PIPE; + case kIOReturnBadArgument: + return LIBUSB_ERROR_INVALID_PARAM; + case kIOUSBTransactionTimeout: + return LIBUSB_ERROR_TIMEOUT; + case kIOReturnNotResponding: + case kIOReturnAborted: + case kIOReturnError: + case kIOUSBNoAsyncPortErr: + default: + return LIBUSB_ERROR_OTHER; + } +} + +/* this function must be called with the darwin_cached_devices_lock held */ +static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { + cached_dev->refcount--; + /* free the device and remove it from the cache */ + if (0 == cached_dev->refcount) { + list_del(&cached_dev->list); + + (*(cached_dev->device))->Release(cached_dev->device); + free (cached_dev); + } +} + +static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) { + cached_dev->refcount++; +} + +static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + + /* current interface */ + struct darwin_interface *cInterface; + + int8_t i, iface; + + usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep); + + for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { + cInterface = &priv->interfaces[iface]; + + if (dev_handle->claimed_interfaces & (1 << iface)) { + for (i = 0 ; i < cInterface->num_endpoints ; i++) { + if (cInterface->endpoint_addrs[i] == ep) { + *pipep = i + 1; + + if (ifcp) + *ifcp = iface; + + if (interface_out) + *interface_out = cInterface; + + usbi_dbg ("pipe %d on interface %d matches", *pipep, iface); + return 0; + } + } + } + } + + /* No pipe found with the correct endpoint address */ + usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); + + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { + CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class); + + if (!matchingDict) + return kIOReturnError; + + if (location) { + CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this + internally (CFNumberType of locationID is kCFNumberSInt32Type) */ + CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); + + if (propertyMatchDict && locationCF) { + CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); + CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); + } + /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ + + /* release our references as per the Create Rule */ + if (propertyMatchDict) + CFRelease (propertyMatchDict); + if (locationCF) + CFRelease (locationCF); + } + + return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); +} + +/* Returns 1 on success, 0 on failure. */ +static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { + CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); + int ret = 0; + + if (cfNumber) { + if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) { + ret = CFNumberGetValue(cfNumber, type, p); + } + + CFRelease (cfNumber); + } + + return ret; +} + +static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { + CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); + int ret = 0; + + if (cfData) { + if (CFGetTypeID (cfData) == CFDataGetTypeID ()) { + CFIndex length = CFDataGetLength (cfData); + if (length < size) { + size = length; + } + + CFDataGetBytes (cfData, CFRangeMake(0, size), p); + ret = 1; + } + + CFRelease (cfData); + } + + return ret; +} + +static usb_device_t **darwin_device_from_service (io_service_t service) +{ + io_cf_plugin_ref_t *plugInInterface = NULL; + usb_device_t **device; + kern_return_t result; + SInt32 score; + + result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &plugInInterface, + &score); + + if (kIOReturnSuccess != result || !plugInInterface) { + usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result)); + return NULL; + } + + (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), + (LPVOID)&device); + /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ + (*plugInInterface)->Release (plugInInterface); + + return device; +} + +static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { + UNUSED(ptr); + struct libusb_context *ctx; + io_service_t service; + + usbi_mutex_lock(&active_contexts_lock); + + while ((service = IOIteratorNext(add_devices))) { + /* add this device to each active context's device list */ + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + process_new_device (ctx, service); + } + + IOObjectRelease(service); + } + + usbi_mutex_unlock(&active_contexts_lock); +} + +static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { + UNUSED(ptr); + struct libusb_device *dev = NULL; + struct libusb_context *ctx; + struct darwin_cached_device *old_device; + + io_service_t device; + UInt64 session; + int ret; + + usbi_mutex_lock(&active_contexts_lock); + + while ((device = IOIteratorNext (rem_devices)) != 0) { + /* get the location from the i/o registry */ + ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); + IOObjectRelease (device); + if (!ret) + continue; + + /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function + otherwise no cached device will ever get freed */ + usbi_mutex_lock(&darwin_cached_devices_lock); + list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) { + if (old_device->session == session) { + darwin_deref_cached_device (old_device); + break; + } + } + usbi_mutex_unlock(&darwin_cached_devices_lock); + + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + usbi_dbg ("notifying context %p of device disconnect", ctx); + + dev = usbi_get_device_by_session_id(ctx, (unsigned long) session); + if (dev) { + /* signal the core that this device has been disconnected. the core will tear down this device + when the reference count reaches 0 */ + usbi_disconnect_device(dev); + libusb_unref_device(dev); + } + } + } + + usbi_mutex_unlock(&active_contexts_lock); +} + +static void darwin_hotplug_poll (void) +{ + /* not sure if 5 seconds will be too long/short but it should work ok */ + mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0}; + + /* since a kernel thread may nodify the IOInterators used for + * hotplug notidication we can't just clear the iterators. + * instead just wait until all IOService providers are quiet */ + (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout); +} + +static void darwin_clear_iterator (io_iterator_t iter) { + io_service_t device; + + while ((device = IOIteratorNext (iter)) != 0) + IOObjectRelease (device); +} + +static void *darwin_event_thread_main (void *arg0) { + IOReturn kresult; + struct libusb_context *ctx = (struct libusb_context *)arg0; + CFRunLoopRef runloop; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 + /* Set this thread's name, so it can be seen in the debugger + and crash reports. */ + pthread_setname_np ("org.libusb.device-hotplug"); +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + /* Tell the Objective-C garbage collector about this thread. + This is required because, unlike NSThreads, pthreads are + not automatically registered. Although we don't use + Objective-C, we use CoreFoundation, which does. + Garbage collection support was entirely removed in 10.12, + so don't bother there. */ + objc_registerThreadWithCollector(); +#endif + + /* hotplug (device arrival/removal) sources */ + CFRunLoopSourceContext libusb_shutdown_cfsourcectx; + CFRunLoopSourceRef libusb_notification_cfsource; + io_notification_port_t libusb_notification_port; + io_iterator_t libusb_rem_device_iterator; + io_iterator_t libusb_add_device_iterator; + + usbi_dbg ("creating hotplug event source"); + + runloop = CFRunLoopGetCurrent (); + CFRetain (runloop); + + /* add the shutdown cfsource to the run loop */ + memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx)); + libusb_shutdown_cfsourcectx.info = runloop; + libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop; + libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx); + CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); + + /* add the notification port to the run loop */ + libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault); + libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port); + CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); + + /* create notifications for removed devices */ + kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification, + IOServiceMatching(darwin_device_class), + darwin_devices_detached, + ctx, &libusb_rem_device_iterator); + + if (kresult != kIOReturnSuccess) { + usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); + + pthread_exit (NULL); + } + + /* create notifications for attached devices */ + kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification, + IOServiceMatching(darwin_device_class), + darwin_devices_attached, + ctx, &libusb_add_device_iterator); + + if (kresult != kIOReturnSuccess) { + usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); + + pthread_exit (NULL); + } + + /* arm notifiers */ + darwin_clear_iterator (libusb_rem_device_iterator); + darwin_clear_iterator (libusb_add_device_iterator); + + usbi_dbg ("darwin event thread ready to receive events"); + + /* signal the main thread that the hotplug runloop has been created. */ + pthread_mutex_lock (&libusb_darwin_at_mutex); + libusb_darwin_acfl = runloop; + pthread_cond_signal (&libusb_darwin_at_cond); + pthread_mutex_unlock (&libusb_darwin_at_mutex); + + /* run the runloop */ + CFRunLoopRun(); + + usbi_dbg ("darwin event thread exiting"); + + /* remove the notification cfsource */ + CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); + + /* remove the shutdown cfsource */ + CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); + + /* delete notification port */ + IONotificationPortDestroy (libusb_notification_port); + + /* delete iterators */ + IOObjectRelease (libusb_rem_device_iterator); + IOObjectRelease (libusb_add_device_iterator); + + CFRelease (libusb_darwin_acfls); + CFRelease (runloop); + + libusb_darwin_acfls = NULL; + libusb_darwin_acfl = NULL; + + pthread_exit (NULL); +} + +/* cleanup function to destroy cached devices */ +static void __attribute__((destructor)) _darwin_finalize(void) { + struct darwin_cached_device *dev, *next; + + usbi_mutex_lock(&darwin_cached_devices_lock); + list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) { + darwin_deref_cached_device(dev); + } + usbi_mutex_unlock(&darwin_cached_devices_lock); +} + +static void darwin_check_version (void) { + /* adjust for changes in the USB stack in xnu 15 */ + int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE}; + long version; + char version_string[256] = {'\0',}; + size_t length = 256; + + sysctl(sysctl_args, 2, version_string, &length, NULL, 0); + + errno = 0; + version = strtol (version_string, NULL, 10); + if (0 == errno && version >= 15) { + darwin_device_class = "IOUSBHostDevice"; + } +} + +static int darwin_init(struct libusb_context *ctx) { + int rc; + + rc = pthread_once (&darwin_init_once, darwin_check_version); + if (rc) { + return LIBUSB_ERROR_OTHER; + } + + rc = darwin_scan_devices (ctx); + if (LIBUSB_SUCCESS != rc) { + return rc; + } + + if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) { +#if !OSX_USE_CLOCK_GETTIME + /* create the clocks that will be used if clock_gettime() is not available */ + host_name_port_t host_self; + + host_self = mach_host_self(); + host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); + host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); + mach_port_deallocate(mach_task_self(), host_self); +#endif + + pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); + + pthread_mutex_lock (&libusb_darwin_at_mutex); + while (!libusb_darwin_acfl) + pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); + pthread_mutex_unlock (&libusb_darwin_at_mutex); + } + + return rc; +} + +static void darwin_exit (struct libusb_context *ctx) { + UNUSED(ctx); + if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) { +#if !OSX_USE_CLOCK_GETTIME + mach_port_deallocate(mach_task_self(), clock_realtime); + mach_port_deallocate(mach_task_self(), clock_monotonic); +#endif + + /* stop the event runloop and wait for the thread to terminate. */ + CFRunLoopSourceSignal(libusb_darwin_acfls); + CFRunLoopWakeUp (libusb_darwin_acfl); + pthread_join (libusb_darwin_at, NULL); + } +} + +static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { + struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); + + /* return cached copy */ + memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH); + + *host_endian = 0; + + return 0; +} + +static int get_configuration_index (struct libusb_device *dev, int config_value) { + struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); + UInt8 i, numConfig; + IOUSBConfigurationDescriptorPtr desc; + IOReturn kresult; + + /* is there a simpler way to determine the index? */ + kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig); + if (kresult != kIOReturnSuccess) + return darwin_to_libusb (kresult); + + for (i = 0 ; i < numConfig ; i++) { + (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc); + + if (desc->bConfigurationValue == config_value) + return i; + } + + /* configuration not found */ + return LIBUSB_ERROR_NOT_FOUND; +} + +static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { + struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); + int config_index; + + if (0 == priv->active_config) + return LIBUSB_ERROR_NOT_FOUND; + + config_index = get_configuration_index (dev, priv->active_config); + if (config_index < 0) + return config_index; + + return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian); +} + +static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { + struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); + IOUSBConfigurationDescriptorPtr desc; + IOReturn kresult; + int ret; + + if (!priv || !priv->device) + return LIBUSB_ERROR_OTHER; + + kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc); + if (kresult == kIOReturnSuccess) { + /* copy descriptor */ + if (libusb_le16_to_cpu(desc->wTotalLength) < len) + len = libusb_le16_to_cpu(desc->wTotalLength); + + memmove (buffer, desc, len); + + /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */ + *host_endian = 0; + } + + ret = darwin_to_libusb (kresult); + if (ret != LIBUSB_SUCCESS) + return ret; + + return (int) len; +} + +/* check whether the os has configured the device */ +static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { + usb_device_t **darwin_device = dev->device; + + IOUSBConfigurationDescriptorPtr configDesc; + IOUSBFindInterfaceRequest request; + kern_return_t kresult; + io_iterator_t interface_iterator; + io_service_t firstInterface; + + if (dev->dev_descriptor.bNumConfigurations < 1) { + usbi_err (ctx, "device has no configurations"); + return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */ + } + + /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is + not usable anyway */ + if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) { + usbi_dbg ("ignoring configuration on root hub simulation"); + dev->active_config = 0; + return 0; + } + + /* find the first configuration */ + kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc); + dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1; + + /* check if the device is already configured. there is probably a better way than iterating over the + to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices + might lock up on the device request) */ + + /* Setup the Interface Request */ + request.bInterfaceClass = kIOUSBFindInterfaceDontCare; + request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; + request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; + request.bAlternateSetting = kIOUSBFindInterfaceDontCare; + + kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); + if (kresult) + return darwin_to_libusb (kresult); + + /* iterate once */ + firstInterface = IOIteratorNext(interface_iterator); + + /* done with the interface iterator */ + IOObjectRelease(interface_iterator); + + if (firstInterface) { + IOObjectRelease (firstInterface); + + /* device is configured */ + if (dev->dev_descriptor.bNumConfigurations == 1) + /* to avoid problems with some devices get the configurations value from the configuration descriptor */ + dev->active_config = dev->first_config; + else + /* devices with more than one configuration should work with GetConfiguration */ + (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config); + } else + /* not configured */ + dev->active_config = 0; + + usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config); + + return 0; +} + +static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { + IOUSBDevRequestTO req; + + memset (buffer, 0, buffer_size); + + /* Set up request for descriptor/ */ + req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); + req.bRequest = kUSBRqGetDescriptor; + req.wValue = desc << 8; + req.wIndex = desc_index; + req.wLength = buffer_size; + req.pData = buffer; + req.noDataTimeout = 20; + req.completionTimeout = 100; + + return (*device)->DeviceRequestTO (device, &req); +} + +static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { + usb_device_t **device = dev->device; + int retries = 1, delay = 30000; + int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; + int is_open = 0; + int ret = 0, ret2; + UInt8 bDeviceClass; + UInt16 idProduct, idVendor; + + dev->can_enumerate = 0; + + (*device)->GetDeviceClass (device, &bDeviceClass); + (*device)->GetDeviceProduct (device, &idProduct); + (*device)->GetDeviceVendor (device, &idVendor); + + /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some + * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still, + * to follow the spec as closely as possible, try opening the device */ + is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess); + + do { + /**** retrieve device descriptor ****/ + ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor)); + + if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType) + /* received an overrun error but we still received a device descriptor */ + ret = kIOReturnSuccess; + + if (kIOUSBVendorIDAppleComputer == idVendor) { + /* NTH: don't bother retrying or unsuspending Apple devices */ + break; + } + + if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations || + 0 == dev->dev_descriptor.bcdUSB)) { + /* work around for incorrectly configured devices */ + if (try_reconfigure && is_open) { + usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again..."); + + /* set the first configuration */ + (*device)->SetConfiguration(device, 1); + + /* don't try to reconfigure again */ + try_reconfigure = 0; + } + + ret = kIOUSBPipeStalled; + } + + if (kIOReturnSuccess != ret && is_open && try_unsuspend) { + /* device may be suspended. unsuspend it and try again */ +#if DeviceVersion >= 320 + UInt32 info = 0; + + /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ + (void)(*device)->GetUSBDeviceInformation (device, &info); + + /* note that the device was suspended */ + if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info) + try_unsuspend = 1; +#endif + + if (try_unsuspend) { + /* try to unsuspend the device */ + ret2 = (*device)->USBDeviceSuspend (device, 0); + if (kIOReturnSuccess != ret2) { + /* prevent log spew from poorly behaving devices. this indicates the + os actually had trouble communicating with the device */ + usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2)); + } else + unsuspended = 1; + + try_unsuspend = 0; + } + } + + if (kIOReturnSuccess != ret) { + usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); + /* sleep for a little while before trying again */ + nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); + } + } while (kIOReturnSuccess != ret && retries--); + + if (unsuspended) + /* resuspend the device */ + (void)(*device)->USBDeviceSuspend (device, 1); + + if (is_open) + (void) (*device)->USBDeviceClose (device); + + if (ret != kIOReturnSuccess) { + /* a debug message was already printed out for this error */ + if (LIBUSB_CLASS_HUB == bDeviceClass) + usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", + idVendor, idProduct, darwin_error_str (ret), ret); + else + usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", + idVendor, idProduct, darwin_error_str (ret), ret); + return darwin_to_libusb (ret); + } + + /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ + if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) { + /* not a valid device */ + usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", + idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct)); + return LIBUSB_ERROR_NO_DEVICE; + } + + usbi_dbg ("cached device descriptor:"); + usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType); + usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB); + usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass); + usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass); + usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol); + usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0); + usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor); + usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct); + usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice); + usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer); + usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct); + usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber); + usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations); + + dev->can_enumerate = 1; + + return LIBUSB_SUCCESS; +} + +static int get_device_port (io_service_t service, UInt8 *port) { + kern_return_t result; + io_service_t parent; + int ret = 0; + + if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) { + return 1; + } + + result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent); + if (kIOReturnSuccess == result) { + ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port); + IOObjectRelease (parent); + } + + return ret; +} + +static int get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) { + kern_return_t result; + io_service_t parent; + + /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */ + parent = service; + while((result = IORegistryEntryGetParentEntry (parent, kIOServicePlane, &parent)) == kIOReturnSuccess) { + if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) { + /* Success */ + return 1; + } + } + + /* We ran out of parents */ + return 0; +} + +static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, + struct darwin_cached_device **cached_out) { + struct darwin_cached_device *new_device; + UInt64 sessionID = 0, parent_sessionID = 0; + int ret = LIBUSB_SUCCESS; + usb_device_t **device; + UInt8 port = 0; + + /* get some info from the io registry */ + (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID); + if (!get_device_port (service, &port)) { + usbi_dbg("could not get connected port number"); + } + + usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); + + if (get_device_parent_sessionID(service, &parent_sessionID)) { + usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID); + } + + usbi_mutex_lock(&darwin_cached_devices_lock); + do { + *cached_out = NULL; + + list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { + usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session); + if (new_device->session == sessionID) { + usbi_dbg("using cached device for device"); + *cached_out = new_device; + break; + } + } + + if (*cached_out) + break; + + usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID); + + device = darwin_device_from_service (service); + if (!device) { + ret = LIBUSB_ERROR_NO_DEVICE; + break; + } + + new_device = calloc (1, sizeof (*new_device)); + if (!new_device) { + ret = LIBUSB_ERROR_NO_MEM; + break; + } + + /* add this device to the cached device list */ + list_add(&new_device->list, &darwin_cached_devices); + + (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); + + /* keep a reference to this device */ + darwin_ref_cached_device(new_device); + + new_device->device = device; + new_device->session = sessionID; + (*device)->GetLocationID (device, &new_device->location); + new_device->port = port; + new_device->parent_session = parent_sessionID; + + /* cache the device descriptor */ + ret = darwin_cache_device_descriptor(ctx, new_device); + if (ret) + break; + + if (new_device->can_enumerate) { + snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address, + new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct, + new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass); + } + } while (0); + + usbi_mutex_unlock(&darwin_cached_devices_lock); + + /* keep track of devices regardless of if we successfully enumerate them to + prevent them from being enumerated multiple times */ + + *cached_out = new_device; + + return ret; +} + +static int process_new_device (struct libusb_context *ctx, io_service_t service) { + struct darwin_device_priv *priv; + struct libusb_device *dev = NULL; + struct darwin_cached_device *cached_device; + UInt8 devSpeed; + int ret = 0; + + do { + ret = darwin_get_cached_device (ctx, service, &cached_device); + + if (ret < 0 || !cached_device->can_enumerate) { + return ret; + } + + /* check current active configuration (and cache the first configuration value-- + which may be used by claim_interface) */ + ret = darwin_check_configuration (ctx, cached_device); + if (ret) + break; + + usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64, + ctx, cached_device->session); + + dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session); + if (!dev) { + return LIBUSB_ERROR_NO_MEM; + } + + priv = (struct darwin_device_priv *)dev->os_priv; + + priv->dev = cached_device; + darwin_ref_cached_device (priv->dev); + + if (cached_device->parent_session > 0) { + dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session); + } else { + dev->parent_dev = NULL; + } + dev->port_number = cached_device->port; + dev->bus_number = cached_device->location >> 24; + dev->device_address = cached_device->address; + + (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); + + switch (devSpeed) { + case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; + case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; + case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 + case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; +#endif + default: + usbi_warn (ctx, "Got unknown device speed %d", devSpeed); + } + + ret = usbi_sanitize_device (dev); + if (ret < 0) + break; + + usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address, + dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path); + } while (0); + + if (0 == ret) { + usbi_connect_device (dev); + } else { + libusb_unref_device (dev); + } + + return ret; +} + +static int darwin_scan_devices(struct libusb_context *ctx) { + io_iterator_t deviceIterator; + io_service_t service; + kern_return_t kresult; + + kresult = usb_setup_device_iterator (&deviceIterator, 0); + if (kresult != kIOReturnSuccess) + return darwin_to_libusb (kresult); + + while ((service = IOIteratorNext (deviceIterator))) { + (void) process_new_device (ctx, service); + + IOObjectRelease(service); + } + + IOObjectRelease(deviceIterator); + + return 0; +} + +static int darwin_open (struct libusb_device_handle *dev_handle) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + IOReturn kresult; + + if (0 == dpriv->open_count) { + /* try to open the device */ + kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); + if (kresult != kIOReturnSuccess) { + usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); + + if (kIOReturnExclusiveAccess != kresult) { + return darwin_to_libusb (kresult); + } + + /* it is possible to perform some actions on a device that is not open so do not return an error */ + priv->is_open = 0; + } else { + priv->is_open = 1; + } + + /* create async event source */ + kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); + if (kresult != kIOReturnSuccess) { + usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); + + if (priv->is_open) { + (*(dpriv->device))->USBDeviceClose (dpriv->device); + } + + priv->is_open = 0; + + return darwin_to_libusb (kresult); + } + + CFRetain (libusb_darwin_acfl); + + /* add the cfSource to the aync run loop */ + CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes); + } + + /* device opened successfully */ + dpriv->open_count++; + + usbi_dbg ("device open for access"); + + return 0; +} + +static void darwin_close (struct libusb_device_handle *dev_handle) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + IOReturn kresult; + int i; + + if (dpriv->open_count == 0) { + /* something is probably very wrong if this is the case */ + usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!"); + return; + } + + dpriv->open_count--; + + /* make sure all interfaces are released */ + for (i = 0 ; i < USB_MAXINTERFACES ; i++) + if (dev_handle->claimed_interfaces & (1 << i)) + libusb_release_interface (dev_handle, i); + + if (0 == dpriv->open_count) { + /* delete the device's async event source */ + if (priv->cfSource) { + CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode); + CFRelease (priv->cfSource); + priv->cfSource = NULL; + CFRelease (libusb_darwin_acfl); + } + + if (priv->is_open) { + /* close the device */ + kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); + if (kresult) { + /* Log the fact that we had a problem closing the file, however failing a + * close isn't really an error, so return success anyway */ + usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); + } + } + } +} + +static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + + *config = (int) dpriv->active_config; + + return 0; +} + +static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + IOReturn kresult; + int i; + + /* Setting configuration will invalidate the interface, so we need + to reclaim it. First, dispose of existing interfaces, if any. */ + for (i = 0 ; i < USB_MAXINTERFACES ; i++) + if (dev_handle->claimed_interfaces & (1 << i)) + darwin_release_interface (dev_handle, i); + + kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config); + if (kresult != kIOReturnSuccess) + return darwin_to_libusb (kresult); + + /* Reclaim any interfaces. */ + for (i = 0 ; i < USB_MAXINTERFACES ; i++) + if (dev_handle->claimed_interfaces & (1 << i)) + darwin_claim_interface (dev_handle, i); + + dpriv->active_config = config; + + return 0; +} + +static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { + IOUSBFindInterfaceRequest request; + kern_return_t kresult; + io_iterator_t interface_iterator; + UInt8 bInterfaceNumber; + int ret; + + *usbInterfacep = IO_OBJECT_NULL; + + /* Setup the Interface Request */ + request.bInterfaceClass = kIOUSBFindInterfaceDontCare; + request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; + request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; + request.bAlternateSetting = kIOUSBFindInterfaceDontCare; + + kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); + if (kresult) + return kresult; + + while ((*usbInterfacep = IOIteratorNext(interface_iterator))) { + /* find the interface number */ + ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type, + &bInterfaceNumber); + + if (ret && bInterfaceNumber == ifc) { + break; + } + + (void) IOObjectRelease (*usbInterfacep); + } + + /* done with the interface iterator */ + IOObjectRelease(interface_iterator); + + return 0; +} + +static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + + /* current interface */ + struct darwin_interface *cInterface = &priv->interfaces[iface]; + + kern_return_t kresult; + + UInt8 numep, direction, number; + UInt8 dont_care1, dont_care3; + UInt16 dont_care2; + int rc; + + usbi_dbg ("building table of endpoints."); + + /* retrieve the total number of endpoints on this interface */ + kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); + return darwin_to_libusb (kresult); + } + + /* iterate through pipe references */ + for (int i = 1 ; i <= numep ; i++) { + kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, + &dont_care2, &dont_care3); + + if (kresult != kIOReturnSuccess) { + /* probably a buggy device. try to get the endpoint address from the descriptors */ + struct libusb_config_descriptor *config; + const struct libusb_endpoint_descriptor *endpoint_desc; + UInt8 alt_setting; + + kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface"); + return darwin_to_libusb (kresult); + } + + rc = libusb_get_active_config_descriptor (dev_handle->dev, &config); + if (LIBUSB_SUCCESS != rc) { + return rc; + } + + endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1; + + cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; + } else { + cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); + } + + usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift, + cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK); + } + + cInterface->num_endpoints = numep; + + return 0; +} + +static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + io_service_t usbInterface = IO_OBJECT_NULL; + IOReturn kresult; + IOCFPlugInInterface **plugInInterface = NULL; + SInt32 score; + + /* current interface */ + struct darwin_interface *cInterface = &priv->interfaces[iface]; + + kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); + if (kresult != kIOReturnSuccess) + return darwin_to_libusb (kresult); + + /* make sure we have an interface */ + if (!usbInterface && dpriv->first_config != 0) { + usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config); + + /* set the configuration */ + kresult = darwin_set_configuration (dev_handle, dpriv->first_config); + if (kresult != LIBUSB_SUCCESS) { + usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); + return kresult; + } + + kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); + return darwin_to_libusb (kresult); + } + } + + if (!usbInterface) { + usbi_err (HANDLE_CTX (dev_handle), "interface not found"); + return LIBUSB_ERROR_NOT_FOUND; + } + + /* get an interface to the device's interface */ + kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, + kIOCFPlugInInterfaceID, &plugInInterface, &score); + + /* ignore release error */ + (void)IOObjectRelease (usbInterface); + + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); + return darwin_to_libusb (kresult); + } + + if (!plugInInterface) { + usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); + return LIBUSB_ERROR_NOT_FOUND; + } + + /* Do the actual claim */ + kresult = (*plugInInterface)->QueryInterface(plugInInterface, + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), + (LPVOID)&cInterface->interface); + /* We no longer need the intermediate plug-in */ + /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ + (*plugInInterface)->Release (plugInInterface); + if (kresult || !cInterface->interface) { + usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); + return darwin_to_libusb (kresult); + } + + /* claim the interface */ + kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); + return darwin_to_libusb (kresult); + } + + /* update list of endpoints */ + kresult = get_endpoints (dev_handle, iface); + if (kresult) { + /* this should not happen */ + darwin_release_interface (dev_handle, iface); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); + return kresult; + } + + cInterface->cfSource = NULL; + + /* create async event source */ + kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); + if (kresult != kIOReturnSuccess) { + usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); + + /* can't continue without an async event source */ + (void)darwin_release_interface (dev_handle, iface); + + return darwin_to_libusb (kresult); + } + + /* add the cfSource to the async thread's run loop */ + CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); + + usbi_dbg ("interface opened"); + + return 0; +} + +static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + IOReturn kresult; + + /* current interface */ + struct darwin_interface *cInterface = &priv->interfaces[iface]; + + /* Check to see if an interface is open */ + if (!cInterface->interface) + return LIBUSB_SUCCESS; + + /* clean up endpoint data */ + cInterface->num_endpoints = 0; + + /* delete the interface's async event source */ + if (cInterface->cfSource) { + CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); + CFRelease (cInterface->cfSource); + } + + kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); + if (kresult) + usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); + + kresult = (*(cInterface->interface))->Release(cInterface->interface); + if (kresult != kIOReturnSuccess) + usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); + + cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL; + + return darwin_to_libusb (kresult); +} + +static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + IOReturn kresult; + + /* current interface */ + struct darwin_interface *cInterface = &priv->interfaces[iface]; + + if (!cInterface->interface) + return LIBUSB_ERROR_NO_DEVICE; + + kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); + if (kresult != kIOReturnSuccess) + darwin_reset_device (dev_handle); + + /* update list of endpoints */ + kresult = get_endpoints (dev_handle, iface); + if (kresult) { + /* this should not happen */ + darwin_release_interface (dev_handle, iface); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); + return kresult; + } + + return darwin_to_libusb (kresult); +} + +static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { + /* current interface */ + struct darwin_interface *cInterface; + IOReturn kresult; + uint8_t pipeRef; + + /* determine the interface/endpoint to use */ + if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, NULL, &cInterface) != 0) { + usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + /* newer versions of darwin support clearing additional bits on the device's endpoint */ + kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); + if (kresult) + usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); + + return darwin_to_libusb (kresult); +} + +static int darwin_reset_device(struct libusb_device_handle *dev_handle) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + IOUSBDeviceDescriptor descriptor; + IOUSBConfigurationDescriptorPtr cached_configuration; + IOUSBConfigurationDescriptor configuration; + bool reenumerate = false; + IOReturn kresult; + int i; + + kresult = (*(dpriv->device))->ResetDevice (dpriv->device); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); + return darwin_to_libusb (kresult); + } + + do { + usbi_dbg ("darwin/reset_device: checking if device descriptor changed"); + + /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */ + (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor)); + + /* check if the device descriptor has changed */ + if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) { + reenumerate = true; + break; + } + + /* check if any configuration descriptor has changed */ + for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { + usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i); + + (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration)); + (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); + + if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) { + reenumerate = true; + break; + } + } + } while (0); + + if (reenumerate) { + usbi_dbg ("darwin/reset_device: device requires reenumeration"); + (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg ("darwin/reset_device: device reset complete"); + + return LIBUSB_SUCCESS; +} + +static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + io_service_t usbInterface; + CFTypeRef driver; + IOReturn kresult; + + kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); + if (kresult) { + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); + + return darwin_to_libusb (kresult); + } + + driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0); + IOObjectRelease (usbInterface); + + if (driver) { + CFRelease (driver); + + return 1; + } + + /* no driver */ + return 0; +} + +/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */ +static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { + UNUSED(dev_handle); + UNUSED(interface); + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { + UNUSED(dev_handle); + UNUSED(interface); + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +static void darwin_destroy_device(struct libusb_device *dev) { + struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv; + + if (dpriv->dev) { + /* need to hold the lock in case this is the last reference to the device */ + usbi_mutex_lock(&darwin_cached_devices_lock); + darwin_deref_cached_device (dpriv->dev); + dpriv->dev = NULL; + usbi_mutex_unlock(&darwin_cached_devices_lock); + } +} + +static int submit_bulk_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + IOReturn ret; + uint8_t transferType; + /* None of the values below are used in libusbx for bulk transfers */ + uint8_t direction, number, interval, pipeRef; + uint16_t maxPacketSize; + + struct darwin_interface *cInterface; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, + &transferType, &maxPacketSize, &interval); + + if (ret) { + usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", + darwin_error_str(ret), ret); + return darwin_to_libusb (ret); + } + + if (0 != (transfer->length % maxPacketSize)) { + /* do not need a zero packet */ + transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET; + } + + /* submit the request */ + /* timeouts are unavailable on interrupt endpoints */ + if (transferType == kUSBInterrupt) { + if (IS_XFERIN(transfer)) + ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, + transfer->length, darwin_async_io_callback, itransfer); + else + ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, + transfer->length, darwin_async_io_callback, itransfer); + } else { + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + + if (IS_XFERIN(transfer)) + ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, + transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, (void *)itransfer); + else + ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, + transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, (void *)itransfer); + } + + if (ret) + usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", + darwin_error_str(ret), ret); + + return darwin_to_libusb (ret); +} + +#if InterfaceVersion >= 550 +static int submit_stream_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_interface *cInterface; + uint8_t pipeRef; + IOReturn ret; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + + if (IS_XFERIN(transfer)) + ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, + transfer->buffer, transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, (void *)itransfer); + else + ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, + transfer->buffer, transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, (void *)itransfer); + + if (ret) + usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", + darwin_error_str(ret), ret); + + return darwin_to_libusb (ret); +} +#endif + +static int submit_iso_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + + IOReturn kresult; + uint8_t direction, number, interval, pipeRef, transferType; + uint16_t maxPacketSize; + UInt64 frame; + AbsoluteTime atTime; + int i; + + struct darwin_interface *cInterface; + + /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ + if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { + free(tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + } + + if (!tpriv->isoc_framelist) { + tpriv->num_iso_packets = transfer->num_iso_packets; + tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); + if (!tpriv->isoc_framelist) + return LIBUSB_ERROR_NO_MEM; + } + + /* copy the frame list from the libusb descriptor (the structures differ only is member order) */ + for (i = 0 ; i < transfer->num_iso_packets ; i++) + tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length; + + /* determine the interface/endpoint to use */ + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + /* determine the properties of this endpoint and the speed of the device */ + (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, + &transferType, &maxPacketSize, &interval); + + /* Last but not least we need the bus frame number */ + kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); + if (kresult) { + usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); + free(tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + + return darwin_to_libusb (kresult); + } + + (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, + &transferType, &maxPacketSize, &interval); + + /* schedule for a frame a little in the future */ + frame += 4; + + if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) + frame = cInterface->frames[transfer->endpoint]; + + /* submit the request */ + if (IS_XFERIN(transfer)) + kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, + transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + itransfer); + else + kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, + transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + itransfer); + + if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) + /* Full speed */ + cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)); + else + /* High/super speed */ + cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8; + + if (kresult != kIOReturnSuccess) { + usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", + darwin_error_str(kresult)); + free (tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + } + + return darwin_to_libusb (kresult); +} + +static int submit_control_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); + struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + + IOReturn kresult; + + memset(&tpriv->req, 0, sizeof(tpriv->req)); + + /* IOUSBDeviceInterface expects the request in cpu endianness */ + tpriv->req.bmRequestType = setup->bmRequestType; + tpriv->req.bRequest = setup->bRequest; + /* these values should be in bus order from libusb_fill_control_setup */ + tpriv->req.wValue = OSSwapLittleToHostInt16 (setup->wValue); + tpriv->req.wIndex = OSSwapLittleToHostInt16 (setup->wIndex); + tpriv->req.wLength = OSSwapLittleToHostInt16 (setup->wLength); + /* data is stored after the libusb control block */ + tpriv->req.pData = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + tpriv->req.completionTimeout = transfer->timeout; + tpriv->req.noDataTimeout = transfer->timeout; + + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + + /* all transfers in libusb-1.0 are async */ + + if (transfer->endpoint) { + struct darwin_interface *cInterface; + uint8_t pipeRef; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); + } else + /* control request on endpoint 0 */ + kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); + + if (kresult != kIOReturnSuccess) + usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); + + return darwin_to_libusb (kresult); +} + +static int darwin_submit_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return submit_control_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + return submit_bulk_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return submit_iso_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: +#if InterfaceVersion >= 550 + return submit_stream_transfer(itransfer); +#else + usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers"); + return LIBUSB_ERROR_NOT_SUPPORTED; +#endif + default: + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int cancel_control_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); + IOReturn kresult; + + usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe"); + + if (!dpriv->device) + return LIBUSB_ERROR_NO_DEVICE; + + kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); + + return darwin_to_libusb (kresult); +} + +static int darwin_abort_transfers (struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); + struct darwin_interface *cInterface; + uint8_t pipeRef, iface; + IOReturn kresult; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + if (!dpriv->device) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef); + + /* abort transactions */ +#if InterfaceVersion >= 550 + if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) + (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); + else +#endif + (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); + + usbi_dbg ("calling clear pipe stall to clear the data toggle bit"); + + /* newer versions of darwin support clearing additional bits on the device's endpoint */ + kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); + + return darwin_to_libusb (kresult); +} + +static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return cancel_control_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return darwin_abort_transfers (itransfer); + default: + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) { + free (tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + } +} + +static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) { + struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon; + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + + usbi_dbg ("an async io operation has completed"); + + /* if requested write a zero packet */ + if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { + struct darwin_interface *cInterface; + uint8_t pipeRef; + + (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface); + + (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); + } + + tpriv->result = result; + tpriv->size = (UInt32) (uintptr_t) arg0; + + /* signal the core that this transfer is complete */ + usbi_signal_transfer_completion(itransfer); +} + +static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { + if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) + result = kIOUSBTransactionTimeout; + + switch (result) { + case kIOReturnUnderrun: + case kIOReturnSuccess: + return LIBUSB_TRANSFER_COMPLETED; + case kIOReturnAborted: + return LIBUSB_TRANSFER_CANCELLED; + case kIOUSBPipeStalled: + usbi_dbg ("transfer error: pipe is stalled"); + return LIBUSB_TRANSFER_STALL; + case kIOReturnOverrun: + usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun"); + return LIBUSB_TRANSFER_OVERFLOW; + case kIOUSBTransactionTimeout: + usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out"); + itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; + return LIBUSB_TRANSFER_TIMED_OUT; + default: + usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result); + return LIBUSB_TRANSFER_ERROR; + } +} + +static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; + int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; + int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; + int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; + int i; + + if (!isIsoc && !isBulk && !isControl && !isInterrupt) { + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } + + usbi_dbg ("handling %s completion with kernel status %d", + isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result); + + if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) { + if (isIsoc && tpriv->isoc_framelist) { + /* copy isochronous results back */ + + for (i = 0; i < transfer->num_iso_packets ; i++) { + struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; + lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus); + lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; + } + } else if (!isIsoc) + itransfer->transferred += tpriv->size; + } + + /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */ + return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result)); +} + +static int darwin_clock_gettime(int clk_id, struct timespec *tp) { +#if !OSX_USE_CLOCK_GETTIME + mach_timespec_t sys_time; + clock_serv_t clock_ref; + + switch (clk_id) { + case USBI_CLOCK_REALTIME: + /* CLOCK_REALTIME represents time since the epoch */ + clock_ref = clock_realtime; + break; + case USBI_CLOCK_MONOTONIC: + /* use system boot time as reference for the monotonic clock */ + clock_ref = clock_monotonic; + break; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } + + clock_get_time (clock_ref, &sys_time); + + tp->tv_sec = sys_time.tv_sec; + tp->tv_nsec = sys_time.tv_nsec; + + return 0; +#else + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + return clock_gettime(CLOCK_MONOTONIC, tp); + case USBI_CLOCK_REALTIME: + return clock_gettime(CLOCK_REALTIME, tp); + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +#endif +} + +#if InterfaceVersion >= 550 +static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, + int num_endpoints) { + struct darwin_interface *cInterface; + UInt32 supportsStreams; + uint8_t pipeRef; + int rc, i; + + /* find the mimimum number of supported streams on the endpoint list */ + for (i = 0 ; i < num_endpoints ; ++i) { + if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) { + return rc; + } + + (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + if (num_streams > supportsStreams) + num_streams = supportsStreams; + } + + /* it is an error if any endpoint in endpoints does not support streams */ + if (0 == num_streams) + return LIBUSB_ERROR_INVALID_PARAM; + + /* create the streams */ + for (i = 0 ; i < num_endpoints ; ++i) { + (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); + + rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams); + if (kIOReturnSuccess != rc) + return darwin_to_libusb(rc); + } + + return num_streams; +} + +static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { + struct darwin_interface *cInterface; + UInt32 supportsStreams; + uint8_t pipeRef; + int rc; + + for (int i = 0 ; i < num_endpoints ; ++i) { + if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) + return rc; + + (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + if (0 == supportsStreams) + return LIBUSB_ERROR_INVALID_PARAM; + + rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0); + if (kIOReturnSuccess != rc) + return darwin_to_libusb(rc); + } + + return LIBUSB_SUCCESS; +} +#endif + +const struct usbi_os_backend usbi_backend = { + .name = "Darwin", + .caps = 0, + .init = darwin_init, + .exit = darwin_exit, + .get_device_list = NULL, /* not needed */ + .get_device_descriptor = darwin_get_device_descriptor, + .get_active_config_descriptor = darwin_get_active_config_descriptor, + .get_config_descriptor = darwin_get_config_descriptor, + .hotplug_poll = darwin_hotplug_poll, + + .open = darwin_open, + .close = darwin_close, + .get_configuration = darwin_get_configuration, + .set_configuration = darwin_set_configuration, + .claim_interface = darwin_claim_interface, + .release_interface = darwin_release_interface, + + .set_interface_altsetting = darwin_set_interface_altsetting, + .clear_halt = darwin_clear_halt, + .reset_device = darwin_reset_device, + +#if InterfaceVersion >= 550 + .alloc_streams = darwin_alloc_streams, + .free_streams = darwin_free_streams, +#endif + + .kernel_driver_active = darwin_kernel_driver_active, + .detach_kernel_driver = darwin_detach_kernel_driver, + .attach_kernel_driver = darwin_attach_kernel_driver, + + .destroy_device = darwin_destroy_device, + + .submit_transfer = darwin_submit_transfer, + .cancel_transfer = darwin_cancel_transfer, + .clear_transfer_priv = darwin_clear_transfer_priv, + + .handle_transfer_completion = darwin_handle_transfer_completion, + + .clock_gettime = darwin_clock_gettime, + + .device_priv_size = sizeof(struct darwin_device_priv), + .device_handle_priv_size = sizeof(struct darwin_device_handle_priv), + .transfer_priv_size = sizeof(struct darwin_transfer_priv), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h new file mode 100644 index 0000000000..474567f6ac --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h @@ -0,0 +1,199 @@ +/* + * darwin backend for libusb 1.0 + * Copyright © 2008-2015 Nathan Hjelm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined(LIBUSB_DARWIN_H) +#define LIBUSB_DARWIN_H + +#include "libusbi.h" + +#include +#include +#include +#include + +/* IOUSBInterfaceInferface */ + +/* New in OS 10.12.0. */ +#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + +#define usb_interface_t IOUSBInterfaceInterface800 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800 +#define InterfaceVersion 800 + +/* New in OS 10.10.0. */ +#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) + +#define usb_interface_t IOUSBInterfaceInterface700 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 +#define InterfaceVersion 700 + +/* New in OS 10.9.0. */ +#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_interface_t IOUSBInterfaceInterface650 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650 +#define InterfaceVersion 650 + +/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_interface_t IOUSBInterfaceInterface550 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 +#define InterfaceVersion 550 + +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) + +#define usb_interface_t IOUSBInterfaceInterface500 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 +#define InterfaceVersion 500 + +/* New in OS 10.5.0. */ +#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) + +#define usb_interface_t IOUSBInterfaceInterface300 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 +#define InterfaceVersion 300 + +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) + +#define usb_interface_t IOUSBInterfaceInterface245 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 +#define InterfaceVersion 245 + +/* New in OS 10.4.0. */ +#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040) + +#define usb_interface_t IOUSBInterfaceInterface220 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 +#define InterfaceVersion 220 + +#else + +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" + +#endif + +/* IOUSBDeviceInterface */ + +/* New in OS 10.9.0. */ +#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_device_t IOUSBDeviceInterface650 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID650 +#define DeviceVersion 650 + +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) + +#define usb_device_t IOUSBDeviceInterface500 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 +#define DeviceVersion 500 + +/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) + +#define usb_device_t IOUSBDeviceInterface320 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID320 +#define DeviceVersion 320 + +/* New in OS 10.5.0. */ +#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) + +#define usb_device_t IOUSBDeviceInterface300 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID300 +#define DeviceVersion 300 + +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) + +#define usb_device_t IOUSBDeviceInterface245 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID245 +#define DeviceVersion 245 + +/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) + +#define usb_device_t IOUSBDeviceInterface197 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 +#define DeviceVersion 197 + +#else + +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" + +#endif + +#if !defined(IO_OBJECT_NULL) +#define IO_OBJECT_NULL ((io_object_t) 0) +#endif + +typedef IOCFPlugInInterface *io_cf_plugin_ref_t; +typedef IONotificationPortRef io_notification_port_t; + +/* private structures */ +struct darwin_cached_device { + struct list_head list; + IOUSBDeviceDescriptor dev_descriptor; + UInt32 location; + UInt64 parent_session; + UInt64 session; + UInt16 address; + char sys_path[21]; + usb_device_t **device; + int open_count; + UInt8 first_config, active_config, port; + int can_enumerate; + int refcount; +}; + +struct darwin_device_priv { + struct darwin_cached_device *dev; +}; + +struct darwin_device_handle_priv { + int is_open; + CFRunLoopSourceRef cfSource; + + struct darwin_interface { + usb_interface_t **interface; + uint8_t num_endpoints; + CFRunLoopSourceRef cfSource; + uint64_t frames[256]; + uint8_t endpoint_addrs[USB_MAXENDPOINTS]; + } interfaces[USB_MAXINTERFACES]; +}; + +struct darwin_transfer_priv { + /* Isoc */ + IOUSBIsocFrame *isoc_framelist; + int num_iso_packets; + + /* Control */ + IOUSBDevRequestTO req; + + /* Bulk */ + + /* Completion status */ + IOReturn result; + UInt32 size; +}; + +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp new file mode 100644 index 0000000000..e0c7713206 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp @@ -0,0 +1,367 @@ +/* + * Copyright 2007-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#include "haiku_usb.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class WatchedEntry { +public: + WatchedEntry(BMessenger *, entry_ref *); + ~WatchedEntry(); + bool EntryCreated(entry_ref *ref); + bool EntryRemoved(ino_t node); + bool InitCheck(); + +private: + BMessenger* fMessenger; + node_ref fNode; + bool fIsDirectory; + USBDevice* fDevice; + WatchedEntry* fEntries; + WatchedEntry* fLink; + bool fInitCheck; +}; + + +class RosterLooper : public BLooper { +public: + RosterLooper(USBRoster *); + void Stop(); + virtual void MessageReceived(BMessage *); + bool InitCheck(); + +private: + USBRoster* fRoster; + WatchedEntry* fRoot; + BMessenger* fMessenger; + bool fInitCheck; +}; + + +WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref) + : fMessenger(messenger), + fIsDirectory(false), + fDevice(NULL), + fEntries(NULL), + fLink(NULL), + fInitCheck(false) +{ + BEntry entry(ref); + entry.GetNodeRef(&fNode); + + BDirectory directory; + if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) { + fIsDirectory = true; + + while (directory.GetNextEntry(&entry) >= B_OK) { + if (entry.GetRef(ref) < B_OK) + continue; + + WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + continue; + if (child->InitCheck() == false) { + delete child; + continue; + } + + child->fLink = fEntries; + fEntries = child; + } + + watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger); + } + else { + if (strncmp(ref->name, "raw", 3) == 0) + return; + + BPath path, parent_path; + entry.GetPath(&path); + fDevice = new(std::nothrow) USBDevice(path.Path()); + if (fDevice != NULL && fDevice->InitCheck() == true) { + // Add this new device to each active context's device list + struct libusb_context *ctx; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev) { + usbi_dbg("using previously allocated device with location %lu", session_id); + libusb_unref_device(dev); + continue; + } + usbi_dbg("allocating new device with location %lu", session_id); + dev = usbi_alloc_device(ctx, session_id); + if (!dev) { + usbi_dbg("device allocation failed"); + continue; + } + *((USBDevice **)dev->os_priv) = fDevice; + + // Calculate pseudo-device-address + int addr, tmp; + if (strcmp(path.Leaf(), "hub") == 0) + tmp = 100; //Random Number + else + sscanf(path.Leaf(), "%d", &tmp); + addr = tmp + 1; + path.GetParent(&parent_path); + while (strcmp(parent_path.Leaf(), "usb") != 0) { + sscanf(parent_path.Leaf(), "%d", &tmp); + addr += tmp + 1; + parent_path.GetParent(&parent_path); + } + sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number); + dev->device_address = addr - (dev->bus_number + 1); + + if (usbi_sanitize_device(dev) < 0) { + usbi_dbg("device sanitization failed"); + libusb_unref_device(dev); + continue; + } + usbi_connect_device(dev); + } + usbi_mutex_unlock(&active_contexts_lock); + } + else if (fDevice) { + delete fDevice; + fDevice = NULL; + return; + } + } + fInitCheck = true; +} + + +WatchedEntry::~WatchedEntry() +{ + if (fIsDirectory) { + watch_node(&fNode, B_STOP_WATCHING, *fMessenger); + + WatchedEntry *child = fEntries; + while (child) { + WatchedEntry *next = child->fLink; + delete child; + child = next; + } + } + + if (fDevice) { + // Remove this device from each active context's device list + struct libusb_context *ctx; + struct libusb_device *dev; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev != NULL) { + usbi_disconnect_device(dev); + libusb_unref_device(dev); + } else { + usbi_dbg("device with location %lu not found", session_id); + } + } + usbi_mutex_static_unlock(&active_contexts_lock); + delete fDevice; + } +} + + +bool +WatchedEntry::EntryCreated(entry_ref *ref) +{ + if (!fIsDirectory) + return false; + + if (ref->directory != fNode.node) { + WatchedEntry *child = fEntries; + while (child) { + if (child->EntryCreated(ref)) + return true; + child = child->fLink; + } + return false; + } + + WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + return false; + child->fLink = fEntries; + fEntries = child; + return true; +} + + +bool +WatchedEntry::EntryRemoved(ino_t node) +{ + if (!fIsDirectory) + return false; + + WatchedEntry *child = fEntries; + WatchedEntry *lastChild = NULL; + while (child) { + if (child->fNode.node == node) { + if (lastChild) + lastChild->fLink = child->fLink; + else + fEntries = child->fLink; + delete child; + return true; + } + + if (child->EntryRemoved(node)) + return true; + + lastChild = child; + child = child->fLink; + } + return false; +} + + +bool +WatchedEntry::InitCheck() +{ + return fInitCheck; +} + + +RosterLooper::RosterLooper(USBRoster *roster) + : BLooper("LibusbRoster Looper"), + fRoster(roster), + fRoot(NULL), + fMessenger(NULL), + fInitCheck(false) +{ + BEntry entry("/dev/bus/usb"); + if (!entry.Exists()) { + usbi_err(NULL, "usb_raw not published"); + return; + } + + Run(); + fMessenger = new(std::nothrow) BMessenger(this); + if (fMessenger == NULL) { + usbi_err(NULL, "error creating BMessenger object"); + return; + } + + if (Lock()) { + entry_ref ref; + entry.GetRef(&ref); + fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref); + Unlock(); + if (fRoot == NULL) + return; + if (fRoot->InitCheck() == false) { + delete fRoot; + fRoot = NULL; + return; + } + } + fInitCheck = true; +} + + +void +RosterLooper::Stop() +{ + Lock(); + delete fRoot; + delete fMessenger; + Quit(); +} + + +void +RosterLooper::MessageReceived(BMessage *message) +{ + int32 opcode; + if (message->FindInt32("opcode", &opcode) < B_OK) + return; + + switch (opcode) { + case B_ENTRY_CREATED: + { + dev_t device; + ino_t directory; + const char *name; + if (message->FindInt32("device", &device) < B_OK || + message->FindInt64("directory", &directory) < B_OK || + message->FindString("name", &name) < B_OK) + break; + + entry_ref ref(device, directory, name); + fRoot->EntryCreated(&ref); + break; + } + case B_ENTRY_REMOVED: + { + ino_t node; + if (message->FindInt64("node", &node) < B_OK) + break; + fRoot->EntryRemoved(node); + break; + } + } +} + + +bool +RosterLooper::InitCheck() +{ + return fInitCheck; +} + + +USBRoster::USBRoster() + : fLooper(NULL) +{ +} + + +USBRoster::~USBRoster() +{ + Stop(); +} + + +int +USBRoster::Start() +{ + if (fLooper == NULL) { + fLooper = new(std::nothrow) RosterLooper(this); + if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) { + if (fLooper) + fLooper = NULL; + return LIBUSB_ERROR_OTHER; + } + } + return LIBUSB_SUCCESS; +} + + +void +USBRoster::Stop() +{ + if (fLooper) { + ((RosterLooper *)fLooper)->Stop(); + fLooper = NULL; + } +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h new file mode 100644 index 0000000000..d51ae9eae8 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h @@ -0,0 +1,112 @@ +/* + * Haiku Backend for libusb + * Copyright © 2014 Akshay Jaggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "libusbi.h" +#include "haiku_usb_raw.h" + +using namespace std; + +class USBDevice; +class USBDeviceHandle; +class USBTransfer; + +class USBDevice { +public: + USBDevice(const char *); + virtual ~USBDevice(); + const char* Location() const; + uint8 CountConfigurations() const; + const usb_device_descriptor* Descriptor() const; + const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const; + const usb_configuration_descriptor* ActiveConfiguration() const; + uint8 EndpointToIndex(uint8) const; + uint8 EndpointToInterface(uint8) const; + int ClaimInterface(int); + int ReleaseInterface(int); + int CheckInterfacesFree(int); + int SetActiveConfiguration(int); + int ActiveConfigurationIndex() const; + bool InitCheck(); +private: + int Initialise(); + unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask + usb_device_descriptor fDeviceDescriptor; + unsigned char** fConfigurationDescriptors; + int fActiveConfiguration; + char* fPath; + map fConfigToIndex; + map* fEndpointToIndex; + map* fEndpointToInterface; + bool fInitCheck; +}; + +class USBDeviceHandle { +public: + USBDeviceHandle(USBDevice *dev); + virtual ~USBDeviceHandle(); + int ClaimInterface(int); + int ReleaseInterface(int); + int SetConfiguration(int); + int SetAltSetting(int, int); + status_t SubmitTransfer(struct usbi_transfer *); + status_t CancelTransfer(USBTransfer *); + bool InitCheck(); +private: + int fRawFD; + static status_t TransfersThread(void *); + void TransfersWorker(); + USBDevice* fUSBDevice; + unsigned int fClaimedInterfaces; + BList fTransfers; + BLocker fTransfersLock; + sem_id fTransfersSem; + thread_id fTransfersThread; + bool fInitCheck; +}; + +class USBTransfer { +public: + USBTransfer(struct usbi_transfer *, USBDevice *); + virtual ~USBTransfer(); + void Do(int); + struct usbi_transfer* UsbiTransfer(); + void SetCancelled(); + bool IsCancelled(); +private: + struct usbi_transfer* fUsbiTransfer; + struct libusb_transfer* fLibusbTransfer; + USBDevice* fUSBDevice; + BLocker fStatusLock; + bool fCancelled; +}; + +class USBRoster { +public: + USBRoster(); + virtual ~USBRoster(); + int Start(); + void Stop(); +private: + void* fLooper; +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp new file mode 100644 index 0000000000..d3de8cc080 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp @@ -0,0 +1,517 @@ +/* + * Haiku Backend for libusb + * Copyright © 2014 Akshay Jaggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include + +#include "haiku_usb.h" + +int _errno_to_libusb(int status) +{ + return status; +} + +USBTransfer::USBTransfer(struct usbi_transfer *itransfer, USBDevice *device) +{ + fUsbiTransfer = itransfer; + fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + fUSBDevice = device; + fCancelled = false; +} + +USBTransfer::~USBTransfer() +{ +} + +struct usbi_transfer * +USBTransfer::UsbiTransfer() +{ + return fUsbiTransfer; +} + +void +USBTransfer::SetCancelled() +{ + fCancelled = true; +} + +bool +USBTransfer::IsCancelled() +{ + return fCancelled; +} + +void +USBTransfer::Do(int fRawFD) +{ + switch (fLibusbTransfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + { + struct libusb_control_setup *setup = (struct libusb_control_setup *)fLibusbTransfer->buffer; + usb_raw_command command; + command.control.request_type = setup->bmRequestType; + command.control.request = setup->bRequest; + command.control.value = setup->wValue; + command.control.index = setup->wIndex; + command.control.length = setup->wLength; + command.control.data = fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + if (fCancelled) + break; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || + command.control.status != B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred = -1; + usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed control transfer"); + break; + } + fUsbiTransfer->transferred = command.control.length; + } + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + { + usb_raw_command command; + command.transfer.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); + command.transfer.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); + command.transfer.data = fLibusbTransfer->buffer; + command.transfer.length = fLibusbTransfer->length; + if (fCancelled) + break; + if (fLibusbTransfer->type == LIBUSB_TRANSFER_TYPE_BULK) { + if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command)) || + command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred = -1; + usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed bulk transfer"); + break; + } + } + else { + if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command)) || + command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred = -1; + usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed interrupt transfer"); + break; + } + } + fUsbiTransfer->transferred = command.transfer.length; + } + break; + // IsochronousTransfers not tested + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + { + usb_raw_command command; + command.isochronous.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); + command.isochronous.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); + command.isochronous.data = fLibusbTransfer->buffer; + command.isochronous.length = fLibusbTransfer->length; + command.isochronous.packet_count = fLibusbTransfer->num_iso_packets; + int i; + usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets]; + for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { + if ((int16)(fLibusbTransfer->iso_packet_desc[i]).length != (fLibusbTransfer->iso_packet_desc[i]).length) { + fUsbiTransfer->transferred = -1; + usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); + break; + } + packetDescriptors[i].request_length = (int16)(fLibusbTransfer->iso_packet_desc[i]).length; + } + if (i < fLibusbTransfer->num_iso_packets) + break; // TODO Handle this error + command.isochronous.packet_descriptors = packetDescriptors; + if (fCancelled) + break; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, sizeof(command)) || + command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred = -1; + usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); + break; + } + for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { + (fLibusbTransfer->iso_packet_desc[i]).actual_length = packetDescriptors[i].actual_length; + switch (packetDescriptors[i].status) { + case B_OK: + (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_COMPLETED; + break; + default: + (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_ERROR; + break; + } + } + delete[] packetDescriptors; + // Do we put the length of transfer here, for isochronous transfers? + fUsbiTransfer->transferred = command.transfer.length; + } + break; + default: + usbi_err(TRANSFER_CTX(fLibusbTransfer), "Unknown type of transfer"); + } +} + +bool +USBDeviceHandle::InitCheck() +{ + return fInitCheck; +} + +status_t +USBDeviceHandle::TransfersThread(void *self) +{ + USBDeviceHandle *handle = (USBDeviceHandle *)self; + handle->TransfersWorker(); + return B_OK; +} + +void +USBDeviceHandle::TransfersWorker() +{ + while (true) { + status_t status = acquire_sem(fTransfersSem); + if (status == B_BAD_SEM_ID) + break; + if (status == B_INTERRUPTED) + continue; + fTransfersLock.Lock(); + USBTransfer *fPendingTransfer = (USBTransfer *) fTransfers.RemoveItem((int32)0); + fTransfersLock.Unlock(); + fPendingTransfer->Do(fRawFD); + usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer()); + } +} + +status_t +USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer) +{ + USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice); + *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer; + BAutolock locker(fTransfersLock); + fTransfers.AddItem(transfer); + release_sem(fTransfersSem); + return LIBUSB_SUCCESS; +} + +status_t +USBDeviceHandle::CancelTransfer(USBTransfer *transfer) +{ + transfer->SetCancelled(); + fTransfersLock.Lock(); + bool removed = fTransfers.RemoveItem(transfer); + fTransfersLock.Unlock(); + if(removed) + usbi_signal_transfer_completion(transfer->UsbiTransfer()); + return LIBUSB_SUCCESS; +} + +USBDeviceHandle::USBDeviceHandle(USBDevice *dev) + : + fTransfersThread(-1), + fUSBDevice(dev), + fClaimedInterfaces(0), + fInitCheck(false) +{ + fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC); + if (fRawFD < 0) { + usbi_err(NULL,"failed to open device"); + return; + } + fTransfersSem = create_sem(0, "Transfers Queue Sem"); + fTransfersThread = spawn_thread(TransfersThread, "Transfer Worker", B_NORMAL_PRIORITY, this); + resume_thread(fTransfersThread); + fInitCheck = true; +} + +USBDeviceHandle::~USBDeviceHandle() +{ + if (fRawFD > 0) + close(fRawFD); + for(int i = 0; i < 32; i++) { + if (fClaimedInterfaces & (1 << i)) + ReleaseInterface(i); + } + delete_sem(fTransfersSem); + if (fTransfersThread > 0) + wait_for_thread(fTransfersThread, NULL); +} + +int +USBDeviceHandle::ClaimInterface(int inumber) +{ + int status = fUSBDevice->ClaimInterface(inumber); + if (status == LIBUSB_SUCCESS) + fClaimedInterfaces |= (1 << inumber); + return status; +} + +int +USBDeviceHandle::ReleaseInterface(int inumber) +{ + fUSBDevice->ReleaseInterface(inumber); + fClaimedInterfaces &= ~(1 << inumber); + return LIBUSB_SUCCESS; +} + +int +USBDeviceHandle::SetConfiguration(int config) +{ + int config_index = fUSBDevice->CheckInterfacesFree(config); + if(config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND) + return config_index; + usb_raw_command command; + command.config.config_index = config_index; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command)) || + command.config.status != B_USB_RAW_STATUS_SUCCESS) { + return _errno_to_libusb(command.config.status); + } + fUSBDevice->SetActiveConfiguration(config_index); + return LIBUSB_SUCCESS; +} + +int +USBDeviceHandle::SetAltSetting(int inumber, int alt) +{ + usb_raw_command command; + command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex(); + command.alternate.interface_index = inumber; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, sizeof(command)) || + command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "Error retrieving active alternate interface"); + return _errno_to_libusb(command.alternate.status); + } + if (command.alternate.alternate_info == alt) { + usbi_dbg("Setting alternate interface successful"); + return LIBUSB_SUCCESS; + } + command.alternate.alternate_info = alt; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, sizeof(command)) || + command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY + usbi_err(NULL, "Error setting alternate interface"); + return _errno_to_libusb(command.alternate.status); + } + usbi_dbg("Setting alternate interface successful"); + return LIBUSB_SUCCESS; +} + + +USBDevice::USBDevice(const char *path) + : + fPath(NULL), + fActiveConfiguration(0), //0? + fConfigurationDescriptors(NULL), + fClaimedInterfaces(0), + fEndpointToIndex(NULL), + fEndpointToInterface(NULL), + fInitCheck(false) +{ + fPath=strdup(path); + Initialise(); +} + +USBDevice::~USBDevice() +{ + free(fPath); + if (fConfigurationDescriptors) { + for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) { + if (fConfigurationDescriptors[i]) + delete fConfigurationDescriptors[i]; + } + delete[] fConfigurationDescriptors; + } + if (fEndpointToIndex) + delete[] fEndpointToIndex; + if (fEndpointToInterface) + delete[] fEndpointToInterface; +} + +bool +USBDevice::InitCheck() +{ + return fInitCheck; +} + +const char * +USBDevice::Location() const +{ + return fPath; +} + +uint8 +USBDevice::CountConfigurations() const +{ + return fDeviceDescriptor.num_configurations; +} + +const usb_device_descriptor * +USBDevice::Descriptor() const +{ + return &fDeviceDescriptor; +} + +const usb_configuration_descriptor * +USBDevice::ConfigurationDescriptor(uint32 index) const +{ + if (index > CountConfigurations()) + return NULL; + return (usb_configuration_descriptor *) fConfigurationDescriptors[index]; +} + +const usb_configuration_descriptor * +USBDevice::ActiveConfiguration() const +{ + return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration]; +} + +int +USBDevice::ActiveConfigurationIndex() const +{ + return fActiveConfiguration; +} + +int USBDevice::ClaimInterface(int interface) +{ + if (interface > ActiveConfiguration()->number_interfaces) + return LIBUSB_ERROR_NOT_FOUND; + if (fClaimedInterfaces & (1 << interface)) + return LIBUSB_ERROR_BUSY; + fClaimedInterfaces |= (1 << interface); + return LIBUSB_SUCCESS; +} + +int USBDevice::ReleaseInterface(int interface) +{ + fClaimedInterfaces &= ~(1 << interface); + return LIBUSB_SUCCESS; +} + +int +USBDevice::CheckInterfacesFree(int config) +{ + if (fConfigToIndex.count(config) == 0) + return LIBUSB_ERROR_NOT_FOUND; + if (fClaimedInterfaces == 0) + return fConfigToIndex[(uint8)config]; + return LIBUSB_ERROR_BUSY; +} + +int +USBDevice::SetActiveConfiguration(int config_index) +{ + fActiveConfiguration = config_index; + return LIBUSB_SUCCESS; +} + +uint8 +USBDevice::EndpointToIndex(uint8 address) const +{ + return fEndpointToIndex[fActiveConfiguration][address]; +} + +uint8 +USBDevice::EndpointToInterface(uint8 address) const +{ + return fEndpointToInterface[fActiveConfiguration][address]; +} + +int +USBDevice::Initialise() //Do we need more error checking, etc? How to report? +{ + int fRawFD = open(fPath, O_RDWR | O_CLOEXEC); + if (fRawFD < 0) + return B_ERROR; + usb_raw_command command; + command.device.descriptor = &fDeviceDescriptor; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command)) || + command.device.status != B_USB_RAW_STATUS_SUCCESS) { + close(fRawFD); + return B_ERROR; + } + + fConfigurationDescriptors = new(std::nothrow) unsigned char *[fDeviceDescriptor.num_configurations]; + fEndpointToIndex = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; + fEndpointToInterface = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; + for (int i = 0; i < fDeviceDescriptor.num_configurations; i++) { + usb_configuration_descriptor tmp_config; + command.config.descriptor = &tmp_config; + command.config.config_index = i; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command)) || + command.config.status != B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "failed retrieving configuration descriptor"); + close(fRawFD); + return B_ERROR; + } + fConfigToIndex[tmp_config.configuration_value] = i; + fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length]; + command.control.request_type = 128; + command.control.request = 6; + command.control.value = (2 << 8) | i; + command.control.index = 0; + command.control.length = tmp_config.total_length; + command.control.data = fConfigurationDescriptors[i]; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || + command.control.status!=B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "failed retrieving full configuration descriptor"); + close(fRawFD); + return B_ERROR; + } + for (int j = 0; j < tmp_config.number_interfaces; j++) { + command.alternate.config_index = i; + command.alternate.interface_index = j; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, sizeof(command)) || + command.config.status != B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "failed retrieving number of alternate interfaces"); + close(fRawFD); + return B_ERROR; + } + int num_alternate = command.alternate.alternate_info; + for (int k = 0; k < num_alternate; k++) { + usb_interface_descriptor tmp_interface; + command.interface_etc.config_index = i; + command.interface_etc.interface_index = j; + command.interface_etc.alternate_index = k; + command.interface_etc.descriptor = &tmp_interface; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, sizeof(command)) || + command.config.status != B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "failed retrieving interface descriptor"); + close(fRawFD); + return B_ERROR; + } + for (int l = 0; l < tmp_interface.num_endpoints; l++) { + usb_endpoint_descriptor tmp_endpoint; + command.endpoint_etc.config_index = i; + command.endpoint_etc.interface_index = j; + command.endpoint_etc.alternate_index = k; + command.endpoint_etc.endpoint_index = l; + command.endpoint_etc.descriptor = &tmp_endpoint; + if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, sizeof(command)) || + command.config.status != B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL, "failed retrieving endpoint descriptor"); + close(fRawFD); + return B_ERROR; + } + fEndpointToIndex[i][tmp_endpoint.endpoint_address] = l; + fEndpointToInterface[i][tmp_endpoint.endpoint_address] = j; + } + } + } + } + close(fRawFD); + fInitCheck = true; + return B_OK; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp new file mode 100644 index 0000000000..c701e34421 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp @@ -0,0 +1,253 @@ +/* + * Haiku Backend for libusb + * Copyright © 2014 Akshay Jaggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include + +#include "haiku_usb.h" + +USBRoster gUsbRoster; +int32 gInitCount = 0; + +static int +haiku_init(struct libusb_context *ctx) +{ + if (atomic_add(&gInitCount, 1) == 0) + return gUsbRoster.Start(); + return LIBUSB_SUCCESS; +} + +static void +haiku_exit(struct libusb_context *ctx) +{ + UNUSED(ctx); + if (atomic_add(&gInitCount, -1) == 1) + gUsbRoster.Stop(); +} + +static int +haiku_open(struct libusb_device_handle *dev_handle) +{ + USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv); + USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev); + if (handle == NULL) + return LIBUSB_ERROR_NO_MEM; + if (handle->InitCheck() == false) { + delete handle; + return LIBUSB_ERROR_NO_DEVICE; + } + *((USBDeviceHandle **)dev_handle->os_priv) = handle; + return LIBUSB_SUCCESS; +} + +static void +haiku_close(struct libusb_device_handle *dev_handle) +{ + USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); + if (handle == NULL) + return; + delete handle; + *((USBDeviceHandle **)dev_handle->os_priv) = NULL; +} + +static int +haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian) +{ + USBDevice *dev = *((USBDevice **)device->os_priv); + memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH); + *host_endian = 0; + return LIBUSB_SUCCESS; +} + +static int +haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian) +{ + USBDevice *dev = *((USBDevice **)device->os_priv); + const usb_configuration_descriptor *act_config = dev->ActiveConfiguration(); + if (len > act_config->total_length) + return LIBUSB_ERROR_OVERFLOW; + memcpy(buffer, act_config, len); + *host_endian = 0; + return LIBUSB_SUCCESS; +} + +static int +haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + USBDevice *dev = *((USBDevice **)device->os_priv); + const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index); + if (config == NULL) { + usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor"); + return LIBUSB_ERROR_INVALID_PARAM; + } + if (len > config->total_length) + len = config->total_length; + memcpy(buffer, config, len); + *host_endian = 0; + return len; +} + +static int +haiku_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv); + return handle->SetConfiguration(config); +} + +static int +haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); + return handle->ClaimInterface(interface_number); +} + +static int +haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting) +{ + USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); + return handle->SetAltSetting(interface_number, altsetting); +} + +static int +haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); + haiku_set_altsetting(dev_handle,interface_number, 0); + return handle->ReleaseInterface(interface_number); +} + +static int +haiku_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); + return fDeviceHandle->SubmitTransfer(itransfer); +} + +static int +haiku_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); + return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer))); +} + +static void +haiku_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); + delete transfer; + *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; +} + +static int +haiku_handle_transfer_completion(struct usbi_transfer *itransfer) +{ + USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); + + usbi_mutex_lock(&itransfer->lock); + if (transfer->IsCancelled()) { + delete transfer; + *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; + usbi_mutex_unlock(&itransfer->lock); + if (itransfer->transferred < 0) + itransfer->transferred = 0; + return usbi_handle_transfer_cancellation(itransfer); + } + libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; + if (itransfer->transferred < 0) { + usbi_err(ITRANSFER_CTX(itransfer), "error in transfer"); + status = LIBUSB_TRANSFER_ERROR; + itransfer->transferred = 0; + } + delete transfer; + *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_completion(itransfer, status); +} + +static int +haiku_clock_gettime(int clkid, struct timespec *tp) +{ + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime(CLOCK_MONOTONIC, tp); + return LIBUSB_ERROR_INVALID_PARAM; +} + +const struct usbi_os_backend usbi_backend = { + /*.name =*/ "Haiku usbfs", + /*.caps =*/ 0, + /*.init =*/ haiku_init, + /*.exit =*/ haiku_exit, + /*.set_option =*/ NULL, + /*.get_device_list =*/ NULL, + /*.hotplug_poll =*/ NULL, + /*.open =*/ haiku_open, + /*.close =*/ haiku_close, + /*.get_device_descriptor =*/ haiku_get_device_descriptor, + /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, + /*.get_config_descriptor =*/ haiku_get_config_descriptor, + /*.get_config_descriptor_by_value =*/ NULL, + + + /*.get_configuration =*/ NULL, + /*.set_configuration =*/ haiku_set_configuration, + /*.claim_interface =*/ haiku_claim_interface, + /*.release_interface =*/ haiku_release_interface, + + /*.set_interface_altsetting =*/ haiku_set_altsetting, + /*.clear_halt =*/ NULL, + /*.reset_device =*/ NULL, + + /*.alloc_streams =*/ NULL, + /*.free_streams =*/ NULL, + + /*.dev_mem_alloc =*/ NULL, + /*.dev_mem_free =*/ NULL, + + /*.kernel_driver_active =*/ NULL, + /*.detach_kernel_driver =*/ NULL, + /*.attach_kernel_driver =*/ NULL, + + /*.destroy_device =*/ NULL, + + /*.submit_transfer =*/ haiku_submit_transfer, + /*.cancel_transfer =*/ haiku_cancel_transfer, + /*.clear_transfer_priv =*/ haiku_clear_transfer_priv, + + /*.handle_events =*/ NULL, + /*.handle_transfer_completion =*/ haiku_handle_transfer_completion, + + /*.clock_gettime =*/ haiku_clock_gettime, + +#ifdef USBI_TIMERFD_AVAILABLE + /*.get_timerfd_clockid =*/ NULL, +#endif + + /*.context_priv_size=*/ 0, + /*.device_priv_size =*/ sizeof(USBDevice *), + /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *), + /*.transfer_priv_size =*/ sizeof(USBTransfer *), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h new file mode 100644 index 0000000000..5baf53d7c9 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h @@ -0,0 +1,180 @@ +/* + * Copyright 2006-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _USB_RAW_H_ +#define _USB_RAW_H_ + +#include + +#define B_USB_RAW_PROTOCOL_VERSION 0x0015 +#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff + +typedef enum { + B_USB_RAW_COMMAND_GET_VERSION = 0x1000, + + B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000, + B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, + B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, + B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, + B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, + B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, + + B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000, + B_USB_RAW_COMMAND_SET_FEATURE, + B_USB_RAW_COMMAND_CLEAR_FEATURE, + B_USB_RAW_COMMAND_GET_STATUS, + B_USB_RAW_COMMAND_GET_DESCRIPTOR, + B_USB_RAW_COMMAND_SET_ALT_INTERFACE, + + B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000, + B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, + B_USB_RAW_COMMAND_BULK_TRANSFER, + B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER +} usb_raw_command_id; + + +typedef enum { + B_USB_RAW_STATUS_SUCCESS = 0, + + B_USB_RAW_STATUS_FAILED, + B_USB_RAW_STATUS_ABORTED, + B_USB_RAW_STATUS_STALLED, + B_USB_RAW_STATUS_CRC_ERROR, + B_USB_RAW_STATUS_TIMEOUT, + + B_USB_RAW_STATUS_INVALID_CONFIGURATION, + B_USB_RAW_STATUS_INVALID_INTERFACE, + B_USB_RAW_STATUS_INVALID_ENDPOINT, + B_USB_RAW_STATUS_INVALID_STRING, + + B_USB_RAW_STATUS_NO_MEMORY +} usb_raw_command_status; + + +typedef union { + struct { + status_t status; + } version; + + struct { + status_t status; + usb_device_descriptor *descriptor; + } device; + + struct { + status_t status; + usb_configuration_descriptor *descriptor; + uint32 config_index; + } config; + + struct { + status_t status; + uint32 alternate_info; + uint32 config_index; + uint32 interface_index; + } alternate; + + struct { + status_t status; + usb_interface_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + } interface; + + struct { + status_t status; + usb_interface_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + } interface_etc; + + struct { + status_t status; + usb_endpoint_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 endpoint_index; + } endpoint; + + struct { + status_t status; + usb_endpoint_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + uint32 endpoint_index; + } endpoint_etc; + + struct { + status_t status; + usb_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 generic_index; + size_t length; + } generic; + + struct { + status_t status; + usb_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + uint32 generic_index; + size_t length; + } generic_etc; + + struct { + status_t status; + usb_string_descriptor *descriptor; + uint32 string_index; + size_t length; + } string; + + struct { + status_t status; + uint8 type; + uint8 index; + uint16 language_id; + void *data; + size_t length; + } descriptor; + + struct { + status_t status; + uint8 request_type; + uint8 request; + uint16 value; + uint16 index; + uint16 length; + void *data; + } control; + + struct { + status_t status; + uint32 interface; + uint32 endpoint; + void *data; + size_t length; + } transfer; + + struct { + status_t status; + uint32 interface; + uint32 endpoint; + void *data; + size_t length; + usb_iso_packet_descriptor *packet_descriptors; + uint32 packet_count; + } isochronous; +} usb_raw_command; + +#endif // _USB_RAW_H_ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c new file mode 100644 index 0000000000..c1ad1ec51f --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c @@ -0,0 +1,409 @@ +/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ +/* + * Linux usbfs backend for libusb + * Copyright (C) 2007-2009 Daniel Drake + * Copyright (c) 2001 Johannes Erdfelt + * Copyright (c) 2013 Nathan Hjelm + * Copyright (c) 2016 Chris Dickens + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ASM_TYPES_H +#include +#endif + +#include +#include + +#include "libusbi.h" +#include "linux_usbfs.h" + +#define NL_GROUP_KERNEL 1 + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif + +static int linux_netlink_socket = -1; +static int netlink_control_pipe[2] = { -1, -1 }; +static pthread_t libusb_linux_event_thread; + +static void *linux_netlink_event_thread_main(void *arg); + +static int set_fd_cloexec_nb(int fd, int socktype) +{ + int flags; + +#if defined(FD_CLOEXEC) + /* Make sure the netlink socket file descriptor is marked as CLOEXEC */ + if (!(socktype & SOCK_CLOEXEC)) { + flags = fcntl(fd, F_GETFD); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); + return -1; + } + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { + usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); + return -1; + } + } +#endif + + /* Make sure the netlink socket is non-blocking */ + if (!(socktype & SOCK_NONBLOCK)) { + flags = fcntl(fd, F_GETFL); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); + return -1; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { + usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); + return -1; + } + } + + return 0; +} + +int linux_netlink_start_event_monitor(void) +{ + struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; + int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC; + int opt = 1; + int ret; + + linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); + if (linux_netlink_socket == -1 && errno == EINVAL) { + usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); + socktype = SOCK_RAW; + linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); + } + + if (linux_netlink_socket == -1) { + usbi_err(NULL, "failed to create netlink socket (%d)", errno); + goto err; + } + + ret = set_fd_cloexec_nb(linux_netlink_socket, socktype); + if (ret == -1) + goto err_close_socket; + + ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); + if (ret == -1) { + usbi_err(NULL, "failed to bind netlink socket (%d)", errno); + goto err_close_socket; + } + + ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); + if (ret == -1) { + usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno); + goto err_close_socket; + } + + ret = usbi_pipe(netlink_control_pipe); + if (ret) { + usbi_err(NULL, "failed to create netlink control pipe"); + goto err_close_socket; + } + + ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL); + if (ret != 0) { + usbi_err(NULL, "failed to create netlink event thread (%d)", ret); + goto err_close_pipe; + } + + return LIBUSB_SUCCESS; + +err_close_pipe: + close(netlink_control_pipe[0]); + close(netlink_control_pipe[1]); + netlink_control_pipe[0] = -1; + netlink_control_pipe[1] = -1; +err_close_socket: + close(linux_netlink_socket); + linux_netlink_socket = -1; +err: + return LIBUSB_ERROR_OTHER; +} + +int linux_netlink_stop_event_monitor(void) +{ + char dummy = 1; + ssize_t r; + + assert(linux_netlink_socket != -1); + + /* Write some dummy data to the control pipe and + * wait for the thread to exit */ + r = write(netlink_control_pipe[1], &dummy, sizeof(dummy)); + if (r <= 0) + usbi_warn(NULL, "netlink control pipe signal failed"); + + pthread_join(libusb_linux_event_thread, NULL); + + close(linux_netlink_socket); + linux_netlink_socket = -1; + + /* close and reset control pipe */ + close(netlink_control_pipe[0]); + close(netlink_control_pipe[1]); + netlink_control_pipe[0] = -1; + netlink_control_pipe[1] = -1; + + return LIBUSB_SUCCESS; +} + +static const char *netlink_message_parse(const char *buffer, size_t len, const char *key) +{ + const char *end = buffer + len; + size_t keylen = strlen(key); + + while (buffer < end && *buffer) { + if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=') + return buffer + keylen + 1; + buffer += strlen(buffer) + 1; + } + + return NULL; +} + +/* parse parts of netlink message common to both libudev and the kernel */ +static int linux_netlink_parse(const char *buffer, size_t len, int *detached, + const char **sys_name, uint8_t *busnum, uint8_t *devaddr) +{ + const char *tmp, *slash; + + errno = 0; + + *sys_name = NULL; + *detached = 0; + *busnum = 0; + *devaddr = 0; + + tmp = netlink_message_parse(buffer, len, "ACTION"); + if (!tmp) { + return -1; + } else if (strcmp(tmp, "remove") == 0) { + *detached = 1; + } else if (strcmp(tmp, "add") != 0) { + usbi_dbg("unknown device action %s", tmp); + return -1; + } + + /* check that this is a usb message */ + tmp = netlink_message_parse(buffer, len, "SUBSYSTEM"); + if (!tmp || strcmp(tmp, "usb") != 0) { + /* not usb. ignore */ + return -1; + } + + /* check that this is an actual usb device */ + tmp = netlink_message_parse(buffer, len, "DEVTYPE"); + if (!tmp || strcmp(tmp, "usb_device") != 0) { + /* not usb. ignore */ + return -1; + } + + tmp = netlink_message_parse(buffer, len, "BUSNUM"); + if (tmp) { + *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + + tmp = netlink_message_parse(buffer, len, "DEVNUM"); + if (NULL == tmp) + return -1; + + *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + } else { + /* no bus number. try "DEVICE" */ + tmp = netlink_message_parse(buffer, len, "DEVICE"); + if (!tmp) { + /* not usb. ignore */ + return -1; + } + + /* Parse a device path such as /dev/bus/usb/003/004 */ + slash = strrchr(tmp, '/'); + if (!slash) + return -1; + + *busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + + *devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + + return 0; + } + + tmp = netlink_message_parse(buffer, len, "DEVPATH"); + if (!tmp) + return -1; + + slash = strrchr(tmp, '/'); + if (slash) + *sys_name = slash + 1; + + /* found a usb device */ + return 0; +} + +static int linux_netlink_read_message(void) +{ + char cred_buffer[CMSG_SPACE(sizeof(struct ucred))]; + char msg_buffer[2048]; + const char *sys_name = NULL; + uint8_t busnum, devaddr; + int detached, r; + ssize_t len; + struct cmsghdr *cmsg; + struct ucred *cred; + struct sockaddr_nl sa_nl; + struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) }; + struct msghdr msg = { + .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer), + .msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl) + }; + + /* read netlink message */ + len = recvmsg(linux_netlink_socket, &msg, 0); + if (len == -1) { + if (errno != EAGAIN && errno != EINTR) + usbi_err(NULL, "error receiving message from netlink (%d)", errno); + return -1; + } + + if (len < 32 || (msg.msg_flags & MSG_TRUNC)) { + usbi_err(NULL, "invalid netlink message length"); + return -1; + } + + if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) { + usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)", + (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid); + return -1; + } + + cmsg = CMSG_FIRSTHDR(&msg); + if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { + usbi_dbg("ignoring netlink message with no sender credentials"); + return -1; + } + + cred = (struct ucred *)CMSG_DATA(cmsg); + if (cred->uid != 0) { + usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid); + return -1; + } + + r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); + if (r) + return r; + + usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", + busnum, devaddr, sys_name, detached ? "yes" : "no"); + + /* signal device is available (or not) to all contexts */ + if (detached) + linux_device_disconnected(busnum, devaddr); + else + linux_hotplug_enumerate(busnum, devaddr, sys_name); + + return 0; +} + +static void *linux_netlink_event_thread_main(void *arg) +{ + char dummy; + int r; + ssize_t nb; + struct pollfd fds[] = { + { .fd = netlink_control_pipe[0], + .events = POLLIN }, + { .fd = linux_netlink_socket, + .events = POLLIN }, + }; + + UNUSED(arg); + + usbi_dbg("netlink event thread entering"); + + while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { + if (r < 0) { + /* temporary failure */ + continue; + } + if (fds[0].revents & POLLIN) { + /* activity on control pipe, read the byte and exit */ + nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) + usbi_warn(NULL, "netlink control pipe read failed"); + break; + } + if (fds[1].revents & POLLIN) { + usbi_mutex_static_lock(&linux_hotplug_lock); + linux_netlink_read_message(); + usbi_mutex_static_unlock(&linux_hotplug_lock); + } + } + + usbi_dbg("netlink event thread exiting"); + + return NULL; +} + +void linux_netlink_hotplug_poll(void) +{ + int r; + + usbi_mutex_static_lock(&linux_hotplug_lock); + do { + r = linux_netlink_read_message(); + } while (r == 0); + usbi_mutex_static_unlock(&linux_hotplug_lock); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c new file mode 100644 index 0000000000..c97806ba6b --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c @@ -0,0 +1,329 @@ +/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ +/* + * Linux usbfs backend for libusb + * Copyright (C) 2007-2009 Daniel Drake + * Copyright (c) 2001 Johannes Erdfelt + * Copyright (c) 2012-2013 Nathan Hjelm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "linux_usbfs.h" + +/* udev context */ +static struct udev *udev_ctx = NULL; +static int udev_monitor_fd = -1; +static int udev_control_pipe[2] = {-1, -1}; +static struct udev_monitor *udev_monitor = NULL; +static pthread_t linux_event_thread; + +static void udev_hotplug_event(struct udev_device* udev_dev); +static void *linux_udev_event_thread_main(void *arg); + +int linux_udev_start_event_monitor(void) +{ + int r; + + assert(udev_ctx == NULL); + udev_ctx = udev_new(); + if (!udev_ctx) { + usbi_err(NULL, "could not create udev context"); + goto err; + } + + udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev"); + if (!udev_monitor) { + usbi_err(NULL, "could not initialize udev monitor"); + goto err_free_ctx; + } + + r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device"); + if (r) { + usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem"); + goto err_free_monitor; + } + + if (udev_monitor_enable_receiving(udev_monitor)) { + usbi_err(NULL, "failed to enable the udev monitor"); + goto err_free_monitor; + } + + udev_monitor_fd = udev_monitor_get_fd(udev_monitor); + +#if defined(FD_CLOEXEC) + /* Make sure the udev file descriptor is marked as CLOEXEC */ + r = fcntl(udev_monitor_fd, F_GETFD); + if (r == -1) { + usbi_err(NULL, "geting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + if (!(r & FD_CLOEXEC)) { + if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) { + usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + } +#endif + + /* Some older versions of udev are not non-blocking by default, + * so make sure this is set */ + r = fcntl(udev_monitor_fd, F_GETFL); + if (r == -1) { + usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno); + goto err_free_monitor; + } + if (!(r & O_NONBLOCK)) { + if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) { + usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno); + goto err_free_monitor; + } + } + + r = usbi_pipe(udev_control_pipe); + if (r) { + usbi_err(NULL, "could not create udev control pipe"); + goto err_free_monitor; + } + + r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL); + if (r) { + usbi_err(NULL, "creating hotplug event thread (%d)", r); + goto err_close_pipe; + } + + return LIBUSB_SUCCESS; + +err_close_pipe: + close(udev_control_pipe[0]); + close(udev_control_pipe[1]); +err_free_monitor: + udev_monitor_unref(udev_monitor); + udev_monitor = NULL; + udev_monitor_fd = -1; +err_free_ctx: + udev_unref(udev_ctx); +err: + udev_ctx = NULL; + return LIBUSB_ERROR_OTHER; +} + +int linux_udev_stop_event_monitor(void) +{ + char dummy = 1; + int r; + + assert(udev_ctx != NULL); + assert(udev_monitor != NULL); + assert(udev_monitor_fd != -1); + + /* Write some dummy data to the control pipe and + * wait for the thread to exit */ + r = write(udev_control_pipe[1], &dummy, sizeof(dummy)); + if (r <= 0) { + usbi_warn(NULL, "udev control pipe signal failed"); + } + pthread_join(linux_event_thread, NULL); + + /* Release the udev monitor */ + udev_monitor_unref(udev_monitor); + udev_monitor = NULL; + udev_monitor_fd = -1; + + /* Clean up the udev context */ + udev_unref(udev_ctx); + udev_ctx = NULL; + + /* close and reset control pipe */ + close(udev_control_pipe[0]); + close(udev_control_pipe[1]); + udev_control_pipe[0] = -1; + udev_control_pipe[1] = -1; + + return LIBUSB_SUCCESS; +} + +static void *linux_udev_event_thread_main(void *arg) +{ + char dummy; + int r; + ssize_t nb; + struct udev_device* udev_dev; + struct pollfd fds[] = { + {.fd = udev_control_pipe[0], + .events = POLLIN}, + {.fd = udev_monitor_fd, + .events = POLLIN}, + }; + + usbi_dbg("udev event thread entering."); + + while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { + if (r < 0) { + /* temporary failure */ + continue; + } + if (fds[0].revents & POLLIN) { + /* activity on control pipe, read the byte and exit */ + nb = read(udev_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) { + usbi_warn(NULL, "udev control pipe read failed"); + } + break; + } + if (fds[1].revents & POLLIN) { + usbi_mutex_static_lock(&linux_hotplug_lock); + udev_dev = udev_monitor_receive_device(udev_monitor); + if (udev_dev) + udev_hotplug_event(udev_dev); + usbi_mutex_static_unlock(&linux_hotplug_lock); + } + } + + usbi_dbg("udev event thread exiting"); + + return NULL; +} + +static int udev_device_info(struct libusb_context *ctx, int detached, + struct udev_device *udev_dev, uint8_t *busnum, + uint8_t *devaddr, const char **sys_name) { + const char *dev_node; + + dev_node = udev_device_get_devnode(udev_dev); + if (!dev_node) { + return LIBUSB_ERROR_OTHER; + } + + *sys_name = udev_device_get_sysname(udev_dev); + if (!*sys_name) { + return LIBUSB_ERROR_OTHER; + } + + return linux_get_device_address(ctx, detached, busnum, devaddr, + dev_node, *sys_name); +} + +static void udev_hotplug_event(struct udev_device* udev_dev) +{ + const char* udev_action; + const char* sys_name = NULL; + uint8_t busnum = 0, devaddr = 0; + int detached; + int r; + + do { + udev_action = udev_device_get_action(udev_dev); + if (!udev_action) { + break; + } + + detached = !strncmp(udev_action, "remove", 6); + + r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name); + if (LIBUSB_SUCCESS != r) { + break; + } + + usbi_dbg("udev hotplug event. action: %s.", udev_action); + + if (strncmp(udev_action, "add", 3) == 0) { + linux_hotplug_enumerate(busnum, devaddr, sys_name); + } else if (detached) { + linux_device_disconnected(busnum, devaddr); + } else { + usbi_err(NULL, "ignoring udev action %s", udev_action); + } + } while (0); + + udev_device_unref(udev_dev); +} + +int linux_udev_scan_devices(struct libusb_context *ctx) +{ + struct udev_enumerate *enumerator; + struct udev_list_entry *devices, *entry; + struct udev_device *udev_dev; + const char *sys_name; + int r; + + assert(udev_ctx != NULL); + + enumerator = udev_enumerate_new(udev_ctx); + if (NULL == enumerator) { + usbi_err(ctx, "error creating udev enumerator"); + return LIBUSB_ERROR_OTHER; + } + + udev_enumerate_add_match_subsystem(enumerator, "usb"); + udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device"); + udev_enumerate_scan_devices(enumerator); + devices = udev_enumerate_get_list_entry(enumerator); + + entry = NULL; + udev_list_entry_foreach(entry, devices) { + const char *path = udev_list_entry_get_name(entry); + uint8_t busnum = 0, devaddr = 0; + + udev_dev = udev_device_new_from_syspath(udev_ctx, path); + + r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name); + if (r) { + udev_device_unref(udev_dev); + continue; + } + + linux_enumerate_device(ctx, busnum, devaddr, sys_name); + udev_device_unref(udev_dev); + } + + udev_enumerate_unref(enumerator); + + return LIBUSB_SUCCESS; +} + +void linux_udev_hotplug_poll(void) +{ + struct udev_device* udev_dev; + + usbi_mutex_static_lock(&linux_hotplug_lock); + do { + udev_dev = udev_monitor_receive_device(udev_monitor); + if (udev_dev) { + usbi_dbg("Handling hotplug event from hotplug_poll"); + udev_hotplug_event(udev_dev); + } + } while (udev_dev); + usbi_mutex_static_unlock(&linux_hotplug_lock); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c new file mode 100644 index 0000000000..768e7d5a64 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c @@ -0,0 +1,2800 @@ +/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ +/* + * Linux usbfs backend for libusb + * Copyright © 2007-2009 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * Copyright © 2013 Nathan Hjelm + * Copyright © 2012-2013 Hans de Goede + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "linux_usbfs.h" + +/* sysfs vs usbfs: + * opening a usbfs node causes the device to be resumed, so we attempt to + * avoid this during enumeration. + * + * sysfs allows us to read the kernel's in-memory copies of device descriptors + * and so forth, avoiding the need to open the device: + * - The binary "descriptors" file contains all config descriptors since + * 2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed + * - The binary "descriptors" file was added in 2.6.23, commit + * 69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the + * active config descriptors + * - The "busnum" file was added in 2.6.22, commit + * 83f7d958eab2fbc6b159ee92bf1493924e1d0f72 + * - The "devnum" file has been present since pre-2.6.18 + * - the "bConfigurationValue" file has been present since pre-2.6.18 + * + * If we have bConfigurationValue, busnum, and devnum, then we can determine + * the active configuration without having to open the usbfs node in RDWR mode. + * The busnum file is important as that is the only way we can relate sysfs + * devices to usbfs nodes. + * + * If we also have all descriptors, we can obtain the device descriptor and + * configuration without touching usbfs at all. + */ + +/* endianness for multi-byte fields: + * + * Descriptors exposed by usbfs have the multi-byte fields in the device + * descriptor as host endian. Multi-byte fields in the other descriptors are + * bus-endian. The kernel documentation says otherwise, but it is wrong. + * + * In sysfs all descriptors are bus-endian. + */ + +static const char *usbfs_path = NULL; + +/* use usbdev*.* device names in /dev instead of the usbfs bus directories */ +static int usbdev_names = 0; + +/* Linux has changed the maximum length of an individual isochronous packet + * over time. Initially this limit was 1,023 bytes, but Linux 2.6.18 + * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to + * 8,192 bytes to support higher bandwidth devices. Linux 3.10 + * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this + * value to 49,152 bytes to support super speed devices. + */ +static unsigned int max_iso_packet_len = 0; + +/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the + * close-on-exec flag in the underlying file descriptor. */ +static int supports_flag_cloexec = -1; + +/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically + * allows us to mark URBs as being part of a specific logical transfer when + * we submit them to the kernel. then, on any error except a cancellation, all + * URBs within that transfer will be cancelled and no more URBs will be + * accepted for the transfer, meaning that no more data can creep in. + * + * The BULK_CONTINUATION flag must be set on all URBs within a bulk transfer + * (in either direction) except the first. + * For IN transfers, we must also set SHORT_NOT_OK on all URBs except the + * last; it means that the kernel should treat a short reply as an error. + * For OUT transfers, SHORT_NOT_OK must not be set. it isn't needed (OUT + * transfers can't be short unless there's already some sort of error), and + * setting this flag is disallowed (a kernel with USB debugging enabled will + * reject such URBs). + */ +static int supports_flag_bulk_continuation = -1; + +/* Linux 2.6.31 fixes support for the zero length packet URB flag. This + * allows us to mark URBs that should be followed by a zero length data + * packet, which can be required by device- or class-specific protocols. + */ +static int supports_flag_zero_packet = -1; + +/* clock ID for monotonic clock, as not all clock sources are available on all + * systems. appropriate choice made at initialization time. */ +static clockid_t monotonic_clkid = -1; + +/* Linux 2.6.22 (commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72) adds a busnum + * to sysfs, so we can relate devices. This also implies that we can read + * the active configuration through bConfigurationValue */ +static int sysfs_can_relate_devices = -1; + +/* Linux 2.6.26 (commit 217a9081d8e69026186067711131b77f0ce219ed) adds all + * config descriptors (rather then just the active config) to the sysfs + * descriptors file, so from then on we can use them. */ +static int sysfs_has_descriptors = -1; + +/* how many times have we initted (and not exited) ? */ +static int init_count = 0; + +/* Serialize hotplug start/stop */ +static usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER; +/* Serialize scan-devices, event-thread, and poll */ +usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER; + +static int linux_start_event_monitor(void); +static int linux_stop_event_monitor(void); +static int linux_scan_devices(struct libusb_context *ctx); +static int sysfs_scan_device(struct libusb_context *ctx, const char *devname); +static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int); + +#if !defined(USE_UDEV) +static int linux_default_scan_devices (struct libusb_context *ctx); +#endif + +struct kernel_version { + int major; + int minor; + int sublevel; +}; + +struct linux_device_priv { + char *sysfs_dir; + unsigned char *descriptors; + int descriptors_len; + int active_config; /* cache val for !sysfs_can_relate_devices */ +}; + +struct linux_device_handle_priv { + int fd; + int fd_removed; + uint32_t caps; +}; + +enum reap_action { + NORMAL = 0, + /* submission failed after the first URB, so await cancellation/completion + * of all the others */ + SUBMIT_FAILED, + + /* cancelled by user or timeout */ + CANCELLED, + + /* completed multi-URB transfer in non-final URB */ + COMPLETED_EARLY, + + /* one or more urbs encountered a low-level error */ + ERROR, +}; + +struct linux_transfer_priv { + union { + struct usbfs_urb *urbs; + struct usbfs_urb **iso_urbs; + }; + + enum reap_action reap_action; + int num_urbs; + int num_retired; + enum libusb_transfer_status reap_status; + + /* next iso packet in user-supplied transfer to be populated */ + int iso_packet_offset; +}; + +static int _open(const char *path, int flags) +{ +#if defined(O_CLOEXEC) + if (supports_flag_cloexec) + return open(path, flags | O_CLOEXEC); + else +#endif + return open(path, flags); +} + +static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + char path[PATH_MAX]; + int fd; + int delay = 10000; + + if (usbdev_names) + snprintf(path, PATH_MAX, "%s/usbdev%d.%d", + usbfs_path, dev->bus_number, dev->device_address); + else + snprintf(path, PATH_MAX, "%s/%03d/%03d", + usbfs_path, dev->bus_number, dev->device_address); + + fd = _open(path, mode); + if (fd != -1) + return fd; /* Success */ + + if (errno == ENOENT) { + if (!silent) + usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000); + + /* Wait 10ms for USB device path creation.*/ + nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); + + fd = _open(path, mode); + if (fd != -1) + return fd; /* Success */ + } + + if (!silent) { + usbi_err(ctx, "libusb couldn't open USB device %s: %s", + path, strerror(errno)); + if (errno == EACCES && mode == O_RDWR) + usbi_err(ctx, "libusb requires write access to USB " + "device nodes."); + } + + if (errno == EACCES) + return LIBUSB_ERROR_ACCESS; + if (errno == ENOENT) + return LIBUSB_ERROR_NO_DEVICE; + return LIBUSB_ERROR_IO; +} + +static struct linux_device_priv *_device_priv(struct libusb_device *dev) +{ + return (struct linux_device_priv *) dev->os_priv; +} + +static struct linux_device_handle_priv *_device_handle_priv( + struct libusb_device_handle *handle) +{ + return (struct linux_device_handle_priv *) handle->os_priv; +} + +/* check dirent for a /dev/usbdev%d.%d name + * optionally return bus/device on success */ +static int _is_usbdev_entry(struct dirent *entry, int *bus_p, int *dev_p) +{ + int busnum, devnum; + + if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2) + return 0; + + usbi_dbg("found: %s", entry->d_name); + if (bus_p != NULL) + *bus_p = busnum; + if (dev_p != NULL) + *dev_p = devnum; + return 1; +} + +static int check_usb_vfs(const char *dirname) +{ + DIR *dir; + struct dirent *entry; + int found = 0; + + dir = opendir(dirname); + if (!dir) + return 0; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_name[0] == '.') + continue; + + /* We assume if we find any files that it must be the right place */ + found = 1; + break; + } + + closedir(dir); + return found; +} + +static const char *find_usbfs_path(void) +{ + const char *path = "/dev/bus/usb"; + const char *ret = NULL; + + if (check_usb_vfs(path)) { + ret = path; + } else { + path = "/proc/bus/usb"; + if (check_usb_vfs(path)) + ret = path; + } + + /* look for /dev/usbdev*.* if the normal places fail */ + if (ret == NULL) { + struct dirent *entry; + DIR *dir; + + path = "/dev"; + dir = opendir(path); + if (dir != NULL) { + while ((entry = readdir(dir)) != NULL) { + if (_is_usbdev_entry(entry, NULL, NULL)) { + /* found one; that's enough */ + ret = path; + usbdev_names = 1; + break; + } + } + closedir(dir); + } + } + +/* On udev based systems without any usb-devices /dev/bus/usb will not + * exist. So if we've not found anything and we're using udev for hotplug + * simply assume /dev/bus/usb rather then making libusb_init fail. */ +#if defined(USE_UDEV) + if (ret == NULL) + ret = "/dev/bus/usb"; +#endif + + if (ret != NULL) + usbi_dbg("found usbfs at %s", ret); + + return ret; +} + +/* the monotonic clock is not usable on all systems (e.g. embedded ones often + * seem to lack it). fall back to REALTIME if we have to. */ +static clockid_t find_monotonic_clock(void) +{ +#ifdef CLOCK_MONOTONIC + struct timespec ts; + int r; + + /* Linux 2.6.28 adds CLOCK_MONOTONIC_RAW but we don't use it + * because it's not available through timerfd */ + r = clock_gettime(CLOCK_MONOTONIC, &ts); + if (r == 0) + return CLOCK_MONOTONIC; + usbi_dbg("monotonic clock doesn't work, errno %d", errno); +#endif + + return CLOCK_REALTIME; +} + +static int get_kernel_version(struct libusb_context *ctx, + struct kernel_version *ver) +{ + struct utsname uts; + int atoms; + + if (uname(&uts) < 0) { + usbi_err(ctx, "uname failed, errno %d", errno); + return -1; + } + + atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel); + if (atoms < 1) { + usbi_err(ctx, "failed to parse uname release '%s'", uts.release); + return -1; + } + + if (atoms < 2) + ver->minor = -1; + if (atoms < 3) + ver->sublevel = -1; + + usbi_dbg("reported kernel version is %s", uts.release); + + return 0; +} + +static int kernel_version_ge(const struct kernel_version *ver, + int major, int minor, int sublevel) +{ + if (ver->major > major) + return 1; + else if (ver->major < major) + return 0; + + /* kmajor == major */ + if (ver->minor == -1 && ver->sublevel == -1) + return 0 == minor && 0 == sublevel; + else if (ver->minor > minor) + return 1; + else if (ver->minor < minor) + return 0; + + /* kminor == minor */ + if (ver->sublevel == -1) + return 0 == sublevel; + + return ver->sublevel >= sublevel; +} + +static int op_init(struct libusb_context *ctx) +{ + struct kernel_version kversion; + struct stat statbuf; + int r; + + usbfs_path = find_usbfs_path(); + if (!usbfs_path) { + usbi_err(ctx, "could not find usbfs"); + return LIBUSB_ERROR_OTHER; + } + + if (monotonic_clkid == -1) + monotonic_clkid = find_monotonic_clock(); + + if (get_kernel_version(ctx, &kversion) < 0) + return LIBUSB_ERROR_OTHER; + + if (supports_flag_cloexec == -1) { + /* O_CLOEXEC flag available from Linux 2.6.23 */ + supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23); + } + + if (supports_flag_bulk_continuation == -1) { + /* bulk continuation URB flag available from Linux 2.6.32 */ + supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32); + } + + if (supports_flag_bulk_continuation) + usbi_dbg("bulk continuation flag supported"); + + if (-1 == supports_flag_zero_packet) { + /* zero length packet URB flag fixed since Linux 2.6.31 */ + supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31); + } + + if (supports_flag_zero_packet) + usbi_dbg("zero length packet flag supported"); + + if (!max_iso_packet_len) { + if (kernel_version_ge(&kversion,3,10,0)) + max_iso_packet_len = 49152; + else if (kernel_version_ge(&kversion,2,6,18)) + max_iso_packet_len = 8192; + else + max_iso_packet_len = 1023; + } + + usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len); + + if (-1 == sysfs_has_descriptors) { + /* sysfs descriptors has all descriptors since Linux 2.6.26 */ + sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26); + } + + if (-1 == sysfs_can_relate_devices) { + /* sysfs has busnum since Linux 2.6.22 */ + sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22); + } + + if (sysfs_can_relate_devices || sysfs_has_descriptors) { + r = stat(SYSFS_DEVICE_PATH, &statbuf); + if (r != 0 || !S_ISDIR(statbuf.st_mode)) { + usbi_warn(ctx, "sysfs not mounted"); + sysfs_can_relate_devices = 0; + sysfs_has_descriptors = 0; + } + } + + if (sysfs_can_relate_devices) + usbi_dbg("sysfs can relate devices"); + + if (sysfs_has_descriptors) + usbi_dbg("sysfs has complete descriptors"); + + usbi_mutex_static_lock(&linux_hotplug_startstop_lock); + r = LIBUSB_SUCCESS; + if (init_count == 0) { + /* start up hotplug event handler */ + r = linux_start_event_monitor(); + } + if (r == LIBUSB_SUCCESS) { + r = linux_scan_devices(ctx); + if (r == LIBUSB_SUCCESS) + init_count++; + else if (init_count == 0) + linux_stop_event_monitor(); + } else + usbi_err(ctx, "error starting hotplug event monitor"); + usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); + + return r; +} + +static void op_exit(struct libusb_context *ctx) +{ + UNUSED(ctx); + usbi_mutex_static_lock(&linux_hotplug_startstop_lock); + assert(init_count != 0); + if (!--init_count) { + /* tear down event handler */ + (void)linux_stop_event_monitor(); + } + usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); +} + +static int linux_start_event_monitor(void) +{ +#if defined(USE_UDEV) + return linux_udev_start_event_monitor(); +#else + return linux_netlink_start_event_monitor(); +#endif +} + +static int linux_stop_event_monitor(void) +{ +#if defined(USE_UDEV) + return linux_udev_stop_event_monitor(); +#else + return linux_netlink_stop_event_monitor(); +#endif +} + +static int linux_scan_devices(struct libusb_context *ctx) +{ + int ret; + + usbi_mutex_static_lock(&linux_hotplug_lock); + +#if defined(USE_UDEV) + ret = linux_udev_scan_devices(ctx); +#else + ret = linux_default_scan_devices(ctx); +#endif + + usbi_mutex_static_unlock(&linux_hotplug_lock); + + return ret; +} + +static void op_hotplug_poll(void) +{ +#if defined(USE_UDEV) + linux_udev_hotplug_poll(); +#else + linux_netlink_hotplug_poll(); +#endif +} + +static int _open_sysfs_attr(struct libusb_device *dev, const char *attr) +{ + struct linux_device_priv *priv = _device_priv(dev); + char filename[PATH_MAX]; + int fd; + + snprintf(filename, PATH_MAX, "%s/%s/%s", + SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); + fd = _open(filename, O_RDONLY); + if (fd < 0) { + usbi_err(DEVICE_CTX(dev), + "open %s failed ret=%d errno=%d", filename, fd, errno); + return LIBUSB_ERROR_IO; + } + + return fd; +} + +/* Note only suitable for attributes which always read >= 0, < 0 is error */ +static int __read_sysfs_attr(struct libusb_context *ctx, + const char *devname, const char *attr) +{ + char filename[PATH_MAX]; + FILE *f; + int fd, r, value; + + snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, + devname, attr); + fd = _open(filename, O_RDONLY); + if (fd == -1) { + if (errno == ENOENT) { + /* File doesn't exist. Assume the device has been + disconnected (see trac ticket #70). */ + return LIBUSB_ERROR_NO_DEVICE; + } + usbi_err(ctx, "open %s failed errno=%d", filename, errno); + return LIBUSB_ERROR_IO; + } + + f = fdopen(fd, "r"); + if (f == NULL) { + usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno); + close(fd); + return LIBUSB_ERROR_OTHER; + } + + r = fscanf(f, "%d", &value); + fclose(f); + if (r != 1) { + usbi_err(ctx, "fscanf %s returned %d, errno=%d", attr, r, errno); + return LIBUSB_ERROR_NO_DEVICE; /* For unplug race (trac #70) */ + } + if (value < 0) { + usbi_err(ctx, "%s contains a negative value", filename); + return LIBUSB_ERROR_IO; + } + + return value; +} + +static int op_get_device_descriptor(struct libusb_device *dev, + unsigned char *buffer, int *host_endian) +{ + struct linux_device_priv *priv = _device_priv(dev); + + *host_endian = sysfs_has_descriptors ? 0 : 1; + memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH); + + return 0; +} + +/* read the bConfigurationValue for a device */ +static int sysfs_get_active_config(struct libusb_device *dev, int *config) +{ + char *endptr; + char tmp[5] = {0, 0, 0, 0, 0}; + long num; + int fd; + ssize_t r; + + fd = _open_sysfs_attr(dev, "bConfigurationValue"); + if (fd < 0) + return fd; + + r = read(fd, tmp, sizeof(tmp)); + close(fd); + if (r < 0) { + usbi_err(DEVICE_CTX(dev), + "read bConfigurationValue failed ret=%d errno=%d", r, errno); + return LIBUSB_ERROR_IO; + } else if (r == 0) { + usbi_dbg("device unconfigured"); + *config = -1; + return 0; + } + + if (tmp[sizeof(tmp) - 1] != 0) { + usbi_err(DEVICE_CTX(dev), "not null-terminated?"); + return LIBUSB_ERROR_IO; + } else if (tmp[0] == 0) { + usbi_err(DEVICE_CTX(dev), "no configuration value?"); + return LIBUSB_ERROR_IO; + } + + num = strtol(tmp, &endptr, 10); + if (endptr == tmp) { + usbi_err(DEVICE_CTX(dev), "error converting '%s' to integer", tmp); + return LIBUSB_ERROR_IO; + } + + *config = (int) num; + return 0; +} + +int linux_get_device_address (struct libusb_context *ctx, int detached, + uint8_t *busnum, uint8_t *devaddr,const char *dev_node, + const char *sys_name) +{ + int sysfs_attr; + + usbi_dbg("getting address for device: %s detached: %d", sys_name, detached); + /* can't use sysfs to read the bus and device number if the + * device has been detached */ + if (!sysfs_can_relate_devices || detached || NULL == sys_name) { + if (NULL == dev_node) { + return LIBUSB_ERROR_OTHER; + } + + /* will this work with all supported kernel versions? */ + if (!strncmp(dev_node, "/dev/bus/usb", 12)) { + sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr); + } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { + sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr); + } + + return LIBUSB_SUCCESS; + } + + usbi_dbg("scan %s", sys_name); + + sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum"); + if (0 > sysfs_attr) + return sysfs_attr; + if (sysfs_attr > 255) + return LIBUSB_ERROR_INVALID_PARAM; + *busnum = (uint8_t) sysfs_attr; + + sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum"); + if (0 > sysfs_attr) + return sysfs_attr; + if (sysfs_attr > 255) + return LIBUSB_ERROR_INVALID_PARAM; + + *devaddr = (uint8_t) sysfs_attr; + + usbi_dbg("bus=%d dev=%d", *busnum, *devaddr); + + return LIBUSB_SUCCESS; +} + +/* Return offset of the next descriptor with the given type */ +static int seek_to_next_descriptor(struct libusb_context *ctx, + uint8_t descriptor_type, unsigned char *buffer, int size) +{ + struct usb_descriptor_header header; + int i; + + for (i = 0; size >= 0; i += header.bLength, size -= header.bLength) { + if (size == 0) + return LIBUSB_ERROR_NOT_FOUND; + + if (size < 2) { + usbi_err(ctx, "short descriptor read %d/2", size); + return LIBUSB_ERROR_IO; + } + usbi_parse_descriptor(buffer + i, "bb", &header, 0); + + if (i && header.bDescriptorType == descriptor_type) + return i; + } + usbi_err(ctx, "bLength overflow by %d bytes", -size); + return LIBUSB_ERROR_IO; +} + +/* Return offset to next config */ +static int seek_to_next_config(struct libusb_context *ctx, + unsigned char *buffer, int size) +{ + struct libusb_config_descriptor config; + + if (size == 0) + return LIBUSB_ERROR_NOT_FOUND; + + if (size < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(ctx, "short descriptor read %d/%d", + size, LIBUSB_DT_CONFIG_SIZE); + return LIBUSB_ERROR_IO; + } + + usbi_parse_descriptor(buffer, "bbwbbbbb", &config, 0); + if (config.bDescriptorType != LIBUSB_DT_CONFIG) { + usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)", + config.bDescriptorType); + return LIBUSB_ERROR_IO; + } + + /* + * In usbfs the config descriptors are config.wTotalLength bytes apart, + * with any short reads from the device appearing as holes in the file. + * + * In sysfs wTotalLength is ignored, instead the kernel returns a + * config descriptor with verified bLength fields, with descriptors + * with an invalid bLength removed. + */ + if (sysfs_has_descriptors) { + int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG, + buffer, size); + if (next == LIBUSB_ERROR_NOT_FOUND) + next = size; + if (next < 0) + return next; + + if (next != config.wTotalLength) + usbi_warn(ctx, "config length mismatch wTotalLength " + "%d real %d", config.wTotalLength, next); + return next; + } else { + if (config.wTotalLength < LIBUSB_DT_CONFIG_SIZE) { + usbi_err(ctx, "invalid wTotalLength %d", + config.wTotalLength); + return LIBUSB_ERROR_IO; + } else if (config.wTotalLength > size) { + usbi_warn(ctx, "short descriptor read %d/%d", + size, config.wTotalLength); + return size; + } else + return config.wTotalLength; + } +} + +static int op_get_config_descriptor_by_value(struct libusb_device *dev, + uint8_t value, unsigned char **buffer, int *host_endian) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + struct linux_device_priv *priv = _device_priv(dev); + unsigned char *descriptors = priv->descriptors; + int size = priv->descriptors_len; + struct libusb_config_descriptor *config; + + *buffer = NULL; + /* Unlike the device desc. config descs. are always in raw format */ + *host_endian = 0; + + /* Skip device header */ + descriptors += DEVICE_DESC_LENGTH; + size -= DEVICE_DESC_LENGTH; + + /* Seek till the config is found, or till "EOF" */ + while (1) { + int next = seek_to_next_config(ctx, descriptors, size); + if (next < 0) + return next; + config = (struct libusb_config_descriptor *)descriptors; + if (config->bConfigurationValue == value) { + *buffer = descriptors; + return next; + } + size -= next; + descriptors += next; + } +} + +static int op_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buffer, size_t len, int *host_endian) +{ + int r, config; + unsigned char *config_desc; + + if (sysfs_can_relate_devices) { + r = sysfs_get_active_config(dev, &config); + if (r < 0) + return r; + } else { + /* Use cached bConfigurationValue */ + struct linux_device_priv *priv = _device_priv(dev); + config = priv->active_config; + } + if (config == -1) + return LIBUSB_ERROR_NOT_FOUND; + + r = op_get_config_descriptor_by_value(dev, config, &config_desc, + host_endian); + if (r < 0) + return r; + + len = MIN(len, (size_t)r); + memcpy(buffer, config_desc, len); + return len; +} + +static int op_get_config_descriptor(struct libusb_device *dev, + uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + struct linux_device_priv *priv = _device_priv(dev); + unsigned char *descriptors = priv->descriptors; + int i, r, size = priv->descriptors_len; + + /* Unlike the device desc. config descs. are always in raw format */ + *host_endian = 0; + + /* Skip device header */ + descriptors += DEVICE_DESC_LENGTH; + size -= DEVICE_DESC_LENGTH; + + /* Seek till the config is found, or till "EOF" */ + for (i = 0; ; i++) { + r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size); + if (r < 0) + return r; + if (i == config_index) + break; + size -= r; + descriptors += r; + } + + len = MIN(len, (size_t)r); + memcpy(buffer, descriptors, len); + return len; +} + +/* send a control message to retrieve active configuration */ +static int usbfs_get_active_config(struct libusb_device *dev, int fd) +{ + struct linux_device_priv *priv = _device_priv(dev); + unsigned char active_config = 0; + int r; + + struct usbfs_ctrltransfer ctrl = { + .bmRequestType = LIBUSB_ENDPOINT_IN, + .bRequest = LIBUSB_REQUEST_GET_CONFIGURATION, + .wValue = 0, + .wIndex = 0, + .wLength = 1, + .timeout = 1000, + .data = &active_config + }; + + r = ioctl(fd, IOCTL_USBFS_CONTROL, &ctrl); + if (r < 0) { + if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + /* we hit this error path frequently with buggy devices :( */ + usbi_warn(DEVICE_CTX(dev), + "get_configuration failed ret=%d errno=%d", r, errno); + priv->active_config = -1; + } else { + if (active_config > 0) { + priv->active_config = active_config; + } else { + /* some buggy devices have a configuration 0, but we're + * reaching into the corner of a corner case here, so let's + * not support buggy devices in these circumstances. + * stick to the specs: a configuration value of 0 means + * unconfigured. */ + usbi_warn(DEVICE_CTX(dev), + "active cfg 0? assuming unconfigured device"); + priv->active_config = -1; + } + } + + return LIBUSB_SUCCESS; +} + +static int initialize_device(struct libusb_device *dev, uint8_t busnum, + uint8_t devaddr, const char *sysfs_dir) +{ + struct linux_device_priv *priv = _device_priv(dev); + struct libusb_context *ctx = DEVICE_CTX(dev); + int descriptors_size = 512; /* Begin with a 1024 byte alloc */ + int fd, speed; + ssize_t r; + + dev->bus_number = busnum; + dev->device_address = devaddr; + + if (sysfs_dir) { + priv->sysfs_dir = strdup(sysfs_dir); + if (!priv->sysfs_dir) + return LIBUSB_ERROR_NO_MEM; + + /* Note speed can contain 1.5, in this case __read_sysfs_attr + will stop parsing at the '.' and return 1 */ + speed = __read_sysfs_attr(DEVICE_CTX(dev), sysfs_dir, "speed"); + if (speed >= 0) { + switch (speed) { + case 1: dev->speed = LIBUSB_SPEED_LOW; break; + case 12: dev->speed = LIBUSB_SPEED_FULL; break; + case 480: dev->speed = LIBUSB_SPEED_HIGH; break; + case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; + case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; + default: + usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); + } + } + } + + /* cache descriptors in memory */ + if (sysfs_has_descriptors) + fd = _open_sysfs_attr(dev, "descriptors"); + else + fd = _get_usbfs_fd(dev, O_RDONLY, 0); + if (fd < 0) + return fd; + + do { + descriptors_size *= 2; + priv->descriptors = usbi_reallocf(priv->descriptors, + descriptors_size); + if (!priv->descriptors) { + close(fd); + return LIBUSB_ERROR_NO_MEM; + } + /* usbfs has holes in the file */ + if (!sysfs_has_descriptors) { + memset(priv->descriptors + priv->descriptors_len, + 0, descriptors_size - priv->descriptors_len); + } + r = read(fd, priv->descriptors + priv->descriptors_len, + descriptors_size - priv->descriptors_len); + if (r < 0) { + usbi_err(ctx, "read descriptor failed ret=%d errno=%d", + fd, errno); + close(fd); + return LIBUSB_ERROR_IO; + } + priv->descriptors_len += r; + } while (priv->descriptors_len == descriptors_size); + + close(fd); + + if (priv->descriptors_len < DEVICE_DESC_LENGTH) { + usbi_err(ctx, "short descriptor read (%d)", + priv->descriptors_len); + return LIBUSB_ERROR_IO; + } + + if (sysfs_can_relate_devices) + return LIBUSB_SUCCESS; + + /* cache active config */ + fd = _get_usbfs_fd(dev, O_RDWR, 1); + if (fd < 0) { + /* cannot send a control message to determine the active + * config. just assume the first one is active. */ + usbi_warn(ctx, "Missing rw usbfs access; cannot determine " + "active configuration descriptor"); + if (priv->descriptors_len >= + (DEVICE_DESC_LENGTH + LIBUSB_DT_CONFIG_SIZE)) { + struct libusb_config_descriptor config; + usbi_parse_descriptor( + priv->descriptors + DEVICE_DESC_LENGTH, + "bbwbbbbb", &config, 0); + priv->active_config = config.bConfigurationValue; + } else + priv->active_config = -1; /* No config dt */ + + return LIBUSB_SUCCESS; + } + + r = usbfs_get_active_config(dev, fd); + close(fd); + + return r; +} + +static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + struct libusb_device *it; + char *parent_sysfs_dir, *tmp; + int ret, add_parent = 1; + + /* XXX -- can we figure out the topology when using usbfs? */ + if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) { + /* either using usbfs or finding the parent of a root hub */ + return LIBUSB_SUCCESS; + } + + parent_sysfs_dir = strdup(sysfs_dir); + if (NULL == parent_sysfs_dir) { + return LIBUSB_ERROR_NO_MEM; + } + if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) || + NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) { + dev->port_number = atoi(tmp + 1); + *tmp = '\0'; + } else { + usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info", + parent_sysfs_dir); + free (parent_sysfs_dir); + return LIBUSB_SUCCESS; + } + + /* is the parent a root hub? */ + if (NULL == strchr(parent_sysfs_dir, '-')) { + tmp = parent_sysfs_dir; + ret = asprintf (&parent_sysfs_dir, "usb%s", tmp); + free (tmp); + if (0 > ret) { + return LIBUSB_ERROR_NO_MEM; + } + } + +retry: + /* find the parent in the context */ + usbi_mutex_lock(&ctx->usb_devs_lock); + list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) { + struct linux_device_priv *priv = _device_priv(it); + if (priv->sysfs_dir) { + if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { + dev->parent_dev = libusb_ref_device(it); + break; + } + } + } + usbi_mutex_unlock(&ctx->usb_devs_lock); + + if (!dev->parent_dev && add_parent) { + usbi_dbg("parent_dev %s not enumerated yet, enumerating now", + parent_sysfs_dir); + sysfs_scan_device(ctx, parent_sysfs_dir); + add_parent = 0; + goto retry; + } + + usbi_dbg("Dev %p (%s) has parent %p (%s) port %d", dev, sysfs_dir, + dev->parent_dev, parent_sysfs_dir, dev->port_number); + + free (parent_sysfs_dir); + + return LIBUSB_SUCCESS; +} + +int linux_enumerate_device(struct libusb_context *ctx, + uint8_t busnum, uint8_t devaddr, const char *sysfs_dir) +{ + unsigned long session_id; + struct libusb_device *dev; + int r = 0; + + /* FIXME: session ID is not guaranteed unique as addresses can wrap and + * will be reused. instead we should add a simple sysfs attribute with + * a session ID. */ + session_id = busnum << 8 | devaddr; + usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr, + session_id); + + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev) { + /* device already exists in the context */ + usbi_dbg("session_id %ld already exists", session_id); + libusb_unref_device(dev); + return LIBUSB_SUCCESS; + } + + usbi_dbg("allocating new device for %d/%d (session %ld)", + busnum, devaddr, session_id); + dev = usbi_alloc_device(ctx, session_id); + if (!dev) + return LIBUSB_ERROR_NO_MEM; + + r = initialize_device(dev, busnum, devaddr, sysfs_dir); + if (r < 0) + goto out; + r = usbi_sanitize_device(dev); + if (r < 0) + goto out; + + r = linux_get_parent_info(dev, sysfs_dir); + if (r < 0) + goto out; +out: + if (r < 0) + libusb_unref_device(dev); + else + usbi_connect_device(dev); + + return r; +} + +void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name) +{ + struct libusb_context *ctx; + + usbi_mutex_static_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + linux_enumerate_device(ctx, busnum, devaddr, sys_name); + } + usbi_mutex_static_unlock(&active_contexts_lock); +} + +void linux_device_disconnected(uint8_t busnum, uint8_t devaddr) +{ + struct libusb_context *ctx; + struct libusb_device *dev; + unsigned long session_id = busnum << 8 | devaddr; + + usbi_mutex_static_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + dev = usbi_get_device_by_session_id (ctx, session_id); + if (NULL != dev) { + usbi_disconnect_device (dev); + libusb_unref_device(dev); + } else { + usbi_dbg("device not found for session %x", session_id); + } + } + usbi_mutex_static_unlock(&active_contexts_lock); +} + +#if !defined(USE_UDEV) +/* open a bus directory and adds all discovered devices to the context */ +static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum) +{ + DIR *dir; + char dirpath[PATH_MAX]; + struct dirent *entry; + int r = LIBUSB_ERROR_IO; + + snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum); + usbi_dbg("%s", dirpath); + dir = opendir(dirpath); + if (!dir) { + usbi_err(ctx, "opendir '%s' failed, errno=%d", dirpath, errno); + /* FIXME: should handle valid race conditions like hub unplugged + * during directory iteration - this is not an error */ + return r; + } + + while ((entry = readdir(dir))) { + int devaddr; + + if (entry->d_name[0] == '.') + continue; + + devaddr = atoi(entry->d_name); + if (devaddr == 0) { + usbi_dbg("unknown dir entry %s", entry->d_name); + continue; + } + + if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) { + usbi_dbg("failed to enumerate dir entry %s", entry->d_name); + continue; + } + + r = 0; + } + + closedir(dir); + return r; +} + +static int usbfs_get_device_list(struct libusb_context *ctx) +{ + struct dirent *entry; + DIR *buses = opendir(usbfs_path); + int r = 0; + + if (!buses) { + usbi_err(ctx, "opendir buses failed errno=%d", errno); + return LIBUSB_ERROR_IO; + } + + while ((entry = readdir(buses))) { + int busnum; + + if (entry->d_name[0] == '.') + continue; + + if (usbdev_names) { + int devaddr; + if (!_is_usbdev_entry(entry, &busnum, &devaddr)) + continue; + + r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL); + if (r < 0) { + usbi_dbg("failed to enumerate dir entry %s", entry->d_name); + continue; + } + } else { + busnum = atoi(entry->d_name); + if (busnum == 0) { + usbi_dbg("unknown dir entry %s", entry->d_name); + continue; + } + + r = usbfs_scan_busdir(ctx, busnum); + if (r < 0) + break; + } + } + + closedir(buses); + return r; + +} +#endif + +static int sysfs_scan_device(struct libusb_context *ctx, const char *devname) +{ + uint8_t busnum, devaddr; + int ret; + + ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname); + if (LIBUSB_SUCCESS != ret) { + return ret; + } + + return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff, + devname); +} + +#if !defined(USE_UDEV) +static int sysfs_get_device_list(struct libusb_context *ctx) +{ + DIR *devices = opendir(SYSFS_DEVICE_PATH); + struct dirent *entry; + int num_devices = 0; + int num_enumerated = 0; + + if (!devices) { + usbi_err(ctx, "opendir devices failed errno=%d", errno); + return LIBUSB_ERROR_IO; + } + + while ((entry = readdir(devices))) { + if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3)) + || strchr(entry->d_name, ':')) + continue; + + num_devices++; + + if (sysfs_scan_device(ctx, entry->d_name)) { + usbi_dbg("failed to enumerate dir entry %s", entry->d_name); + continue; + } + + num_enumerated++; + } + + closedir(devices); + + /* successful if at least one device was enumerated or no devices were found */ + if (num_enumerated || !num_devices) + return LIBUSB_SUCCESS; + else + return LIBUSB_ERROR_IO; +} + +static int linux_default_scan_devices (struct libusb_context *ctx) +{ + /* we can retrieve device list and descriptors from sysfs or usbfs. + * sysfs is preferable, because if we use usbfs we end up resuming + * any autosuspended USB devices. however, sysfs is not available + * everywhere, so we need a usbfs fallback too. + * + * as described in the "sysfs vs usbfs" comment at the top of this + * file, sometimes we have sysfs but not enough information to + * relate sysfs devices to usbfs nodes. op_init() determines the + * adequacy of sysfs and sets sysfs_can_relate_devices. + */ + if (sysfs_can_relate_devices != 0) + return sysfs_get_device_list(ctx); + else + return usbfs_get_device_list(ctx); +} +#endif + +static int op_open(struct libusb_device_handle *handle) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); + int r; + + hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); + if (hpriv->fd < 0) { + if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) { + /* device will still be marked as attached if hotplug monitor thread + * hasn't processed remove event yet */ + usbi_mutex_static_lock(&linux_hotplug_lock); + if (handle->dev->attached) { + usbi_dbg("open failed with no device, but device still attached"); + linux_device_disconnected(handle->dev->bus_number, + handle->dev->device_address); + } + usbi_mutex_static_unlock(&linux_hotplug_lock); + } + return hpriv->fd; + } + + r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); + if (r < 0) { + if (errno == ENOTTY) + usbi_dbg("getcap not available"); + else + usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno); + hpriv->caps = 0; + if (supports_flag_zero_packet) + hpriv->caps |= USBFS_CAP_ZERO_PACKET; + if (supports_flag_bulk_continuation) + hpriv->caps |= USBFS_CAP_BULK_CONTINUATION; + } + + r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); + if (r < 0) + close(hpriv->fd); + + return r; +} + +static void op_close(struct libusb_device_handle *dev_handle) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(dev_handle); + /* fd may have already been removed by POLLERR condition in op_handle_events() */ + if (!hpriv->fd_removed) + usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd); + close(hpriv->fd); +} + +static int op_get_configuration(struct libusb_device_handle *handle, + int *config) +{ + int r; + + if (sysfs_can_relate_devices) { + r = sysfs_get_active_config(handle->dev, config); + } else { + r = usbfs_get_active_config(handle->dev, + _device_handle_priv(handle)->fd); + if (r == LIBUSB_SUCCESS) + *config = _device_priv(handle->dev)->active_config; + } + if (r < 0) + return r; + + if (*config == -1) { + usbi_err(HANDLE_CTX(handle), "device unconfigured"); + *config = 0; + } + + return 0; +} + +static int op_set_configuration(struct libusb_device_handle *handle, int config) +{ + struct linux_device_priv *priv = _device_priv(handle->dev); + int fd = _device_handle_priv(handle)->fd; + int r = ioctl(fd, IOCTL_USBFS_SETCONFIG, &config); + if (r) { + if (errno == EINVAL) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == EBUSY) + return LIBUSB_ERROR_BUSY; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + + /* update our cached active config descriptor */ + priv->active_config = config; + + return LIBUSB_SUCCESS; +} + +static int claim_interface(struct libusb_device_handle *handle, int iface) +{ + int fd = _device_handle_priv(handle)->fd; + int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface); + if (r) { + if (errno == ENOENT) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == EBUSY) + return LIBUSB_ERROR_BUSY; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "claim interface failed, error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + return 0; +} + +static int release_interface(struct libusb_device_handle *handle, int iface) +{ + int fd = _device_handle_priv(handle)->fd; + int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface); + if (r) { + if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "release interface failed, error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + return 0; +} + +static int op_set_interface(struct libusb_device_handle *handle, int iface, + int altsetting) +{ + int fd = _device_handle_priv(handle)->fd; + struct usbfs_setinterface setintf; + int r; + + setintf.interface = iface; + setintf.altsetting = altsetting; + r = ioctl(fd, IOCTL_USBFS_SETINTF, &setintf); + if (r) { + if (errno == EINVAL) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "setintf failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + + return 0; +} + +static int op_clear_halt(struct libusb_device_handle *handle, + unsigned char endpoint) +{ + int fd = _device_handle_priv(handle)->fd; + unsigned int _endpoint = endpoint; + int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint); + if (r) { + if (errno == ENOENT) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "clear_halt failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + + return 0; +} + +static int op_reset_device(struct libusb_device_handle *handle) +{ + int fd = _device_handle_priv(handle)->fd; + int i, r, ret = 0; + + /* Doing a device reset will cause the usbfs driver to get unbound + from any interfaces it is bound to. By voluntarily unbinding + the usbfs driver ourself, we stop the kernel from rebinding + the interface after reset (which would end up with the interface + getting bound to the in kernel driver if any). */ + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (handle->claimed_interfaces & (1L << i)) { + release_interface(handle, i); + } + } + + usbi_mutex_lock(&handle->lock); + r = ioctl(fd, IOCTL_USBFS_RESET, NULL); + if (r) { + if (errno == ENODEV) { + ret = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + + usbi_err(HANDLE_CTX(handle), + "reset failed error %d errno %d", r, errno); + ret = LIBUSB_ERROR_OTHER; + goto out; + } + + /* And re-claim any interfaces which were claimed before the reset */ + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (handle->claimed_interfaces & (1L << i)) { + /* + * A driver may have completed modprobing during + * IOCTL_USBFS_RESET, and bound itself as soon as + * IOCTL_USBFS_RESET released the device lock + */ + r = detach_kernel_driver_and_claim(handle, i); + if (r) { + usbi_warn(HANDLE_CTX(handle), + "failed to re-claim interface %d after reset: %s", + i, libusb_error_name(r)); + handle->claimed_interfaces &= ~(1L << i); + ret = LIBUSB_ERROR_NOT_FOUND; + } + } + } +out: + usbi_mutex_unlock(&handle->lock); + return ret; +} + +static int do_streams_ioctl(struct libusb_device_handle *handle, long req, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints) +{ + int r, fd = _device_handle_priv(handle)->fd; + struct usbfs_streams *streams; + + if (num_endpoints > 30) /* Max 15 in + 15 out eps */ + return LIBUSB_ERROR_INVALID_PARAM; + + streams = malloc(sizeof(struct usbfs_streams) + num_endpoints); + if (!streams) + return LIBUSB_ERROR_NO_MEM; + + streams->num_streams = num_streams; + streams->num_eps = num_endpoints; + memcpy(streams->eps, endpoints, num_endpoints); + + r = ioctl(fd, req, streams); + + free(streams); + + if (r < 0) { + if (errno == ENOTTY) + return LIBUSB_ERROR_NOT_SUPPORTED; + else if (errno == EINVAL) + return LIBUSB_ERROR_INVALID_PARAM; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "streams-ioctl failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + return r; +} + +static int op_alloc_streams(struct libusb_device_handle *handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints) +{ + return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS, + num_streams, endpoints, num_endpoints); +} + +static int op_free_streams(struct libusb_device_handle *handle, + unsigned char *endpoints, int num_endpoints) +{ + return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0, + endpoints, num_endpoints); +} + +static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle, + size_t len) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); + unsigned char *buffer = (unsigned char *)mmap(NULL, len, + PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0); + if (buffer == MAP_FAILED) { + usbi_err(HANDLE_CTX(handle), "alloc dev mem failed errno %d", + errno); + return NULL; + } + return buffer; +} + +static int op_dev_mem_free(struct libusb_device_handle *handle, + unsigned char *buffer, size_t len) +{ + if (munmap(buffer, len) != 0) { + usbi_err(HANDLE_CTX(handle), "free dev mem failed errno %d", + errno); + return LIBUSB_ERROR_OTHER; + } else { + return LIBUSB_SUCCESS; + } +} + +static int op_kernel_driver_active(struct libusb_device_handle *handle, + int interface) +{ + int fd = _device_handle_priv(handle)->fd; + struct usbfs_getdriver getdrv; + int r; + + getdrv.interface = interface; + r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); + if (r) { + if (errno == ENODATA) + return 0; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "get driver failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + + return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1; +} + +static int op_detach_kernel_driver(struct libusb_device_handle *handle, + int interface) +{ + int fd = _device_handle_priv(handle)->fd; + struct usbfs_ioctl command; + struct usbfs_getdriver getdrv; + int r; + + command.ifno = interface; + command.ioctl_code = IOCTL_USBFS_DISCONNECT; + command.data = NULL; + + getdrv.interface = interface; + r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); + if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0) + return LIBUSB_ERROR_NOT_FOUND; + + r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); + if (r) { + if (errno == ENODATA) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == EINVAL) + return LIBUSB_ERROR_INVALID_PARAM; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), + "detach failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } + + return 0; +} + +static int op_attach_kernel_driver(struct libusb_device_handle *handle, + int interface) +{ + int fd = _device_handle_priv(handle)->fd; + struct usbfs_ioctl command; + int r; + + command.ifno = interface; + command.ioctl_code = IOCTL_USBFS_CONNECT; + command.data = NULL; + + r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); + if (r < 0) { + if (errno == ENODATA) + return LIBUSB_ERROR_NOT_FOUND; + else if (errno == EINVAL) + return LIBUSB_ERROR_INVALID_PARAM; + else if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + else if (errno == EBUSY) + return LIBUSB_ERROR_BUSY; + + usbi_err(HANDLE_CTX(handle), + "attach failed error %d errno %d", r, errno); + return LIBUSB_ERROR_OTHER; + } else if (r == 0) { + return LIBUSB_ERROR_NOT_FOUND; + } + + return 0; +} + +static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, + int interface) +{ + struct usbfs_disconnect_claim dc; + int r, fd = _device_handle_priv(handle)->fd; + + dc.interface = interface; + strcpy(dc.driver, "usbfs"); + dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; + r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); + if (r != 0 && errno != ENOTTY) { + switch (errno) { + case EBUSY: + return LIBUSB_ERROR_BUSY; + case EINVAL: + return LIBUSB_ERROR_INVALID_PARAM; + case ENODEV: + return LIBUSB_ERROR_NO_DEVICE; + } + usbi_err(HANDLE_CTX(handle), + "disconnect-and-claim failed errno %d", errno); + return LIBUSB_ERROR_OTHER; + } else if (r == 0) + return 0; + + /* Fallback code for kernels which don't support the + disconnect-and-claim ioctl */ + r = op_detach_kernel_driver(handle, interface); + if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND) + return r; + + return claim_interface(handle, interface); +} + +static int op_claim_interface(struct libusb_device_handle *handle, int iface) +{ + if (handle->auto_detach_kernel_driver) + return detach_kernel_driver_and_claim(handle, iface); + else + return claim_interface(handle, iface); +} + +static int op_release_interface(struct libusb_device_handle *handle, int iface) +{ + int r; + + r = release_interface(handle, iface); + if (r) + return r; + + if (handle->auto_detach_kernel_driver) + op_attach_kernel_driver(handle, iface); + + return 0; +} + +static void op_destroy_device(struct libusb_device *dev) +{ + struct linux_device_priv *priv = _device_priv(dev); + if (priv->descriptors) + free(priv->descriptors); + if (priv->sysfs_dir) + free(priv->sysfs_dir); +} + +/* URBs are discarded in reverse order of submission to avoid races. */ +static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = + usbi_transfer_get_os_priv(itransfer); + struct linux_device_handle_priv *dpriv = + _device_handle_priv(transfer->dev_handle); + int i, ret = 0; + struct usbfs_urb *urb; + + for (i = last_plus_one - 1; i >= first; i--) { + if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type) + urb = tpriv->iso_urbs[i]; + else + urb = &tpriv->urbs[i]; + + if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb)) + continue; + + if (EINVAL == errno) { + usbi_dbg("URB not found --> assuming ready to be reaped"); + if (i == (last_plus_one - 1)) + ret = LIBUSB_ERROR_NOT_FOUND; + } else if (ENODEV == errno) { + usbi_dbg("Device not found for URB --> assuming ready to be reaped"); + ret = LIBUSB_ERROR_NO_DEVICE; + } else { + usbi_warn(TRANSFER_CTX(transfer), + "unrecognised discard errno %d", errno); + ret = LIBUSB_ERROR_OTHER; + } + } + return ret; +} + +static void free_iso_urbs(struct linux_transfer_priv *tpriv) +{ + int i; + for (i = 0; i < tpriv->num_urbs; i++) { + struct usbfs_urb *urb = tpriv->iso_urbs[i]; + if (!urb) + break; + free(urb); + } + + free(tpriv->iso_urbs); + tpriv->iso_urbs = NULL; +} + +static int submit_bulk_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + struct linux_device_handle_priv *dpriv = + _device_handle_priv(transfer->dev_handle); + struct usbfs_urb *urbs; + int is_out = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) + == LIBUSB_ENDPOINT_OUT; + int bulk_buffer_len, use_bulk_continuation; + int r; + int i; + + if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) && + !(dpriv->caps & USBFS_CAP_ZERO_PACKET)) + return LIBUSB_ERROR_NOT_SUPPORTED; + + /* + * Older versions of usbfs place a 16kb limit on bulk URBs. We work + * around this by splitting large transfers into 16k blocks, and then + * submit all urbs at once. it would be simpler to submit one urb at + * a time, but there is a big performance gain doing it this way. + * + * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM), + * using arbritary large transfers can still be a bad idea though, as + * the kernel needs to allocate physical contiguous memory for this, + * which may fail for large buffers. + * + * The kernel solves this problem by splitting the transfer into + * blocks itself when the host-controller is scatter-gather capable + * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are. + * + * Last, there is the issue of short-transfers when splitting, for + * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION + * is needed, but this is not always available. + */ + if (dpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) { + /* Good! Just submit everything in one go */ + bulk_buffer_len = transfer->length ? transfer->length : 1; + use_bulk_continuation = 0; + } else if (dpriv->caps & USBFS_CAP_BULK_CONTINUATION) { + /* Split the transfers and use bulk-continuation to + avoid issues with short-transfers */ + bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; + use_bulk_continuation = 1; + } else if (dpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) { + /* Don't split, assume the kernel can alloc the buffer + (otherwise the submit will fail with -ENOMEM) */ + bulk_buffer_len = transfer->length ? transfer->length : 1; + use_bulk_continuation = 0; + } else { + /* Bad, splitting without bulk-continuation, short transfers + which end before the last urb will not work reliable! */ + /* Note we don't warn here as this is "normal" on kernels < + 2.6.32 and not a problem for most applications */ + bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; + use_bulk_continuation = 0; + } + + int num_urbs = transfer->length / bulk_buffer_len; + int last_urb_partial = 0; + + if (transfer->length == 0) { + num_urbs = 1; + } else if ((transfer->length % bulk_buffer_len) > 0) { + last_urb_partial = 1; + num_urbs++; + } + usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, + transfer->length); + urbs = calloc(num_urbs, sizeof(struct usbfs_urb)); + if (!urbs) + return LIBUSB_ERROR_NO_MEM; + tpriv->urbs = urbs; + tpriv->num_urbs = num_urbs; + tpriv->num_retired = 0; + tpriv->reap_action = NORMAL; + tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED; + + for (i = 0; i < num_urbs; i++) { + struct usbfs_urb *urb = &urbs[i]; + urb->usercontext = itransfer; + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_BULK: + urb->type = USBFS_URB_TYPE_BULK; + urb->stream_id = 0; + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + urb->type = USBFS_URB_TYPE_BULK; + urb->stream_id = itransfer->stream_id; + break; + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + urb->type = USBFS_URB_TYPE_INTERRUPT; + break; + } + urb->endpoint = transfer->endpoint; + urb->buffer = transfer->buffer + (i * bulk_buffer_len); + /* don't set the short not ok flag for the last URB */ + if (use_bulk_continuation && !is_out && (i < num_urbs - 1)) + urb->flags = USBFS_URB_SHORT_NOT_OK; + if (i == num_urbs - 1 && last_urb_partial) + urb->buffer_length = transfer->length % bulk_buffer_len; + else if (transfer->length == 0) + urb->buffer_length = 0; + else + urb->buffer_length = bulk_buffer_len; + + if (i > 0 && use_bulk_continuation) + urb->flags |= USBFS_URB_BULK_CONTINUATION; + + /* we have already checked that the flag is supported */ + if (is_out && i == num_urbs - 1 && + transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) + urb->flags |= USBFS_URB_ZERO_PACKET; + + r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); + if (r < 0) { + if (errno == ENODEV) { + r = LIBUSB_ERROR_NO_DEVICE; + } else { + usbi_err(TRANSFER_CTX(transfer), + "submiturb failed error %d errno=%d", r, errno); + r = LIBUSB_ERROR_IO; + } + + /* if the first URB submission fails, we can simply free up and + * return failure immediately. */ + if (i == 0) { + usbi_dbg("first URB failed, easy peasy"); + free(urbs); + tpriv->urbs = NULL; + return r; + } + + /* if it's not the first URB that failed, the situation is a bit + * tricky. we may need to discard all previous URBs. there are + * complications: + * - discarding is asynchronous - discarded urbs will be reaped + * later. the user must not have freed the transfer when the + * discarded URBs are reaped, otherwise libusb will be using + * freed memory. + * - the earlier URBs may have completed successfully and we do + * not want to throw away any data. + * - this URB failing may be no error; EREMOTEIO means that + * this transfer simply didn't need all the URBs we submitted + * so, we report that the transfer was submitted successfully and + * in case of error we discard all previous URBs. later when + * the final reap completes we can report error to the user, + * or success if an earlier URB was completed successfully. + */ + tpriv->reap_action = EREMOTEIO == errno ? COMPLETED_EARLY : SUBMIT_FAILED; + + /* The URBs we haven't submitted yet we count as already + * retired. */ + tpriv->num_retired += num_urbs - i; + + /* If we completed short then don't try to discard. */ + if (COMPLETED_EARLY == tpriv->reap_action) + return 0; + + discard_urbs(itransfer, 0, i); + + usbi_dbg("reporting successful submission but waiting for %d " + "discards before reporting error", i); + return 0; + } + } + + return 0; +} + +static int submit_iso_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + struct linux_device_handle_priv *dpriv = + _device_handle_priv(transfer->dev_handle); + struct usbfs_urb **urbs; + int num_packets = transfer->num_iso_packets; + int num_packets_remaining; + int i, j; + int num_urbs; + unsigned int packet_len; + unsigned int total_len = 0; + unsigned char *urb_buffer = transfer->buffer; + + if (num_packets < 1) + return LIBUSB_ERROR_INVALID_PARAM; + + /* usbfs places arbitrary limits on iso URBs. this limit has changed + * at least three times, but we attempt to detect this limit during + * init and check it here. if the kernel rejects the request due to + * its size, we return an error indicating such to the user. + */ + for (i = 0; i < num_packets; i++) { + packet_len = transfer->iso_packet_desc[i].length; + + if (packet_len > max_iso_packet_len) { + usbi_warn(TRANSFER_CTX(transfer), + "iso packet length of %u bytes exceeds maximum of %u bytes", + packet_len, max_iso_packet_len); + return LIBUSB_ERROR_INVALID_PARAM; + } + + total_len += packet_len; + } + + if (transfer->length < (int)total_len) + return LIBUSB_ERROR_INVALID_PARAM; + + /* usbfs limits the number of iso packets per URB */ + num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB; + + usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, + transfer->length); + + urbs = calloc(num_urbs, sizeof(*urbs)); + if (!urbs) + return LIBUSB_ERROR_NO_MEM; + + tpriv->iso_urbs = urbs; + tpriv->num_urbs = num_urbs; + tpriv->num_retired = 0; + tpriv->reap_action = NORMAL; + tpriv->iso_packet_offset = 0; + + /* allocate + initialize each URB with the correct number of packets */ + num_packets_remaining = num_packets; + for (i = 0, j = 0; i < num_urbs; i++) { + int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB); + struct usbfs_urb *urb; + size_t alloc_size; + int k; + + alloc_size = sizeof(*urb) + + (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc)); + urb = calloc(1, alloc_size); + if (!urb) { + free_iso_urbs(tpriv); + return LIBUSB_ERROR_NO_MEM; + } + urbs[i] = urb; + + /* populate packet lengths */ + for (k = 0; k < num_packets_in_urb; j++, k++) { + packet_len = transfer->iso_packet_desc[j].length; + urb->buffer_length += packet_len; + urb->iso_frame_desc[k].length = packet_len; + } + + urb->usercontext = itransfer; + urb->type = USBFS_URB_TYPE_ISO; + /* FIXME: interface for non-ASAP data? */ + urb->flags = USBFS_URB_ISO_ASAP; + urb->endpoint = transfer->endpoint; + urb->number_of_packets = num_packets_in_urb; + urb->buffer = urb_buffer; + + urb_buffer += urb->buffer_length; + num_packets_remaining -= num_packets_in_urb; + } + + /* submit URBs */ + for (i = 0; i < num_urbs; i++) { + int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]); + if (r < 0) { + if (errno == ENODEV) { + r = LIBUSB_ERROR_NO_DEVICE; + } else if (errno == EINVAL) { + usbi_warn(TRANSFER_CTX(transfer), + "submiturb failed, transfer too large"); + r = LIBUSB_ERROR_INVALID_PARAM; + } else if (errno == EMSGSIZE) { + usbi_warn(TRANSFER_CTX(transfer), + "submiturb failed, iso packet length too large"); + r = LIBUSB_ERROR_INVALID_PARAM; + } else { + usbi_err(TRANSFER_CTX(transfer), + "submiturb failed error %d errno=%d", r, errno); + r = LIBUSB_ERROR_IO; + } + + /* if the first URB submission fails, we can simply free up and + * return failure immediately. */ + if (i == 0) { + usbi_dbg("first URB failed, easy peasy"); + free_iso_urbs(tpriv); + return r; + } + + /* if it's not the first URB that failed, the situation is a bit + * tricky. we must discard all previous URBs. there are + * complications: + * - discarding is asynchronous - discarded urbs will be reaped + * later. the user must not have freed the transfer when the + * discarded URBs are reaped, otherwise libusb will be using + * freed memory. + * - the earlier URBs may have completed successfully and we do + * not want to throw away any data. + * so, in this case we discard all the previous URBs BUT we report + * that the transfer was submitted successfully. then later when + * the final discard completes we can report error to the user. + */ + tpriv->reap_action = SUBMIT_FAILED; + + /* The URBs we haven't submitted yet we count as already + * retired. */ + tpriv->num_retired = num_urbs - i; + discard_urbs(itransfer, 0, i); + + usbi_dbg("reporting successful submission but waiting for %d " + "discards before reporting error", i); + return 0; + } + } + + return 0; +} + +static int submit_control_transfer(struct usbi_transfer *itransfer) +{ + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_device_handle_priv *dpriv = + _device_handle_priv(transfer->dev_handle); + struct usbfs_urb *urb; + int r; + + if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH) + return LIBUSB_ERROR_INVALID_PARAM; + + urb = calloc(1, sizeof(struct usbfs_urb)); + if (!urb) + return LIBUSB_ERROR_NO_MEM; + tpriv->urbs = urb; + tpriv->num_urbs = 1; + tpriv->reap_action = NORMAL; + + urb->usercontext = itransfer; + urb->type = USBFS_URB_TYPE_CONTROL; + urb->endpoint = transfer->endpoint; + urb->buffer = transfer->buffer; + urb->buffer_length = transfer->length; + + r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); + if (r < 0) { + free(urb); + tpriv->urbs = NULL; + if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(TRANSFER_CTX(transfer), + "submiturb failed error %d errno=%d", r, errno); + return LIBUSB_ERROR_IO; + } + return 0; +} + +static int op_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return submit_control_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return submit_bulk_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + return submit_bulk_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return submit_iso_transfer(itransfer); + default: + usbi_err(TRANSFER_CTX(transfer), + "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int op_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int r; + + if (!tpriv->urbs) + return LIBUSB_ERROR_NOT_FOUND; + + r = discard_urbs(itransfer, 0, tpriv->num_urbs); + if (r != 0) + return r; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + if (tpriv->reap_action == ERROR) + break; + /* else, fall through */ + default: + tpriv->reap_action = CANCELLED; + } + + return 0; +} + +static void op_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (tpriv->urbs) { + free(tpriv->urbs); + tpriv->urbs = NULL; + } + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + if (tpriv->iso_urbs) { + free_iso_urbs(tpriv); + tpriv->iso_urbs = NULL; + } + break; + default: + usbi_err(TRANSFER_CTX(transfer), + "unknown endpoint type %d", transfer->type); + } +} + +static int handle_bulk_completion(struct usbi_transfer *itransfer, + struct usbfs_urb *urb) +{ + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int urb_idx = urb - tpriv->urbs; + + usbi_mutex_lock(&itransfer->lock); + usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, + urb_idx + 1, tpriv->num_urbs); + + tpriv->num_retired++; + + if (tpriv->reap_action != NORMAL) { + /* cancelled, submit_fail, or completed early */ + usbi_dbg("abnormal reap: urb status %d", urb->status); + + /* even though we're in the process of cancelling, it's possible that + * we may receive some data in these URBs that we don't want to lose. + * examples: + * 1. while the kernel is cancelling all the packets that make up an + * URB, a few of them might complete. so we get back a successful + * cancellation *and* some data. + * 2. we receive a short URB which marks the early completion condition, + * so we start cancelling the remaining URBs. however, we're too + * slow and another URB completes (or at least completes partially). + * (this can't happen since we always use BULK_CONTINUATION.) + * + * When this happens, our objectives are not to lose any "surplus" data, + * and also to stick it at the end of the previously-received data + * (closing any holes), so that libusb reports the total amount of + * transferred data and presents it in a contiguous chunk. + */ + if (urb->actual_length > 0) { + unsigned char *target = transfer->buffer + itransfer->transferred; + usbi_dbg("received %d bytes of surplus data", urb->actual_length); + if (urb->buffer != target) { + usbi_dbg("moving surplus data from offset %d to offset %d", + (unsigned char *) urb->buffer - transfer->buffer, + target - transfer->buffer); + memmove(target, urb->buffer, urb->actual_length); + } + itransfer->transferred += urb->actual_length; + } + + if (tpriv->num_retired == tpriv->num_urbs) { + usbi_dbg("abnormal reap: last URB handled, reporting"); + if (tpriv->reap_action != COMPLETED_EARLY && + tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) + tpriv->reap_status = LIBUSB_TRANSFER_ERROR; + goto completed; + } + goto out_unlock; + } + + itransfer->transferred += urb->actual_length; + + /* Many of these errors can occur on *any* urb of a multi-urb + * transfer. When they do, we tear down the rest of the transfer. + */ + switch (urb->status) { + case 0: + break; + case -EREMOTEIO: /* short transfer */ + break; + case -ENOENT: /* cancelled */ + case -ECONNRESET: + break; + case -ENODEV: + case -ESHUTDOWN: + usbi_dbg("device removed"); + tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE; + goto cancel_remaining; + case -EPIPE: + usbi_dbg("detected endpoint stall"); + if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) + tpriv->reap_status = LIBUSB_TRANSFER_STALL; + goto cancel_remaining; + case -EOVERFLOW: + /* overflow can only ever occur in the last urb */ + usbi_dbg("overflow, actual_length=%d", urb->actual_length); + if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) + tpriv->reap_status = LIBUSB_TRANSFER_OVERFLOW; + goto completed; + case -ETIME: + case -EPROTO: + case -EILSEQ: + case -ECOMM: + case -ENOSR: + usbi_dbg("low level error %d", urb->status); + tpriv->reap_action = ERROR; + goto cancel_remaining; + default: + usbi_warn(ITRANSFER_CTX(itransfer), + "unrecognised urb status %d", urb->status); + tpriv->reap_action = ERROR; + goto cancel_remaining; + } + + /* if we're the last urb or we got less data than requested then we're + * done */ + if (urb_idx == tpriv->num_urbs - 1) { + usbi_dbg("last URB in transfer --> complete!"); + goto completed; + } else if (urb->actual_length < urb->buffer_length) { + usbi_dbg("short transfer %d/%d --> complete!", + urb->actual_length, urb->buffer_length); + if (tpriv->reap_action == NORMAL) + tpriv->reap_action = COMPLETED_EARLY; + } else + goto out_unlock; + +cancel_remaining: + if (ERROR == tpriv->reap_action && LIBUSB_TRANSFER_COMPLETED == tpriv->reap_status) + tpriv->reap_status = LIBUSB_TRANSFER_ERROR; + + if (tpriv->num_retired == tpriv->num_urbs) /* nothing to cancel */ + goto completed; + + /* cancel remaining urbs and wait for their completion before + * reporting results */ + discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs); + +out_unlock: + usbi_mutex_unlock(&itransfer->lock); + return 0; + +completed: + free(tpriv->urbs); + tpriv->urbs = NULL; + usbi_mutex_unlock(&itransfer->lock); + return CANCELLED == tpriv->reap_action ? + usbi_handle_transfer_cancellation(itransfer) : + usbi_handle_transfer_completion(itransfer, tpriv->reap_status); +} + +static int handle_iso_completion(struct usbi_transfer *itransfer, + struct usbfs_urb *urb) +{ + struct libusb_transfer *transfer = + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + int num_urbs = tpriv->num_urbs; + int urb_idx = 0; + int i; + enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; + + usbi_mutex_lock(&itransfer->lock); + for (i = 0; i < num_urbs; i++) { + if (urb == tpriv->iso_urbs[i]) { + urb_idx = i + 1; + break; + } + } + if (urb_idx == 0) { + usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); + usbi_mutex_unlock(&itransfer->lock); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("handling completion status %d of iso urb %d/%d", urb->status, + urb_idx, num_urbs); + + /* copy isochronous results back in */ + + for (i = 0; i < urb->number_of_packets; i++) { + struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i]; + struct libusb_iso_packet_descriptor *lib_desc = + &transfer->iso_packet_desc[tpriv->iso_packet_offset++]; + lib_desc->status = LIBUSB_TRANSFER_COMPLETED; + switch (urb_desc->status) { + case 0: + break; + case -ENOENT: /* cancelled */ + case -ECONNRESET: + break; + case -ENODEV: + case -ESHUTDOWN: + usbi_dbg("device removed"); + lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE; + break; + case -EPIPE: + usbi_dbg("detected endpoint stall"); + lib_desc->status = LIBUSB_TRANSFER_STALL; + break; + case -EOVERFLOW: + usbi_dbg("overflow error"); + lib_desc->status = LIBUSB_TRANSFER_OVERFLOW; + break; + case -ETIME: + case -EPROTO: + case -EILSEQ: + case -ECOMM: + case -ENOSR: + case -EXDEV: + usbi_dbg("low-level USB error %d", urb_desc->status); + lib_desc->status = LIBUSB_TRANSFER_ERROR; + break; + default: + usbi_warn(TRANSFER_CTX(transfer), + "unrecognised urb status %d", urb_desc->status); + lib_desc->status = LIBUSB_TRANSFER_ERROR; + break; + } + lib_desc->actual_length = urb_desc->actual_length; + } + + tpriv->num_retired++; + + if (tpriv->reap_action != NORMAL) { /* cancelled or submit_fail */ + usbi_dbg("CANCEL: urb status %d", urb->status); + + if (tpriv->num_retired == num_urbs) { + usbi_dbg("CANCEL: last URB handled, reporting"); + free_iso_urbs(tpriv); + if (tpriv->reap_action == CANCELLED) { + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_cancellation(itransfer); + } else { + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_completion(itransfer, + LIBUSB_TRANSFER_ERROR); + } + } + goto out; + } + + switch (urb->status) { + case 0: + break; + case -ENOENT: /* cancelled */ + case -ECONNRESET: + break; + case -ESHUTDOWN: + usbi_dbg("device removed"); + status = LIBUSB_TRANSFER_NO_DEVICE; + break; + default: + usbi_warn(TRANSFER_CTX(transfer), + "unrecognised urb status %d", urb->status); + status = LIBUSB_TRANSFER_ERROR; + break; + } + + /* if we're the last urb then we're done */ + if (urb_idx == num_urbs) { + usbi_dbg("last URB in transfer --> complete!"); + free_iso_urbs(tpriv); + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_completion(itransfer, status); + } + +out: + usbi_mutex_unlock(&itransfer->lock); + return 0; +} + +static int handle_control_completion(struct usbi_transfer *itransfer, + struct usbfs_urb *urb) +{ + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); + int status; + + usbi_mutex_lock(&itransfer->lock); + usbi_dbg("handling completion status %d", urb->status); + + itransfer->transferred += urb->actual_length; + + if (tpriv->reap_action == CANCELLED) { + if (urb->status != 0 && urb->status != -ENOENT) + usbi_warn(ITRANSFER_CTX(itransfer), + "cancel: unrecognised urb status %d", urb->status); + free(tpriv->urbs); + tpriv->urbs = NULL; + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_cancellation(itransfer); + } + + switch (urb->status) { + case 0: + status = LIBUSB_TRANSFER_COMPLETED; + break; + case -ENOENT: /* cancelled */ + status = LIBUSB_TRANSFER_CANCELLED; + break; + case -ENODEV: + case -ESHUTDOWN: + usbi_dbg("device removed"); + status = LIBUSB_TRANSFER_NO_DEVICE; + break; + case -EPIPE: + usbi_dbg("unsupported control request"); + status = LIBUSB_TRANSFER_STALL; + break; + case -EOVERFLOW: + usbi_dbg("control overflow error"); + status = LIBUSB_TRANSFER_OVERFLOW; + break; + case -ETIME: + case -EPROTO: + case -EILSEQ: + case -ECOMM: + case -ENOSR: + usbi_dbg("low-level bus error occurred"); + status = LIBUSB_TRANSFER_ERROR; + break; + default: + usbi_warn(ITRANSFER_CTX(itransfer), + "unrecognised urb status %d", urb->status); + status = LIBUSB_TRANSFER_ERROR; + break; + } + + free(tpriv->urbs); + tpriv->urbs = NULL; + usbi_mutex_unlock(&itransfer->lock); + return usbi_handle_transfer_completion(itransfer, status); +} + +static int reap_for_handle(struct libusb_device_handle *handle) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); + int r; + struct usbfs_urb *urb; + struct usbi_transfer *itransfer; + struct libusb_transfer *transfer; + + r = ioctl(hpriv->fd, IOCTL_USBFS_REAPURBNDELAY, &urb); + if (r == -1 && errno == EAGAIN) + return 1; + if (r < 0) { + if (errno == ENODEV) + return LIBUSB_ERROR_NO_DEVICE; + + usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d", + r, errno); + return LIBUSB_ERROR_IO; + } + + itransfer = urb->usercontext; + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status, + urb->actual_length); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return handle_iso_completion(itransfer, urb); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + return handle_bulk_completion(itransfer, urb); + case LIBUSB_TRANSFER_TYPE_CONTROL: + return handle_control_completion(itransfer, urb); + default: + usbi_err(HANDLE_CTX(handle), "unrecognised endpoint type %x", + transfer->type); + return LIBUSB_ERROR_OTHER; + } +} + +static int op_handle_events(struct libusb_context *ctx, + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) +{ + int r; + unsigned int i = 0; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + struct pollfd *pollfd = &fds[i]; + struct libusb_device_handle *handle; + struct linux_device_handle_priv *hpriv = NULL; + + if (!pollfd->revents) + continue; + + num_ready--; + list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { + hpriv = _device_handle_priv(handle); + if (hpriv->fd == pollfd->fd) + break; + } + + if (!hpriv || hpriv->fd != pollfd->fd) { + usbi_err(ctx, "cannot find handle for fd %d", + pollfd->fd); + continue; + } + + if (pollfd->revents & POLLERR) { + /* remove the fd from the pollfd set so that it doesn't continuously + * trigger an event, and flag that it has been removed so op_close() + * doesn't try to remove it a second time */ + usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd); + hpriv->fd_removed = 1; + + /* device will still be marked as attached if hotplug monitor thread + * hasn't processed remove event yet */ + usbi_mutex_static_lock(&linux_hotplug_lock); + if (handle->dev->attached) + linux_device_disconnected(handle->dev->bus_number, + handle->dev->device_address); + usbi_mutex_static_unlock(&linux_hotplug_lock); + + if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) { + do { + r = reap_for_handle(handle); + } while (r == 0); + } + + usbi_handle_disconnect(handle); + continue; + } + + do { + r = reap_for_handle(handle); + } while (r == 0); + if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE) + continue; + else if (r < 0) + goto out; + } + + r = 0; +out: + usbi_mutex_unlock(&ctx->open_devs_lock); + return r; +} + +static int op_clock_gettime(int clk_id, struct timespec *tp) +{ + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + return clock_gettime(monotonic_clkid, tp); + case USBI_CLOCK_REALTIME: + return clock_gettime(CLOCK_REALTIME, tp); + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +#ifdef USBI_TIMERFD_AVAILABLE +static clockid_t op_get_timerfd_clockid(void) +{ + return monotonic_clkid; + +} +#endif + +const struct usbi_os_backend usbi_backend = { + .name = "Linux usbfs", + .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, + .init = op_init, + .exit = op_exit, + .get_device_list = NULL, + .hotplug_poll = op_hotplug_poll, + .get_device_descriptor = op_get_device_descriptor, + .get_active_config_descriptor = op_get_active_config_descriptor, + .get_config_descriptor = op_get_config_descriptor, + .get_config_descriptor_by_value = op_get_config_descriptor_by_value, + + .open = op_open, + .close = op_close, + .get_configuration = op_get_configuration, + .set_configuration = op_set_configuration, + .claim_interface = op_claim_interface, + .release_interface = op_release_interface, + + .set_interface_altsetting = op_set_interface, + .clear_halt = op_clear_halt, + .reset_device = op_reset_device, + + .alloc_streams = op_alloc_streams, + .free_streams = op_free_streams, + + .dev_mem_alloc = op_dev_mem_alloc, + .dev_mem_free = op_dev_mem_free, + + .kernel_driver_active = op_kernel_driver_active, + .detach_kernel_driver = op_detach_kernel_driver, + .attach_kernel_driver = op_attach_kernel_driver, + + .destroy_device = op_destroy_device, + + .submit_transfer = op_submit_transfer, + .cancel_transfer = op_cancel_transfer, + .clear_transfer_priv = op_clear_transfer_priv, + + .handle_events = op_handle_events, + + .clock_gettime = op_clock_gettime, + +#ifdef USBI_TIMERFD_AVAILABLE + .get_timerfd_clockid = op_get_timerfd_clockid, +#endif + + .device_priv_size = sizeof(struct linux_device_priv), + .device_handle_priv_size = sizeof(struct linux_device_handle_priv), + .transfer_priv_size = sizeof(struct linux_transfer_priv), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h new file mode 100644 index 0000000000..24496325f6 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h @@ -0,0 +1,194 @@ +/* + * usbfs header structures + * Copyright © 2007 Daniel Drake + * Copyright © 2001 Johannes Erdfelt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_USBFS_H +#define LIBUSB_USBFS_H + +#include + +#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices" + +struct usbfs_ctrltransfer { + /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */ + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + + uint32_t timeout; /* in milliseconds */ + + /* pointer to data */ + void *data; +}; + +struct usbfs_bulktransfer { + /* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */ + unsigned int ep; + unsigned int len; + unsigned int timeout; /* in milliseconds */ + + /* pointer to data */ + void *data; +}; + +struct usbfs_setinterface { + /* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */ + unsigned int interface; + unsigned int altsetting; +}; + +#define USBFS_MAXDRIVERNAME 255 + +struct usbfs_getdriver { + unsigned int interface; + char driver[USBFS_MAXDRIVERNAME + 1]; +}; + +#define USBFS_URB_SHORT_NOT_OK 0x01 +#define USBFS_URB_ISO_ASAP 0x02 +#define USBFS_URB_BULK_CONTINUATION 0x04 +#define USBFS_URB_QUEUE_BULK 0x10 +#define USBFS_URB_ZERO_PACKET 0x40 + +enum usbfs_urb_type { + USBFS_URB_TYPE_ISO = 0, + USBFS_URB_TYPE_INTERRUPT = 1, + USBFS_URB_TYPE_CONTROL = 2, + USBFS_URB_TYPE_BULK = 3, +}; + +struct usbfs_iso_packet_desc { + unsigned int length; + unsigned int actual_length; + unsigned int status; +}; + +#define MAX_BULK_BUFFER_LENGTH 16384 +#define MAX_CTRL_BUFFER_LENGTH 4096 + +#define MAX_ISO_PACKETS_PER_URB 128 + +struct usbfs_urb { + unsigned char type; + unsigned char endpoint; + int status; + unsigned int flags; + void *buffer; + int buffer_length; + int actual_length; + int start_frame; + union { + int number_of_packets; /* Only used for isoc urbs */ + unsigned int stream_id; /* Only used with bulk streams */ + }; + int error_count; + unsigned int signr; + void *usercontext; + struct usbfs_iso_packet_desc iso_frame_desc[0]; +}; + +struct usbfs_connectinfo { + unsigned int devnum; + unsigned char slow; +}; + +struct usbfs_ioctl { + int ifno; /* interface 0..N ; negative numbers reserved */ + int ioctl_code; /* MUST encode size + direction of data so the + * macros in give correct values */ + void *data; /* param buffer (in, or out) */ +}; + +struct usbfs_hub_portinfo { + unsigned char numports; + unsigned char port[127]; /* port to device num mapping */ +}; + +#define USBFS_CAP_ZERO_PACKET 0x01 +#define USBFS_CAP_BULK_CONTINUATION 0x02 +#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04 +#define USBFS_CAP_BULK_SCATTER_GATHER 0x08 +#define USBFS_CAP_REAP_AFTER_DISCONNECT 0x10 + +#define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01 +#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02 + +struct usbfs_disconnect_claim { + unsigned int interface; + unsigned int flags; + char driver[USBFS_MAXDRIVERNAME + 1]; +}; + +struct usbfs_streams { + unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */ + unsigned int num_eps; + unsigned char eps[0]; +}; + +#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer) +#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer) +#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int) +#define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface) +#define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int) +#define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver) +#define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb) +#define IOCTL_USBFS_DISCARDURB _IO('U', 11) +#define IOCTL_USBFS_REAPURB _IOW('U', 12, void *) +#define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *) +#define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int) +#define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int) +#define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo) +#define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl) +#define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo) +#define IOCTL_USBFS_RESET _IO('U', 20) +#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int) +#define IOCTL_USBFS_DISCONNECT _IO('U', 22) +#define IOCTL_USBFS_CONNECT _IO('U', 23) +#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int) +#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int) +#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32) +#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim) +#define IOCTL_USBFS_ALLOC_STREAMS _IOR('U', 28, struct usbfs_streams) +#define IOCTL_USBFS_FREE_STREAMS _IOR('U', 29, struct usbfs_streams) + +extern usbi_mutex_static_t linux_hotplug_lock; + +#if defined(HAVE_LIBUDEV) +int linux_udev_start_event_monitor(void); +int linux_udev_stop_event_monitor(void); +int linux_udev_scan_devices(struct libusb_context *ctx); +void linux_udev_hotplug_poll(void); +#else +int linux_netlink_start_event_monitor(void); +int linux_netlink_stop_event_monitor(void); +void linux_netlink_hotplug_poll(void); +#endif + +void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name); +void linux_device_disconnected(uint8_t busnum, uint8_t devaddr); + +int linux_get_device_address (struct libusb_context *ctx, int detached, + uint8_t *busnum, uint8_t *devaddr, const char *dev_node, + const char *sys_name); +int linux_enumerate_device(struct libusb_context *ctx, + uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); + +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c new file mode 100644 index 0000000000..d9c059a776 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c @@ -0,0 +1,677 @@ +/* + * Copyright © 2011 Martin Pieuchot + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "libusbi.h" + +struct device_priv { + char devnode[16]; + int fd; + + unsigned char *cdesc; /* active config descriptor */ + usb_device_descriptor_t ddesc; /* usb device descriptor */ +}; + +struct handle_priv { + int endpoints[USB_MAX_ENDPOINTS]; +}; + +/* + * Backend functions + */ +static int netbsd_get_device_list(struct libusb_context *, + struct discovered_devs **); +static int netbsd_open(struct libusb_device_handle *); +static void netbsd_close(struct libusb_device_handle *); + +static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *, + int *); +static int netbsd_get_active_config_descriptor(struct libusb_device *, + unsigned char *, size_t, int *); +static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t, + unsigned char *, size_t, int *); + +static int netbsd_get_configuration(struct libusb_device_handle *, int *); +static int netbsd_set_configuration(struct libusb_device_handle *, int); + +static int netbsd_claim_interface(struct libusb_device_handle *, int); +static int netbsd_release_interface(struct libusb_device_handle *, int); + +static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int, + int); +static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char); +static int netbsd_reset_device(struct libusb_device_handle *); +static void netbsd_destroy_device(struct libusb_device *); + +static int netbsd_submit_transfer(struct usbi_transfer *); +static int netbsd_cancel_transfer(struct usbi_transfer *); +static void netbsd_clear_transfer_priv(struct usbi_transfer *); +static int netbsd_handle_transfer_completion(struct usbi_transfer *); +static int netbsd_clock_gettime(int, struct timespec *); + +/* + * Private functions + */ +static int _errno_to_libusb(int); +static int _cache_active_config_descriptor(struct libusb_device *, int); +static int _sync_control_transfer(struct usbi_transfer *); +static int _sync_gen_transfer(struct usbi_transfer *); +static int _access_endpoint(struct libusb_transfer *); + +const struct usbi_os_backend usbi_backend = { + "Synchronous NetBSD backend", + 0, + NULL, /* init() */ + NULL, /* exit() */ + NULL, /* set_option() */ + netbsd_get_device_list, + NULL, /* hotplug_poll */ + netbsd_open, + netbsd_close, + + netbsd_get_device_descriptor, + netbsd_get_active_config_descriptor, + netbsd_get_config_descriptor, + NULL, /* get_config_descriptor_by_value() */ + + netbsd_get_configuration, + netbsd_set_configuration, + + netbsd_claim_interface, + netbsd_release_interface, + + netbsd_set_interface_altsetting, + netbsd_clear_halt, + netbsd_reset_device, + + NULL, /* alloc_streams */ + NULL, /* free_streams */ + + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + + NULL, /* kernel_driver_active() */ + NULL, /* detach_kernel_driver() */ + NULL, /* attach_kernel_driver() */ + + netbsd_destroy_device, + + netbsd_submit_transfer, + netbsd_cancel_transfer, + netbsd_clear_transfer_priv, + + NULL, /* handle_events() */ + netbsd_handle_transfer_completion, + + netbsd_clock_gettime, + 0, /* context_priv_size */ + sizeof(struct device_priv), + sizeof(struct handle_priv), + 0, /* transfer_priv_size */ +}; + +int +netbsd_get_device_list(struct libusb_context * ctx, + struct discovered_devs **discdevs) +{ + struct libusb_device *dev; + struct device_priv *dpriv; + struct usb_device_info di; + unsigned long session_id; + char devnode[16]; + int fd, err, i; + + usbi_dbg(""); + + /* Only ugen(4) is supported */ + for (i = 0; i < USB_MAX_DEVICES; i++) { + /* Control endpoint is always .00 */ + snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i); + + if ((fd = open(devnode, O_RDONLY)) < 0) { + if (errno != ENOENT && errno != ENXIO) + usbi_err(ctx, "could not open %s", devnode); + continue; + } + + if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0) + continue; + + session_id = (di.udi_bus << 8 | di.udi_addr); + dev = usbi_get_device_by_session_id(ctx, session_id); + + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) + return (LIBUSB_ERROR_NO_MEM); + + dev->bus_number = di.udi_bus; + dev->device_address = di.udi_addr; + dev->speed = di.udi_speed; + + dpriv = (struct device_priv *)dev->os_priv; + strlcpy(dpriv->devnode, devnode, sizeof(devnode)); + dpriv->fd = -1; + + if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) { + err = errno; + goto error; + } + + dpriv->cdesc = NULL; + if (_cache_active_config_descriptor(dev, fd)) { + err = errno; + goto error; + } + + if ((err = usbi_sanitize_device(dev))) + goto error; + } + close(fd); + + if (discovered_devs_append(*discdevs, dev) == NULL) + return (LIBUSB_ERROR_NO_MEM); + + libusb_unref_device(dev); + } + + return (LIBUSB_SUCCESS); + +error: + close(fd); + libusb_unref_device(dev); + return _errno_to_libusb(err); +} + +int +netbsd_open(struct libusb_device_handle *handle) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + dpriv->fd = open(dpriv->devnode, O_RDWR); + if (dpriv->fd < 0) { + dpriv->fd = open(dpriv->devnode, O_RDONLY); + if (dpriv->fd < 0) + return _errno_to_libusb(errno); + } + + usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); + + return (LIBUSB_SUCCESS); +} + +void +netbsd_close(struct libusb_device_handle *handle) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + usbi_dbg("close: fd %d", dpriv->fd); + + close(dpriv->fd); + dpriv->fd = -1; +} + +int +netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, + int *host_endian) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + + usbi_dbg(""); + + memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); + + *host_endian = 0; + + return (LIBUSB_SUCCESS); +} + +int +netbsd_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buf, size_t len, int *host_endian) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + usb_config_descriptor_t *ucd; + + ucd = (usb_config_descriptor_t *) dpriv->cdesc; + len = MIN(len, UGETW(ucd->wTotalLength)); + + usbi_dbg("len %d", len); + + memcpy(buf, dpriv->cdesc, len); + + *host_endian = 0; + + return len; +} + +int +netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, + unsigned char *buf, size_t len, int *host_endian) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + struct usb_full_desc ufd; + int fd, err; + + usbi_dbg("index %d, len %d", idx, len); + + /* A config descriptor may be requested before opening the device */ + if (dpriv->fd >= 0) { + fd = dpriv->fd; + } else { + fd = open(dpriv->devnode, O_RDONLY); + if (fd < 0) + return _errno_to_libusb(errno); + } + + ufd.ufd_config_index = idx; + ufd.ufd_size = len; + ufd.ufd_data = buf; + + if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { + err = errno; + if (dpriv->fd < 0) + close(fd); + return _errno_to_libusb(err); + } + + if (dpriv->fd < 0) + close(fd); + + *host_endian = 0; + + return len; +} + +int +netbsd_get_configuration(struct libusb_device_handle *handle, int *config) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + usbi_dbg(""); + + if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0) + return _errno_to_libusb(errno); + + usbi_dbg("configuration %d", *config); + + return (LIBUSB_SUCCESS); +} + +int +netbsd_set_configuration(struct libusb_device_handle *handle, int config) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + usbi_dbg("configuration %d", config); + + if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) + return _errno_to_libusb(errno); + + return _cache_active_config_descriptor(handle->dev, dpriv->fd); +} + +int +netbsd_claim_interface(struct libusb_device_handle *handle, int iface) +{ + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + hpriv->endpoints[i] = -1; + + return (LIBUSB_SUCCESS); +} + +int +netbsd_release_interface(struct libusb_device_handle *handle, int iface) +{ + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + if (hpriv->endpoints[i] >= 0) + close(hpriv->endpoints[i]); + + return (LIBUSB_SUCCESS); +} + +int +netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, + int altsetting) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + struct usb_alt_interface intf; + + usbi_dbg("iface %d, setting %d", iface, altsetting); + + memset(&intf, 0, sizeof(intf)); + + intf.uai_interface_index = iface; + intf.uai_alt_no = altsetting; + + if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) + return _errno_to_libusb(errno); + + return (LIBUSB_SUCCESS); +} + +int +netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + struct usb_ctl_request req; + + usbi_dbg(""); + + req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; + req.ucr_request.bRequest = UR_CLEAR_FEATURE; + USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); + USETW(req.ucr_request.wIndex, endpoint); + USETW(req.ucr_request.wLength, 0); + + if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) + return _errno_to_libusb(errno); + + return (LIBUSB_SUCCESS); +} + +int +netbsd_reset_device(struct libusb_device_handle *handle) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +netbsd_destroy_device(struct libusb_device *dev) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + + usbi_dbg(""); + + free(dpriv->cdesc); +} + +int +netbsd_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct handle_priv *hpriv; + int err = 0; + + usbi_dbg(""); + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + err = _sync_control_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + if (IS_XFEROUT(transfer)) { + /* Isochronous write is not supported */ + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + err = _sync_gen_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && + transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + err = _sync_gen_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + + if (err) + return (err); + + usbi_signal_transfer_completion(itransfer); + + return (LIBUSB_SUCCESS); +} + +int +netbsd_cancel_transfer(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +netbsd_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + /* Nothing to do */ +} + +int +netbsd_handle_transfer_completion(struct usbi_transfer *itransfer) +{ + return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); +} + +int +netbsd_clock_gettime(int clkid, struct timespec *tp) +{ + usbi_dbg("clock %d", clkid); + + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); + + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime(CLOCK_MONOTONIC, tp); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +int +_errno_to_libusb(int err) +{ + switch (err) { + case EIO: + return (LIBUSB_ERROR_IO); + case EACCES: + return (LIBUSB_ERROR_ACCESS); + case ENOENT: + return (LIBUSB_ERROR_NO_DEVICE); + case ENOMEM: + return (LIBUSB_ERROR_NO_MEM); + } + + usbi_dbg("error: %s", strerror(err)); + + return (LIBUSB_ERROR_OTHER); +} + +int +_cache_active_config_descriptor(struct libusb_device *dev, int fd) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + struct usb_config_desc ucd; + struct usb_full_desc ufd; + unsigned char* buf; + int len; + + usbi_dbg("fd %d", fd); + + ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX; + + if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0) + return _errno_to_libusb(errno); + + usbi_dbg("active bLength %d", ucd.ucd_desc.bLength); + + len = UGETW(ucd.ucd_desc.wTotalLength); + buf = malloc(len); + if (buf == NULL) + return (LIBUSB_ERROR_NO_MEM); + + ufd.ufd_config_index = ucd.ucd_config_index; + ufd.ufd_size = len; + ufd.ufd_data = buf; + + usbi_dbg("index %d, len %d", ufd.ufd_config_index, len); + + if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { + free(buf); + return _errno_to_libusb(errno); + } + + if (dpriv->cdesc) + free(dpriv->cdesc); + dpriv->cdesc = buf; + + return (0); +} + +int +_sync_control_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct libusb_control_setup *setup; + struct device_priv *dpriv; + struct usb_ctl_request req; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; + setup = (struct libusb_control_setup *)transfer->buffer; + + usbi_dbg("type %d request %d value %d index %d length %d timeout %d", + setup->bmRequestType, setup->bRequest, + libusb_le16_to_cpu(setup->wValue), + libusb_le16_to_cpu(setup->wIndex), + libusb_le16_to_cpu(setup->wLength), transfer->timeout); + + req.ucr_request.bmRequestType = setup->bmRequestType; + req.ucr_request.bRequest = setup->bRequest; + /* Don't use USETW, libusb already deals with the endianness */ + (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; + (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; + (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; + req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + + if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) + req.ucr_flags = USBD_SHORT_XFER_OK; + + if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + return _errno_to_libusb(errno); + + if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) + return _errno_to_libusb(errno); + + itransfer->transferred = req.ucr_actlen; + + usbi_dbg("transferred %d", itransfer->transferred); + + return (0); +} + +int +_access_endpoint(struct libusb_transfer *transfer) +{ + struct handle_priv *hpriv; + struct device_priv *dpriv; + char *s, devnode[16]; + int fd, endpt; + mode_t mode; + + hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; + dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; + + endpt = UE_GET_ADDR(transfer->endpoint); + mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; + + usbi_dbg("endpoint %d mode %d", endpt, mode); + + if (hpriv->endpoints[endpt] < 0) { + /* Pick the right node given the control one */ + strlcpy(devnode, dpriv->devnode, sizeof(devnode)); + s = strchr(devnode, '.'); + snprintf(s, 4, ".%02d", endpt); + + /* We may need to read/write to the same endpoint later. */ + if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) + if ((fd = open(devnode, mode)) < 0) + return (-1); + + hpriv->endpoints[endpt] = fd; + } + + return (hpriv->endpoints[endpt]); +} + +int +_sync_gen_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + int fd, nr = 1; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + /* + * Bulk, Interrupt or Isochronous transfer depends on the + * endpoint and thus the node to open. + */ + if ((fd = _access_endpoint(transfer)) < 0) + return _errno_to_libusb(errno); + + if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + return _errno_to_libusb(errno); + + if (IS_XFERIN(transfer)) { + if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) + if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) + return _errno_to_libusb(errno); + + nr = read(fd, transfer->buffer, transfer->length); + } else { + nr = write(fd, transfer->buffer, transfer->length); + } + + if (nr < 0) + return _errno_to_libusb(errno); + + itransfer->transferred = nr; + + return (0); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c new file mode 100644 index 0000000000..f174e496c4 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c @@ -0,0 +1,771 @@ +/* + * Copyright © 2011-2013 Martin Pieuchot + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "libusbi.h" + +struct device_priv { + char *devname; /* name of the ugen(4) node */ + int fd; /* device file descriptor */ + + unsigned char *cdesc; /* active config descriptor */ + usb_device_descriptor_t ddesc; /* usb device descriptor */ +}; + +struct handle_priv { + int endpoints[USB_MAX_ENDPOINTS]; +}; + +/* + * Backend functions + */ +static int obsd_get_device_list(struct libusb_context *, + struct discovered_devs **); +static int obsd_open(struct libusb_device_handle *); +static void obsd_close(struct libusb_device_handle *); + +static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *, + int *); +static int obsd_get_active_config_descriptor(struct libusb_device *, + unsigned char *, size_t, int *); +static int obsd_get_config_descriptor(struct libusb_device *, uint8_t, + unsigned char *, size_t, int *); + +static int obsd_get_configuration(struct libusb_device_handle *, int *); +static int obsd_set_configuration(struct libusb_device_handle *, int); + +static int obsd_claim_interface(struct libusb_device_handle *, int); +static int obsd_release_interface(struct libusb_device_handle *, int); + +static int obsd_set_interface_altsetting(struct libusb_device_handle *, int, + int); +static int obsd_clear_halt(struct libusb_device_handle *, unsigned char); +static int obsd_reset_device(struct libusb_device_handle *); +static void obsd_destroy_device(struct libusb_device *); + +static int obsd_submit_transfer(struct usbi_transfer *); +static int obsd_cancel_transfer(struct usbi_transfer *); +static void obsd_clear_transfer_priv(struct usbi_transfer *); +static int obsd_handle_transfer_completion(struct usbi_transfer *); +static int obsd_clock_gettime(int, struct timespec *); + +/* + * Private functions + */ +static int _errno_to_libusb(int); +static int _cache_active_config_descriptor(struct libusb_device *); +static int _sync_control_transfer(struct usbi_transfer *); +static int _sync_gen_transfer(struct usbi_transfer *); +static int _access_endpoint(struct libusb_transfer *); + +static int _bus_open(int); + + +const struct usbi_os_backend usbi_backend = { + "Synchronous OpenBSD backend", + 0, + NULL, /* init() */ + NULL, /* exit() */ + NULL, /* set_option() */ + obsd_get_device_list, + NULL, /* hotplug_poll */ + obsd_open, + obsd_close, + + obsd_get_device_descriptor, + obsd_get_active_config_descriptor, + obsd_get_config_descriptor, + NULL, /* get_config_descriptor_by_value() */ + + obsd_get_configuration, + obsd_set_configuration, + + obsd_claim_interface, + obsd_release_interface, + + obsd_set_interface_altsetting, + obsd_clear_halt, + obsd_reset_device, + + NULL, /* alloc_streams */ + NULL, /* free_streams */ + + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + + NULL, /* kernel_driver_active() */ + NULL, /* detach_kernel_driver() */ + NULL, /* attach_kernel_driver() */ + + obsd_destroy_device, + + obsd_submit_transfer, + obsd_cancel_transfer, + obsd_clear_transfer_priv, + + NULL, /* handle_events() */ + obsd_handle_transfer_completion, + + obsd_clock_gettime, + 0, /* context_priv_size */ + sizeof(struct device_priv), + sizeof(struct handle_priv), + 0, /* transfer_priv_size */ +}; + +#define DEVPATH "/dev/" +#define USBDEV DEVPATH "usb" + +int +obsd_get_device_list(struct libusb_context * ctx, + struct discovered_devs **discdevs) +{ + struct discovered_devs *ddd; + struct libusb_device *dev; + struct device_priv *dpriv; + struct usb_device_info di; + struct usb_device_ddesc dd; + unsigned long session_id; + char devices[USB_MAX_DEVICES]; + char busnode[16]; + char *udevname; + int fd, addr, i, j; + + usbi_dbg(""); + + for (i = 0; i < 8; i++) { + snprintf(busnode, sizeof(busnode), USBDEV "%d", i); + + if ((fd = open(busnode, O_RDWR)) < 0) { + if (errno != ENOENT && errno != ENXIO) + usbi_err(ctx, "could not open %s", busnode); + continue; + } + + bzero(devices, sizeof(devices)); + for (addr = 1; addr < USB_MAX_DEVICES; addr++) { + if (devices[addr]) + continue; + + di.udi_addr = addr; + if (ioctl(fd, USB_DEVICEINFO, &di) < 0) + continue; + + /* + * XXX If ugen(4) is attached to the USB device + * it will be used. + */ + udevname = NULL; + for (j = 0; j < USB_MAX_DEVNAMES; j++) + if (!strncmp("ugen", di.udi_devnames[j], 4)) { + udevname = strdup(di.udi_devnames[j]); + break; + } + + session_id = (di.udi_bus << 8 | di.udi_addr); + dev = usbi_get_device_by_session_id(ctx, session_id); + + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + close(fd); + return (LIBUSB_ERROR_NO_MEM); + } + + dev->bus_number = di.udi_bus; + dev->device_address = di.udi_addr; + dev->speed = di.udi_speed; + + dpriv = (struct device_priv *)dev->os_priv; + dpriv->fd = -1; + dpriv->cdesc = NULL; + dpriv->devname = udevname; + + dd.udd_bus = di.udi_bus; + dd.udd_addr = di.udi_addr; + if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) { + libusb_unref_device(dev); + continue; + } + dpriv->ddesc = dd.udd_desc; + + if (_cache_active_config_descriptor(dev)) { + libusb_unref_device(dev); + continue; + } + + if (usbi_sanitize_device(dev)) { + libusb_unref_device(dev); + continue; + } + } + + ddd = discovered_devs_append(*discdevs, dev); + if (ddd == NULL) { + close(fd); + return (LIBUSB_ERROR_NO_MEM); + } + libusb_unref_device(dev); + + *discdevs = ddd; + devices[addr] = 1; + } + + close(fd); + } + + return (LIBUSB_SUCCESS); +} + +int +obsd_open(struct libusb_device_handle *handle) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + char devnode[16]; + + if (dpriv->devname) { + /* + * Only open ugen(4) attached devices read-write, all + * read-only operations are done through the bus node. + */ + snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", + dpriv->devname); + dpriv->fd = open(devnode, O_RDWR); + if (dpriv->fd < 0) + return _errno_to_libusb(errno); + + usbi_dbg("open %s: fd %d", devnode, dpriv->fd); + } + + return (LIBUSB_SUCCESS); +} + +void +obsd_close(struct libusb_device_handle *handle) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + if (dpriv->devname) { + usbi_dbg("close: fd %d", dpriv->fd); + + close(dpriv->fd); + dpriv->fd = -1; + } +} + +int +obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, + int *host_endian) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + + usbi_dbg(""); + + memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); + + *host_endian = 0; + + return (LIBUSB_SUCCESS); +} + +int +obsd_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buf, size_t len, int *host_endian) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; + + len = MIN(len, UGETW(ucd->wTotalLength)); + + usbi_dbg("len %d", len); + + memcpy(buf, dpriv->cdesc, len); + + *host_endian = 0; + + return (len); +} + +int +obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, + unsigned char *buf, size_t len, int *host_endian) +{ + struct usb_device_fdesc udf; + int fd, err; + + if ((fd = _bus_open(dev->bus_number)) < 0) + return _errno_to_libusb(errno); + + udf.udf_bus = dev->bus_number; + udf.udf_addr = dev->device_address; + udf.udf_config_index = idx; + udf.udf_size = len; + udf.udf_data = buf; + + usbi_dbg("index %d, len %d", udf.udf_config_index, len); + + if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { + err = errno; + close(fd); + return _errno_to_libusb(err); + } + close(fd); + + *host_endian = 0; + + return (len); +} + +int +obsd_get_configuration(struct libusb_device_handle *handle, int *config) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; + + *config = ucd->bConfigurationValue; + + usbi_dbg("bConfigurationValue %d", *config); + + return (LIBUSB_SUCCESS); +} + +int +obsd_set_configuration(struct libusb_device_handle *handle, int config) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + + if (dpriv->devname == NULL) + return (LIBUSB_ERROR_NOT_SUPPORTED); + + usbi_dbg("bConfigurationValue %d", config); + + if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) + return _errno_to_libusb(errno); + + return _cache_active_config_descriptor(handle->dev); +} + +int +obsd_claim_interface(struct libusb_device_handle *handle, int iface) +{ + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + hpriv->endpoints[i] = -1; + + return (LIBUSB_SUCCESS); +} + +int +obsd_release_interface(struct libusb_device_handle *handle, int iface) +{ + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + if (hpriv->endpoints[i] >= 0) + close(hpriv->endpoints[i]); + + return (LIBUSB_SUCCESS); +} + +int +obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, + int altsetting) +{ + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + struct usb_alt_interface intf; + + if (dpriv->devname == NULL) + return (LIBUSB_ERROR_NOT_SUPPORTED); + + usbi_dbg("iface %d, setting %d", iface, altsetting); + + memset(&intf, 0, sizeof(intf)); + + intf.uai_interface_index = iface; + intf.uai_alt_no = altsetting; + + if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) + return _errno_to_libusb(errno); + + return (LIBUSB_SUCCESS); +} + +int +obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) +{ + struct usb_ctl_request req; + int fd, err; + + if ((fd = _bus_open(handle->dev->bus_number)) < 0) + return _errno_to_libusb(errno); + + usbi_dbg(""); + + req.ucr_addr = handle->dev->device_address; + req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; + req.ucr_request.bRequest = UR_CLEAR_FEATURE; + USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); + USETW(req.ucr_request.wIndex, endpoint); + USETW(req.ucr_request.wLength, 0); + + if (ioctl(fd, USB_REQUEST, &req) < 0) { + err = errno; + close(fd); + return _errno_to_libusb(err); + } + close(fd); + + return (LIBUSB_SUCCESS); +} + +int +obsd_reset_device(struct libusb_device_handle *handle) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +obsd_destroy_device(struct libusb_device *dev) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + + usbi_dbg(""); + + free(dpriv->cdesc); + free(dpriv->devname); +} + +int +obsd_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct handle_priv *hpriv; + int err = 0; + + usbi_dbg(""); + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + err = _sync_control_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + if (IS_XFEROUT(transfer)) { + /* Isochronous write is not supported */ + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + err = _sync_gen_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && + transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + err = _sync_gen_transfer(itransfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + + if (err) + return (err); + + usbi_signal_transfer_completion(itransfer); + + return (LIBUSB_SUCCESS); +} + +int +obsd_cancel_transfer(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +obsd_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + /* Nothing to do */ +} + +int +obsd_handle_transfer_completion(struct usbi_transfer *itransfer) +{ + return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); +} + +int +obsd_clock_gettime(int clkid, struct timespec *tp) +{ + usbi_dbg("clock %d", clkid); + + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); + + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime(CLOCK_MONOTONIC, tp); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +int +_errno_to_libusb(int err) +{ + usbi_dbg("error: %s (%d)", strerror(err), err); + + switch (err) { + case EIO: + return (LIBUSB_ERROR_IO); + case EACCES: + return (LIBUSB_ERROR_ACCESS); + case ENOENT: + return (LIBUSB_ERROR_NO_DEVICE); + case ENOMEM: + return (LIBUSB_ERROR_NO_MEM); + case ETIMEDOUT: + return (LIBUSB_ERROR_TIMEOUT); + } + + return (LIBUSB_ERROR_OTHER); +} + +int +_cache_active_config_descriptor(struct libusb_device *dev) +{ + struct device_priv *dpriv = (struct device_priv *)dev->os_priv; + struct usb_device_cdesc udc; + struct usb_device_fdesc udf; + unsigned char* buf; + int fd, len, err; + + if ((fd = _bus_open(dev->bus_number)) < 0) + return _errno_to_libusb(errno); + + usbi_dbg("fd %d, addr %d", fd, dev->device_address); + + udc.udc_bus = dev->bus_number; + udc.udc_addr = dev->device_address; + udc.udc_config_index = USB_CURRENT_CONFIG_INDEX; + if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) { + err = errno; + close(fd); + return _errno_to_libusb(errno); + } + + usbi_dbg("active bLength %d", udc.udc_desc.bLength); + + len = UGETW(udc.udc_desc.wTotalLength); + buf = malloc(len); + if (buf == NULL) + return (LIBUSB_ERROR_NO_MEM); + + udf.udf_bus = dev->bus_number; + udf.udf_addr = dev->device_address; + udf.udf_config_index = udc.udc_config_index; + udf.udf_size = len; + udf.udf_data = buf; + + usbi_dbg("index %d, len %d", udf.udf_config_index, len); + + if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { + err = errno; + close(fd); + free(buf); + return _errno_to_libusb(err); + } + close(fd); + + if (dpriv->cdesc) + free(dpriv->cdesc); + dpriv->cdesc = buf; + + return (LIBUSB_SUCCESS); +} + +int +_sync_control_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct libusb_control_setup *setup; + struct device_priv *dpriv; + struct usb_ctl_request req; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; + setup = (struct libusb_control_setup *)transfer->buffer; + + usbi_dbg("type %x request %x value %x index %d length %d timeout %d", + setup->bmRequestType, setup->bRequest, + libusb_le16_to_cpu(setup->wValue), + libusb_le16_to_cpu(setup->wIndex), + libusb_le16_to_cpu(setup->wLength), transfer->timeout); + + req.ucr_addr = transfer->dev_handle->dev->device_address; + req.ucr_request.bmRequestType = setup->bmRequestType; + req.ucr_request.bRequest = setup->bRequest; + /* Don't use USETW, libusb already deals with the endianness */ + (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; + (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; + (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; + req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + + if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) + req.ucr_flags = USBD_SHORT_XFER_OK; + + if (dpriv->devname == NULL) { + /* + * XXX If the device is not attached to ugen(4) it is + * XXX still possible to submit a control transfer but + * XXX with the default timeout only. + */ + int fd, err; + + if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) + return _errno_to_libusb(errno); + + if ((ioctl(fd, USB_REQUEST, &req)) < 0) { + err = errno; + close(fd); + return _errno_to_libusb(err); + } + close(fd); + } else { + if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + return _errno_to_libusb(errno); + + if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) + return _errno_to_libusb(errno); + } + + itransfer->transferred = req.ucr_actlen; + + usbi_dbg("transferred %d", itransfer->transferred); + + return (0); +} + +int +_access_endpoint(struct libusb_transfer *transfer) +{ + struct handle_priv *hpriv; + struct device_priv *dpriv; + char devnode[16]; + int fd, endpt; + mode_t mode; + + hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; + dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; + + endpt = UE_GET_ADDR(transfer->endpoint); + mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; + + usbi_dbg("endpoint %d mode %d", endpt, mode); + + if (hpriv->endpoints[endpt] < 0) { + /* Pick the right endpoint node */ + snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d", + dpriv->devname, endpt); + + /* We may need to read/write to the same endpoint later. */ + if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) + if ((fd = open(devnode, mode)) < 0) + return (-1); + + hpriv->endpoints[endpt] = fd; + } + + return (hpriv->endpoints[endpt]); +} + +int +_sync_gen_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct device_priv *dpriv; + int fd, nr = 1; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; + + if (dpriv->devname == NULL) + return (LIBUSB_ERROR_NOT_SUPPORTED); + + /* + * Bulk, Interrupt or Isochronous transfer depends on the + * endpoint and thus the node to open. + */ + if ((fd = _access_endpoint(transfer)) < 0) + return _errno_to_libusb(errno); + + if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) + return _errno_to_libusb(errno); + + if (IS_XFERIN(transfer)) { + if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) + if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) + return _errno_to_libusb(errno); + + nr = read(fd, transfer->buffer, transfer->length); + } else { + nr = write(fd, transfer->buffer, transfer->length); + } + + if (nr < 0) + return _errno_to_libusb(errno); + + itransfer->transferred = nr; + + return (0); +} + +int +_bus_open(int number) +{ + char busnode[16]; + + snprintf(busnode, sizeof(busnode), USBDEV "%d", number); + + return open(busnode, O_RDWR); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c new file mode 100644 index 0000000000..337714aa6b --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c @@ -0,0 +1,84 @@ +/* + * poll_posix: poll compatibility wrapper for POSIX systems + * Copyright © 2013 RealVNC Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include +#include +#include + +#include "libusbi.h" + +int usbi_pipe(int pipefd[2]) +{ +#if defined(HAVE_PIPE2) + int ret = pipe2(pipefd, O_CLOEXEC); +#else + int ret = pipe(pipefd); +#endif + + if (ret != 0) { + usbi_err(NULL, "failed to create pipe (%d)", errno); + return ret; + } + +#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC) + ret = fcntl(pipefd[0], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } + + ret = fcntl(pipefd[1], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } +#endif + + ret = fcntl(pipefd[1], F_GETFL); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno); + goto err_close_pipe; + } + + return 0; + +err_close_pipe: + close(pipefd[0]); + close(pipefd[1]); + return ret; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h new file mode 100644 index 0000000000..5b4b2c905e --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h @@ -0,0 +1,11 @@ +#ifndef LIBUSB_POLL_POSIX_H +#define LIBUSB_POLL_POSIX_H + +#define usbi_write write +#define usbi_read read +#define usbi_close close +#define usbi_poll poll + +int usbi_pipe(int pipefd[2]); + +#endif /* LIBUSB_POLL_POSIX_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c new file mode 100644 index 0000000000..4d283333d1 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c @@ -0,0 +1,364 @@ +/* + * poll_windows: poll compatibility wrapper for Windows + * Copyright © 2017 Chris Dickens + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* + * poll() and pipe() Windows compatibility layer for libusb 1.0 + * + * The way this layer works is by using OVERLAPPED with async I/O transfers, as + * OVERLAPPED have an associated event which is flagged for I/O completion. + * + * For USB pollable async I/O, you would typically: + * - obtain a Windows HANDLE to a file or device that has been opened in + * OVERLAPPED mode + * - call usbi_create_fd with this handle to obtain a custom fd. + * - leave the core functions call the poll routine and flag POLLIN/POLLOUT + * + * The pipe pollable synchronous I/O works using the overlapped event associated + * with a fake pipe. The read/write functions are only meant to be used in that + * context. + */ +#include + +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" + +// public fd data +const struct winfd INVALID_WINFD = { -1, NULL }; + +// private data +struct file_descriptor { + enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type; + OVERLAPPED overlapped; +}; + +static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER; +static struct file_descriptor *fd_table[MAX_FDS]; + +static struct file_descriptor *create_fd(enum fd_type type) +{ + struct file_descriptor *fd = calloc(1, sizeof(*fd)); + if (fd == NULL) + return NULL; + fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (fd->overlapped.hEvent == NULL) { + free(fd); + return NULL; + } + fd->type = type; + return fd; +} + +static void free_fd(struct file_descriptor *fd) +{ + CloseHandle(fd->overlapped.hEvent); + free(fd); +} + +/* + * Create both an fd and an OVERLAPPED, so that it can be used with our + * polling function + * The handle MUST support overlapped transfers (usually requires CreateFile + * with FILE_FLAG_OVERLAPPED) + * Return a pollable file descriptor struct, or INVALID_WINFD on error + * + * Note that the fd returned by this function is a per-transfer fd, rather + * than a per-session fd and cannot be used for anything else but our + * custom functions. + * if you plan to do R/W on the same handle, you MUST create 2 fds: one for + * read and one for write. Using a single R/W fd is unsupported and will + * produce unexpected results + */ +struct winfd usbi_create_fd(void) +{ + struct file_descriptor *fd; + struct winfd wfd; + + fd = create_fd(FD_TYPE_TRANSFER); + if (fd == NULL) + return INVALID_WINFD; + + usbi_mutex_static_lock(&fd_table_lock); + for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) { + if (fd_table[wfd.fd] != NULL) + continue; + fd_table[wfd.fd] = fd; + break; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (wfd.fd == MAX_FDS) { + free_fd(fd); + return INVALID_WINFD; + } + + wfd.overlapped = &fd->overlapped; + + return wfd; +} + +static int check_pollfds(struct pollfd *fds, unsigned int nfds, + HANDLE *wait_handles, DWORD *nb_wait_handles) +{ + struct file_descriptor *fd; + unsigned int n; + int nready = 0; + + usbi_mutex_static_lock(&fd_table_lock); + + for (n = 0; n < nfds; ++n) { + fds[n].revents = 0; + + // Keep it simple - only allow either POLLIN *or* POLLOUT + assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT)); + if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS)) + fd = fd_table[fds[n].fd]; + else + fd = NULL; + + assert(fd != NULL); + if (fd == NULL) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if (HasOverlappedIoCompleted(&fd->overlapped) + && (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) { + fds[n].revents = fds[n].events; + nready++; + } else if (wait_handles != NULL) { + if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) { + usbi_warn(NULL, "too many HANDLEs to wait on"); + continue; + } + wait_handles[*nb_wait_handles] = fd->overlapped.hEvent; + (*nb_wait_handles)++; + } + } + + usbi_mutex_static_unlock(&fd_table_lock); + + return nready; +} +/* + * POSIX poll equivalent, using Windows OVERLAPPED + * Currently, this function only accepts one of POLLIN or POLLOUT per fd + * (but you can create multiple fds from the same handle for read and write) + */ +int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) +{ + HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; + DWORD nb_wait_handles = 0; + DWORD ret; + int nready; + + nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles); + + // If nothing was triggered, wait on all fds that require it + if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) { + ret = WaitForMultipleObjects(nb_wait_handles, wait_handles, + FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout); + if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) { + nready = check_pollfds(fds, nfds, NULL, NULL); + } else if (ret != WAIT_TIMEOUT) { + if (ret == WAIT_FAILED) + usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError()); + nready = -1; + } + } + + return nready; +} + +/* + * close a fake file descriptor + */ +int usbi_close(int _fd) +{ + struct file_descriptor *fd; + + if (_fd < 0 || _fd >= MAX_FDS) + goto err_badfd; + + usbi_mutex_static_lock(&fd_table_lock); + fd = fd_table[_fd]; + fd_table[_fd] = NULL; + usbi_mutex_static_unlock(&fd_table_lock); + + if (fd == NULL) + goto err_badfd; + + if (fd->type == FD_TYPE_PIPE) { + // InternalHigh is our reference count + fd->overlapped.InternalHigh--; + if (fd->overlapped.InternalHigh == 0) + free_fd(fd); + } else { + free_fd(fd); + } + + return 0; + +err_badfd: + errno = EBADF; + return -1; +} + +/* +* Create a fake pipe. +* As libusb only uses pipes for signaling, all we need from a pipe is an +* event. To that extent, we create a single wfd and overlapped as a means +* to access that event. +*/ +int usbi_pipe(int filedes[2]) +{ + struct file_descriptor *fd; + int r_fd = -1, w_fd = -1; + int i; + + fd = create_fd(FD_TYPE_PIPE); + if (fd == NULL) { + errno = ENOMEM; + return -1; + } + + // Use InternalHigh as a reference count + fd->overlapped.Internal = STATUS_PENDING; + fd->overlapped.InternalHigh = 2; + + usbi_mutex_static_lock(&fd_table_lock); + do { + for (i = 0; i < MAX_FDS; i++) { + if (fd_table[i] != NULL) + continue; + if (r_fd == -1) { + r_fd = i; + } else if (w_fd == -1) { + w_fd = i; + break; + } + } + + if (i == MAX_FDS) + break; + + fd_table[r_fd] = fd; + fd_table[w_fd] = fd; + + } while (0); + usbi_mutex_static_unlock(&fd_table_lock); + + if (i == MAX_FDS) { + free_fd(fd); + errno = EMFILE; + return -1; + } + + filedes[0] = r_fd; + filedes[1] = w_fd; + + return 0; +} + +/* + * synchronous write for fake "pipe" signaling + */ +ssize_t usbi_write(int fd, const void *buf, size_t count) +{ + int error = EBADF; + + UNUSED(buf); + + if (fd < 0 || fd >= MAX_FDS) + goto err_out; + + if (count != sizeof(unsigned char)) { + usbi_err(NULL, "this function should only used for signaling"); + error = EINVAL; + goto err_out; + } + + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_WAIT_0; + SetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (error) + goto err_out; + + return sizeof(unsigned char); + +err_out: + errno = error; + return -1; +} + +/* + * synchronous read for fake "pipe" signaling + */ +ssize_t usbi_read(int fd, void *buf, size_t count) +{ + int error = EBADF; + + UNUSED(buf); + + if (fd < 0 || fd >= MAX_FDS) + goto err_out; + + if (count != sizeof(unsigned char)) { + usbi_err(NULL, "this function should only used for signaling"); + error = EINVAL; + goto err_out; + } + + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_PENDING; + ResetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (error) + goto err_out; + + return sizeof(unsigned char); + +err_out: + errno = error; + return -1; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h new file mode 100644 index 0000000000..bd22c7f623 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h @@ -0,0 +1,97 @@ +/* + * Windows compat: POSIX compatibility wrapper + * Copyright © 2012-2013 RealVNC Ltd. + * Copyright © 2009-2010 Pete Batard + * Copyright © 2016-2018 Chris Dickens + * With contributions from Michael Plante, Orin Eman et al. + * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#pragma once + +#if defined(_MSC_VER) +// disable /W4 MSVC warnings that are benign +#pragma warning(disable:4127) // conditional expression is constant +#endif + +// Handle synchronous completion through the overlapped structure +#if !defined(STATUS_REPARSE) // reuse the REPARSE status code +#define STATUS_REPARSE ((LONG)0x00000104L) +#endif +#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE +#if defined(_WIN32_WCE) +// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it +#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING) +#endif +#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) + +#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) + +#define MAX_FDS 256 + +#define POLLIN 0x0001 /* There is data to read */ +#define POLLPRI 0x0002 /* There is urgent data to read */ +#define POLLOUT 0x0004 /* Writing now will not block */ +#define POLLERR 0x0008 /* Error condition */ +#define POLLHUP 0x0010 /* Hung up */ +#define POLLNVAL 0x0020 /* Invalid request: fd not open */ + +struct pollfd { + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; + +struct winfd { + int fd; // what's exposed to libusb core + OVERLAPPED *overlapped; // what will report our I/O status +}; + +extern const struct winfd INVALID_WINFD; + +struct winfd usbi_create_fd(void); + +int usbi_pipe(int pipefd[2]); +int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); +ssize_t usbi_write(int fd, const void *buf, size_t count); +ssize_t usbi_read(int fd, void *buf, size_t count); +int usbi_close(int fd); + +/* + * Timeval operations + */ +#if defined(DDKBUILD) +#include // defines timeval functions on DDK +#endif + +#if !defined(TIMESPEC_TO_TIMEVAL) +#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (long)(ts)->tv_sec; \ + (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \ +} +#endif +#if !defined(timersub) +#define timersub(a, b, result) \ +do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ +} while (0) +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c new file mode 100644 index 0000000000..7150a3e9d9 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c @@ -0,0 +1,1675 @@ +/* + * + * Copyright (c) 2016, Oracle and/or its affiliates. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "sunos_usb.h" + +#define UPDATEDRV_PATH "/usr/sbin/update_drv" +#define UPDATEDRV "update_drv" + +typedef list_t string_list_t; +typedef struct string_node { + char *string; + list_node_t link; +} string_node_t; + +/* + * Backend functions + */ +static int sunos_init(struct libusb_context *); +static void sunos_exit(struct libusb_context *); +static int sunos_get_device_list(struct libusb_context *, + struct discovered_devs **); +static int sunos_open(struct libusb_device_handle *); +static void sunos_close(struct libusb_device_handle *); +static int sunos_get_device_descriptor(struct libusb_device *, + uint8_t*, int *); +static int sunos_get_active_config_descriptor(struct libusb_device *, + uint8_t*, size_t, int *); +static int sunos_get_config_descriptor(struct libusb_device *, uint8_t, + uint8_t*, size_t, int *); +static int sunos_get_configuration(struct libusb_device_handle *, int *); +static int sunos_set_configuration(struct libusb_device_handle *, int); +static int sunos_claim_interface(struct libusb_device_handle *, int); +static int sunos_release_interface(struct libusb_device_handle *, int); +static int sunos_set_interface_altsetting(struct libusb_device_handle *, + int, int); +static int sunos_clear_halt(struct libusb_device_handle *, uint8_t); +static int sunos_reset_device(struct libusb_device_handle *); +static void sunos_destroy_device(struct libusb_device *); +static int sunos_submit_transfer(struct usbi_transfer *); +static int sunos_cancel_transfer(struct usbi_transfer *); +static void sunos_clear_transfer_priv(struct usbi_transfer *); +static int sunos_handle_transfer_completion(struct usbi_transfer *); +static int sunos_clock_gettime(int, struct timespec *); +static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface); +static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv); +static int sunos_usb_ioctl(struct libusb_device *dev, int cmd); + +static struct devctl_iocdata iocdata; +static int sunos_get_link(di_devlink_t devlink, void *arg) +{ + walk_link_t *larg = (walk_link_t *)arg; + const char *p; + const char *q; + + if (larg->path) { + char *content = (char *)di_devlink_content(devlink); + char *start = strstr(content, "/devices/"); + start += strlen("/devices"); + usbi_dbg("%s", start); + + /* line content must have minor node */ + if (start == NULL || + strncmp(start, larg->path, larg->len) != 0 || + start[larg->len] != ':') + return (DI_WALK_CONTINUE); + } + + p = di_devlink_path(devlink); + q = strrchr(p, '/'); + usbi_dbg("%s", q); + + *(larg->linkpp) = strndup(p, strlen(p) - strlen(q)); + + return (DI_WALK_TERMINATE); +} + + +static int sunos_physpath_to_devlink( + const char *node_path, const char *match, char **link_path) +{ + walk_link_t larg; + di_devlink_handle_t hdl; + + *link_path = NULL; + larg.linkpp = link_path; + if ((hdl = di_devlink_init(NULL, 0)) == NULL) { + usbi_dbg("di_devlink_init failure"); + return (-1); + } + + larg.len = strlen(node_path); + larg.path = (char *)node_path; + + (void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK, + (void *)&larg, sunos_get_link); + + (void) di_devlink_fini(&hdl); + + if (*link_path == NULL) { + usbi_dbg("there is no devlink for this path"); + return (-1); + } + + return 0; +} + +static int +sunos_usb_ioctl(struct libusb_device *dev, int cmd) +{ + int fd; + nvlist_t *nvlist; + char *end; + char *phypath; + char *hubpath; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + devctl_ap_state_t devctl_ap_state; + + dpriv = (sunos_dev_priv_t *)dev->os_priv; + phypath = dpriv->phypath; + + end = strrchr(phypath, '/'); + if (end == NULL) + return (-1); + hubpath = strndup(phypath, end - phypath); + if (hubpath == NULL) + return (-1); + + end = strrchr(hubpath, '@'); + if (end == NULL) { + free(hubpath); + return (-1); + } + end++; + usbi_dbg("unitaddr: %s", end); + + nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); + nvlist_add_int32(nvlist, "port", dev->port_number); + //find the hub path + snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath); + usbi_dbg("ioctl hub path: %s", path_arg); + + fd = open(path_arg, O_RDONLY); + if (fd < 0) { + usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno)); + nvlist_free(nvlist); + free(hubpath); + return (-1); + } + + memset(&iocdata, 0, sizeof(iocdata)); + memset(&devctl_ap_state, 0, sizeof(devctl_ap_state)); + + nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0); + + iocdata.cmd = DEVCTL_AP_GETSTATE; + iocdata.flags = 0; + iocdata.c_nodename = "hub"; + iocdata.c_unitaddr = end; + iocdata.cpyout_buf = &devctl_ap_state; + usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz); + + errno = 0; + if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, DEVCTL_AP_GETSTATE, errno, strerror(errno)); + } else { + usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate); + usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate); + } + + errno = 0; + iocdata.cmd = cmd; + if (ioctl(fd, (int)cmd, &iocdata) != 0) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, cmd, errno, strerror(errno)); + sleep(2); + } + + close(fd); + free(iocdata.nvl_user); + nvlist_free(nvlist); + free(hubpath); + + return (-errno); +} + +static int +sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface) +{ + sunos_dev_priv_t *dpriv; + dpriv = (sunos_dev_priv_t *)dev->dev->os_priv; + + usbi_dbg("%s", dpriv->ugenpath); + + return (dpriv->ugenpath == NULL); +} + +/* + * Private functions + */ +static int _errno_to_libusb(int); +static int sunos_usb_get_status(int fd); + +static int sunos_init(struct libusb_context *ctx) +{ + return (LIBUSB_SUCCESS); +} + +static void sunos_exit(struct libusb_context *ctx) +{ + usbi_dbg(""); +} + +static string_list_t * +sunos_new_string_list(void) +{ + string_list_t *list; + + list = calloc(1, sizeof(*list)); + if (list != NULL) + list_create(list, sizeof(string_node_t), + offsetof(string_node_t, link)); + + return (list); +} + +static int +sunos_append_to_string_list(string_list_t *list, const char *arg) +{ + string_node_t *np; + + np = calloc(1, sizeof(*np)); + if (!np) + return (-1); + + np->string = strdup(arg); + if (!np->string) { + free(np); + return (-1); + } + + list_insert_tail(list, np); + + return (0); +} + +static void +sunos_free_string_list(string_list_t *list) +{ + string_node_t *np; + + while ((np = list_remove_head(list)) != NULL) { + free(np->string); + free(np); + } + + free(list); +} + +static char ** +sunos_build_argv_list(string_list_t *list) +{ + char **argv_list; + string_node_t *np; + int n; + + n = 1; /* Start at 1 for NULL terminator */ + for (np = list_head(list); np != NULL; np = list_next(list, np)) + n++; + + argv_list = calloc(n, sizeof(char *)); + if (argv_list == NULL) + return NULL; + + n = 0; + for (np = list_head(list); np != NULL; np = list_next(list, np)) + argv_list[n++] = np->string; + + return (argv_list); +} + + +static int +sunos_exec_command(struct libusb_context *ctx, const char *path, + string_list_t *list) +{ + pid_t pid; + int status; + int waitstat; + int exit_status; + char **argv_list; + + argv_list = sunos_build_argv_list(list); + if (argv_list == NULL) + return (-1); + + pid = fork(); + if (pid == 0) { + /* child */ + execv(path, argv_list); + _exit(127); + } else if (pid > 0) { + /* parent */ + do { + waitstat = waitpid(pid, &status, 0); + } while ((waitstat == -1 && errno == EINTR) || + (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status))); + + if (waitstat == 0) { + if (WIFEXITED(status)) + exit_status = WEXITSTATUS(status); + else + exit_status = WTERMSIG(status); + } else { + usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + } else { + /* fork failed */ + usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + + free(argv_list); + + return (exit_status); +} + +static int +sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* attach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-a"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor, + dpriv->dev_descr.idProduct); + sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath); + + if (access(dpriv->ugenpath, F_OK) == -1) { + usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver"); + return (LIBUSB_ERROR_IO); + } + + return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv); +} + +static int +sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + /* we open the dev in detach driver, so we need close it first. */ + sunos_close(dev_handle); + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* detach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-d"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + return 0; +} + +static int +sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) +{ + int proplen; + int n, *addr, *port_prop; + char *phypath; + uint8_t *rdata; + struct libusb_device_descriptor *descr; + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + char match_str[PATH_MAX]; + + /* Device descriptors */ + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-dev-descriptor", &rdata); + if (proplen <= 0) { + + return (LIBUSB_ERROR_IO); + } + + descr = (struct libusb_device_descriptor *)rdata; + bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); + dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB); + dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor); + dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct); + dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice); + + /* Raw configuration descriptors */ + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-raw-cfg-descriptors", &rdata); + if (proplen <= 0) { + usbi_dbg("can't find raw config descriptors"); + + return (LIBUSB_ERROR_IO); + } + dpriv->raw_cfgdescr = calloc(1, proplen); + if (dpriv->raw_cfgdescr == NULL) { + return (LIBUSB_ERROR_NO_MEM); + } else { + bcopy(rdata, dpriv->raw_cfgdescr, proplen); + dpriv->cfgvalue = ((struct libusb_config_descriptor *) + rdata)->bConfigurationValue; + } + + n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop); + + if ((n != 1) || (*port_prop <= 0)) { + return (LIBUSB_ERROR_IO); + } + dev->port_number = *port_prop; + + /* device physical path */ + phypath = di_devfs_path(node); + if (phypath) { + dpriv->phypath = strdup(phypath); + snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct); + usbi_dbg("match is %s", match_str); + sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath); + di_devfs_path_free(phypath); + + } else { + free(dpriv->raw_cfgdescr); + + return (LIBUSB_ERROR_IO); + } + + /* address */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr); + if (n != 1 || *addr == 0) { + usbi_dbg("can't get address"); + } else { + dev->device_address = *addr; + } + + /* speed */ + if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { + dev->speed = LIBUSB_SPEED_LOW; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { + dev->speed = LIBUSB_SPEED_HIGH; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { + dev->speed = LIBUSB_SPEED_FULL; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { + dev->speed = LIBUSB_SPEED_SUPER; + } + + usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, " + "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct, + dpriv->phypath, dev->bus_number, dev->port_number, dev->speed); + + return (LIBUSB_SUCCESS); +} + +static int +sunos_add_devices(di_devlink_t link, void *arg) +{ + struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; + struct node_args *nargs; + di_node_t myself, dn; + uint64_t session_id = 0; + uint64_t sid = 0; + uint64_t bdf = 0; + struct libusb_device *dev; + sunos_dev_priv_t *devpriv; + int n; + int i = 0; + int *addr_prop; + uint8_t bus_number = 0; + uint32_t * regbuf = NULL; + uint32_t reg; + + nargs = (struct node_args *)largs->nargs; + myself = largs->myself; + + /* + * Construct session ID. + * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf + * 8 bits 8bits 8 bits 16bits + */ + if (myself == DI_NODE_NIL) + return (DI_WALK_CONTINUE); + + dn = myself; + /* find the root hub */ + while (di_prop_exists(DDI_DEV_T_ANY, dn, "root-hub") != 1) { + usbi_dbg("find_root_hub:%s", di_devfs_path(dn)); + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, + "assigned-address", &addr_prop); + session_id |= ((addr_prop[0] & 0xff) << i++ * 8); + dn = di_parent_node(dn); + } + + /* dn is the root hub node */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf); + reg = regbuf[0]; + bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + /* bdf must larger than i*8 bits */ + session_id |= (bdf << i * 8); + bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + + usbi_dbg("device bus address=%s:%x, name:%s", + di_bus_addr(myself), bus_number, di_node_name(dn)); + usbi_dbg("session id org:%lx", session_id); + + /* dn is the usb device */ + for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) { + usbi_dbg("device path:%s", di_devfs_path(dn)); + /* skip hub devices, because its driver can not been unload */ + if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1) + continue; + /* usb_addr */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, + "assigned-address", &addr_prop); + if ((n != 1) || (addr_prop[0] == 0)) { + usbi_dbg("cannot get valid usb_addr"); + continue; + } + + sid = (session_id << 8) | (addr_prop[0] & 0xff) ; + usbi_dbg("session id %lx", sid); + + dev = usbi_get_device_by_session_id(nargs->ctx, sid); + if (dev == NULL) { + dev = usbi_alloc_device(nargs->ctx, sid); + if (dev == NULL) { + usbi_dbg("can't alloc device"); + continue; + } + devpriv = (sunos_dev_priv_t *)dev->os_priv; + dev->bus_number = bus_number; + + if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + usbi_dbg("get infomation fail"); + continue; + } + if (usbi_sanitize_device(dev) < 0) { + libusb_unref_device(dev); + usbi_dbg("sanatize failed: "); + return (DI_WALK_TERMINATE); + } + } else { + devpriv = (sunos_dev_priv_t *)dev->os_priv; + usbi_dbg("Dev %s exists", devpriv->ugenpath); + } + + if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { + usbi_dbg("cannot append device"); + } + + /* + * we alloc and hence ref this dev. We don't need to ref it + * hereafter. Front end or app should take care of their ref. + */ + libusb_unref_device(dev); + + usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", + devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid, + (*nargs->discdevs)->len, bdf); + } + + return (DI_WALK_CONTINUE); +} + +static int +sunos_walk_minor_node_link(di_node_t node, void *args) +{ + di_minor_t minor = DI_MINOR_NIL; + char *minor_path; + struct devlink_cbarg arg; + struct node_args *nargs = (struct node_args *)args; + di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; + + /* walk each minor to find usb devices */ + while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { + minor_path = di_devfs_minor_path(minor); + arg.nargs = args; + arg.myself = node; + arg.minor = minor; + (void) di_devlink_walk(devlink_hdl, + "^usb/hub[0-9]+", minor_path, + DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); + di_devfs_path_free(minor_path); + } + + /* switch to a different node */ + nargs->last_ugenpath = NULL; + + return (DI_WALK_CONTINUE); +} + +int +sunos_get_device_list(struct libusb_context * ctx, + struct discovered_devs **discdevs) +{ + di_node_t root_node; + struct node_args args; + di_devlink_handle_t devlink_hdl; + + args.ctx = ctx; + args.discdevs = discdevs; + args.last_ugenpath = NULL; + if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { + usbi_dbg("di_int() failed: %s", strerror(errno)); + return (LIBUSB_ERROR_IO); + } + + if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { + di_fini(root_node); + usbi_dbg("di_devlink_init() failed: %s", strerror(errno)); + + return (LIBUSB_ERROR_IO); + } + args.dlink_hdl = devlink_hdl; + + /* walk each node to find USB devices */ + if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args, + sunos_walk_minor_node_link) == -1) { + usbi_dbg("di_walk_node() failed: %s", strerror(errno)); + di_fini(root_node); + + return (LIBUSB_ERROR_IO); + } + + di_fini(root_node); + di_devlink_fini(&devlink_hdl); + + usbi_dbg("%d devices", (*discdevs)->len); + + return ((*discdevs)->len); +} + +static int +sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv) +{ + char filename[PATH_MAX + 1]; + + if (hpriv->eps[0].datafd > 0) { + + return (LIBUSB_SUCCESS); + } + snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath); + + usbi_dbg("opening %s", filename); + hpriv->eps[0].datafd = open(filename, O_RDWR); + if (hpriv->eps[0].datafd < 0) { + return(_errno_to_libusb(errno)); + } + + snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath); + hpriv->eps[0].statfd = open(filename, O_RDONLY); + if (hpriv->eps[0].statfd < 0) { + close(hpriv->eps[0].datafd); + hpriv->eps[0].datafd = -1; + + return(_errno_to_libusb(errno)); + } + + return (LIBUSB_SUCCESS); +} + +static void +sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev) +{ + int i; + + /* not close ep0 */ + for (i = 1; i < USB_MAXENDPOINTS; i++) { + if (hdev->eps[i].datafd != -1) { + (void) close(hdev->eps[i].datafd); + hdev->eps[i].datafd = -1; + } + if (hdev->eps[i].statfd != -1) { + (void) close(hdev->eps[i].statfd); + hdev->eps[i].statfd = -1; + } + } +} + +static void +sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv) +{ + if (hdev->eps[0].datafd >= 0) { + close(hdev->eps[0].datafd); + close(hdev->eps[0].statfd); + hdev->eps[0].datafd = -1; + hdev->eps[0].statfd = -1; + } +} + +static uchar_t +sunos_usb_ep_index(uint8_t ep_addr) +{ + return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) + + ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0)); +} + +static int +sunos_find_interface(struct libusb_device_handle *hdev, + uint8_t endpoint, uint8_t *interface) +{ + struct libusb_config_descriptor *config; + int r; + int iface_idx; + + r = libusb_get_active_config_descriptor(hdev->dev, &config); + if (r < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { + const struct libusb_interface *iface = + &config->interface[iface_idx]; + int altsetting_idx; + + for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; + altsetting_idx++) { + const struct libusb_interface_descriptor *altsetting = + &iface->altsetting[altsetting_idx]; + int ep_idx; + + for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; + ep_idx++) { + const struct libusb_endpoint_descriptor *ep = + &altsetting->endpoint[ep_idx]; + if (ep->bEndpointAddress == endpoint) { + *interface = iface_idx; + libusb_free_config_descriptor(config); + + return (LIBUSB_SUCCESS); + } + } + } + } + libusb_free_config_descriptor(config); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +static int +sunos_check_device_and_status_open(struct libusb_device_handle *hdl, + uint8_t ep_addr, int ep_type) +{ + char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1]; + char cfg_num[16], alt_num[16]; + int fd, fdstat, mode; + uint8_t ifc = 0; + uint8_t ep_index; + sunos_dev_handle_priv_t *hpriv; + + usbi_dbg("open ep 0x%02x", ep_addr); + hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; + ep_index = sunos_usb_ep_index(ep_addr); + /* ep already opened */ + if ((hpriv->eps[ep_index].datafd > 0) && + (hpriv->eps[ep_index].statfd > 0)) { + usbi_dbg("ep 0x%02x already opened, return success", + ep_addr); + + return (0); + } + + if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) { + usbi_dbg("can't find interface for endpoint 0x%02x", + ep_addr); + + return (EACCES); + } + + /* create filename */ + if (hpriv->config_index > 0) { + (void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d", + hpriv->config_index + 1); + } else { + bzero(cfg_num, sizeof (cfg_num)); + } + + if (hpriv->altsetting[ifc] > 0) { + (void) snprintf(alt_num, sizeof (alt_num), ".%d", + hpriv->altsetting[ifc]); + } else { + bzero(alt_num, sizeof (alt_num)); + } + + (void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d", + hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num, + (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : + "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK)); + (void) snprintf(statfilename, PATH_MAX, "%sstat", filename); + + /* + * for interrupt IN endpoints, we need to enable one xfer + * mode before opening the endpoint + */ + if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) && + (ep_addr & LIBUSB_ENDPOINT_IN)) { + char control = USB_EP_INTR_ONE_XFER; + int count; + + /* open the status device node for the ep first RDWR */ + if ((fdstat = open(statfilename, O_RDWR)) == -1) { + usbi_dbg("can't open %s RDWR: %d", + statfilename, errno); + } else { + count = write(fdstat, &control, sizeof (control)); + if (count != 1) { + /* this should have worked */ + usbi_dbg("can't write to %s: %d", + statfilename, errno); + (void) close(fdstat); + + return (errno); + } + /* close status node and open xfer node first */ + close (fdstat); + } + } + + /* open the xfer node first in case alt needs to be changed */ + if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + mode = O_RDWR; + } else if (ep_addr & LIBUSB_ENDPOINT_IN) { + mode = O_RDONLY; + } else { + mode = O_WRONLY; + } + + /* + * IMPORTANT: must open data xfer node first and then open stat node + * Otherwise, it will fail on multi-config or multi-altsetting devices + * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and + * ugen_epxs_check_alt_switch() in ugen driver source code. + */ + if ((fd = open(filename, mode)) == -1) { + usbi_dbg("can't open %s: %d(%s)", filename, errno, + strerror(errno)); + + return (errno); + } + /* open the status node */ + if ((fdstat = open(statfilename, O_RDONLY)) == -1) { + usbi_dbg("can't open %s: %d", statfilename, errno); + + (void) close(fd); + + return (errno); + } + + hpriv->eps[ep_index].datafd = fd; + hpriv->eps[ep_index].statfd = fdstat; + usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat); + + return (0); +} + +int +sunos_open(struct libusb_device_handle *handle) +{ + sunos_dev_handle_priv_t *hpriv; + sunos_dev_priv_t *dpriv; + int i; + int ret; + + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + hpriv->dpriv = dpriv; + + /* set all file descriptors to "closed" */ + for (i = 0; i < USB_MAXENDPOINTS; i++) { + hpriv->eps[i].datafd = -1; + hpriv->eps[i].statfd = -1; + } + + if (sunos_kernel_driver_active(handle, 0)) { + /* pretend we can open the device */ + return (LIBUSB_SUCCESS); + } + + if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { + usbi_dbg("fail: %d", ret); + return (ret); + } + + return (LIBUSB_SUCCESS); +} + +void +sunos_close(struct libusb_device_handle *handle) +{ + sunos_dev_handle_priv_t *hpriv; + sunos_dev_priv_t *dpriv; + + usbi_dbg(""); + if (!handle) { + return; + } + + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + if (!hpriv) { + return; + } + dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + if (!dpriv) { + return; + } + + sunos_usb_close_all_eps(hpriv); + sunos_usb_close_ep0(hpriv, dpriv); +} + +int +sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf, + int *host_endian) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + + memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); + *host_endian = 0; + + return (LIBUSB_SUCCESS); +} + +int +sunos_get_active_config_descriptor(struct libusb_device *dev, + uint8_t *buf, size_t len, int *host_endian) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + struct libusb_config_descriptor *cfg; + int proplen; + di_node_t node; + uint8_t *rdata; + + /* + * Keep raw configuration descriptors updated, in case config + * has ever been changed through setCfg. + */ + if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) { + usbi_dbg("di_int() failed: %s", strerror(errno)); + return (LIBUSB_ERROR_IO); + } + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-raw-cfg-descriptors", &rdata); + if (proplen <= 0) { + usbi_dbg("can't find raw config descriptors"); + + return (LIBUSB_ERROR_IO); + } + dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen); + if (dpriv->raw_cfgdescr == NULL) { + return (LIBUSB_ERROR_NO_MEM); + } else { + bcopy(rdata, dpriv->raw_cfgdescr, proplen); + dpriv->cfgvalue = ((struct libusb_config_descriptor *) + rdata)->bConfigurationValue; + } + di_fini(node); + + cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr; + len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength)); + memcpy(buf, dpriv->raw_cfgdescr, len); + *host_endian = 0; + usbi_dbg("path:%s len %d", dpriv->phypath, len); + + return (len); +} + +int +sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx, + uint8_t *buf, size_t len, int *host_endian) +{ + /* XXX */ + return(sunos_get_active_config_descriptor(dev, buf, len, host_endian)); +} + +int +sunos_get_configuration(struct libusb_device_handle *handle, int *config) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + + *config = dpriv->cfgvalue; + + usbi_dbg("bConfigurationValue %d", *config); + + return (LIBUSB_SUCCESS); +} + +int +sunos_set_configuration(struct libusb_device_handle *handle, int config) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + sunos_dev_handle_priv_t *hpriv; + + usbi_dbg("bConfigurationValue %d", config); + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + + if (dpriv->ugenpath == NULL) + return (LIBUSB_ERROR_NOT_SUPPORTED); + + if (config < 1 || config > dpriv->dev_descr.bNumConfigurations) + return (LIBUSB_ERROR_INVALID_PARAM); + + dpriv->cfgvalue = config; + hpriv->config_index = config - 1; + + return (LIBUSB_SUCCESS); +} + +int +sunos_claim_interface(struct libusb_device_handle *handle, int iface) +{ + usbi_dbg("iface %d", iface); + if (iface < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + return (LIBUSB_SUCCESS); +} + +int +sunos_release_interface(struct libusb_device_handle *handle, int iface) +{ + sunos_dev_handle_priv_t *hpriv = + (sunos_dev_handle_priv_t *)handle->os_priv; + + usbi_dbg("iface %d", iface); + if (iface < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + /* XXX: can we release it? */ + hpriv->altsetting[iface] = 0; + + return (LIBUSB_SUCCESS); +} + +int +sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface, + int altsetting) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + sunos_dev_handle_priv_t *hpriv = + (sunos_dev_handle_priv_t *)handle->os_priv; + + usbi_dbg("iface %d, setting %d", iface, altsetting); + + if (iface < 0 || altsetting < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + if (dpriv->ugenpath == NULL) + return (LIBUSB_ERROR_NOT_FOUND); + + /* XXX: can we switch altsetting? */ + hpriv->altsetting[iface] = altsetting; + + return (LIBUSB_SUCCESS); +} + +static void +usb_dump_data(unsigned char *data, size_t size) +{ + int i; + + if (getenv("LIBUSB_DEBUG") == NULL) { + return; + } + + (void) fprintf(stderr, "data dump:"); + for (i = 0; i < size; i++) { + if (i % 16 == 0) { + (void) fprintf(stderr, "\n%08x ", i); + } + (void) fprintf(stderr, "%02x ", (uchar_t)data[i]); + } + (void) fprintf(stderr, "\n"); +} + +static void +sunos_async_callback(union sigval arg) +{ + struct sunos_transfer_priv *tpriv = + (struct sunos_transfer_priv *)arg.sival_ptr; + struct libusb_transfer *xfer = tpriv->transfer; + struct aiocb *aiocb = &tpriv->aiocb; + int ret; + sunos_dev_handle_priv_t *hpriv; + uint8_t ep; + + hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(xfer->endpoint); + + ret = aio_error(aiocb); + if (ret != 0) { + xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); + } else { + xfer->actual_length = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = + aio_return(aiocb); + } + + usb_dump_data(xfer->buffer, xfer->actual_length); + + usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, + xfer->actual_length); + + /* async notification */ + usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); +} + +static int +sunos_do_async_io(struct libusb_transfer *transfer) +{ + int ret = -1; + struct aiocb *aiocb; + sunos_dev_handle_priv_t *hpriv; + uint8_t ep; + struct sunos_transfer_priv *tpriv; + + usbi_dbg(""); + + tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); + hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(transfer->endpoint); + + tpriv->transfer = transfer; + aiocb = &tpriv->aiocb; + bzero(aiocb, sizeof (*aiocb)); + aiocb->aio_fildes = hpriv->eps[ep].datafd; + aiocb->aio_buf = transfer->buffer; + aiocb->aio_nbytes = transfer->length; + aiocb->aio_lio_opcode = + ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) == + LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE; + aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD; + aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv; + aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback; + + if (aiocb->aio_lio_opcode == LIO_READ) { + ret = aio_read(aiocb); + } else { + ret = aio_write(aiocb); + } + + return (ret); +} + +/* return the number of bytes read/written */ +static int +usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status) +{ + int error; + int ret = -1; + + usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s", + fd, stat_fd, size, flag? "WRITE":"READ"); + + switch (flag) { + case READ: + errno = 0; + ret = read(fd, data, size); + usb_dump_data(data, size); + break; + case WRITE: + usb_dump_data(data, size); + errno = 0; + ret = write(fd, data, size); + break; + } + + usbi_dbg("usb_do_io(): amount=%d", ret); + + if (ret < 0) { + int save_errno = errno; + + usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(), + flag?"WRITE":"READ", errno, strerror(errno), ret); + + /* sunos_usb_get_status will do a read and overwrite errno */ + error = sunos_usb_get_status(stat_fd); + usbi_dbg("io status=%d errno=%d(%s)", error, + save_errno, strerror(save_errno)); + + if (status) { + *status = save_errno; + } + + return (save_errno); + + } else if (status) { + *status = 0; + } + + return (ret); +} + +static int +solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) +{ + int ret = -1, setup_ret; + int status; + sunos_dev_handle_priv_t *hpriv; + struct libusb_device_handle *hdl = transfer->dev_handle; + uint16_t wLength; + uint8_t *data = transfer->buffer; + + hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; + wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + if (hpriv->eps[0].datafd == -1) { + usbi_dbg("ep0 not opened"); + + return (LIBUSB_ERROR_NOT_FOUND); + } + + if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { + usbi_dbg("IN request"); + ret = usb_do_io(hpriv->eps[0].datafd, + hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE, + WRITE, (int *)&status); + } else { + usbi_dbg("OUT request"); + ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, + transfer->buffer, transfer->length, WRITE, + (int *)&transfer->status); + } + + setup_ret = ret; + if (ret < LIBUSB_CONTROL_SETUP_SIZE) { + usbi_dbg("error sending control msg: %d", ret); + + return (LIBUSB_ERROR_IO); + } + + ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + /* Read the remaining bytes for IN request */ + if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == + LIBUSB_ENDPOINT_IN)) { + usbi_dbg("DATA: %d", transfer->length - setup_ret); + ret = usb_do_io(hpriv->eps[0].datafd, + hpriv->eps[0].statfd, + (char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, + wLength, READ, (int *)&transfer->status); + } + + if (ret >= 0) { + transfer->actual_length = ret; + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret; + } + usbi_dbg("Done: ctrl data bytes %d", ret); + + /* sync transfer handling */ + ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), + transfer->status); + + return (ret); +} + +int +sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint) +{ + int ret; + + usbi_dbg("endpoint=0x%02x", endpoint); + + ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | + LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD, + LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000); + + usbi_dbg("ret=%d", ret); + + return (ret); +} + +int +sunos_reset_device(struct libusb_device_handle *handle) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +sunos_destroy_device(struct libusb_device *dev) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + usbi_dbg("destroy everyting"); + free(dpriv->raw_cfgdescr); + free(dpriv->ugenpath); + free(dpriv->phypath); +} + +int +sunos_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct libusb_device_handle *hdl; + int err = 0; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hdl = transfer->dev_handle; + + err = sunos_check_device_and_status_open(hdl, + transfer->endpoint, transfer->type); + if (err < 0) { + + return (_errno_to_libusb(err)); + } + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + /* sync transfer */ + usbi_dbg("CTRL transfer: %d", transfer->length); + err = solaris_submit_ctrl_on_default(transfer); + break; + + case LIBUSB_TRANSFER_TYPE_BULK: + /* fallthru */ + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK) + usbi_dbg("BULK transfer: %d", transfer->length); + else + usbi_dbg("INTR transfer: %d", transfer->length); + err = sunos_do_async_io(transfer); + break; + + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + /* Isochronous/Stream is not supported */ + + /* fallthru */ + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) + usbi_dbg("ISOC transfer: %d", transfer->length); + else + usbi_dbg("BULK STREAM transfer: %d", transfer->length); + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + + return (err); +} + +int +sunos_cancel_transfer(struct usbi_transfer *itransfer) +{ + sunos_xfer_priv_t *tpriv; + sunos_dev_handle_priv_t *hpriv; + struct libusb_transfer *transfer; + struct aiocb *aiocb; + uint8_t ep; + int ret; + + tpriv = usbi_transfer_get_os_priv(itransfer); + aiocb = &tpriv->aiocb; + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(transfer->endpoint); + + ret = aio_cancel(hpriv->eps[ep].datafd, aiocb); + + usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes, + hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)? + strerror(0):strerror(errno)); + + if (ret != AIO_CANCELED) { + ret = _errno_to_libusb(errno); + } else { + /* + * we don't need to call usbi_handle_transfer_cancellation(), + * because we'll handle everything in sunos_async_callback. + */ + ret = LIBUSB_SUCCESS; + } + + return (ret); +} + +void +sunos_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + /* Nothing to do */ +} + +int +sunos_handle_transfer_completion(struct usbi_transfer *itransfer) +{ + return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); +} + +int +sunos_clock_gettime(int clkid, struct timespec *tp) +{ + usbi_dbg("clock %d", clkid); + + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); + + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime(CLOCK_MONOTONIC, tp); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +int +_errno_to_libusb(int err) +{ + usbi_dbg("error: %s (%d)", strerror(err), err); + + switch (err) { + case EIO: + return (LIBUSB_ERROR_IO); + case EACCES: + return (LIBUSB_ERROR_ACCESS); + case ENOENT: + return (LIBUSB_ERROR_NO_DEVICE); + case ENOMEM: + return (LIBUSB_ERROR_NO_MEM); + case ETIMEDOUT: + return (LIBUSB_ERROR_TIMEOUT); + } + + return (LIBUSB_ERROR_OTHER); +} + +/* + * sunos_usb_get_status: + * gets status of endpoint + * + * Returns: ugen's last cmd status + */ +static int +sunos_usb_get_status(int fd) +{ + int status, ret; + + usbi_dbg("sunos_usb_get_status(): fd=%d", fd); + + ret = read(fd, &status, sizeof (status)); + if (ret == sizeof (status)) { + switch (status) { + case USB_LC_STAT_NOERROR: + usbi_dbg("No Error"); + break; + case USB_LC_STAT_CRC: + usbi_dbg("CRC Timeout Detected\n"); + break; + case USB_LC_STAT_BITSTUFFING: + usbi_dbg("Bit Stuffing Violation\n"); + break; + case USB_LC_STAT_DATA_TOGGLE_MM: + usbi_dbg("Data Toggle Mismatch\n"); + break; + case USB_LC_STAT_STALL: + usbi_dbg("End Point Stalled\n"); + break; + case USB_LC_STAT_DEV_NOT_RESP: + usbi_dbg("Device is Not Responding\n"); + break; + case USB_LC_STAT_PID_CHECKFAILURE: + usbi_dbg("PID Check Failure\n"); + break; + case USB_LC_STAT_UNEXP_PID: + usbi_dbg("Unexpected PID\n"); + break; + case USB_LC_STAT_DATA_OVERRUN: + usbi_dbg("Data Exceeded Size\n"); + break; + case USB_LC_STAT_DATA_UNDERRUN: + usbi_dbg("Less data received\n"); + break; + case USB_LC_STAT_BUFFER_OVERRUN: + usbi_dbg("Buffer Size Exceeded\n"); + break; + case USB_LC_STAT_BUFFER_UNDERRUN: + usbi_dbg("Buffer Underrun\n"); + break; + case USB_LC_STAT_TIMEOUT: + usbi_dbg("Command Timed Out\n"); + break; + case USB_LC_STAT_NOT_ACCESSED: + usbi_dbg("Not Accessed by h/w\n"); + break; + case USB_LC_STAT_UNSPECIFIED_ERR: + usbi_dbg("Unspecified Error\n"); + break; + case USB_LC_STAT_NO_BANDWIDTH: + usbi_dbg("No Bandwidth\n"); + break; + case USB_LC_STAT_HW_ERR: + usbi_dbg("Host Controller h/w Error\n"); + break; + case USB_LC_STAT_SUSPENDED: + usbi_dbg("Device was Suspended\n"); + break; + case USB_LC_STAT_DISCONNECTED: + usbi_dbg("Device was Disconnected\n"); + break; + case USB_LC_STAT_INTR_BUF_FULL: + usbi_dbg("Interrupt buffer was full\n"); + break; + case USB_LC_STAT_INVALID_REQ: + usbi_dbg("Request was Invalid\n"); + break; + case USB_LC_STAT_INTERRUPTED: + usbi_dbg("Request was Interrupted\n"); + break; + case USB_LC_STAT_NO_RESOURCES: + usbi_dbg("No resources available for " + "request\n"); + break; + case USB_LC_STAT_INTR_POLLING_FAILED: + usbi_dbg("Failed to Restart Poll"); + break; + default: + usbi_dbg("Error Not Determined %d\n", + status); + break; + } + } else { + usbi_dbg("read stat error: %s",strerror(errno)); + status = -1; + } + + return (status); +} + +const struct usbi_os_backend usbi_backend = { + .name = "Solaris", + .caps = 0, + .init = sunos_init, + .exit = sunos_exit, + .get_device_list = sunos_get_device_list, + .get_device_descriptor = sunos_get_device_descriptor, + .get_active_config_descriptor = sunos_get_active_config_descriptor, + .get_config_descriptor = sunos_get_config_descriptor, + .hotplug_poll = NULL, + .open = sunos_open, + .close = sunos_close, + .get_configuration = sunos_get_configuration, + .set_configuration = sunos_set_configuration, + + .claim_interface = sunos_claim_interface, + .release_interface = sunos_release_interface, + .set_interface_altsetting = sunos_set_interface_altsetting, + .clear_halt = sunos_clear_halt, + .reset_device = sunos_reset_device, /* TODO */ + .alloc_streams = NULL, + .free_streams = NULL, + .kernel_driver_active = sunos_kernel_driver_active, + .detach_kernel_driver = sunos_detach_kernel_driver, + .attach_kernel_driver = sunos_attach_kernel_driver, + .destroy_device = sunos_destroy_device, + .submit_transfer = sunos_submit_transfer, + .cancel_transfer = sunos_cancel_transfer, + .handle_events = NULL, + .clear_transfer_priv = sunos_clear_transfer_priv, + .handle_transfer_completion = sunos_handle_transfer_completion, + .clock_gettime = sunos_clock_gettime, + .device_priv_size = sizeof(sunos_dev_priv_t), + .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), + .transfer_priv_size = sizeof(sunos_xfer_priv_t), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h new file mode 100644 index 0000000000..52bb3d33a0 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2016, Oracle and/or its affiliates. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_SUNOS_H +#define LIBUSB_SUNOS_H + +#include +#include +#include "libusbi.h" + +#define READ 0 +#define WRITE 1 + +typedef struct sunos_device_priv { + uint8_t cfgvalue; /* active config value */ + uint8_t *raw_cfgdescr; /* active config descriptor */ + struct libusb_device_descriptor dev_descr; /* usb device descriptor */ + char *ugenpath; /* name of the ugen(4) node */ + char *phypath; /* physical path */ +} sunos_dev_priv_t; + +typedef struct endpoint { + int datafd; /* data file */ + int statfd; /* state file */ +} sunos_ep_priv_t; + +typedef struct sunos_device_handle_priv { + uint8_t altsetting[USB_MAXINTERFACES]; /* a interface's alt */ + uint8_t config_index; + sunos_ep_priv_t eps[USB_MAXENDPOINTS]; + sunos_dev_priv_t *dpriv; /* device private */ +} sunos_dev_handle_priv_t; + +typedef struct sunos_transfer_priv { + struct aiocb aiocb; + struct libusb_transfer *transfer; +} sunos_xfer_priv_t; + +struct node_args { + struct libusb_context *ctx; + struct discovered_devs **discdevs; + const char *last_ugenpath; + di_devlink_handle_t dlink_hdl; +}; + +struct devlink_cbarg { + struct node_args *nargs; /* di node walk arguments */ + di_node_t myself; /* the di node */ + di_minor_t minor; +}; + +typedef struct walk_link { + char *path; + int len; + char **linkpp; +} walk_link_t; + +/* AIO callback args */ +struct aio_callback_args{ + struct libusb_transfer *transfer; + struct aiocb aiocb; +}; + +#endif /* LIBUSB_SUNOS_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c new file mode 100644 index 0000000000..16a7578b81 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c @@ -0,0 +1,80 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright © 2011 Vitali Lovich + * Copyright © 2011 Peter Stuge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#if defined(__linux__) || defined(__OpenBSD__) +# if defined(__OpenBSD__) +# define _BSD_SOURCE +# endif +# include +# include +#elif defined(__APPLE__) +# include +#elif defined(__CYGWIN__) +# include +#endif + +#include "threads_posix.h" +#include "libusbi.h" + +int usbi_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timeval *tv) +{ + struct timespec timeout; + int r; + + r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout); + if (r < 0) + return r; + + timeout.tv_sec += tv->tv_sec; + timeout.tv_nsec += tv->tv_usec * 1000; + while (timeout.tv_nsec >= 1000000000L) { + timeout.tv_nsec -= 1000000000L; + timeout.tv_sec++; + } + + return pthread_cond_timedwait(cond, mutex, &timeout); +} + +int usbi_get_tid(void) +{ + int ret; +#if defined(__ANDROID__) + ret = gettid(); +#elif defined(__linux__) + ret = syscall(SYS_gettid); +#elif defined(__OpenBSD__) + /* The following only works with OpenBSD > 5.1 as it requires + real thread support. For 5.1 and earlier, -1 is returned. */ + ret = syscall(SYS_getthrid); +#elif defined(__APPLE__) + ret = (int)pthread_mach_thread_np(pthread_self()); +#elif defined(__CYGWIN__) + ret = GetCurrentThreadId(); +#else + ret = -1; +#endif +/* TODO: NetBSD thread ID support */ + return ret; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h new file mode 100644 index 0000000000..9f1ef94bc7 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h @@ -0,0 +1,102 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright © 2010 Peter Stuge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_THREADS_POSIX_H +#define LIBUSB_THREADS_POSIX_H + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t usbi_mutex_static_t; +static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} + +typedef pthread_mutex_t usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + return pthread_mutex_init(mutex, NULL); +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return pthread_mutex_trylock(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_destroy(mutex); +} + +typedef pthread_cond_t usbi_cond_t; +static inline void usbi_cond_init(pthread_cond_t *cond) +{ + (void)pthread_cond_init(cond, NULL); +} +static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + return pthread_cond_wait(cond, mutex); +} +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv); +static inline void usbi_cond_broadcast(usbi_cond_t *cond) +{ + (void)pthread_cond_broadcast(cond); +} +static inline void usbi_cond_destroy(usbi_cond_t *cond) +{ + (void)pthread_cond_destroy(cond); +} + +typedef pthread_key_t usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + (void)pthread_key_create(key, NULL); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return pthread_getspecific(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)pthread_setspecific(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)pthread_key_delete(key); +} + +int usbi_get_tid(void); + +#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c new file mode 100644 index 0000000000..409c490553 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c @@ -0,0 +1,126 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright © 2010 Michael Plante + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "libusbi.h" + +struct usbi_cond_perthread { + struct list_head list; + HANDLE event; +}; + +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + while (InterlockedExchange(mutex, 1L) == 1L) + SleepEx(0, TRUE); +} + +void usbi_cond_init(usbi_cond_t *cond) +{ + list_init(&cond->waiters); + list_init(&cond->not_waiting); +} + +static int usbi_cond_intwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, DWORD timeout_ms) +{ + struct usbi_cond_perthread *pos; + DWORD r; + + // Same assumption as usbi_cond_broadcast() holds + if (list_empty(&cond->not_waiting)) { + pos = malloc(sizeof(*pos)); + if (pos == NULL) + return ENOMEM; // This errno is not POSIX-allowed. + pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. + if (pos->event == NULL) { + free(pos); + return ENOMEM; + } + } else { + pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list); + list_del(&pos->list); // remove from not_waiting list. + // Ensure the event is clear before waiting + WaitForSingleObject(pos->event, 0); + } + + list_add(&pos->list, &cond->waiters); + + LeaveCriticalSection(mutex); + r = WaitForSingleObject(pos->event, timeout_ms); + EnterCriticalSection(mutex); + + list_del(&pos->list); + list_add(&pos->list, &cond->not_waiting); + + if (r == WAIT_OBJECT_0) + return 0; + else if (r == WAIT_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; +} + +// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + return usbi_cond_intwait(cond, mutex, INFINITE); +} + +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv) +{ + DWORD millis; + + millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); + /* round up to next millisecond */ + if (tv->tv_usec % 1000) + millis++; + return usbi_cond_intwait(cond, mutex, millis); +} + +void usbi_cond_broadcast(usbi_cond_t *cond) +{ + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + struct usbi_cond_perthread *pos; + + list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) + SetEvent(pos->event); + // The wait function will remove its respective item from the list. +} + +void usbi_cond_destroy(usbi_cond_t *cond) +{ + // This assumes no one is using this anymore. The check MAY NOT BE safe. + struct usbi_cond_perthread *pos, *next; + + if (!list_empty(&cond->waiters)) + return; // (!see above!) + list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) { + CloseHandle(pos->event); + list_del(&pos->list); + free(pos); + } +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h new file mode 100644 index 0000000000..409de2d0e2 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h @@ -0,0 +1,111 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright © 2010 Michael Plante + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_THREADS_WINDOWS_H +#define LIBUSB_THREADS_WINDOWS_H + +#define USBI_MUTEX_INITIALIZER 0L +#ifdef _WIN32_WCE +typedef LONG usbi_mutex_static_t; +#else +typedef volatile LONG usbi_mutex_static_t; +#endif +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex); +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + InterlockedExchange(mutex, 0L); +} + +typedef CRITICAL_SECTION usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + InitializeCriticalSection(mutex); + return 0; +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + EnterCriticalSection(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + LeaveCriticalSection(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return !TryEnterCriticalSection(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + DeleteCriticalSection(mutex); +} + +// We *were* getting timespec from pthread.h: +#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) +#define HAVE_STRUCT_TIMESPEC 1 +#define _TIMESPEC_DEFINED 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */ + +// We *were* getting ETIMEDOUT from pthread.h: +#ifndef ETIMEDOUT +#define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +typedef struct usbi_cond { + // Every time a thread touches the CV, it winds up in one of these lists. + // It stays there until the CV is destroyed, even if the thread terminates. + struct list_head waiters; + struct list_head not_waiting; +} usbi_cond_t; + +void usbi_cond_init(usbi_cond_t *cond); +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv); +void usbi_cond_broadcast(usbi_cond_t *cond); +void usbi_cond_destroy(usbi_cond_t *cond); + +typedef DWORD usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + *key = TlsAlloc(); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return TlsGetValue(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)TlsSetValue(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)TlsFree(key); +} + +static inline int usbi_get_tid(void) +{ + return (int)GetCurrentThreadId(); +} + +#endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c new file mode 100644 index 0000000000..a0f35e93e5 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c @@ -0,0 +1,888 @@ +/* + * Windows CE backend for libusb 1.0 + * Copyright © 2011-2013 RealVNC Ltd. + * Large portions taken from Windows backend, which is + * Copyright © 2009-2010 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "libusbi.h" +#include "wince_usb.h" + +// Global variables +int errno = 0; +static uint64_t hires_frequency, hires_ticks_to_ps; +static HANDLE driver_handle = INVALID_HANDLE_VALUE; +static int concurrent_usage = -1; + +/* + * Converts a windows error to human readable string + * uses retval as errorcode, or, if 0, use GetLastError() + */ +#if defined(ENABLE_LOGGING) +static const char *windows_error_str(DWORD error_code) +{ + static TCHAR wErr_string[ERR_BUFFER_SIZE]; + static char err_string[ERR_BUFFER_SIZE]; + + DWORD size; + int len; + + if (error_code == 0) + error_code = GetLastError(); + + len = sprintf(err_string, "[%u] ", (unsigned int)error_code); + + size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + wErr_string, ERR_BUFFER_SIZE, NULL); + if (size == 0) { + DWORD format_error = GetLastError(); + if (format_error) + snprintf(err_string, ERR_BUFFER_SIZE, + "Windows error code %u (FormatMessage error code %u)", + (unsigned int)error_code, (unsigned int)format_error); + else + snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); + } else { + // Remove CR/LF terminators, if present + size_t pos = size - 2; + if (wErr_string[pos] == 0x0D) + wErr_string[pos] = 0; + + if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL)) + strcpy(err_string, "Unable to convert error string"); + } + + return err_string; +} +#endif + +static struct wince_device_priv *_device_priv(struct libusb_device *dev) +{ + return (struct wince_device_priv *)dev->os_priv; +} + +// ceusbkwrapper to libusb error code mapping +static int translate_driver_error(DWORD error) +{ + switch (error) { + case ERROR_INVALID_PARAMETER: + return LIBUSB_ERROR_INVALID_PARAM; + case ERROR_CALL_NOT_IMPLEMENTED: + case ERROR_NOT_SUPPORTED: + return LIBUSB_ERROR_NOT_SUPPORTED; + case ERROR_NOT_ENOUGH_MEMORY: + return LIBUSB_ERROR_NO_MEM; + case ERROR_INVALID_HANDLE: + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_BUSY: + return LIBUSB_ERROR_BUSY; + + // Error codes that are either unexpected, or have + // no suitable LIBUSB_ERROR equivalent. + case ERROR_CANCELLED: + case ERROR_INTERNAL_ERROR: + default: + return LIBUSB_ERROR_OTHER; + } +} + +static BOOL init_dllimports(void) +{ + DLL_GET_HANDLE(ceusbkwrapper); + DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); + + return TRUE; +} + +static void exit_dllimports(void) +{ + DLL_FREE_HANDLE(ceusbkwrapper); +} + +static int init_device( + struct libusb_device *dev, UKW_DEVICE drv_dev, + unsigned char bus_addr, unsigned char dev_addr) +{ + struct wince_device_priv *priv = _device_priv(dev); + int r = LIBUSB_SUCCESS; + + dev->bus_number = bus_addr; + dev->device_address = dev_addr; + priv->dev = drv_dev; + + if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) + r = translate_driver_error(GetLastError()); + + return r; +} + +// Internal API functions +static int wince_init(struct libusb_context *ctx) +{ + int r = LIBUSB_ERROR_OTHER; + HANDLE semaphore; + LARGE_INTEGER li_frequency; + TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + + _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphore(NULL, 1, 1, sem_name); + if (semaphore == NULL) { + usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_MEM; + } + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore's release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); + CloseHandle(semaphore); + return LIBUSB_ERROR_NO_MEM; + } + + // NB: concurrent usage supposes that init calls are equally balanced with + // exit calls. If init is called more than exit, we will not exit properly + if ( ++concurrent_usage == 0 ) { // First init? + // Load DLL imports + if (!init_dllimports()) { + usbi_err(ctx, "could not resolve DLL functions"); + r = LIBUSB_ERROR_NOT_SUPPORTED; + goto init_exit; + } + + // try to open a handle to the driver + driver_handle = UkwOpenDriver(); + if (driver_handle == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not connect to driver"); + r = LIBUSB_ERROR_NOT_SUPPORTED; + goto init_exit; + } + + // find out if we have access to a monotonic (hires) timer + if (QueryPerformanceFrequency(&li_frequency)) { + hires_frequency = li_frequency.QuadPart; + // The hires frequency can go as high as 4 GHz, so we'll use a conversion + // to picoseconds to compute the tv_nsecs part in clock_gettime + hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; + usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); + } else { + usbi_dbg("no hires timer available on this platform"); + hires_frequency = 0; + hires_ticks_to_ps = UINT64_C(0); + } + } + // At this stage, either we went through full init successfully, or didn't need to + r = LIBUSB_SUCCESS; + +init_exit: // Holds semaphore here. + if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? + exit_dllimports(); + + if (driver_handle != INVALID_HANDLE_VALUE) { + UkwCloseDriver(driver_handle); + driver_handle = INVALID_HANDLE_VALUE; + } + } + + if (r != LIBUSB_SUCCESS) + --concurrent_usage; // Not expected to call libusb_exit if we failed. + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); + return r; +} + +static void wince_exit(struct libusb_context *ctx) +{ + HANDLE semaphore; + TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); + + _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphore(NULL, 1, 1, sem_name); + if (semaphore == NULL) + return; + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + CloseHandle(semaphore); + return; + } + + // Only works if exits and inits are balanced exactly + if (--concurrent_usage < 0) { // Last exit + exit_dllimports(); + + if (driver_handle != INVALID_HANDLE_VALUE) { + UkwCloseDriver(driver_handle); + driver_handle = INVALID_HANDLE_VALUE; + } + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); +} + +static int wince_get_device_list( + struct libusb_context *ctx, + struct discovered_devs **discdevs) +{ + UKW_DEVICE devices[MAX_DEVICE_COUNT]; + struct discovered_devs *new_devices = *discdevs; + DWORD count = 0, i; + struct libusb_device *dev = NULL; + unsigned char bus_addr, dev_addr; + unsigned long session_id; + BOOL success; + DWORD release_list_offset = 0; + int r = LIBUSB_SUCCESS; + + success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count); + if (!success) { + int libusbErr = translate_driver_error(GetLastError()); + usbi_err(ctx, "could not get devices: %s", windows_error_str(0)); + return libusbErr; + } + + for (i = 0; i < count; ++i) { + release_list_offset = i; + success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id); + if (!success) { + r = translate_driver_error(GetLastError()); + usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0)); + goto err_out; + } + + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev) { + usbi_dbg("using existing device for %u/%u (session %lu)", + bus_addr, dev_addr, session_id); + // Release just this element in the device list (as we already hold a + // reference to it). + UkwReleaseDeviceList(driver_handle, &devices[i], 1); + release_list_offset++; + } else { + usbi_dbg("allocating new device for %u/%u (session %lu)", + bus_addr, dev_addr, session_id); + dev = usbi_alloc_device(ctx, session_id); + if (!dev) { + r = LIBUSB_ERROR_NO_MEM; + goto err_out; + } + + r = init_device(dev, devices[i], bus_addr, dev_addr); + if (r < 0) + goto err_out; + + r = usbi_sanitize_device(dev); + if (r < 0) + goto err_out; + } + + new_devices = discovered_devs_append(new_devices, dev); + if (!new_devices) { + r = LIBUSB_ERROR_NO_MEM; + goto err_out; + } + + libusb_unref_device(dev); + } + + *discdevs = new_devices; + return r; +err_out: + *discdevs = new_devices; + libusb_unref_device(dev); + // Release the remainder of the unprocessed device list. + // The devices added to new_devices already will still be passed up to libusb, + // which can dispose of them at its leisure. + UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset); + return r; +} + +static int wince_open(struct libusb_device_handle *handle) +{ + // Nothing to do to open devices as a handle to it has + // been retrieved by wince_get_device_list + return LIBUSB_SUCCESS; +} + +static void wince_close(struct libusb_device_handle *handle) +{ + // Nothing to do as wince_open does nothing. +} + +static int wince_get_device_descriptor( + struct libusb_device *device, + unsigned char *buffer, int *host_endian) +{ + struct wince_device_priv *priv = _device_priv(device); + + *host_endian = 1; + memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH); + return LIBUSB_SUCCESS; +} + +static int wince_get_active_config_descriptor( + struct libusb_device *device, + unsigned char *buffer, size_t len, int *host_endian) +{ + struct wince_device_priv *priv = _device_priv(device); + DWORD actualSize = len; + + *host_endian = 0; + if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) + return translate_driver_error(GetLastError()); + + return actualSize; +} + +static int wince_get_config_descriptor( + struct libusb_device *device, + uint8_t config_index, + unsigned char *buffer, size_t len, int *host_endian) +{ + struct wince_device_priv *priv = _device_priv(device); + DWORD actualSize = len; + + *host_endian = 0; + if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) + return translate_driver_error(GetLastError()); + + return actualSize; +} + +static int wince_get_configuration( + struct libusb_device_handle *handle, + int *config) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + UCHAR cv = 0; + + if (!UkwGetConfig(priv->dev, &cv)) + return translate_driver_error(GetLastError()); + + (*config) = cv; + return LIBUSB_SUCCESS; +} + +static int wince_set_configuration( + struct libusb_device_handle *handle, + int config) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + // Setting configuration 0 places the device in Address state. + // This should correspond to the "unconfigured state" required by + // libusb when the specified configuration is -1. + UCHAR cv = (config < 0) ? 0 : config; + if (!UkwSetConfig(priv->dev, cv)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_claim_interface( + struct libusb_device_handle *handle, + int interface_number) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwClaimInterface(priv->dev, interface_number)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_release_interface( + struct libusb_device_handle *handle, + int interface_number) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) + return translate_driver_error(GetLastError()); + + if (!UkwReleaseInterface(priv->dev, interface_number)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_set_interface_altsetting( + struct libusb_device_handle *handle, + int interface_number, int altsetting) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_clear_halt( + struct libusb_device_handle *handle, + unsigned char endpoint) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwClearHaltHost(priv->dev, endpoint)) + return translate_driver_error(GetLastError()); + + if (!UkwClearHaltDevice(priv->dev, endpoint)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_reset_device( + struct libusb_device_handle *handle) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwResetDevice(priv->dev)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_kernel_driver_active( + struct libusb_device_handle *handle, + int interface_number) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + BOOL result = FALSE; + + if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) + return translate_driver_error(GetLastError()); + + return result ? 1 : 0; +} + +static int wince_detach_kernel_driver( + struct libusb_device_handle *handle, + int interface_number) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwDetachKernelDriver(priv->dev, interface_number)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_attach_kernel_driver( + struct libusb_device_handle *handle, + int interface_number) +{ + struct wince_device_priv *priv = _device_priv(handle->dev); + + if (!UkwAttachKernelDriver(priv->dev, interface_number)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static void wince_destroy_device(struct libusb_device *dev) +{ + struct wince_device_priv *priv = _device_priv(dev); + + UkwReleaseDeviceList(driver_handle, &priv->dev, 1); +} + +static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; +} + +static int wince_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + + if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) + return translate_driver_error(GetLastError()); + + return LIBUSB_SUCCESS; +} + +static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); + BOOL direction_in, ret; + struct winfd wfd; + DWORD flags; + PUKW_CONTROL_HEADER setup = NULL; + const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; + int r; + + if (control_transfer) { + setup = (PUKW_CONTROL_HEADER) transfer->buffer; + direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; + } else { + direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; + } + flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; + flags |= UKW_TF_SHORT_TRANSFER_OK; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT); + if (r) { + usbi_close(wfd.fd); + return r; + } + + transfer_priv->pollable_fd = wfd; + + if (control_transfer) { + // Split out control setup header and data buffer + DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); + PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)]; + + ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped); + } else { + ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, + transfer->length, &transfer->actual_length, wfd.overlapped); + } + + if (!ret) { + int libusbErr = translate_driver_error(GetLastError()); + usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", + control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + return libusbErr; + } + + + return LIBUSB_SUCCESS; +} + +static int wince_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + return wince_submit_control_or_bulk_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return LIBUSB_ERROR_NOT_SUPPORTED; + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static void wince_transfer_callback( + struct usbi_transfer *itransfer, + uint32_t io_result, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int status; + + usbi_dbg("handling I/O completion with errcode %u", io_result); + + if (io_result == ERROR_NOT_SUPPORTED && + transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) { + /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper + * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the + * endpoint isn't actually stalled. + * + * One example of this is that some devices will occasionally fail to reply to an IN + * token. The WinCE USB layer carries on with the transaction until it is completed + * (or cancelled) but then completes it with USB_ERROR_STALL. + * + * This code therefore needs to confirm that there really is a stall error, by both + * checking the pipe status and requesting the endpoint status from the device. + */ + BOOL halted = FALSE; + usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall"); + if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) { + /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS + * control request to the device. This is done synchronously, which is a bit + * naughty, but this is a special corner case. + */ + WORD wStatus = 0; + DWORD written = 0; + UKW_CONTROL_HEADER ctrlHeader; + ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD | + LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT; + ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS; + ctrlHeader.wValue = 0; + ctrlHeader.wIndex = transfer->endpoint; + ctrlHeader.wLength = sizeof(wStatus); + if (UkwIssueControlTransfer(priv->dev, + UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT, + &ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) { + if (written == sizeof(wStatus) && + (wStatus & STATUS_HALT_FLAG) == 0) { + if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) { + usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success"); + io_result = ERROR_SUCCESS; + } else { + usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error"); + io_result = ERROR_IO_DEVICE; + } + } + } + } + } + + switch(io_result) { + case ERROR_SUCCESS: + itransfer->transferred += io_size; + status = LIBUSB_TRANSFER_COMPLETED; + break; + case ERROR_CANCELLED: + usbi_dbg("detected transfer cancel"); + status = LIBUSB_TRANSFER_CANCELLED; + break; + case ERROR_NOT_SUPPORTED: + case ERROR_GEN_FAILURE: + usbi_dbg("detected endpoint stall"); + status = LIBUSB_TRANSFER_STALL; + break; + case ERROR_SEM_TIMEOUT: + usbi_dbg("detected semaphore timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + break; + case ERROR_OPERATION_ABORTED: + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); + status = LIBUSB_TRANSFER_ERROR; + break; + } + + wince_clear_transfer_priv(itransfer); + if (status == LIBUSB_TRANSFER_CANCELLED) + usbi_handle_transfer_cancellation(itransfer); + else + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); +} + +static void wince_handle_callback( + struct usbi_transfer *itransfer, + uint32_t io_result, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + wince_transfer_callback (itransfer, io_result, io_size); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + } +} + +static int wince_handle_events( + struct libusb_context *ctx, + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) +{ + struct wince_transfer_priv* transfer_priv = NULL; + POLL_NFDS_TYPE i = 0; + BOOL found = FALSE; + struct usbi_transfer *itransfer; + DWORD io_size, io_result; + int r = LIBUSB_SUCCESS; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + + usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); + + if (!fds[i].revents) + continue; + + num_ready--; + + // Because a Windows OVERLAPPED is used for poll emulation, + // a pollable fd is created and stored with each transfer + usbi_mutex_lock(&ctx->flying_transfers_lock); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_priv = usbi_transfer_get_os_priv(itransfer); + if (transfer_priv->pollable_fd.fd == fds[i].fd) { + found = TRUE; + break; + } + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { + io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; + io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; + usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); + // let handle_callback free the event using the transfer wfd + // If you don't use the transfer wfd, you run a risk of trying to free a + // newly allocated wfd that took the place of the one from the transfer. + wince_handle_callback(itransfer, io_result, io_size); + } else if (found) { + usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); + r = LIBUSB_ERROR_OTHER; + break; + } else { + usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); + r = LIBUSB_ERROR_NOT_FOUND; + break; + } + } + usbi_mutex_unlock(&ctx->open_devs_lock); + + return r; +} + +/* + * Monotonic and real time functions + */ +static int wince_clock_gettime(int clk_id, struct timespec *tp) +{ + LARGE_INTEGER hires_counter; + ULARGE_INTEGER rtime; + FILETIME filetime; + SYSTEMTIME st; + + switch(clk_id) { + case USBI_CLOCK_MONOTONIC: + if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) { + tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); + tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); + return LIBUSB_SUCCESS; + } + // Fall through and return real-time if monotonic read failed or was not detected @ init + case USBI_CLOCK_REALTIME: + // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx + // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 + // Note however that our resolution is bounded by the Windows system time + // functions and is at best of the order of 1 ms (or, usually, worse) + GetSystemTime(&st); + SystemTimeToFileTime(&st, &filetime); + rtime.LowPart = filetime.dwLowDateTime; + rtime.HighPart = filetime.dwHighDateTime; + rtime.QuadPart -= EPOCH_TIME; + tp->tv_sec = (long)(rtime.QuadPart / 10000000); + tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +const struct usbi_os_backend usbi_backend = { + "Windows CE", + 0, + wince_init, + wince_exit, + NULL, /* set_option() */ + + wince_get_device_list, + NULL, /* hotplug_poll */ + wince_open, + wince_close, + + wince_get_device_descriptor, + wince_get_active_config_descriptor, + wince_get_config_descriptor, + NULL, /* get_config_descriptor_by_value() */ + + wince_get_configuration, + wince_set_configuration, + wince_claim_interface, + wince_release_interface, + + wince_set_interface_altsetting, + wince_clear_halt, + wince_reset_device, + + NULL, /* alloc_streams */ + NULL, /* free_streams */ + + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + + wince_kernel_driver_active, + wince_detach_kernel_driver, + wince_attach_kernel_driver, + + wince_destroy_device, + + wince_submit_transfer, + wince_cancel_transfer, + wince_clear_transfer_priv, + + wince_handle_events, + NULL, /* handle_transfer_completion() */ + + wince_clock_gettime, + 0, + sizeof(struct wince_device_priv), + 0, + sizeof(struct wince_transfer_priv), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h new file mode 100644 index 0000000000..edcb9fcc40 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h @@ -0,0 +1,126 @@ +/* + * Windows CE backend for libusb 1.0 + * Copyright © 2011-2013 RealVNC Ltd. + * Portions taken from Windows backend, which is + * Copyright © 2009-2010 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#pragma once + +#include "windows_common.h" + +#include +#include "poll_windows.h" + +#define MAX_DEVICE_COUNT 256 + +// This is a modified dump of the types in the ceusbkwrapper.h library header +// with functions transformed into extern pointers. +// +// This backend dynamically loads ceusbkwrapper.dll and doesn't include +// ceusbkwrapper.h directly to simplify the build process. The kernel +// side wrapper driver is built using the platform image build tools, +// which makes it difficult to reference directly from the libusb build +// system. +struct UKW_DEVICE_PRIV; +typedef struct UKW_DEVICE_PRIV *UKW_DEVICE; +typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE; + +typedef struct { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 bcdUSB; + UINT8 bDeviceClass; + UINT8 bDeviceSubClass; + UINT8 bDeviceProtocol; + UINT8 bMaxPacketSize0; + UINT16 idVendor; + UINT16 idProduct; + UINT16 bcdDevice; + UINT8 iManufacturer; + UINT8 iProduct; + UINT8 iSerialNumber; + UINT8 bNumConfigurations; +} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR; + +typedef struct { + UINT8 bmRequestType; + UINT8 bRequest; + UINT16 wValue; + UINT16 wIndex; + UINT16 wLength; +} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER; + +// Collection of flags which can be used when issuing transfer requests +/* Indicates that the transfer direction is 'in' */ +#define UKW_TF_IN_TRANSFER 0x00000001 +/* Indicates that the transfer direction is 'out' */ +#define UKW_TF_OUT_TRANSFER 0x00000000 +/* Specifies that the transfer should complete as soon as possible, + * even if no OVERLAPPED structure has been provided. */ +#define UKW_TF_NO_WAIT 0x00000100 +/* Indicates that transfers shorter than the buffer are ok */ +#define UKW_TF_SHORT_TRANSFER_OK 0x00000200 +#define UKW_TF_SEND_TO_DEVICE 0x00010000 +#define UKW_TF_SEND_TO_INTERFACE 0x00020000 +#define UKW_TF_SEND_TO_ENDPOINT 0x00040000 +/* Don't block when waiting for memory allocations */ +#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000 + +/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor, + * to specify the currently active configuration for the device. */ +#define UKW_ACTIVE_CONFIGURATION -1 + +DLL_DECLARE_HANDLE(ceusbkwrapper); +DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ()); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD)); +DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD)); +DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL)); + +// Used to determine if an endpoint status really is halted on a failed transfer. +#define STATUS_HALT_FLAG 0x1 + +struct wince_device_priv { + UKW_DEVICE dev; + UKW_DEVICE_DESCRIPTOR desc; +}; + +struct wince_transfer_priv { + struct winfd pollable_fd; + uint8_t interface_number; +}; + diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h new file mode 100644 index 0000000000..b1725c2e32 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h @@ -0,0 +1,128 @@ +/* + * Windows backend common header for libusb 1.0 + * + * This file brings together header code common between + * the desktop Windows and Windows CE backends. + * Copyright © 2012-2013 RealVNC Ltd. + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +// Windows API default is uppercase - ugh! +#if !defined(bool) +#define bool BOOL +#endif +#if !defined(true) +#define true TRUE +#endif +#if !defined(false) +#define false FALSE +#endif + +#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime + +#if defined(__CYGWIN__ ) +#define _stricmp strcasecmp +#define _strdup strdup +// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread +#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) +#endif + +#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0) + +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +#define ERR_BUFFER_SIZE 256 + +/* + * API macros - leveraged from libusb-win32 1.x + */ +#ifndef _WIN32_WCE +#define DLL_STRINGIFY(s) #s +#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name)) +#else +#define DLL_STRINGIFY(s) L#s +#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name)) +#endif + +/* + * Macros for handling DLL themselves + */ +#define DLL_HANDLE_NAME(name) __dll_##name##_handle + +#define DLL_DECLARE_HANDLE(name) \ + static HMODULE DLL_HANDLE_NAME(name) = NULL + +#define DLL_GET_HANDLE(name) \ + do { \ + DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \ + if (!DLL_HANDLE_NAME(name)) \ + return FALSE; \ + } while (0) + +#define DLL_FREE_HANDLE(name) \ + do { \ + if (DLL_HANDLE_NAME(name)) { \ + FreeLibrary(DLL_HANDLE_NAME(name)); \ + DLL_HANDLE_NAME(name) = NULL; \ + } \ + } while (0) + + +/* + * Macros for handling functions within a DLL + */ +#define DLL_FUNC_NAME(name) __dll_##name##_func_t + +#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ + typedef ret (api * DLL_FUNC_NAME(name))args; \ + static DLL_FUNC_NAME(name) prefixname = NULL + +#define DLL_DECLARE_FUNC(api, ret, name, args) \ + DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) +#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args) \ + DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args) + +#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ + do { \ + HMODULE h = DLL_HANDLE_NAME(dll); \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ + DLL_STRINGIFY(name)); \ + if (prefixname) \ + break; \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ + if (prefixname) \ + break; \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ + if (prefixname) \ + break; \ + if (ret_on_failure) \ + return FALSE; \ + } while (0) + +#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ + DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) +#define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure) \ + DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure) diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c new file mode 100644 index 0000000000..92dbde5a84 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c @@ -0,0 +1,1008 @@ +/* + * windows backend for libusb 1.0 + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software + * Hash table functions adapted from glibc, by Ulrich Drepper et al. + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" +#include "windows_nt_common.h" + +// Public +BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); +enum windows_version windows_version = WINDOWS_UNDEFINED; + + // Global variables for init/exit +static unsigned int init_count = 0; +static bool usbdk_available = false; + +// Global variables for clock_gettime mechanism +static uint64_t hires_ticks_to_ps; +static uint64_t hires_frequency; + +#define TIMER_REQUEST_RETRY_MS 100 +#define WM_TIMER_REQUEST (WM_USER + 1) +#define WM_TIMER_EXIT (WM_USER + 2) + +// used for monotonic clock_gettime() +struct timer_request { + struct timespec *tp; + HANDLE event; +}; + +// Timer thread +static HANDLE timer_thread = NULL; +static DWORD timer_thread_id = 0; + +/* Kernel32 dependencies */ +DLL_DECLARE_HANDLE(Kernel32); +/* This call is only available from XP SP2 */ +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); + +/* User32 dependencies */ +DLL_DECLARE_HANDLE(User32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); + +static unsigned __stdcall windows_clock_gettime_threaded(void *param); + +/* +* Converts a windows error to human readable string +* uses retval as errorcode, or, if 0, use GetLastError() +*/ +#if defined(ENABLE_LOGGING) +const char *windows_error_str(DWORD error_code) +{ + static char err_string[ERR_BUFFER_SIZE]; + + DWORD size; + int len; + + if (error_code == 0) + error_code = GetLastError(); + + len = sprintf(err_string, "[%u] ", (unsigned int)error_code); + + // Translate codes returned by SetupAPI. The ones we are dealing with are either + // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. + // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx + switch (error_code & 0xE0000000) { + case 0: + error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified + break; + case 0xE0000000: + error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); + break; + default: + break; + } + + size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + &err_string[len], ERR_BUFFER_SIZE - len, NULL); + if (size == 0) { + DWORD format_error = GetLastError(); + if (format_error) + snprintf(err_string, ERR_BUFFER_SIZE, + "Windows error code %u (FormatMessage error code %u)", + (unsigned int)error_code, (unsigned int)format_error); + else + snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); + } else { + // Remove CRLF from end of message, if present + size_t pos = len + size - 2; + if (err_string[pos] == '\r') + err_string[pos] = '\0'; + } + + return err_string; +} +#endif + +static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx) +{ + return (struct windows_context_priv *)ctx->os_priv; +} + +/* Hash table functions - modified From glibc 2.3.2: + [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 + [Knuth] The Art of Computer Programming, part 3 (6.4) */ + +#define HTAB_SIZE 1021UL // *MUST* be a prime number!! + +typedef struct htab_entry { + unsigned long used; + char *str; +} htab_entry; + +static htab_entry *htab_table = NULL; +static usbi_mutex_t htab_mutex; +static unsigned long htab_filled; + +/* Before using the hash table we must allocate memory for it. + We allocate one element more as the found prime number says. + This is done for more effective indexing as explained in the + comment for the hash function. */ +static bool htab_create(struct libusb_context *ctx) +{ + if (htab_table != NULL) { + usbi_err(ctx, "hash table already allocated"); + return true; + } + + // Create a mutex + usbi_mutex_init(&htab_mutex); + + usbi_dbg("using %lu entries hash table", HTAB_SIZE); + htab_filled = 0; + + // allocate memory and zero out. + htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry)); + if (htab_table == NULL) { + usbi_err(ctx, "could not allocate space for hash table"); + return false; + } + + return true; +} + +/* After using the hash table it has to be destroyed. */ +static void htab_destroy(void) +{ + unsigned long i; + + if (htab_table == NULL) + return; + + for (i = 0; i < HTAB_SIZE; i++) + free(htab_table[i].str); + + safe_free(htab_table); + + usbi_mutex_destroy(&htab_mutex); +} + +/* This is the search function. It uses double hashing with open addressing. + We use a trick to speed up the lookup. The table is created with one + more element available. This enables us to use the index zero special. + This index will never be used because we store the first hash index in + the field used where zero means not used. Every other value means used. + The used field can be used as a first fast comparison for equality of + the stored and the parameter value. This helps to prevent unnecessary + expensive calls of strcmp. */ +unsigned long htab_hash(const char *str) +{ + unsigned long hval, hval2; + unsigned long idx; + unsigned long r = 5381; + int c; + const char *sz = str; + + if (str == NULL) + return 0; + + // Compute main hash value (algorithm suggested by Nokia) + while ((c = *sz++) != 0) + r = ((r << 5) + r) + c; + if (r == 0) + ++r; + + // compute table hash: simply take the modulus + hval = r % HTAB_SIZE; + if (hval == 0) + ++hval; + + // Try the first index + idx = hval; + + // Mutually exclusive access (R/W lock would be better) + usbi_mutex_lock(&htab_mutex); + + if (htab_table[idx].used) { + if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) + goto out_unlock; // existing hash + + usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str); + + // Second hash function, as suggested in [Knuth] + hval2 = 1 + hval % (HTAB_SIZE - 2); + + do { + // Because size is prime this guarantees to step through all available indexes + if (idx <= hval2) + idx = HTAB_SIZE + idx - hval2; + else + idx -= hval2; + + // If we visited all entries leave the loop unsuccessfully + if (idx == hval) + break; + + // If entry is found use it. + if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) + goto out_unlock; + } while (htab_table[idx].used); + } + + // Not found => New entry + + // If the table is full return an error + if (htab_filled >= HTAB_SIZE) { + usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE); + idx = 0; + goto out_unlock; + } + + htab_table[idx].str = _strdup(str); + if (htab_table[idx].str == NULL) { + usbi_err(NULL, "could not duplicate string for hash table"); + idx = 0; + goto out_unlock; + } + + htab_table[idx].used = hval; + ++htab_filled; + +out_unlock: + usbi_mutex_unlock(&htab_mutex); + + return idx; +} + +/* +* Make a transfer complete synchronously +*/ +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size) +{ + overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + overlapped->InternalHigh = size; + SetEvent(overlapped->hEvent); +} + +static BOOL windows_init_dlls(void) +{ + DLL_GET_HANDLE(Kernel32); + DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); + pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED)) + GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx"); + usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : ""); + + DLL_GET_HANDLE(User32); + DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); + DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); + DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); + + return TRUE; +} + +static void windows_exit_dlls(void) +{ + DLL_FREE_HANDLE(Kernel32); + DLL_FREE_HANDLE(User32); +} + +static bool windows_init_clock(struct libusb_context *ctx) +{ + DWORD_PTR affinity, dummy; + HANDLE event; + LARGE_INTEGER li_frequency; + int i; + + if (QueryPerformanceFrequency(&li_frequency)) { + // The hires frequency can go as high as 4 GHz, so we'll use a conversion + // to picoseconds to compute the tv_nsecs part in clock_gettime + hires_frequency = li_frequency.QuadPart; + hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; + usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); + + // Because QueryPerformanceCounter might report different values when + // running on different cores, we create a separate thread for the timer + // calls, which we glue to the first available core always to prevent timing discrepancies. + if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) { + usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0)); + return false; + } + + // The process affinity mask is a bitmask where each set bit represents a core on + // which this process is allowed to run, so we find the first set bit + for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++); + affinity = (DWORD_PTR)(1 << i); + + usbi_dbg("timer thread will run on core #%d", i); + + event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (event == NULL) { + usbi_err(ctx, "could not create event: %s", windows_error_str(0)); + return false; + } + + timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event, + 0, (unsigned int *)&timer_thread_id); + if (timer_thread == NULL) { + usbi_err(ctx, "unable to create timer thread - aborting"); + CloseHandle(event); + return false; + } + + if (!SetThreadAffinityMask(timer_thread, affinity)) + usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise"); + + // Wait for timer thread to init before continuing. + if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) { + usbi_err(ctx, "failed to wait for timer thread to become ready - aborting"); + CloseHandle(event); + return false; + } + + CloseHandle(event); + } else { + usbi_dbg("no hires timer available on this platform"); + hires_frequency = 0; + hires_ticks_to_ps = UINT64_C(0); + } + + return true; +} + +static void windows_destroy_clock(void) +{ + if (timer_thread) { + // actually the signal to quit the thread. + if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) + || (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) { + usbi_dbg("could not wait for timer thread to quit"); + TerminateThread(timer_thread, 1); + // shouldn't happen, but we're destroying + // all objects it might have held anyway. + } + CloseHandle(timer_thread); + timer_thread = NULL; + timer_thread_id = 0; + } +} + +/* Windows version detection */ +static BOOL is_x64(void) +{ + BOOL ret = FALSE; + + // Detect if we're running a 32 or 64 bit system + if (sizeof(uintptr_t) < 8) { + if (pIsWow64Process != NULL) + pIsWow64Process(GetCurrentProcess(), &ret); + } else { + ret = TRUE; + } + + return ret; +} + +static void get_windows_version(void) +{ + OSVERSIONINFOEXA vi, vi2; + const char *arch, *w = NULL; + unsigned major, minor, version; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + windows_version = WINDOWS_UNDEFINED; + + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) + return; + } + + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return; + + if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) { + // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx + + major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (major = vi.dwMajorVersion; major <= 9; major++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMajorVersion = major; + if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) + continue; + + if (vi.dwMajorVersion < major) { + vi.dwMajorVersion = major; + vi.dwMinorVersion = 0; + } + + minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (minor = vi.dwMinorVersion; minor <= 9; minor++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMinorVersion = minor; + if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) + continue; + + vi.dwMinorVersion = minor; + break; + } + + break; + } + } + + if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf)) + return; + + ws = (vi.wProductType <= VER_NT_WORKSTATION); + version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (version) { + case 0x50: windows_version = WINDOWS_2000; w = "2000"; break; + case 0x51: windows_version = WINDOWS_XP; w = "XP"; break; + case 0x52: windows_version = WINDOWS_2003; w = "2003"; break; + case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break; + case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break; + case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break; + case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break; + case 0x64: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break; + default: + if (version < 0x50) { + return; + } else { + windows_version = WINDOWS_11_OR_LATER; + w = "11 or later"; + } + } + + arch = is_x64() ? "64-bit" : "32-bit"; + + if (vi.wServicePackMinor) + usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch); + else if (vi.wServicePackMajor) + usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch); + else + usbi_dbg("Windows %s %s", w, arch); +} + +/* +* Monotonic and real time functions +*/ +static unsigned __stdcall windows_clock_gettime_threaded(void *param) +{ + struct timer_request *request; + LARGE_INTEGER hires_counter; + MSG msg; + + // The following call will create this thread's message queue + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx + pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + // Signal windows_init_clock() that we're ready to service requests + if (!SetEvent((HANDLE)param)) + usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0)); + param = NULL; + + // Main loop - wait for requests + while (1) { + if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) { + usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0)); + return 1; + } + + switch (msg.message) { + case WM_TIMER_REQUEST: + // Requests to this thread are for hires always + // Microsoft says that this function always succeeds on XP and later + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx + request = (struct timer_request *)msg.lParam; + QueryPerformanceCounter(&hires_counter); + request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); + request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); + if (!SetEvent(request->event)) + usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0)); + break; + case WM_TIMER_EXIT: + usbi_dbg("timer thread quitting"); + return 0; + } + } +} + +static void windows_transfer_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + int status, istatus; + + usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size); + + switch (io_result) { + case NO_ERROR: + status = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + break; + case ERROR_GEN_FAILURE: + usbi_dbg("detected endpoint stall"); + status = LIBUSB_TRANSFER_STALL; + break; + case ERROR_SEM_TIMEOUT: + usbi_dbg("detected semaphore timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + break; + case ERROR_OPERATION_ABORTED: + istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + if (istatus != LIBUSB_TRANSFER_COMPLETED) + usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); + + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + break; + case ERROR_FILE_NOT_FOUND: + usbi_dbg("detected device removed"); + status = LIBUSB_TRANSFER_NO_DEVICE; + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result)); + status = LIBUSB_TRANSFER_ERROR; + break; + } + backend->clear_transfer_priv(itransfer); // Cancel polling + if (status == LIBUSB_TRANSFER_CANCELLED) + usbi_handle_transfer_cancellation(itransfer); + else + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); +} + +static void windows_handle_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + windows_transfer_callback(backend, itransfer, io_result, io_size); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + } +} + +static int windows_init(struct libusb_context *ctx) +{ + struct windows_context_priv *priv = _context_priv(ctx); + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + int r = LIBUSB_ERROR_OTHER; + bool winusb_backend_init = false; + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) { + usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_MEM; + } + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore's release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); + CloseHandle(semaphore); + return LIBUSB_ERROR_NO_MEM; + } + + // NB: concurrent usage supposes that init calls are equally balanced with + // exit calls. If init is called more than exit, we will not exit properly + if (++init_count == 1) { // First init? + // Load DLL imports + if (!windows_init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + goto init_exit; + } + + get_windows_version(); + + if (windows_version == WINDOWS_UNDEFINED) { + usbi_err(ctx, "failed to detect Windows version"); + r = LIBUSB_ERROR_NOT_SUPPORTED; + goto init_exit; + } + + if (!windows_init_clock(ctx)) + goto init_exit; + + if (!htab_create(ctx)) + goto init_exit; + + r = winusb_backend.init(ctx); + if (r != LIBUSB_SUCCESS) + goto init_exit; + winusb_backend_init = true; + + r = usbdk_backend.init(ctx); + if (r == LIBUSB_SUCCESS) { + usbi_dbg("UsbDk backend is available"); + usbdk_available = true; + } else { + usbi_info(ctx, "UsbDk backend is not available"); + // Do not report this as an error + r = LIBUSB_SUCCESS; + } + } + + // By default, new contexts will use the WinUSB backend + priv->backend = &winusb_backend; + + r = LIBUSB_SUCCESS; + +init_exit: // Holds semaphore here + if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed? + if (winusb_backend_init) + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + --init_count; + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); + return r; +} + +static void windows_exit(struct libusb_context *ctx) +{ + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) + return; + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + CloseHandle(semaphore); + return; + } + + // Only works if exits and inits are balanced exactly + if (--init_count == 0) { // Last exit + if (usbdk_available) { + usbdk_backend.exit(ctx); + usbdk_available = false; + } + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); +} + +static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) +{ + struct windows_context_priv *priv = _context_priv(ctx); + + UNUSED(ap); + + switch (option) { + case LIBUSB_OPTION_USE_USBDK: + if (usbdk_available) { + usbi_dbg("switching context %p to use UsbDk backend", ctx); + priv->backend = &usbdk_backend; + } else { + usbi_err(ctx, "UsbDk backend not available"); + return LIBUSB_ERROR_NOT_FOUND; + } + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } + +} + +static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs) +{ + struct windows_context_priv *priv = _context_priv(ctx); + return priv->backend->get_device_list(ctx, discdevs); +} + +static int windows_open(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->open(dev_handle); +} + +static void windows_close(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + priv->backend->close(dev_handle); +} + +static int windows_get_device_descriptor(struct libusb_device *dev, + unsigned char *buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_device_descriptor(dev, buffer); +} + +static int windows_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_active_config_descriptor(dev, buffer, len); +} + +static int windows_get_config_descriptor(struct libusb_device *dev, + uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor(dev, config_index, buffer, len); +} + +static int windows_get_config_descriptor_by_value(struct libusb_device *dev, + uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer); +} + +static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->get_configuration(dev_handle, config); +} + +static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_configuration(dev_handle, config); +} + +static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->claim_interface(dev_handle, interface_number); +} + +static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->release_interface(dev_handle, interface_number); +} + +static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting); +} + +static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->clear_halt(dev_handle, endpoint); +} + +static int windows_reset_device(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->reset_device(dev_handle); +} + +static void windows_destroy_device(struct libusb_device *dev) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + priv->backend->destroy_device(dev); +} + +static int windows_submit_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->submit_transfer(itransfer); +} + +static int windows_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->cancel_transfer(itransfer); +} + +static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + priv->backend->clear_transfer_priv(itransfer); +} + +static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) +{ + struct windows_context_priv *priv = _context_priv(ctx); + struct usbi_transfer *itransfer; + DWORD io_size, io_result; + POLL_NFDS_TYPE i; + bool found; + int transfer_fd; + int r = LIBUSB_SUCCESS; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + + usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); + + if (!fds[i].revents) + continue; + + num_ready--; + + // Because a Windows OVERLAPPED is used for poll emulation, + // a pollable fd is created and stored with each transfer + found = false; + transfer_fd = -1; + usbi_mutex_lock(&ctx->flying_transfers_lock); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_fd = priv->backend->get_transfer_fd(itransfer); + if (transfer_fd == fds[i].fd) { + found = true; + break; + } + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (found) { + priv->backend->get_overlapped_result(itransfer, &io_result, &io_size); + + usbi_remove_pollfd(ctx, transfer_fd); + + // let handle_callback free the event using the transfer wfd + // If you don't use the transfer wfd, you run a risk of trying to free a + // newly allocated wfd that took the place of the one from the transfer. + windows_handle_callback(priv->backend, itransfer, io_result, io_size); + } else { + usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd); + r = LIBUSB_ERROR_NOT_FOUND; + break; + } + } + usbi_mutex_unlock(&ctx->open_devs_lock); + + return r; +} + +static int windows_clock_gettime(int clk_id, struct timespec *tp) +{ + struct timer_request request; +#if !defined(_MSC_VER) || (_MSC_VER < 1900) + FILETIME filetime; + ULARGE_INTEGER rtime; +#endif + DWORD r; + + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + if (timer_thread) { + request.tp = tp; + request.event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (request.event == NULL) + return LIBUSB_ERROR_NO_MEM; + + if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) { + usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0)); + CloseHandle(request.event); + return LIBUSB_ERROR_OTHER; + } + + do { + r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS); + if (r == WAIT_TIMEOUT) + usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); + else if (r == WAIT_FAILED) + usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0)); + } while (r == WAIT_TIMEOUT); + CloseHandle(request.event); + + if (r == WAIT_OBJECT_0) + return LIBUSB_SUCCESS; + else + return LIBUSB_ERROR_OTHER; + } + // Fall through and return real-time if monotonic was not detected @ timer init + case USBI_CLOCK_REALTIME: +#if defined(_MSC_VER) && (_MSC_VER >= 1900) + timespec_get(tp, TIME_UTC); +#else + // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx + // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 + // Note however that our resolution is bounded by the Windows system time + // functions and is at best of the order of 1 ms (or, usually, worse) + GetSystemTimeAsFileTime(&filetime); + rtime.LowPart = filetime.dwLowDateTime; + rtime.HighPart = filetime.dwHighDateTime; + rtime.QuadPart -= EPOCH_TIME; + tp->tv_sec = (long)(rtime.QuadPart / 10000000); + tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); +#endif + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +// NB: MSVC6 does not support named initializers. +const struct usbi_os_backend usbi_backend = { + "Windows", + USBI_CAP_HAS_HID_ACCESS, + windows_init, + windows_exit, + windows_set_option, + windows_get_device_list, + NULL, /* hotplug_poll */ + windows_open, + windows_close, + windows_get_device_descriptor, + windows_get_active_config_descriptor, + windows_get_config_descriptor, + windows_get_config_descriptor_by_value, + windows_get_configuration, + windows_set_configuration, + windows_claim_interface, + windows_release_interface, + windows_set_interface_altsetting, + windows_clear_halt, + windows_reset_device, + NULL, /* alloc_streams */ + NULL, /* free_streams */ + NULL, /* dev_mem_alloc */ + NULL, /* dev_mem_free */ + NULL, /* kernel_driver_active */ + NULL, /* detach_kernel_driver */ + NULL, /* attach_kernel_driver */ + windows_destroy_device, + windows_submit_transfer, + windows_cancel_transfer, + windows_clear_transfer_priv, + windows_handle_events, + NULL, /* handle_transfer_completion */ + windows_clock_gettime, + sizeof(struct windows_context_priv), + sizeof(union windows_device_priv), + sizeof(union windows_device_handle_priv), + sizeof(union windows_transfer_priv), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h new file mode 100644 index 0000000000..e155b5d3e3 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h @@ -0,0 +1,110 @@ +/* + * Windows backend common header for libusb 1.0 + * + * This file brings together header code common between + * the desktop Windows backends. + * Copyright © 2012-2013 RealVNC Ltd. + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "windows_nt_shared_types.h" + + /* Windows versions */ +enum windows_version { + WINDOWS_UNDEFINED, + WINDOWS_2000, + WINDOWS_XP, + WINDOWS_2003, // Also XP x64 + WINDOWS_VISTA, + WINDOWS_7, + WINDOWS_8, + WINDOWS_8_1, + WINDOWS_10, + WINDOWS_11_OR_LATER +}; + +extern enum windows_version windows_version; + +/* This call is only available from Vista */ +extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); + +struct windows_backend { + int (*init)(struct libusb_context *ctx); + void (*exit)(struct libusb_context *ctx); + int (*get_device_list)(struct libusb_context *ctx, + struct discovered_devs **discdevs); + int (*open)(struct libusb_device_handle *dev_handle); + void (*close)(struct libusb_device_handle *dev_handle); + int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer); + int (*get_active_config_descriptor)(struct libusb_device *device, + unsigned char *buffer, size_t len); + int (*get_config_descriptor)(struct libusb_device *device, + uint8_t config_index, unsigned char *buffer, size_t len); + int (*get_config_descriptor_by_value)(struct libusb_device *device, + uint8_t bConfigurationValue, unsigned char **buffer); + int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); + int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); + int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting); + int (*clear_halt)(struct libusb_device_handle *dev_handle, + unsigned char endpoint); + int (*reset_device)(struct libusb_device_handle *dev_handle); + void (*destroy_device)(struct libusb_device *dev); + int (*submit_transfer)(struct usbi_transfer *itransfer); + int (*cancel_transfer)(struct usbi_transfer *itransfer); + void (*clear_transfer_priv)(struct usbi_transfer *itransfer); + int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size); + int (*get_transfer_fd)(struct usbi_transfer *itransfer); + void (*get_overlapped_result)(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size); +}; + +struct windows_context_priv { + const struct windows_backend *backend; +}; + +union windows_device_priv { + struct usbdk_device_priv usbdk_priv; + struct winusb_device_priv winusb_priv; +}; + +union windows_device_handle_priv { + struct usbdk_device_handle_priv usbdk_priv; + struct winusb_device_handle_priv winusb_priv; +}; + +union windows_transfer_priv { + struct usbdk_transfer_priv usbdk_priv; + struct winusb_transfer_priv winusb_priv; +}; + +extern const struct windows_backend usbdk_backend; +extern const struct windows_backend winusb_backend; + +unsigned long htab_hash(const char *str); +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size); + +#if defined(ENABLE_LOGGING) +const char *windows_error_str(DWORD error_code); +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h new file mode 100644 index 0000000000..68bf261d5d --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h @@ -0,0 +1,138 @@ +#pragma once + +#include "windows_common.h" + +#include + +typedef struct USB_DEVICE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + USHORT idVendor; + USHORT idProduct; + USHORT bcdDevice; + UCHAR iManufacturer; + UCHAR iProduct; + UCHAR iSerialNumber; + UCHAR bNumConfigurations; +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct USB_CONFIGURATION_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +#include + +#define MAX_DEVICE_ID_LEN 200 + +typedef struct USB_DK_DEVICE_ID { + WCHAR DeviceID[MAX_DEVICE_ID_LEN]; + WCHAR InstanceID[MAX_DEVICE_ID_LEN]; +} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; + +typedef struct USB_DK_DEVICE_INFO { + USB_DK_DEVICE_ID ID; + ULONG64 FilterID; + ULONG64 Port; + ULONG64 Speed; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; +} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; + +typedef struct USB_DK_ISO_TRANSFER_RESULT { + ULONG64 ActualLength; + ULONG64 TransferResult; +} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; + +typedef struct USB_DK_GEN_TRANSFER_RESULT { + ULONG64 BytesTransferred; + ULONG64 UsbdStatus; // USBD_STATUS code +} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_RESULT { + USB_DK_GEN_TRANSFER_RESULT GenResult; + PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT +} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_REQUEST { + ULONG64 EndpointAddress; + PVOID64 Buffer; + ULONG64 BufferLength; + ULONG64 TransferType; + ULONG64 IsochronousPacketsArraySize; + PVOID64 IsochronousPacketsArray; + USB_DK_TRANSFER_RESULT Result; +} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; + +struct usbdk_device_priv { + USB_DK_DEVICE_INFO info; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; + HANDLE redirector_handle; + HANDLE system_handle; + uint8_t active_configuration; +}; + +struct winusb_device_priv { + bool initialized; + bool root_hub; + uint8_t active_config; + uint8_t depth; // distance to HCD + const struct windows_usb_api_backend *apib; + char *dev_id; + char *path; // device interface path + int sub_api; // for WinUSB-like APIs + struct { + char *path; // each interface needs a device interface path, + const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support), + int sub_api; + int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) + uint8_t *endpoint; + bool restricted_functionality; // indicates if the interface functionality is restricted + // by Windows (eg. HID keyboards or mice cannot do R/W) + } usb_interface[USB_MAXINTERFACES]; + struct hid_device_priv *hid; + USB_DEVICE_DESCRIPTOR dev_descriptor; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors +}; + +struct usbdk_device_handle_priv { + // Not currently used + char dummy; +}; + +struct winusb_device_handle_priv { + int active_interface; + struct { + HANDLE dev_handle; // WinUSB needs an extra handle for the file + HANDLE api_handle; // used by the API to communicate with the device + } interface_handle[USB_MAXINTERFACES]; + int autoclaim_count[USB_MAXINTERFACES]; // For auto-release +}; + +struct usbdk_transfer_priv { + USB_DK_TRANSFER_REQUEST request; + struct winfd pollable_fd; + HANDLE system_handle; + PULONG64 IsochronousPacketsArray; + PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; +}; + +struct winusb_transfer_priv { + struct winfd pollable_fd; + HANDLE handle; + uint8_t interface_number; + uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID + uint8_t *hid_dest; // transfer buffer destination, required for HID + size_t hid_expected_size; + void *iso_context; +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c new file mode 100644 index 0000000000..fbccbd5cff --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c @@ -0,0 +1,830 @@ +/* + * windows UsbDk backend for libusb 1.0 + * Copyright © 2014 Red Hat, Inc. + + * Authors: + * Dmitry Fleytman + * Pavel Gurvich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "libusbi.h" +#include "windows_common.h" +#include "windows_nt_common.h" +#include "windows_usbdk.h" + +#if !defined(STATUS_SUCCESS) +typedef LONG NTSTATUS; +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#endif + +#if !defined(STATUS_CANCELLED) +#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) +#endif + +#if !defined(STATUS_REQUEST_CANCELED) +#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) +#endif + +#if !defined(USBD_SUCCESS) +typedef LONG USBD_STATUS; +#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) +#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) +#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) +#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) +#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) +#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) +#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) +#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) +#endif + +static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) +{ + return (struct usbdk_device_priv *)dev->os_priv; +} + +static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) +{ + return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer); +} + +static struct { + HMODULE module; + + USBDK_GET_DEVICES_LIST GetDevicesList; + USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; + USBDK_START_REDIRECT StartRedirect; + USBDK_STOP_REDIRECT StopRedirect; + USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; + USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; + USBDK_READ_PIPE ReadPipe; + USBDK_WRITE_PIPE WritePipe; + USBDK_ABORT_PIPE AbortPipe; + USBDK_RESET_PIPE ResetPipe; + USBDK_SET_ALTSETTING SetAltsetting; + USBDK_RESET_DEVICE ResetDevice; + USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; +} usbdk_helper; + +static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) +{ + FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); + + if (api_ptr == NULL) + usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0)); + + return api_ptr; +} + +static void unload_usbdk_helper_dll(void) +{ + if (usbdk_helper.module != NULL) { + FreeLibrary(usbdk_helper.module); + usbdk_helper.module = NULL; + } +} + +static int load_usbdk_helper_dll(struct libusb_context *ctx) +{ + usbdk_helper.module = LoadLibraryA("UsbDkHelper"); + if (usbdk_helper.module == NULL) { + usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); + if (usbdk_helper.GetDevicesList == NULL) + goto error_unload; + + usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); + if (usbdk_helper.ReleaseDevicesList == NULL) + goto error_unload; + + usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); + if (usbdk_helper.StartRedirect == NULL) + goto error_unload; + + usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); + if (usbdk_helper.StopRedirect == NULL) + goto error_unload; + + usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); + if (usbdk_helper.GetConfigurationDescriptor == NULL) + goto error_unload; + + usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); + if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) + goto error_unload; + + usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); + if (usbdk_helper.ReadPipe == NULL) + goto error_unload; + + usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); + if (usbdk_helper.WritePipe == NULL) + goto error_unload; + + usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); + if (usbdk_helper.AbortPipe == NULL) + goto error_unload; + + usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); + if (usbdk_helper.ResetPipe == NULL) + goto error_unload; + + usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); + if (usbdk_helper.SetAltsetting == NULL) + goto error_unload; + + usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); + if (usbdk_helper.ResetDevice == NULL) + goto error_unload; + + usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); + if (usbdk_helper.GetRedirectorSystemHandle == NULL) + goto error_unload; + + return LIBUSB_SUCCESS; + +error_unload: + FreeLibrary(usbdk_helper.module); + usbdk_helper.module = NULL; + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usbdk_init(struct libusb_context *ctx) +{ + SC_HANDLE managerHandle; + SC_HANDLE serviceHandle; + + managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (managerHandle == NULL) { + usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ); + CloseServiceHandle(managerHandle); + + if (serviceHandle == NULL) { + if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) + usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; + } + + CloseServiceHandle(serviceHandle); + + return load_usbdk_helper_dll(ctx); +} + +static void usbdk_exit(struct libusb_context *ctx) +{ + UNUSED(ctx); + unload_usbdk_helper_dll(); +} + +static int usbdk_get_session_id_for_device(struct libusb_context *ctx, + PUSB_DK_DEVICE_ID id, unsigned long *session_id) +{ + char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1]; + + if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) { + usbi_warn(ctx, "cannot form device identity", id->DeviceID); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + *session_id = htab_hash(dev_identity); + + return LIBUSB_SUCCESS; +} + +static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count) +{ + uint8_t i; + + for (i = 0; i < count; i++) + usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); + + free(p->config_descriptors); + p->config_descriptors = NULL; +} + +static int usbdk_cache_config_descriptors(struct libusb_context *ctx, + struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info) +{ + uint8_t i; + USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; + Request.ID = info->ID; + + p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (p->config_descriptors == NULL) { + usbi_err(ctx, "failed to allocate configuration descriptors holder"); + return LIBUSB_ERROR_NO_MEM; + } + + for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { + ULONG Length; + + Request.Index = i; + if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) { + usbi_err(ctx, "failed to retrieve configuration descriptors"); + usbdk_release_config_descriptors(p, i); + return LIBUSB_ERROR_OTHER; + } + } + + return LIBUSB_SUCCESS; +} + +static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info) +{ + struct usbdk_device_priv *p = _usbdk_device_priv(dev); + + p->info = *info; + p->active_configuration = 0; + + return usbdk_cache_config_descriptors(ctx, p, info); +} + +static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) +{ + dev->bus_number = (uint8_t)info->FilterID; + dev->port_number = (uint8_t)info->Port; + dev->parent_dev = NULL; + + // Addresses in libusb are 1-based + dev->device_address = (uint8_t)(info->Port + 1); + + dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; + memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); + + switch (info->Speed) { + case LowSpeed: + dev->speed = LIBUSB_SPEED_LOW; + break; + case FullSpeed: + dev->speed = LIBUSB_SPEED_FULL; + break; + case HighSpeed: + dev->speed = LIBUSB_SPEED_HIGH; + break; + case SuperSpeed: + dev->speed = LIBUSB_SPEED_SUPER; + break; + case NoSpeed: + default: + dev->speed = LIBUSB_SPEED_UNKNOWN; + break; + } +} + +static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) +{ + int r = LIBUSB_SUCCESS; + ULONG i; + struct discovered_devs *discdevs = NULL; + ULONG dev_number; + PUSB_DK_DEVICE_INFO devices; + + if (!usbdk_helper.GetDevicesList(&devices, &dev_number)) + return LIBUSB_ERROR_OTHER; + + for (i = 0; i < dev_number; i++) { + unsigned long session_id; + struct libusb_device *dev = NULL; + + if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) + continue; + + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "failed to allocate a new device structure"); + continue; + } + + usbdk_device_init(dev, &devices[i]); + if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + continue; + } + } + + discdevs = discovered_devs_append(*_discdevs, dev); + libusb_unref_device(dev); + if (!discdevs) { + usbi_err(ctx, "cannot append new device to list"); + r = LIBUSB_ERROR_NO_MEM; + goto func_exit; + } + + *_discdevs = discdevs; + } + +func_exit: + usbdk_helper.ReleaseDevicesList(devices); + return r; +} + +static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + + memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); + + return LIBUSB_SUCCESS; +} + +static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + size_t size; + + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_INVALID_PARAM; + + config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index]; + + size = min(config_header->wTotalLength, len); + memcpy(buffer, config_header, size); + return (int)size; +} + +static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = priv->config_descriptors[index]; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = (unsigned char *)priv->config_descriptors[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) +{ + return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, + buffer, len); +} + +static int usbdk_open(struct libusb_device_handle *dev_handle) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); + if (priv->redirector_handle == INVALID_HANDLE_VALUE) { + usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); + return LIBUSB_ERROR_OTHER; + } + + priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + return LIBUSB_SUCCESS; +} + +static void usbdk_close(struct libusb_device_handle *dev_handle) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.StopRedirect(priv->redirector_handle)) + usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed"); +} + +static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; + + return LIBUSB_SUCCESS; +} + +static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + UNUSED(dev_handle); + UNUSED(config); + return LIBUSB_SUCCESS; +} + +static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface) +{ + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_SUCCESS; +} + +static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { + usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface) +{ + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_SUCCESS; +} + +static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { + usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_reset_device(struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { + usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static void usbdk_destroy_device(struct libusb_device *dev) +{ + struct usbdk_device_priv* p = _usbdk_device_priv(dev); + + if (p->config_descriptors != NULL) + usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); +} + +static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->system_handle = NULL; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + safe_free(transfer_priv->IsochronousPacketsArray); + safe_free(transfer_priv->IsochronousResultsArray); + } +} + +static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; + TransferResult transResult; + + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.TransferType = ControlTransferType; + + if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) + transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); + else + transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); + + switch (transResult) { + case TransferSuccess: + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); + break; + case TransferSuccessAsync: + break; + case TransferFailure: + usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; + TransferResult transferRes; + + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_BULK: + transfer_priv->request.TransferType = BulkTransferType; + break; + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + transfer_priv->request.TransferType = InterruptTransferType; + break; + default: + usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (IS_XFERIN(transfer)) + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); + else + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); + + switch (transferRes) { + case TransferSuccess: + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); + break; + case TransferSuccessAsync: + break; + case TransferFailure: + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; + TransferResult transferRes; + int i; + + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + transfer_priv->request.TransferType = IsochronousTransferType; + transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; + transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); + transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray; + if (!transfer_priv->IsochronousPacketsArray) { + usbi_err(ctx, "Allocation of IsochronousPacketsArray failed"); + return LIBUSB_ERROR_NO_MEM; + } + + transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); + transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray; + if (!transfer_priv->IsochronousResultsArray) { + usbi_err(ctx, "Allocation of isochronousResultsArray failed"); + return LIBUSB_ERROR_NO_MEM; + } + + for (i = 0; i < transfer->num_iso_packets; i++) + transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; + + if (IS_XFERIN(transfer)) + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); + else + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); + + switch (transferRes) { + case TransferSuccess: + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); + break; + case TransferSuccessAsync: + break; + case TransferFailure: + return LIBUSB_ERROR_IO; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer, + short events, int (*transfer_fn)(struct usbi_transfer *)) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd wfd; + int r; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); + return r; + } + + // Use transfer_priv to store data needed for async polling + transfer_priv->pollable_fd = wfd; + transfer_priv->system_handle = priv->system_handle; + + r = transfer_fn(itransfer); + if (r != LIBUSB_SUCCESS) { + usbi_remove_pollfd(ctx, wfd.fd); + usbdk_clear_transfer_priv(itransfer); + return r; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int (*transfer_fn)(struct usbi_transfer *); + short events; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_control_transfer; + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) + return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_bulk_transfer; + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_iso_transfer; + break; + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } + + return usbdk_do_submit_transfer(itransfer, events, transfer_fn); +} + +static int usbdk_abort_transfers(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; + + if (pCancelIoEx != NULL) { + // Use CancelIoEx if available to cancel just a single transfer + if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) { + usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + } else { + if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + // Control transfers cancelled by IoCancelXXX() API + // No special treatment needed + return LIBUSB_SUCCESS; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return usbdk_abort_transfers(itransfer); + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +{ + itransfer->transferred += io_size; + return LIBUSB_TRANSFER_COMPLETED; +} + +static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer) +{ + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + return transfer_priv->pollable_fd.fd; +} + +static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) +{ + if (USBD_SUCCESS(UsbdStatus)) + return NO_ERROR; + + switch (UsbdStatus) { + case USBD_STATUS_TIMEOUT: + return ERROR_SEM_TIMEOUT; + case USBD_STATUS_CANCELED: + return ERROR_OPERATION_ABORTED; + default: + return ERROR_GEN_FAILURE; + } +} + +static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size) +{ + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; + + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first + || GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + ULONG64 i; + for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { + struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; + + switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { + case STATUS_SUCCESS: + case STATUS_CANCELLED: + case STATUS_REQUEST_CANCELED: + lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS + break; + default: + lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; + break; + } + + lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength; + } + } + + *io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred; + *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus); + } else { + *io_result = GetLastError(); + } +} + +const struct windows_backend usbdk_backend = { + usbdk_init, + usbdk_exit, + usbdk_get_device_list, + usbdk_open, + usbdk_close, + usbdk_get_device_descriptor, + usbdk_get_active_config_descriptor, + usbdk_get_config_descriptor, + usbdk_get_config_descriptor_by_value, + usbdk_get_configuration, + usbdk_set_configuration, + usbdk_claim_interface, + usbdk_release_interface, + usbdk_set_interface_altsetting, + usbdk_clear_halt, + usbdk_reset_device, + usbdk_destroy_device, + usbdk_submit_transfer, + usbdk_cancel_transfer, + usbdk_clear_transfer_priv, + usbdk_copy_transfer_data, + usbdk_get_transfer_fd, + usbdk_get_overlapped_result, +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h new file mode 100644 index 0000000000..77660ae97f --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h @@ -0,0 +1,103 @@ +/* +* windows UsbDk backend for libusb 1.0 +* Copyright © 2014 Red Hat, Inc. + +* Authors: +* Dmitry Fleytman +* Pavel Gurvich +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include "windows_nt_common.h" + +typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST { + USB_DK_DEVICE_ID ID; + ULONG64 Index; +} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; + +typedef enum { + TransferFailure = 0, + TransferSuccess, + TransferSuccessAsync +} TransferResult; + +typedef enum { + NoSpeed = 0, + LowSpeed, + FullSpeed, + HighSpeed, + SuperSpeed +} USB_DK_DEVICE_SPEED; + +typedef enum { + ControlTransferType, + BulkTransferType, + InterruptTransferType, + IsochronousTransferType +} USB_DK_TRANSFER_TYPE; + +typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)( + PUSB_DK_DEVICE_INFO *DeviceInfo, + PULONG DeviceNumber +); +typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)( + PUSB_DK_DEVICE_INFO DeviceInfo +); +typedef HANDLE (__cdecl *USBDK_START_REDIRECT)( + PUSB_DK_DEVICE_ID DeviceId +); +typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)( + HANDLE DeviceHandle +); +typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)( + PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, + PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, + PULONG Length +); +typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)( + PUSB_CONFIGURATION_DESCRIPTOR Descriptor +); +typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)( + HANDLE DeviceHandle, + PUSB_DK_TRANSFER_REQUEST Request, + LPOVERLAPPED lpOverlapped +); +typedef TransferResult (__cdecl *USBDK_READ_PIPE)( + HANDLE DeviceHandle, + PUSB_DK_TRANSFER_REQUEST Request, + LPOVERLAPPED lpOverlapped +); +typedef BOOL (__cdecl *USBDK_ABORT_PIPE)( + HANDLE DeviceHandle, + ULONG64 PipeAddress +); +typedef BOOL (__cdecl *USBDK_RESET_PIPE)( + HANDLE DeviceHandle, + ULONG64 PipeAddress +); +typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)( + HANDLE DeviceHandle, + ULONG64 InterfaceIdx, + ULONG64 AltSettingIdx +); +typedef BOOL (__cdecl *USBDK_RESET_DEVICE)( + HANDLE DeviceHandle +); +typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)( + HANDLE DeviceHandle +); diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c new file mode 100644 index 0000000000..ce1b55cd61 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c @@ -0,0 +1,3009 @@ +/* + * windows backend for libusb 1.0 + * Copyright © 2009-2012 Pete Batard + * Copyright © 2016-2018 Chris Dickens + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software + * Hash table functions adapted from glibc, by Ulrich Drepper et al. + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" +#include "windows_nt_common.h" +#include "windows_winusb.h" + +// Unfuckup the 'inferface' keyword +#undef interface + +#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE)) + +// The 2 macros below are used in conjunction with safe loops. +#define LOOP_CHECK(fcall) \ + { \ + r = fcall; \ + if (r != LIBUSB_SUCCESS) \ + continue; \ + } +#define LOOP_BREAK(err) \ + { \ + r = err; \ + continue; \ + } + +// WinUSB-like API prototypes +static int winusbx_init(struct libusb_context *ctx); +static void winusbx_exit(void); +static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); +static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); +static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); +static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); +static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); +// Composite API prototypes +static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); +static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); +static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); +static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); +static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer); +static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer); +static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); +static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); + +static usbi_mutex_t autoclaim_lock; + +// API globals +static HMODULE WinUSBX_handle = NULL; +static struct winusb_interface WinUSBX[SUB_API_MAX]; +#define CHECK_WINUSBX_AVAILABLE(sub_api) \ + do { \ + if (sub_api == SUB_API_NOTSET) \ + sub_api = priv->sub_api; \ + if (!WinUSBX[sub_api].initialized) \ + return LIBUSB_ERROR_ACCESS; \ + } while (0) + +static bool api_hid_available = false; +#define CHECK_HID_AVAILABLE \ + do { \ + if (!api_hid_available) \ + return LIBUSB_ERROR_ACCESS; \ + } while (0) + +#if defined(ENABLE_LOGGING) +static const char *guid_to_string(const GUID *guid) +{ + static char guid_string[MAX_GUID_STRING_LENGTH]; + + if (guid == NULL) + return ""; + + sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + (unsigned int)guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); + + return guid_string; +} +#endif + +/* + * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. + * Return an allocated sanitized string or NULL on error. + */ +static char *sanitize_path(const char *path) +{ + const char root_prefix[] = {'\\', '\\', '.', '\\'}; + size_t j, size; + char *ret_path; + size_t add_root = 0; + + if (path == NULL) + return NULL; + + size = strlen(path) + 1; + + // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. + if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) + || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { + add_root = sizeof(root_prefix); + size += add_root; + } + + ret_path = malloc(size); + if (ret_path == NULL) + return NULL; + + strcpy(&ret_path[add_root], path); + + // Ensure consistency with root prefix + memcpy(ret_path, root_prefix, sizeof(root_prefix)); + + // Same goes for '\' and '#' after the root prefix. Ensure '#' is used + for (j = sizeof(root_prefix); j < size; j++) { + ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too + if (ret_path[j] == '\\') + ret_path[j] = '#'; + } + + return ret_path; +} + +/* + * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions + */ +static BOOL init_dlls(void) +{ + DLL_GET_HANDLE(Cfgmgr32); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); + + // Prefixed to avoid conflict with header files + DLL_GET_HANDLE(AdvAPI32); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); + + DLL_GET_HANDLE(OLE32); + DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE); + + DLL_GET_HANDLE(SetupAPI); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); + + return TRUE; +} + +static void exit_dlls(void) +{ + DLL_FREE_HANDLE(Cfgmgr32); + DLL_FREE_HANDLE(AdvAPI32); + DLL_FREE_HANDLE(OLE32); + DLL_FREE_HANDLE(SetupAPI); +} + +/* + * enumerate interfaces for the whole USB class + * + * Parameters: + * dev_info: a pointer to a dev_info list + * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) + * enumerator: the generic USB class for which to retrieve interface details + * index: zero based index of the interface in the device info list + * + * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA + * structure returned and call this function repeatedly using the same guid (with an + * incremented index starting at zero) until all interfaces have been returned. + */ +static bool get_devinfo_data(struct libusb_context *ctx, + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index) +{ + if (_index == 0) { + *dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); + if (*dev_info == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s", + enumerator, windows_error_str(0)); + return false; + } + } + + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s", + enumerator, _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return false; + } + return true; +} + +/* + * enumerate interfaces for a specific GUID + * + * Parameters: + * dev_info: a pointer to a dev_info list + * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) + * guid: the GUID for which to retrieve interface details + * index: zero based index of the interface in the device info list + * + * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA + * structure returned and call this function repeatedly using the same guid (with an + * incremented index starting at zero) until all interfaces have been returned. + */ +static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info, + PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path) +{ + SP_DEVICE_INTERFACE_DATA dev_interface_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details; + DWORD size; + + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + for (;;) { + if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain device info data for %s index %u: %s", + guid_to_string(guid), *_index, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + // No more devices + return LIBUSB_SUCCESS; + } + + // Always advance the index for the next iteration + (*_index)++; + + if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data)) + break; + + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain interface data for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + // Device does not have an interface matching this GUID, skip + } + + // Read interface data (dummy + actual) to access the device path + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { + // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + usbi_err(ctx, "could not access interface data (dummy) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + } else { + usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong"); + return LIBUSB_ERROR_OTHER; + } + + dev_interface_details = malloc(size); + if (dev_interface_details == NULL) { + usbi_err(ctx, "could not allocate interface data for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; + } + + dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, + dev_interface_details, size, NULL, NULL)) { + usbi_err(ctx, "could not access interface data (actual) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + free(dev_interface_details); + return LIBUSB_ERROR_OTHER; + } + + *dev_interface_path = sanitize_path(dev_interface_details->DevicePath); + free(dev_interface_details); + + if (*dev_interface_path == NULL) { + usbi_err(ctx, "could not allocate interface path for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; + } + + return LIBUSB_SUCCESS; +} + +/* For libusb0 filter */ +static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) +{ + SP_DEVICE_INTERFACE_DATA dev_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; + DWORD size; + + if (_index == 0) + *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); + + if (dev_info_data != NULL) { + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "Could not obtain device info data for index %u: %s", + _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; + } + } + + dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "Could not obtain interface data for index %u: %s", + _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; + } + + // Read interface data (dummy + actual) to access the device path + if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { + // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", + _index, windows_error_str(0)); + goto err_exit; + } + } else { + usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); + goto err_exit; + } + + dev_interface_details = calloc(1, size); + if (dev_interface_details == NULL) { + usbi_err(ctx, "could not allocate interface data for index %u.", _index); + goto err_exit; + } + + dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) + usbi_err(ctx, "could not access interface data (actual) for index %u: %s", + _index, windows_error_str(0)); + + // [trobinso] lookup the libusb0 symbolic index. + if (dev_interface_details) { + HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); + if (hkey_device_interface != INVALID_HANDLE_VALUE) { + DWORD libusb0_symboliclink_index = 0; + DWORD value_length = sizeof(DWORD); + DWORD value_type = 0; + LONG status; + + status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, + (LPBYTE)&libusb0_symboliclink_index, &value_length); + if (status == ERROR_SUCCESS) { + if (libusb0_symboliclink_index < 256) { + // libusb0.sys is connected to this device instance. + // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. + sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); + usbi_dbg("assigned libusb0 symbolic link %s", filter_path); + } else { + // libusb0.sys was connected to this device instance at one time; but not anymore. + } + } + pRegCloseKey(hkey_device_interface); + } + } + + return dev_interface_details; + +err_exit: + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; +} + +/* + * Returns the first known ancestor of a device + */ +static struct libusb_device *get_ancestor(struct libusb_context *ctx, + DEVINST devinst, PDEVINST _parent_devinst) +{ + struct libusb_device *dev = NULL; + DEVINST parent_devinst; + + while (dev == NULL) { + if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) + break; + devinst = parent_devinst; + dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst); + } + + if ((dev != NULL) && (_parent_devinst != NULL)) + *_parent_devinst = devinst; + + return dev; +} + +/* + * Determine which interface the given endpoint address belongs to + */ +static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep) +{ + const struct libusb_interface *intf; + const struct libusb_interface_descriptor *intf_desc; + int i, j, k; + + for (i = 0; i < conf_desc->bNumInterfaces; i++) { + intf = &conf_desc->interface[i]; + for (j = 0; j < intf->num_altsetting; j++) { + intf_desc = &intf->altsetting[j]; + for (k = 0; k < intf_desc->bNumEndpoints; k++) { + if (intf_desc->endpoint[k].bEndpointAddress == ep) { + usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i); + return intf_desc->bInterfaceNumber; + } + } + } + } + + usbi_dbg("endpoint %02X not found on any interface", ep); + return LIBUSB_ERROR_NOT_FOUND; +} + +/* + * Populate the endpoints addresses of the device_priv interface helper structs + */ +static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + int i, r; + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct libusb_config_descriptor *conf_desc; + const struct libusb_interface_descriptor *if_desc; + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + + r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); + if (r != LIBUSB_SUCCESS) { + usbi_warn(ctx, "could not read config descriptor: error %d", r); + return r; + } + + if_desc = &conf_desc->interface[iface].altsetting[altsetting]; + safe_free(priv->usb_interface[iface].endpoint); + + if (if_desc->bNumEndpoints == 0) { + usbi_dbg("no endpoints found for interface %d", iface); + libusb_free_config_descriptor(conf_desc); + return LIBUSB_SUCCESS; + } + + priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); + if (priv->usb_interface[iface].endpoint == NULL) { + libusb_free_config_descriptor(conf_desc); + return LIBUSB_ERROR_NO_MEM; + } + + priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; + for (i = 0; i < if_desc->bNumEndpoints; i++) { + priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; + usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); + } + libusb_free_config_descriptor(conf_desc); + + // Extra init may be required to configure endpoints + if (priv->apib->configure_endpoints) + r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); + + return r; +} + +// Lookup for a match in the list of API driver names +// return -1 if not found, driver match number otherwise +static int get_sub_api(char *driver, int api) +{ + int i; + const char sep_str[2] = {LIST_SEPARATOR, 0}; + char *tok, *tmp_str; + size_t len = strlen(driver); + + if (len == 0) + return SUB_API_NOTSET; + + tmp_str = _strdup(driver); + if (tmp_str == NULL) + return SUB_API_NOTSET; + + tok = strtok(tmp_str, sep_str); + while (tok != NULL) { + for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { + if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { + free(tmp_str); + return i; + } + } + tok = strtok(NULL, sep_str); + } + + free(tmp_str); + return SUB_API_NOTSET; +} + +/* + * auto-claiming and auto-release helper functions + */ +static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) +{ + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv( + transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = *interface_number; + int r = LIBUSB_SUCCESS; + + switch (api_type) { + case USB_API_WINUSBX: + case USB_API_HID: + break; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } + + usbi_mutex_lock(&autoclaim_lock); + if (current_interface < 0) { // No serviceable interface was found + for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { + // Must claim an interface of the same API type + if ((priv->usb_interface[current_interface].apib->id == api_type) + && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { + usbi_dbg("auto-claimed interface %d for control request", current_interface); + if (handle_priv->autoclaim_count[current_interface] != 0) + usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); + handle_priv->autoclaim_count[current_interface]++; + break; + } + } + if (current_interface == USB_MAXINTERFACES) { + usbi_err(ctx, "could not auto-claim any interface"); + r = LIBUSB_ERROR_NOT_FOUND; + } + } else { + // If we have a valid interface that was autoclaimed, we must increment + // its autoclaim count so that we can prevent an early release. + if (handle_priv->autoclaim_count[current_interface] != 0) + handle_priv->autoclaim_count[current_interface]++; + } + usbi_mutex_unlock(&autoclaim_lock); + + *interface_number = current_interface; + return r; +} + +static void auto_release(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + libusb_device_handle *dev_handle = transfer->dev_handle; + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + int r; + + usbi_mutex_lock(&autoclaim_lock); + if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) { + handle_priv->autoclaim_count[transfer_priv->interface_number]--; + if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { + r = libusb_release_interface(dev_handle, transfer_priv->interface_number); + if (r == LIBUSB_SUCCESS) + usbi_dbg("auto-released interface %d", transfer_priv->interface_number); + else + usbi_dbg("failed to auto-release interface %d (%s)", + transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); + } + } + usbi_mutex_unlock(&autoclaim_lock); +} + +/* + * init: libusb backend init function + */ +static int winusb_init(struct libusb_context *ctx) +{ + int i; + + // We need a lock for proper auto-release + usbi_mutex_init(&autoclaim_lock); + + // Load DLL imports + if (!init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + return LIBUSB_ERROR_OTHER; + } + + // Initialize the low level APIs (we don't care about errors at this stage) + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].init && usb_api_backend[i].init(ctx)) + usbi_warn(ctx, "error initializing %s backend", + usb_api_backend[i].designation); + } + + return LIBUSB_SUCCESS; +} + +/* +* exit: libusb backend deinitialization function +*/ +static void winusb_exit(struct libusb_context *ctx) +{ + int i; + + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].exit) + usb_api_backend[i].exit(); + } + + exit_dlls(); + usbi_mutex_destroy(&autoclaim_lock); +} + +/* + * fetch and cache all the config descriptors through I/O + */ +static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + struct winusb_device_priv *priv = _device_priv(dev); + DWORD size, ret_size; + uint8_t i; + + USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request + PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request + PUSB_CONFIGURATION_DESCRIPTOR cd_data; + + if (dev->num_configurations == 0) + return; + + priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (priv->config_descriptor == NULL) { + usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id); + return; + } + + for (i = 0; i <= dev->num_configurations; i++) { + safe_free(cd_buf_actual); + + if (i == dev->num_configurations) + break; + + size = sizeof(cd_buf_short); + memset(&cd_buf_short, 0, size); + + cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number; + cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; + cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; + cd_buf_short.req.SetupPacket.wIndex = 0; + cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR); + + // Dummy call to get the required data size. Initial failures are reported as info rather + // than error as they can occur for non-penalizing situations, such as with some hubs. + // coverity[tainted_data_argument] + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, + &cd_buf_short, size, &ret_size, NULL)) { + usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; + } + + if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { + usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id); + continue; + } + + size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength; + cd_buf_actual = malloc(size); + if (cd_buf_actual == NULL) { + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + continue; + } + + // Actual call + cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number; + cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; + cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; + cd_buf_actual->SetupPacket.wIndex = 0; + cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength; + + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, + cd_buf_actual, size, &ret_size, NULL)) { + usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; + } + + cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); + + if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) { + usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id); + continue; + } + + if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) { + usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id); + continue; + } + + usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)", + i, cd_data->bConfigurationValue, cd_data->wTotalLength); + + // Cache the descriptor + priv->config_descriptor[i] = malloc(cd_data->wTotalLength); + if (priv->config_descriptor[i] != NULL) { + memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); + } else { + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + } + } +} + +/* + * Populate a libusb device structure + */ +static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, + uint8_t port_number, DEVINST devinst) +{ + struct libusb_context *ctx; + struct libusb_device *tmp_dev; + struct winusb_device_priv *priv, *parent_priv; + USB_NODE_CONNECTION_INFORMATION_EX conn_info; + USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; + HANDLE hub_handle; + DWORD size; + uint8_t bus_number, depth; + int r; + + priv = _device_priv(dev); + + // If the device is already initialized, we can stop here + if (priv->initialized) + return LIBUSB_SUCCESS; + + if (parent_dev != NULL) { // Not a HCD root hub + ctx = DEVICE_CTX(dev); + parent_priv = _device_priv(parent_dev); + if (parent_priv->apib->id != USB_API_HUB) { + usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + // Calculate depth and fetch bus number + bus_number = parent_dev->bus_number; + if (bus_number == 0) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev != parent_dev) { + usbi_err(ctx, "program assertion failed - first ancestor is not parent"); + return LIBUSB_ERROR_NOT_FOUND; + } + libusb_unref_device(tmp_dev); + + for (depth = 1; bus_number == 0; depth++) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev->bus_number != 0) { + bus_number = tmp_dev->bus_number; + depth += _device_priv(tmp_dev)->depth; + } + libusb_unref_device(tmp_dev); + } + } else { + depth = parent_priv->depth + 1; + } + + if (bus_number == 0) { + usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + dev->bus_number = bus_number; + dev->port_number = port_number; + dev->parent_dev = parent_dev; + priv->depth = depth; + + hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + 0, NULL); + if (hub_handle == INVALID_HANDLE_VALUE) { + usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + + memset(&conn_info, 0, sizeof(conn_info)); + conn_info.ConnectionIndex = (ULONG)port_number; + // coverity[tainted_data_argument] + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), + &conn_info, sizeof(conn_info), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information for device '%s': %s", + priv->dev_id, windows_error_str(0)); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (conn_info.ConnectionStatus == NoDeviceConnected) { + usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); + dev->num_configurations = priv->dev_descriptor.bNumConfigurations; + priv->active_config = conn_info.CurrentConfigurationValue; + usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); + + // Cache as many config descriptors as we can + cache_config_descriptors(dev, hub_handle); + + // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 + if (windows_version >= WINDOWS_8) { + conn_info_v2.ConnectionIndex = (ULONG)port_number; + conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); + conn_info_v2.SupportedUsbProtocols.Usb300 = 1; + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, + &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", + priv->dev_id, windows_error_str(0)); + } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { + conn_info.Speed = 3; + } + } + + CloseHandle(hub_handle); + + if (conn_info.DeviceAddress > UINT8_MAX) + usbi_err(ctx, "program assertion failed - device address overflow"); + + dev->device_address = (uint8_t)conn_info.DeviceAddress; + + switch (conn_info.Speed) { + case 0: dev->speed = LIBUSB_SPEED_LOW; break; + case 1: dev->speed = LIBUSB_SPEED_FULL; break; + case 2: dev->speed = LIBUSB_SPEED_HIGH; break; + case 3: dev->speed = LIBUSB_SPEED_SUPER; break; + default: + usbi_warn(ctx, "unknown device speed %u", conn_info.Speed); + break; + } + } + + r = usbi_sanitize_device(dev); + if (r) + return r; + + priv->initialized = true; + + usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", + dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id); + + return LIBUSB_SUCCESS; +} + +static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, + uint8_t bus_number, DEVINST devinst) +{ + struct libusb_device *dev; + struct winusb_device_priv *priv; + unsigned long session_id; + DEVINST child_devinst; + + if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) { + usbi_err(ctx, "could not get child devinst for '%s'", dev_id); + return LIBUSB_ERROR_OTHER; + } + + session_id = (unsigned long)child_devinst; + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (dev->bus_number == 0) { + // Only do this once + usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number); + priv = _device_priv(dev); + dev->bus_number = bus_number; + dev->num_configurations = 1; + priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE; + priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE; + priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB; + priv->dev_descriptor.bNumConfigurations = 1; + priv->active_config = 1; + priv->root_hub = true; + if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) { + usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id); + priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub + priv->dev_descriptor.idProduct = 1; + } + } + + libusb_unref_device(dev); + return LIBUSB_SUCCESS; +} + +// Returns the api type, or 0 if not found/unsupported +static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, + SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) +{ + // Precedence for filter drivers vs driver is in the order of this array + struct driver_lookup lookup[3] = { + {"\0\0", SPDRP_SERVICE, "driver"}, + {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"}, + {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"} + }; + DWORD size, reg_type; + unsigned k, l; + int i, j; + + // Check the service & filter names to know the API we should use + for (k = 0; k < 3; k++) { + if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, + ®_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) { + // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ + if (lookup[k].reg_prop == SPDRP_SERVICE) + // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed + lookup[k].list[strlen(lookup[k].list) + 1] = 0; + + // MULTI_SZ is a pain to work with. Turn it into something much more manageable + // NB: none of the driver names we check against contain LIST_SEPARATOR, + // (currently ';'), so even if an unsuported one does, it's not an issue + for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { + if (lookup[k].list[l] == 0) + lookup[k].list[l] = LIST_SEPARATOR; + } + usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); + } else { + if (GetLastError() != ERROR_INVALID_DATA) + usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); + lookup[k].list[0] = 0; + } + } + + for (i = 2; i < USB_API_MAX; i++) { + for (k = 0; k < 3; k++) { + j = get_sub_api(lookup[k].list, i); + if (j >= 0) { + usbi_dbg("matched %s name against %s", lookup[k].designation, + (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]); + *api = i; + *sub_api = j; + return; + } + } + } +} + +static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path, char *device_id, int api, int sub_api) +{ + struct winusb_device_priv *priv = _device_priv(dev); + int interface_number; + const char *mi_str; + + // Because MI_## are not necessarily in sequential order (some composite + // devices will have only MI_00 & MI_03 for instance), we retrieve the actual + // interface number from the path's MI value + mi_str = strstr(device_id, "MI_"); + if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) { + interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0'); + } else { + usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id); + interface_number = 0; + } + + if (interface_number >= USB_MAXINTERFACES) { + usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path); + return LIBUSB_ERROR_ACCESS; + } + + if (priv->usb_interface[interface_number].path != NULL) { + if (api == USB_API_HID) { + // HID devices can have multiple collections (COL##) for each MI_## interface + usbi_dbg("interface[%d] already set - ignoring HID collection: %s", + interface_number, device_id); + return LIBUSB_ERROR_ACCESS; + } + // In other cases, just use the latest data + safe_free(priv->usb_interface[interface_number].path); + } + + usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); + priv->usb_interface[interface_number].path = dev_interface_path; + priv->usb_interface[interface_number].apib = &usb_api_backend[api]; + priv->usb_interface[interface_number].sub_api = sub_api; + if ((api == USB_API_HID) && (priv->hid == NULL)) { + priv->hid = calloc(1, sizeof(struct hid_device_priv)); + if (priv->hid == NULL) + return LIBUSB_ERROR_NO_MEM; + } + + return LIBUSB_SUCCESS; +} + +static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path) +{ + int i; + struct winusb_device_priv *priv = _device_priv(dev); + + if (priv->hid == NULL) { + usbi_err(ctx, "program assertion failed: parent is not HID"); + return LIBUSB_ERROR_NO_DEVICE; + } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { + usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); + return LIBUSB_ERROR_NO_DEVICE; + } + + for (i = 0; i < priv->hid->nb_interfaces; i++) { + if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { + usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); + return LIBUSB_ERROR_ACCESS; + } + } + + priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; + priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; + usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path); + priv->hid->nb_interfaces++; + return LIBUSB_SUCCESS; +} + +/* + * get_device_list: libusb backend device enumeration function + */ +static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) +{ + struct discovered_devs *discdevs; + HDEVINFO *dev_info, dev_info_intf, dev_info_enum; + SP_DEVINFO_DATA dev_info_data; + DWORD _index = 0; + GUID hid_guid; + int r = LIBUSB_SUCCESS; + int api, sub_api; + unsigned int pass, i, j; + char enumerator[16]; + char dev_id[MAX_PATH_LENGTH]; + struct libusb_device *dev, *parent_dev; + struct winusb_device_priv *priv, *parent_priv; + char *dev_interface_path = NULL; + unsigned long session_id; + DWORD size, port_nr, reg_type, install_state; + HKEY key; + WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; + GUID *if_guid; + LONG s; +#define HUB_PASS 0 +#define DEV_PASS 1 +#define HCD_PASS 2 +#define GEN_PASS 3 +#define HID_PASS 4 +#define EXT_PASS 5 + // Keep a list of guids that will be enumerated +#define GUID_SIZE_STEP 8 + const GUID **guid_list, **new_guid_list; + unsigned int guid_size = GUID_SIZE_STEP; + unsigned int nb_guids; + // Keep a list of PnP enumerator strings that are found + char *usb_enumerator[8] = { "USB" }; + unsigned int nb_usb_enumerators = 1; + unsigned int usb_enum_index = 0; + // Keep a list of newly allocated devs to unref +#define UNREF_SIZE_STEP 16 + libusb_device **unref_list, **new_unref_list; + unsigned int unref_size = UNREF_SIZE_STEP; + unsigned int unref_cur = 0; + + // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) + // PASS 2 : (re)enumerate HUBS + // PASS 3 : (re)enumerate generic USB devices (including driverless) + // and list additional USB device interface GUIDs to explore + // PASS 4 : (re)enumerate master USB devices that have a device interface + // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and + // set the device interfaces. + + // Init the GUID table + guid_list = malloc(guid_size * sizeof(void *)); + if (guid_list == NULL) { + usbi_err(ctx, "failed to alloc guid list"); + return LIBUSB_ERROR_NO_MEM; + } + + guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; + guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; + guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; + guid_list[GEN_PASS] = NULL; + if (api_hid_available) { + HidD_GetHidGuid(&hid_guid); + guid_list[HID_PASS] = &hid_guid; + } else { + guid_list[HID_PASS] = NULL; + } + nb_guids = EXT_PASS; + + unref_list = malloc(unref_size * sizeof(void *)); + if (unref_list == NULL) { + usbi_err(ctx, "failed to alloc unref list"); + free((void *)guid_list); + return LIBUSB_ERROR_NO_MEM; + } + + dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info_intf == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0)); + free(unref_list); + free((void *)guid_list); + return LIBUSB_ERROR_OTHER; + } + + for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { +//#define ENUM_DEBUG +#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) + const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; + usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass])); +#endif + if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) + continue; + + dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum; + + for (i = 0; ; i++) { + // safe loop: free up any (unprotected) dynamic resource + // NB: this is always executed before breaking the loop + safe_free(dev_interface_path); + priv = parent_priv = NULL; + dev = parent_dev = NULL; + + // Safe loop: end of loop conditions + if (r != LIBUSB_SUCCESS) + break; + + if ((pass == HCD_PASS) && (i == UINT8_MAX)) { + usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX); + break; + } + + if (pass != GEN_PASS) { + // Except for GEN, all passes deal with device interfaces + r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path); + if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) { + _index = 0; + break; + } + } else { + // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are + // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". + // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" + // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" + for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) { + if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i)) + break; + i = 0; + } + if (usb_enum_index == nb_usb_enumerators) + break; + } + + // Read the Device ID path + if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) { + usbi_warn(ctx, "could not read the device instance ID for devInst %X, skipping", + dev_info_data.DevInst); + continue; + } + +#ifdef ENUM_DEBUG + usbi_dbg("PRO: %s", dev_id); +#endif + + // Set API to use or get additional data from generic pass + api = USB_API_UNSUPPORTED; + sub_api = SUB_API_NOTSET; + switch (pass) { + case HCD_PASS: + break; + case HUB_PASS: + api = USB_API_HUB; + // Fetch the PnP enumerator class for this hub + // This will allow us to enumerate all classes during the GEN pass + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, + NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) { + usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0)); + LOOP_BREAK(LIBUSB_ERROR_OTHER); + } + for (j = 0; j < nb_usb_enumerators; j++) { + if (strcmp(usb_enumerator[j], enumerator) == 0) + break; + } + if (j == nb_usb_enumerators) { + usbi_dbg("found new PnP enumerator string '%s'", enumerator); + if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) { + usb_enumerator[nb_usb_enumerators] = _strdup(enumerator); + if (usb_enumerator[nb_usb_enumerators] != NULL) { + nb_usb_enumerators++; + } else { + usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + } else { + usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible"); + } + } + break; + case GEN_PASS: + // We use the GEN pass to detect driverless devices... + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER, + NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { + usbi_info(ctx, "The following device has no driver: '%s'", dev_id); + usbi_info(ctx, "libusb will not be able to access it"); + } + // ...and to add the additional device interface GUIDs + key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (key == INVALID_HANDLE_VALUE) + break; + // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order + size = sizeof(guid_string_w); + s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + if (s == ERROR_FILE_NOT_FOUND) + s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + pRegCloseKey(key); + if ((s == ERROR_SUCCESS) && + (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) || + ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) { + if (nb_guids == guid_size) { + new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); + if (new_guid_list == NULL) { + usbi_err(ctx, "failed to realloc guid list"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + guid_list = new_guid_list; + guid_size += GUID_SIZE_STEP; + } + if_guid = malloc(sizeof(*if_guid)); + if (if_guid == NULL) { + usbi_err(ctx, "failed to alloc if_guid"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + if (pIIDFromString(guid_string_w, if_guid) != 0) { + usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id); + free(if_guid); + } else { + // Check if we've already seen this GUID + for (j = EXT_PASS; j < nb_guids; j++) { + if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0) + break; + } + if (j == nb_guids) { + usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); + guid_list[nb_guids++] = if_guid; + } else { + // Duplicate, ignore + free(if_guid); + } + } + } else if (s == ERROR_SUCCESS) { + usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id); + } + break; + case HID_PASS: + api = USB_API_HID; + break; + default: + // Get the API type (after checking that the driver installation is OK) + if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE, + NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) { + usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", + dev_id, windows_error_str(0)); + } else if (install_state != 0) { + usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", + dev_id, (unsigned int)install_state); + continue; + } + get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api); + break; + } + + // Find parent device (for the passes that need it) + if (pass >= GEN_PASS) { + parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL); + if (parent_dev == NULL) { + // Root hubs will not have a parent + dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst); + if (dev != NULL) { + priv = _device_priv(dev); + if (priv->root_hub) + goto track_unref; + libusb_unref_device(dev); + } + + usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id); + continue; + } + + parent_priv = _device_priv(parent_dev); + // virtual USB devices are also listed during GEN - don't process these yet + if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { + libusb_unref_device(parent_dev); + continue; + } + } + + // Create new or match existing device, using the devInst as session id + if ((pass <= GEN_PASS) && (pass != HCD_PASS)) { // For subsequent passes, we'll lookup the parent + // These are the passes that create "new" devices + session_id = (unsigned long)dev_info_data.DevInst; + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + alloc_device: + usbi_dbg("allocating new device for session [%lX]", session_id); + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + + priv = winusb_device_priv_init(dev); + priv->dev_id = _strdup(dev_id); + if (priv->dev_id == NULL) { + libusb_unref_device(dev); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + } else { + usbi_dbg("found existing device for session [%lX]", session_id); + + priv = _device_priv(dev); + if (strcmp(priv->dev_id, dev_id) != 0) { + usbi_dbg("device instance ID for session [%lX] changed", session_id); + usbi_disconnect_device(dev); + libusb_unref_device(dev); + goto alloc_device; + } + } + + track_unref: + // Keep track of devices that need unref + if (unref_cur == unref_size) { + new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *)); + if (new_unref_list == NULL) { + usbi_err(ctx, "could not realloc list for unref - aborting"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + unref_list = new_unref_list; + unref_size += UNREF_SIZE_STEP; + } + unref_list[unref_cur++] = dev; + } + + // Setup device + switch (pass) { + case HUB_PASS: + case DEV_PASS: + // If the device has already been setup, don't do it again + if (priv->path != NULL) + break; + // Take care of API initialization + priv->path = dev_interface_path; + dev_interface_path = NULL; + priv->apib = &usb_api_backend[api]; + priv->sub_api = sub_api; + switch (api) { + case USB_API_COMPOSITE: + case USB_API_HUB: + break; + case USB_API_HID: + priv->hid = calloc(1, sizeof(struct hid_device_priv)); + if (priv->hid == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + break; + default: + // For other devices, the first interface is the same as the device + priv->usb_interface[0].path = _strdup(priv->path); + if (priv->usb_interface[0].path == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + // The following is needed if we want API calls to work for both simple + // and composite devices. + for (j = 0; j < USB_MAXINTERFACES; j++) + priv->usb_interface[j].apib = &usb_api_backend[api]; + break; + } + break; + case HCD_PASS: + r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); + break; + case GEN_PASS: + // The SPDRP_ADDRESS for USB devices is the device port number on the hub + port_nr = 0; + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS, + NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr))) + usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0)); + r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst); + if (r == LIBUSB_SUCCESS) { + // Append device to the list of discovered devices + discdevs = discovered_devs_append(*_discdevs, dev); + if (!discdevs) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + + *_discdevs = discdevs; + } else if (r == LIBUSB_ERROR_NO_DEVICE) { + // This can occur if the device was disconnected but Windows hasn't + // refreshed its enumeration yet - in that case, we ignore the device + r = LIBUSB_SUCCESS; + } + break; + default: // HID_PASS and later + if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { + if (parent_priv->apib->id == USB_API_HID) { + usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); + r = set_hid_interface(ctx, parent_dev, dev_interface_path); + } else { + usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); + r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api); + } + switch (r) { + case LIBUSB_SUCCESS: + dev_interface_path = NULL; + break; + case LIBUSB_ERROR_ACCESS: + // interface has already been set => make sure dev_interface_path is freed then + r = LIBUSB_SUCCESS; + break; + default: + LOOP_BREAK(r); + break; + } + } + libusb_unref_device(parent_dev); + break; + } + } + } + + pSetupDiDestroyDeviceInfoList(dev_info_intf); + + // Free any additional GUIDs + for (pass = EXT_PASS; pass < nb_guids; pass++) + free((void *)guid_list[pass]); + free((void *)guid_list); + + // Free any PnP enumerator strings + for (i = 1; i < nb_usb_enumerators; i++) + free(usb_enumerator[i]); + + // Unref newly allocated devs + for (i = 0; i < unref_cur; i++) + libusb_unref_device(unref_list[i]); + free(unref_list); + + return r; +} + +static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) +{ + struct winusb_device_priv *priv = _device_priv(dev); + + memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); + return LIBUSB_SUCCESS; +} + +static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) +{ + struct winusb_device_priv *priv = _device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + size_t size; + + // config index is zero based + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_INVALID_PARAM; + + if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) + return LIBUSB_ERROR_NOT_FOUND; + + config_header = priv->config_descriptor[config_index]; + + size = MIN(config_header->wTotalLength, len); + memcpy(buffer, priv->config_descriptor[config_index], size); + return (int)size; +} + +static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) +{ + struct winusb_device_priv *priv = _device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + if (priv->config_descriptor == NULL) + return LIBUSB_ERROR_NOT_FOUND; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = priv->config_descriptor[index]; + if (config_header == NULL) + continue; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = (unsigned char *)priv->config_descriptor[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + +/* + * return the cached copy of the active config descriptor + */ +static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) +{ + struct winusb_device_priv *priv = _device_priv(dev); + unsigned char *config_desc; + int r; + + if (priv->active_config == 0) + return LIBUSB_ERROR_NOT_FOUND; + + r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc); + if (r < 0) + return r; + + len = MIN((size_t)r, len); + memcpy(buffer, config_desc, len); + return (int)len; +} + +static int winusb_open(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, open); + + return priv->apib->open(SUB_API_NOTSET, dev_handle); +} + +static void winusb_close(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + if (priv->apib->close) + priv->apib->close(SUB_API_NOTSET, dev_handle); +} + +static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + if (priv->active_config == 0) { + *config = 0; + return LIBUSB_ERROR_NOT_FOUND; + } + + *config = priv->active_config; + return LIBUSB_SUCCESS; +} + +/* + * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver + * does not currently expose a service that allows higher-level drivers to set + * the configuration." + */ +static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r = LIBUSB_SUCCESS; + + if (config >= USB_MAXCONFIG) + return LIBUSB_ERROR_INVALID_PARAM; + + r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, + LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, + 0, NULL, 0, 1000); + + if (r == LIBUSB_SUCCESS) + priv->active_config = (uint8_t)config; + + return r; +} + +static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, claim_interface); + + safe_free(priv->usb_interface[iface].endpoint); + priv->usb_interface[iface].nb_endpoints = 0; + + r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); + + if (r == LIBUSB_SUCCESS) + r = windows_assign_endpoints(dev_handle, iface, 0); + + return r; +} + +static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting); + + safe_free(priv->usb_interface[iface].endpoint); + priv->usb_interface[iface].nb_endpoints = 0; + + r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); + + if (r == LIBUSB_SUCCESS) + r = windows_assign_endpoints(dev_handle, iface, altsetting); + + return r; +} + +static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, release_interface); + + return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); +} + +static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, clear_halt); + + return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); +} + +static int winusb_reset_device(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, reset_device); + + return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); +} + +static void winusb_destroy_device(struct libusb_device *dev) +{ + winusb_device_priv_release(dev); +} + +static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->handle = NULL; + safe_free(transfer_priv->hid_buffer); + safe_free(transfer_priv->iso_context); + + // When auto claim is in use, attempt to release the auto-claimed interface + auto_release(itransfer); +} + +static int do_submit_transfer(struct usbi_transfer *itransfer, short events, + int (*transfer_fn)(int, struct usbi_transfer *)) +{ + struct libusb_context *ctx = ITRANSFER_CTX(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd wfd; + int r; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); + return r; + } + + // Use transfer_priv to store data needed for async polling + transfer_priv->pollable_fd = wfd; + + r = transfer_fn(SUB_API_NOTSET, itransfer); + + if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) { + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + } + + return r; +} + +static int winusb_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int (*transfer_fn)(int, struct usbi_transfer *); + short events; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_control_transfer; + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) + return LIBUSB_ERROR_NOT_SUPPORTED; + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_bulk_transfer; + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_iso_transfer; + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return LIBUSB_ERROR_NOT_SUPPORTED; + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (transfer_fn == NULL) { + usbi_warn(TRANSFER_CTX(transfer), + "unsupported transfer type %d (unrecognized device driver)", + transfer->type); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + return do_submit_transfer(itransfer, events, transfer_fn); +} + +static int windows_abort_control(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_control); + + return priv->apib->abort_control(SUB_API_NOTSET, itransfer); +} + +static int windows_abort_transfers(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_transfers); + + return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); +} + +static int winusb_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return windows_abort_control(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return windows_abort_transfers(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return LIBUSB_ERROR_NOT_SUPPORTED; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); +} + +static int winusb_get_transfer_fd(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + return transfer_priv->pollable_fd.fd; +} + +static void winusb_get_overlapped_result(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; + + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { + *io_result = NO_ERROR; + *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; + } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) { + // Regular async overlapped + *io_result = NO_ERROR; + } else { + *io_result = GetLastError(); + } +} + +// NB: MSVC6 does not support named initializers. +const struct windows_backend winusb_backend = { + winusb_init, + winusb_exit, + winusb_get_device_list, + winusb_open, + winusb_close, + winusb_get_device_descriptor, + winusb_get_active_config_descriptor, + winusb_get_config_descriptor, + winusb_get_config_descriptor_by_value, + winusb_get_configuration, + winusb_set_configuration, + winusb_claim_interface, + winusb_release_interface, + winusb_set_interface_altsetting, + winusb_clear_halt, + winusb_reset_device, + winusb_destroy_device, + winusb_submit_transfer, + winusb_cancel_transfer, + winusb_clear_transfer_priv, + winusb_copy_transfer_data, + winusb_get_transfer_fd, + winusb_get_overlapped_result, +}; + +/* + * USB API backends + */ + +static const char * const composite_driver_names[] = {"USBCCGP"}; +static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"}; +static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; +const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { + { + USB_API_UNSUPPORTED, + "Unsupported API", + // No supported operations + }, + { + USB_API_HUB, + "HUB API", + // No supported operations + }, + { + USB_API_COMPOSITE, + "Composite API", + composite_driver_names, + ARRAYSIZE(composite_driver_names), + NULL, /* init */ + NULL, /* exit */ + composite_open, + composite_close, + NULL, /* configure_endpoints */ + composite_claim_interface, + composite_set_interface_altsetting, + composite_release_interface, + composite_clear_halt, + composite_reset_device, + composite_submit_bulk_transfer, + composite_submit_iso_transfer, + composite_submit_control_transfer, + composite_abort_control, + composite_abort_transfers, + composite_copy_transfer_data, + }, + { + USB_API_WINUSBX, + "WinUSB-like APIs", + winusbx_driver_names, + ARRAYSIZE(winusbx_driver_names), + winusbx_init, + winusbx_exit, + winusbx_open, + winusbx_close, + winusbx_configure_endpoints, + winusbx_claim_interface, + winusbx_set_interface_altsetting, + winusbx_release_interface, + winusbx_clear_halt, + winusbx_reset_device, + winusbx_submit_bulk_transfer, + winusbx_submit_iso_transfer, + winusbx_submit_control_transfer, + winusbx_abort_control, + winusbx_abort_transfers, + winusbx_copy_transfer_data, + }, + { + USB_API_HID, + "HID API", + // No supported operations + }, +}; + + +/* + * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions + */ +#define WinUSBX_Set(fn) \ + do { \ + if (native_winusb) \ + WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ + else \ + pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ + } while (0) + +static int winusbx_init(struct libusb_context *ctx) +{ + HMODULE h; + bool native_winusb; + int i; + KLIB_VERSION LibK_Version; + LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; + LibK_GetVersion_t pLibK_GetVersion; + + h = LoadLibraryA("libusbK"); + + if (h == NULL) { + usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); + h = LoadLibraryA("WinUSB"); + + if (h == NULL) { + usbi_warn(ctx, "WinUSB DLL is not available either, " + "you will not be able to access devices outside of enumeration"); + return LIBUSB_ERROR_NOT_FOUND; + } + } else { + usbi_dbg("using libusbK DLL for universal access"); + pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); + if (pLibK_GetVersion != NULL) { + pLibK_GetVersion(&LibK_Version); + usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, + LibK_Version.Micro, LibK_Version.Nano); + } + pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); + if (pLibK_GetProcAddress == NULL) { + usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); + FreeLibrary(h); + return LIBUSB_ERROR_NOT_FOUND; + } + } + + native_winusb = (pLibK_GetProcAddress == NULL); + for (i = 0; i < SUB_API_MAX; i++) { + WinUSBX_Set(AbortPipe); + WinUSBX_Set(ControlTransfer); + WinUSBX_Set(FlushPipe); + WinUSBX_Set(Free); + WinUSBX_Set(GetAssociatedInterface); + WinUSBX_Set(Initialize); + WinUSBX_Set(ReadPipe); + if (!native_winusb) + WinUSBX_Set(ResetDevice); + WinUSBX_Set(ResetPipe); + WinUSBX_Set(SetCurrentAlternateSetting); + WinUSBX_Set(SetPipePolicy); + WinUSBX_Set(WritePipe); + WinUSBX_Set(IsoReadPipe); + WinUSBX_Set(IsoWritePipe); + + if (WinUSBX[i].Initialize != NULL) { + WinUSBX[i].initialized = true; + // Assume driver supports CancelIoEx() if it is available + WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); + usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); + } else { + usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); + WinUSBX[i].initialized = false; + } + } + + WinUSBX_handle = h; + return LIBUSB_SUCCESS; +} + +static void winusbx_exit(void) +{ + if (WinUSBX_handle != NULL) { + FreeLibrary(WinUSBX_handle); + WinUSBX_handle = NULL; + + /* Reset the WinUSBX API structures */ + memset(&WinUSBX, 0, sizeof(WinUSBX)); + } +} + +// NB: open and close must ensure that they only handle interface of +// the right API type, as these functions can be called wholesale from +// composite_open(), with interfaces belonging to different APIs +static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + HANDLE file_handle; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // WinUSB requires a separate handle for each interface + for (i = 0; i < USB_MAXINTERFACES; i++) { + if ((priv->usb_interface[i].path != NULL) + && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { + file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + if (file_handle == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: // The device was disconnected + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_ACCESS_DENIED: + return LIBUSB_ERROR_ACCESS; + default: + return LIBUSB_ERROR_IO; + } + } + handle_priv->interface_handle[i].dev_handle = file_handle; + } + } + return LIBUSB_SUCCESS; +} + +static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE handle; + int i; + + if (sub_api == SUB_API_NOTSET) + sub_api = priv->sub_api; + + if (!WinUSBX[sub_api].initialized) + return; + + if (priv->apib->id == USB_API_COMPOSITE) { + // If this is a composite device, just free and close all WinUSB-like + // interfaces directly (each is independent and not associated with another) + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[i].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } + } + } else { + // If this is a WinUSB device, free all interfaces above interface 0, + // then free and close interface 0 last + for (i = 1; i < USB_MAXINTERFACES; i++) { + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + } + handle = handle_priv->interface_handle[0].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[0].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } +} + +static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; + UCHAR policy; + ULONG timeout = 0; + uint8_t endpoint_address; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // With handle and enpoints set (in parent), we can setup the default pipe properties + // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx + for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { + endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) + usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); + + if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) + continue; // Other policies don't apply to control endpoint or libusb0 + + policy = false; + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) + usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); + + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) + usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); + + policy = true; + /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: + https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) + usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); + + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) + usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); + SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; + HDEVINFO dev_info = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA dev_info_data; + char *dev_path_no_guid = NULL; + char filter_path[] = "\\\\.\\libusb0-0000"; + bool found_filter = false; + HANDLE file_handle, winusb_handle; + DWORD err; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // If the device is composite, but using the default Windows composite parent driver (usbccgp) + // or if it's the first WinUSB-like interface, we get a handle through Initialize(). + if ((is_using_usbccgp) || (iface == 0)) { + // composite device (independent interfaces) or interface 0 + file_handle = handle_priv->interface_handle[iface].dev_handle; + if (!HANDLE_VALID(file_handle)) + return LIBUSB_ERROR_NOT_FOUND; + + if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + err = GetLastError(); + switch (err) { + case ERROR_BAD_COMMAND: + // The device was disconnected + usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + default: + // it may be that we're using the libusb0 filter driver. + // TODO: can we move this whole business into the K/0 DLL? + for (i = 0; ; i++) { + safe_free(dev_interface_details); + safe_free(dev_path_no_guid); + + dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); + if ((found_filter) || (dev_interface_details == NULL)) + break; + + // ignore GUID part + dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); + if (dev_path_no_guid == NULL) + continue; + + if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { + file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + if (file_handle != INVALID_HANDLE_VALUE) { + if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + // Replace the existing file handle with the working one + CloseHandle(handle_priv->interface_handle[iface].dev_handle); + handle_priv->interface_handle[iface].dev_handle = file_handle; + found_filter = true; + } else { + usbi_err(ctx, "could not initialize filter driver for %s", filter_path); + CloseHandle(file_handle); + } + } else { + usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); + } + } + } + free(dev_interface_details); + if (!found_filter) { + usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); + return LIBUSB_ERROR_ACCESS; + } + } + } + handle_priv->interface_handle[iface].api_handle = winusb_handle; + } else { + // For all other interfaces, use GetAssociatedInterface() + winusb_handle = handle_priv->interface_handle[0].api_handle; + // It is a requirement for multiple interface devices on Windows that, to you + // must first claim the first interface before you claim the others + if (!HANDLE_VALID(winusb_handle)) { + file_handle = handle_priv->interface_handle[0].dev_handle; + if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + handle_priv->interface_handle[0].api_handle = winusb_handle; + usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface); + } else { + usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + } + if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), + &handle_priv->interface_handle[iface].api_handle)) { + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + switch (GetLastError()) { + case ERROR_NO_MORE_ITEMS: // invalid iface + return LIBUSB_ERROR_NOT_FOUND; + case ERROR_BAD_COMMAND: // The device was disconnected + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_ALREADY_EXISTS: // already claimed + return LIBUSB_ERROR_BUSY; + default: + usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + } + } + usbi_dbg("claimed interface %d", iface); + handle_priv->active_interface = iface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + winusb_handle = handle_priv->interface_handle[iface].api_handle; + if (!HANDLE_VALID(winusb_handle)) + return LIBUSB_ERROR_NOT_FOUND; + + WinUSBX[sub_api].Free(winusb_handle); + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + + return LIBUSB_SUCCESS; +} + +/* + * Return the first valid interface (of the same API type), for control transfers + */ +static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int i; + + if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { + usbi_dbg("unsupported API ID"); + return -1; + } + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) + && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) + && (priv->usb_interface[i].apib->id == api_id)) + return i; + } + + return -1; +} + +/* + * Lookup interface by endpoint address. -1 if not found + */ +static int interface_by_endpoint(struct winusb_device_priv *priv, + struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address) +{ + int i, j; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) + continue; + if (priv->usb_interface[i].endpoint == NULL) + continue; + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { + if (priv->usb_interface[i].endpoint[j] == endpoint_address) + return i; + } + } + + return -1; +} + +static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer; + ULONG size; + HANDLE winusb_handle; + OVERLAPPED *overlapped; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + // Windows places upper limits on the control transfer size + // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx + if (size > MAX_CTRL_BUFFER_LENGTH) + return LIBUSB_ERROR_INVALID_PARAM; + + current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); + if (current_interface < 0) { + if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("will use interface %d", current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + // Sending of set configuration control requests from WinUSB creates issues + if ((LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD) + && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) { + if (setup->Value != priv->active_config) { + usbi_warn(ctx, "cannot set configuration other than the default one"); + return LIBUSB_ERROR_INVALID_PARAM; + } + windows_force_sync_completion(overlapped, 0); + } else { + if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, size); + } + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + if (altsetting > 255) + return LIBUSB_ERROR_INVALID_PARAM; + + winusb_handle = handle_priv->interface_handle[iface].api_handle; + if (!HANDLE_VALID(winusb_handle)) { + usbi_err(ctx, "interface must be claimed first"); + return LIBUSB_ERROR_NOT_FOUND; + } + + if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) { + usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE winusb_handle; + OVERLAPPED *overlapped; + bool ret; + int current_interface; + int i; + UINT offset; + PKISO_CONTEXT iso_context; + size_t iso_ctx_size; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + if ((sub_api != SUB_API_LIBUSBK) && (sub_api != SUB_API_LIBUSB0)) { + // iso only supported on libusbk-based backends + PRINT_UNSUPPORTED_API(submit_iso_transfer); + return LIBUSB_ERROR_NOT_SUPPORTED; + }; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET)); + transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size); + if (transfer_priv->iso_context == NULL) + return LIBUSB_ERROR_NO_MEM; + + // start ASAP + iso_context->StartFrame = 0; + iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets; + + // convert the transfer packet lengths to iso_packet offsets + offset = 0; + for (i = 0; i < transfer->num_iso_packets; i++) { + iso_context->IsoPackets[i].offset = offset; + offset += transfer->iso_packet_desc[i].length; + } + + if (IS_XFERIN(transfer)) { + usbi_dbg("reading %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } else { + usbi_dbg("writing %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } + + if (!ret) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE winusb_handle; + OVERLAPPED *overlapped; + bool ret; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + if (IS_XFERIN(transfer)) { + usbi_dbg("reading %d bytes", transfer->length); + ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); + } else { + usbi_dbg("writing %d bytes", transfer->length); + ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); + } + + if (!ret) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = interface_by_endpoint(priv, handle_priv, endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); + winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + + if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) { + usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +/* + * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed + * through testing as well): + * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel + * the control transfer using CancelIo" + */ +static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer) +{ + // Cancelling of the I/O is done in the parent + return LIBUSB_SUCCESS; +} + +static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE handle; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = transfer_priv->interface_number; + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(ctx, "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + usbi_dbg("will use interface %d", current_interface); + + if (WinUSBX[sub_api].CancelIoEx_supported) { + // Try to use CancelIoEx if available to cancel just a single transfer + handle = handle_priv->interface_handle[current_interface].dev_handle; + if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) + return LIBUSB_SUCCESS; + else if (GetLastError() == ERROR_NOT_FOUND) + return LIBUSB_ERROR_NOT_FOUND; + + // Not every driver implements the necessary functionality for CancelIoEx + usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]); + WinUSBX[sub_api].CancelIoEx_supported = false; + } + + handle = handle_priv->interface_handle[current_interface].api_handle; + if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +/* + * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper + * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx): + * "WinUSB does not support host-initiated reset port and cycle port operations" and + * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the + * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is + * cycle the pipes (and even then, the control pipe can not be reset using WinUSB) + */ +// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?) +static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + int i, j; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // Reset any available pipe (except control) + for (i = 0; i < USB_MAXINTERFACES; i++) { + winusb_handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(winusb_handle)) { + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { + usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); + if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) + usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + + // FlushPipe seems to fail on OUT pipes + if (IS_EPIN(priv->usb_interface[i].endpoint[j]) + && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) + usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + + if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) + usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + } + } + } + + // libusbK & libusb0 have the ability to issue an actual device reset + if (WinUSBX[sub_api].ResetDevice != NULL) { + winusb_handle = handle_priv->interface_handle[0].api_handle; + if (HANDLE_VALID(winusb_handle)) + WinUSBX[sub_api].ResetDevice(winusb_handle); + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + PKISO_CONTEXT iso_context; + int i; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + CHECK_WINUSBX_AVAILABLE(sub_api); + + // for isochronous, need to copy the individual iso packet actual_lengths and statuses + if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) { + // iso only supported on libusbk-based backends for now + iso_context = transfer_priv->iso_context; + for (i = 0; i < transfer->num_iso_packets; i++) { + transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length; + // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status + //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status; + } + } else { + // This should only occur if backend is not set correctly or other backend isoc is partially implemented + PRINT_UNSUPPORTED_API(copy_transfer_data); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + } + + itransfer->transferred += io_size; + return LIBUSB_TRANSFER_COMPLETED; +} + +/* + * Composite API functions + */ +static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r = LIBUSB_ERROR_NOT_FOUND; + uint8_t i; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + switch (priv->usb_interface[i].apib->id) { + case USB_API_WINUSBX: + if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) { + available[priv->usb_interface[i].sub_api] = true; + } + break; + case USB_API_HID: + available[SUB_API_MAX] = true; + break; + default: + break; + } + } + + for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers + if (available[i]) { + r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle); + if (r != LIBUSB_SUCCESS) { + return r; + } + } + } +/* + if (available[SUB_API_MAX]) // HID driver + r = hid_open(SUB_API_NOTSET, dev_handle); +*/ + return r; +} + +static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + uint8_t i; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + switch (priv->usb_interface[i].apib->id) { + case USB_API_WINUSBX: + if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) + available[priv->usb_interface[i].sub_api] = true; + break; + case USB_API_HID: + available[SUB_API_MAX] = true; + break; + default: + break; + } + } + + for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers + if (available[i]) + usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); + } +/* + if (available[SUB_API_MAX]) // HID driver + hid_close(SUB_API_NOTSET, dev_handle); +*/ +} + +static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface); + + return priv->usb_interface[iface].apib-> + claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); +} + +static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting); + + return priv->usb_interface[iface].apib-> + set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); +} + +static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface); + + return priv->usb_interface[iface].apib-> + release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); +} + +static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct libusb_config_descriptor *conf_desc; + WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; + int iface, pass, r; + + // Interface shouldn't matter for control, but it does in practice, with Windows' + // restrictions with regards to accessing HID keyboards and mice. Try to target + // a specific interface first, if possible. + switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) { + case LIBUSB_RECIPIENT_INTERFACE: + iface = setup->Index & 0xFF; + break; + case LIBUSB_RECIPIENT_ENDPOINT: + r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); + if (r == LIBUSB_SUCCESS) { + iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF)); + libusb_free_config_descriptor(conf_desc); + break; + } + // Fall through if not able to determine interface + default: + iface = -1; + break; + } + + // Try and target a specific interface if the control setup indicates such + if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { + usbi_dbg("attempting control transfer targeted to interface %d", iface); + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { + r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); + if (r == LIBUSB_SUCCESS) + return r; + } + } + + // Either not targeted to a specific interface or no luck in doing so. + // Try a 2 pass approach with all interfaces. + for (pass = 0; pass < 2; pass++) { + for (iface = 0; iface < USB_MAXINTERFACES; iface++) { + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { + if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { + usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); + continue; + } + usbi_dbg("using interface %d", iface); + r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); + // If not supported on this API, it may be supported on another, so don't give up yet!! + if (r == LIBUSB_ERROR_NOT_SUPPORTED) + continue; + return r; + } + } + } + usbi_err(ctx, "no libusb supported interfaces to complete request"); + return LIBUSB_ERROR_NOT_FOUND; +} + +static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer); + + return priv->usb_interface[current_interface].apib-> + submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer); + + return priv->usb_interface[current_interface].apib-> + submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt); + + return priv->usb_interface[current_interface].apib-> + clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); +} + +static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control); + + return priv->usb_interface[current_interface].apib-> + abort_control(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers); + + return priv->usb_interface[current_interface].apib-> + abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + uint8_t i; + bool available[SUB_API_MAX]; + + for (i = 0; i < SUB_API_MAX; i++) + available[i] = false; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) + && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) + available[priv->usb_interface[i].sub_api] = true; + } + + for (i = 0; i < SUB_API_MAX; i++) { + if (available[i]) { + r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle); + if (r != LIBUSB_SUCCESS) + return r; + } + } + + return LIBUSB_SUCCESS; +} + +static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data); + + return priv->usb_interface[current_interface].apib-> + copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h new file mode 100644 index 0000000000..c1ad4eb9b2 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h @@ -0,0 +1,680 @@ +/* + * Windows backend for libusb 1.0 + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "windows_common.h" +#include "windows_nt_common.h" + +#if defined(_MSC_VER) +// disable /W4 MSVC warnings that are benign +#pragma warning(disable:4100) // unreferenced formal parameter +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int +#pragma warning(disable:4996) // deprecated API calls +#pragma warning(disable:28159) // more deprecated API calls +#endif + +// Missing from MSVC6 setupapi.h +#ifndef SPDRP_ADDRESS +#define SPDRP_ADDRESS 28 +#endif +#ifndef SPDRP_INSTALL_STATE +#define SPDRP_INSTALL_STATE 34 +#endif + +#define MAX_CTRL_BUFFER_LENGTH 4096 +#define MAX_USB_STRING_LENGTH 128 +#define MAX_HID_REPORT_SIZE 1024 +#define MAX_HID_DESCRIPTOR_SIZE 256 +#define MAX_GUID_STRING_LENGTH 40 +#define MAX_PATH_LENGTH 128 +#define MAX_KEY_LENGTH 256 +#define LIST_SEPARATOR ';' + +// Handle code for HID interface that have been claimed ("dibs") +#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5) +// Additional return code for HID operations that completed synchronously +#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) + +// http://msdn.microsoft.com/en-us/library/ff545978.aspx +// http://msdn.microsoft.com/en-us/library/ff545972.aspx +// http://msdn.microsoft.com/en-us/library/ff545982.aspx +#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER +const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}}; +#endif +#ifndef GUID_DEVINTERFACE_USB_DEVICE +const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}; +#endif +#ifndef GUID_DEVINTERFACE_USB_HUB +const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}}; +#endif +#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER +const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}}; +#endif + + +/* + * Multiple USB API backend support + */ +#define USB_API_UNSUPPORTED 0 +#define USB_API_HUB 1 +#define USB_API_COMPOSITE 2 +#define USB_API_WINUSBX 3 +#define USB_API_HID 4 +#define USB_API_MAX 5 + +// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL) +// Must have the same values as the KUSB_DRVID enum from libusbk.h +#define SUB_API_NOTSET -1 +#define SUB_API_LIBUSBK 0 +#define SUB_API_LIBUSB0 1 +#define SUB_API_WINUSB 2 +#define SUB_API_MAX 3 + +struct windows_usb_api_backend { + const uint8_t id; + const char * const designation; + const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp" + const uint8_t nb_driver_names; + int (*init)(struct libusb_context *ctx); + void (*exit)(void); + int (*open)(int sub_api, struct libusb_device_handle *dev_handle); + void (*close)(int sub_api, struct libusb_device_handle *dev_handle); + int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface); + int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); + int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); + int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); + int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); + int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle); + int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer); + int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer); + int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer); + int (*abort_control)(int sub_api, struct usbi_transfer *itransfer); + int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer); + int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); +}; + +extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; + +#define PRINT_UNSUPPORTED_API(fname) \ + usbi_dbg("unsupported API call for '%s' " \ + "(unrecognized device driver)", #fname) + +#define CHECK_SUPPORTED_API(apip, fname) \ + do { \ + if ((apip)->fname == NULL) { \ + PRINT_UNSUPPORTED_API(fname); \ + return LIBUSB_ERROR_NOT_SUPPORTED; \ + } \ + } while (0) + +/* + * private structures definition + * with inline pseudo constructors/destructors + */ + +// TODO (v2+): move hid desc to libusb.h? +struct libusb_hid_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bClassDescriptorType; + uint16_t wClassDescriptorLength; +}; + +#define LIBUSB_DT_HID_SIZE 9 +#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \ + + LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE) +#define HID_MAX_REPORT_SIZE 1024 +#define HID_IN_EP 0x81 +#define HID_OUT_EP 0x02 +#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F) +#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5)) +#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) +#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) + +#ifndef CTL_CODE +#define CTL_CODE(DeviceType, Function, Method, Access) \ + (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) +#endif + +// The following are used for HID reports IOCTLs +#define HID_IN_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + +#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) +#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) +#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100) +#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101) + +enum libusb_hid_request_type { + HID_REQ_GET_REPORT = 0x01, + HID_REQ_GET_IDLE = 0x02, + HID_REQ_GET_PROTOCOL = 0x03, + HID_REQ_SET_REPORT = 0x09, + HID_REQ_SET_IDLE = 0x0A, + HID_REQ_SET_PROTOCOL = 0x0B +}; + +enum libusb_hid_report_type { + HID_REPORT_TYPE_INPUT = 0x01, + HID_REPORT_TYPE_OUTPUT = 0x02, + HID_REPORT_TYPE_FEATURE = 0x03 +}; + +struct hid_device_priv { + uint16_t vid; + uint16_t pid; + uint8_t config; + uint8_t nb_interfaces; + bool uses_report_ids[3]; // input, ouptput, feature + uint16_t input_report_size; + uint16_t output_report_size; + uint16_t feature_report_size; + uint16_t usage; + uint16_t usagePage; + WCHAR string[3][MAX_USB_STRING_LENGTH]; + uint8_t string_index[3]; // man, prod, ser +}; + +static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev) +{ + return (struct winusb_device_priv *)dev->os_priv; +} + +static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev) +{ + struct winusb_device_priv *p = _device_priv(dev); + int i; + + p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; + p->sub_api = SUB_API_NOTSET; + for (i = 0; i < USB_MAXINTERFACES; i++) { + p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; + p->usb_interface[i].sub_api = SUB_API_NOTSET; + } + + return p; +} + +static inline void winusb_device_priv_release(struct libusb_device *dev) +{ + struct winusb_device_priv *p = _device_priv(dev); + int i; + + free(p->dev_id); + free(p->path); + if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { + for (i = 0; i < dev->num_configurations; i++) + free(p->config_descriptor[i]); + } + free(p->config_descriptor); + free(p->hid); + for (i = 0; i < USB_MAXINTERFACES; i++) { + free(p->usb_interface[i].path); + free(p->usb_interface[i].endpoint); + } +} + +static inline struct winusb_device_handle_priv *_device_handle_priv( + struct libusb_device_handle *handle) +{ + return (struct winusb_device_handle_priv *)handle->os_priv; +} + +// used to match a device driver (including filter drivers) against a supported API +struct driver_lookup { + char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names + const DWORD reg_prop; // SPDRP registry key to use to retrieve list + const char* designation; // internal designation (for debug output) +}; + +/* + * Windows DDK API definitions. Most of it copied from MinGW's includes + */ +typedef DWORD DEVNODE, DEVINST; +typedef DEVNODE *PDEVNODE, *PDEVINST; +typedef DWORD RETURN_TYPE; +typedef RETURN_TYPE CONFIGRET; + +#define CR_SUCCESS 0x00000000 + +/* Cfgmgr32 dependencies */ +DLL_DECLARE_HANDLE(Cfgmgr32); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); + +/* AdvAPI32 dependencies */ +DLL_DECLARE_HANDLE(AdvAPI32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); + +/* OLE32 dependency */ +DLL_DECLARE_HANDLE(OLE32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID)); + +/* SetupAPI dependencies */ +DLL_DECLARE_HANDLE(SetupAPI); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, + LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA, + PCSTR, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, + PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, + PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); + + +#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION +#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 +#endif +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX +#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 +#endif +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 +#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 +#endif + +#ifndef FILE_DEVICE_USB +#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN +#endif + +#define USB_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ + USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) + +typedef enum USB_CONNECTION_STATUS { + NoDeviceConnected, + DeviceConnected, + DeviceFailedEnumeration, + DeviceGeneralFailure, + DeviceCausedOvercurrent, + DeviceNotEnoughPower, + DeviceNotEnoughBandwidth, + DeviceHubNestedTooDeeply, + DeviceInLegacyHub +} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS; + +typedef enum USB_HUB_NODE { + UsbHub, + UsbMIParent +} USB_HUB_NODE; + +// Most of the structures below need to be packed +#include + +typedef struct _USB_DESCRIPTOR_REQUEST { + ULONG ConnectionIndex; + struct { + UCHAR bmRequest; + UCHAR bRequest; + USHORT wValue; + USHORT wIndex; + USHORT wLength; + } SetupPacket; +// UCHAR Data[0]; +} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT { + USB_DESCRIPTOR_REQUEST req; + USB_CONFIGURATION_DESCRIPTOR desc; +} USB_CONFIGURATION_DESCRIPTOR_SHORT; + +typedef struct USB_INTERFACE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; +} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; + +typedef struct _USB_NODE_CONNECTION_INFORMATION_EX { + ULONG ConnectionIndex; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; + UCHAR CurrentConfigurationValue; + UCHAR Speed; + BOOLEAN DeviceIsHub; + USHORT DeviceAddress; + ULONG NumberOfOpenPipes; + USB_CONNECTION_STATUS ConnectionStatus; +// USB_PIPE_INFO PipeList[0]; +} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX; + +typedef union _USB_PROTOCOLS { + ULONG ul; + struct { + ULONG Usb110:1; + ULONG Usb200:1; + ULONG Usb300:1; + ULONG ReservedMBZ:29; + }; +} USB_PROTOCOLS, *PUSB_PROTOCOLS; + +typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS { + ULONG ul; + struct { + ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1; + ULONG DeviceIsSuperSpeedCapableOrHigher:1; + ULONG ReservedMBZ:30; + }; +} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS; + +typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 { + ULONG ConnectionIndex; + ULONG Length; + USB_PROTOCOLS SupportedUsbProtocols; + USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; +} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; + +#include + +/* winusb.dll interface */ + +#define SHORT_PACKET_TERMINATE 0x01 +#define AUTO_CLEAR_STALL 0x02 +#define PIPE_TRANSFER_TIMEOUT 0x03 +#define IGNORE_SHORT_PACKETS 0x04 +#define ALLOW_PARTIAL_READS 0x05 +#define AUTO_FLUSH 0x06 +#define RAW_IO 0x07 +#define MAXIMUM_TRANSFER_SIZE 0x08 + +typedef enum _USBD_PIPE_TYPE { + UsbdPipeTypeControl, + UsbdPipeTypeIsochronous, + UsbdPipeTypeBulk, + UsbdPipeTypeInterrupt +} USBD_PIPE_TYPE; + +#include + +typedef struct _WINUSB_SETUP_PACKET { + UCHAR RequestType; + UCHAR Request; + USHORT Value; + USHORT Index; + USHORT Length; +} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; + +#include + +typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; + +typedef BOOL (WINAPI *WinUsb_AbortPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID +); +typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + WINUSB_SETUP_PACKET SetupPacket, + PUCHAR Buffer, + ULONG BufferLength, + PULONG LengthTransferred, + LPOVERLAPPED Overlapped +); +typedef BOOL (WINAPI *WinUsb_FlushPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID +); +typedef BOOL (WINAPI *WinUsb_Free_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle +); +typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR AssociatedInterfaceIndex, + PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle +); +typedef BOOL (WINAPI *WinUsb_Initialize_t)( + HANDLE DeviceHandle, + PWINUSB_INTERFACE_HANDLE InterfaceHandle +); +typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + PULONG LengthTransferred, + LPOVERLAPPED Overlapped +); +typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle +); +typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID +); +typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR AlternateSetting +); +typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + ULONG PolicyType, + ULONG ValueLength, + PVOID Value +); +typedef BOOL (WINAPI *WinUsb_WritePipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + PULONG LengthTransferred, + LPOVERLAPPED Overlapped +); + +/* /!\ These must match the ones from the official libusbk.h */ +typedef enum _KUSB_FNID { + KUSB_FNID_Init, + KUSB_FNID_Free, + KUSB_FNID_ClaimInterface, + KUSB_FNID_ReleaseInterface, + KUSB_FNID_SetAltInterface, + KUSB_FNID_GetAltInterface, + KUSB_FNID_GetDescriptor, + KUSB_FNID_ControlTransfer, + KUSB_FNID_SetPowerPolicy, + KUSB_FNID_GetPowerPolicy, + KUSB_FNID_SetConfiguration, + KUSB_FNID_GetConfiguration, + KUSB_FNID_ResetDevice, + KUSB_FNID_Initialize, + KUSB_FNID_SelectInterface, + KUSB_FNID_GetAssociatedInterface, + KUSB_FNID_Clone, + KUSB_FNID_QueryInterfaceSettings, + KUSB_FNID_QueryDeviceInformation, + KUSB_FNID_SetCurrentAlternateSetting, + KUSB_FNID_GetCurrentAlternateSetting, + KUSB_FNID_QueryPipe, + KUSB_FNID_SetPipePolicy, + KUSB_FNID_GetPipePolicy, + KUSB_FNID_ReadPipe, + KUSB_FNID_WritePipe, + KUSB_FNID_ResetPipe, + KUSB_FNID_AbortPipe, + KUSB_FNID_FlushPipe, + KUSB_FNID_IsoReadPipe, + KUSB_FNID_IsoWritePipe, + KUSB_FNID_GetCurrentFrameNumber, + KUSB_FNID_GetOverlappedResult, + KUSB_FNID_GetProperty, + KUSB_FNID_COUNT, +} KUSB_FNID; + +typedef struct _KLIB_VERSION { + INT Major; + INT Minor; + INT Micro; + INT Nano; +} KLIB_VERSION, *PKLIB_VERSION; + +typedef BOOL (WINAPI *LibK_GetProcAddress_t)( + PVOID *ProcAddress, + ULONG DriverID, + ULONG FunctionID +); + +typedef VOID (WINAPI *LibK_GetVersion_t)( + PKLIB_VERSION Version +); + +//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths +typedef struct _KISO_PACKET { + UINT offset; + USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity + USHORT status; +} KISO_PACKET, *PKISO_PACKET; + +typedef enum _KISO_FLAG { + KISO_FLAG_NONE = 0, + KISO_FLAG_SET_START_FRAME = 0x00000001, +} KISO_FLAG; + +//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version +typedef struct _KISO_CONTEXT { + KISO_FLAG Flags; + UINT StartFrame; + SHORT ErrorCount; + SHORT NumberOfPackets; + UINT UrbHdrStatus; + KISO_PACKET IsoPackets[0]; +} KISO_CONTEXT, *PKISO_CONTEXT; + +typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + +typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + +struct winusb_interface { + bool initialized; + bool CancelIoEx_supported; + WinUsb_AbortPipe_t AbortPipe; + WinUsb_ControlTransfer_t ControlTransfer; + WinUsb_FlushPipe_t FlushPipe; + WinUsb_Free_t Free; + WinUsb_GetAssociatedInterface_t GetAssociatedInterface; + WinUsb_Initialize_t Initialize; + WinUsb_ReadPipe_t ReadPipe; + WinUsb_ResetDevice_t ResetDevice; + WinUsb_ResetPipe_t ResetPipe; + WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; + WinUsb_SetPipePolicy_t SetPipePolicy; + WinUsb_WritePipe_t WritePipe; + WinUsb_IsoReadPipe_t IsoReadPipe; + WinUsb_IsoWritePipe_t IsoWritePipe; +}; + +/* hid.dll interface */ + +#define HIDP_STATUS_SUCCESS 0x110000 +typedef void * PHIDP_PREPARSED_DATA; + +#include +#include + +typedef USHORT USAGE; + +typedef enum _HIDP_REPORT_TYPE { + HidP_Input, + HidP_Output, + HidP_Feature +} HIDP_REPORT_TYPE; + +typedef struct _HIDP_VALUE_CAPS { + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + USHORT BitField; + USHORT LinkCollection; + USAGE LinkUsage; + USAGE LinkUsagePage; + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + BOOLEAN HasNull; + UCHAR Reserved; + USHORT BitSize; + USHORT ReportCount; + USHORT Reserved2[5]; + ULONG UnitsExp; + ULONG Units; + LONG LogicalMin, LogicalMax; + LONG PhysicalMin, PhysicalMax; + union { + struct { + USAGE UsageMin, UsageMax; + USHORT StringMin, StringMax; + USHORT DesignatorMin, DesignatorMax; + USHORT DataIndexMin, DataIndexMax; + } Range; + struct { + USAGE Usage, Reserved1; + USHORT StringIndex, Reserved2; + USHORT DesignatorIndex, Reserved3; + USHORT DataIndex, Reserved4; + } NotRange; + } u; +} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; + +DLL_DECLARE_HANDLE(hid); +DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c b/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c new file mode 100644 index 0000000000..d2be0e2a00 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c @@ -0,0 +1,202 @@ +/* + * libusb strerror code + * Copyright © 2013 Hans de Goede + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#if defined(HAVE_STRINGS_H) +#include +#endif + +#include "libusbi.h" + +#if defined(_MSC_VER) +#define strncasecmp _strnicmp +#endif + +static size_t usbi_locale = 0; + +/** \ingroup libusb_misc + * How to add a new \ref libusb_strerror() translation: + *
    + *
  1. Download the latest \c strerror.c from:
    + * https://raw.github.com/libusb/libusb/master/libusb/sterror.c
  2. + *
  3. Open the file in an UTF-8 capable editor
  4. + *
  5. Add the 2 letter ISO 639-1 + * code for your locale at the end of \c usbi_locale_supported[]
    + * Eg. for Chinese, you would add "zh" so that: + * \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode + * becomes: + * \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode
  6. + *
  7. Copy the { / * English (en) * / ... } section and add it at the end of \c usbi_localized_errors
    + * Eg. for Chinese, the last section of \c usbi_localized_errors could look like: + * \code + * }, { / * Chinese (zh) * / + * "Success", + * ... + * "Other error", + * } + * };\endcode
  8. + *
  9. Translate each of the English messages from the section you copied into your language
  10. + *
  11. Save the file (in UTF-8 format) and send it to \c libusb-devel\@lists.sourceforge.net
  12. + *
+ */ + +static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" }; +static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = { + { /* English (en) */ + "Success", + "Input/Output Error", + "Invalid parameter", + "Access denied (insufficient permissions)", + "No such device (it may have been disconnected)", + "Entity not found", + "Resource busy", + "Operation timed out", + "Overflow", + "Pipe error", + "System call interrupted (perhaps due to signal)", + "Insufficient memory", + "Operation not supported or unimplemented on this platform", + "Other error", + }, { /* Dutch (nl) */ + "Gelukt", + "Invoer-/uitvoerfout", + "Ongeldig argument", + "Toegang geweigerd (onvoldoende toegangsrechten)", + "Apparaat bestaat niet (verbinding met apparaat verbroken?)", + "Niet gevonden", + "Apparaat of hulpbron is bezig", + "Bewerking verlopen", + "Waarde is te groot", + "Gebroken pijp", + "Onderbroken systeemaanroep", + "Onvoldoende geheugen beschikbaar", + "Bewerking wordt niet ondersteund", + "Andere fout", + }, { /* French (fr) */ + "Succès", + "Erreur d'entrée/sortie", + "Paramètre invalide", + "Accès refusé (permissions insuffisantes)", + "Périphérique introuvable (peut-être déconnecté)", + "Elément introuvable", + "Resource déjà occupée", + "Operation expirée", + "Débordement", + "Erreur de pipe", + "Appel système abandonné (peut-être à cause d’un signal)", + "Mémoire insuffisante", + "Opération non supportée or non implémentée sur cette plateforme", + "Autre erreur", + }, { /* Russian (ru) */ + "Успех", + "Ошибка ввода/вывода", + "Неверный параметр", + "Доступ запрещён (не хватает прав)", + "Устройство отсутствует (возможно, оно было отсоединено)", + "Элемент не найден", + "Ресурс занят", + "Истекло время ожидания операции", + "Переполнение", + "Ошибка канала", + "Системный вызов прерван (возможно, сигналом)", + "Память исчерпана", + "Операция не поддерживается данной платформой", + "Неизвестная ошибка" + } +}; + +/** \ingroup libusb_misc + * Set the language, and only the language, not the encoding! used for + * translatable libusb messages. + * + * This takes a locale string in the default setlocale format: lang[-region] + * or lang[_country_region][.codeset]. Only the lang part of the string is + * used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de". + * The optional region, country_region or codeset parts are ignored. This + * means that functions which return translatable strings will NOT honor the + * specified encoding. + * All strings returned are encoded as UTF-8 strings. + * + * If libusb_setlocale() is not called, all messages will be in English. + * + * The following functions return translatable strings: libusb_strerror(). + * Note that the libusb log messages controlled through libusb_set_debug() + * are not translated, they are always in English. + * + * For POSIX UTF-8 environments if you want libusb to follow the standard + * locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)), + * after your app has done its locale setup. + * + * \param locale locale-string in the form of lang[_country_region][.codeset] + * or lang[-region], where lang is a 2 letter ISO 639-1 code + * \returns LIBUSB_SUCCESS on success + * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements + * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported + * \returns a LIBUSB_ERROR code on other errors + */ + +int API_EXPORTED libusb_setlocale(const char *locale) +{ + size_t i; + + if ( (locale == NULL) || (strlen(locale) < 2) + || ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) ) + return LIBUSB_ERROR_INVALID_PARAM; + + for (i=0; i= ARRAYSIZE(usbi_locale_supported)) { + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_locale = i; + + return LIBUSB_SUCCESS; +} + +/** \ingroup libusb_misc + * Returns a constant string with a short description of the given error code, + * this description is intended for displaying to the end user and will be in + * the language set by libusb_setlocale(). + * + * The returned string is encoded in UTF-8. + * + * The messages always start with a capital letter and end without any dot. + * The caller must not free() the returned string. + * + * \param errcode the error code whose description is desired + * \returns a short description of the error code in UTF-8 encoding + */ +DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode) +{ + int errcode_index = -errcode; + + if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) { + /* "Other Error", which should always be our last message, is returned */ + errcode_index = LIBUSB_ERROR_COUNT - 1; + } + + return usbi_localized_errors[usbi_locale][errcode_index]; +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/sync.c b/vendor/github.com/karalabe/usb/libusb/libusb/sync.c new file mode 100644 index 0000000000..a609f65f44 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/sync.c @@ -0,0 +1,327 @@ +/* + * Synchronous I/O functions for libusb + * Copyright © 2007-2008 Daniel Drake + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include + +#include "libusbi.h" + +/** + * @defgroup libusb_syncio Synchronous device I/O + * + * This page documents libusb's synchronous (blocking) API for USB device I/O. + * This interface is easy to use but has some limitations. More advanced users + * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead. + */ + +static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) +{ + int *completed = transfer->user_data; + *completed = 1; + usbi_dbg("actual_length=%d", transfer->actual_length); + /* caller interprets result and frees transfer */ +} + +static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) +{ + int r, *completed = transfer->user_data; + struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); + + while (!*completed) { + r = libusb_handle_events_completed(ctx, completed); + if (r < 0) { + if (r == LIBUSB_ERROR_INTERRUPTED) + continue; + usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", + libusb_error_name(r)); + libusb_cancel_transfer(transfer); + continue; + } + } +} + +/** \ingroup libusb_syncio + * Perform a USB control transfer. + * + * The direction of the transfer is inferred from the bmRequestType field of + * the setup packet. + * + * The wValue, wIndex and wLength fields values should be given in host-endian + * byte order. + * + * \param dev_handle a handle for the device to communicate with + * \param bmRequestType the request type field for the setup packet + * \param bRequest the request field for the setup packet + * \param wValue the value field for the setup packet + * \param wIndex the index field for the setup packet + * \param data a suitably-sized data buffer for either input or output + * (depending on direction bits within bmRequestType) + * \param wLength the length field for the setup packet. The data buffer should + * be at least this size. + * \param timeout timeout (in millseconds) that this function should wait + * before giving up due to no response being received. For an unlimited + * timeout, use value 0. + * \returns on success, the number of bytes actually transferred + * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out + * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the + * device + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_BUSY if called from event handling context + * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * the operating system and/or hardware can support + * \returns another LIBUSB_ERROR code on other failures + */ +int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout) +{ + struct libusb_transfer *transfer; + unsigned char *buffer; + int completed = 0; + int r; + + if (usbi_handling_events(HANDLE_CTX(dev_handle))) + return LIBUSB_ERROR_BUSY; + + transfer = libusb_alloc_transfer(0); + if (!transfer) + return LIBUSB_ERROR_NO_MEM; + + buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); + if (!buffer) { + libusb_free_transfer(transfer); + return LIBUSB_ERROR_NO_MEM; + } + + libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, + wLength); + if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) + memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); + + libusb_fill_control_transfer(transfer, dev_handle, buffer, + sync_transfer_cb, &completed, timeout); + transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; + r = libusb_submit_transfer(transfer); + if (r < 0) { + libusb_free_transfer(transfer); + return r; + } + + sync_transfer_wait_for_completion(transfer); + + if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) + memcpy(data, libusb_control_transfer_get_data(transfer), + transfer->actual_length); + + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + r = transfer->actual_length; + break; + case LIBUSB_TRANSFER_TIMED_OUT: + r = LIBUSB_ERROR_TIMEOUT; + break; + case LIBUSB_TRANSFER_STALL: + r = LIBUSB_ERROR_PIPE; + break; + case LIBUSB_TRANSFER_NO_DEVICE: + r = LIBUSB_ERROR_NO_DEVICE; + break; + case LIBUSB_TRANSFER_OVERFLOW: + r = LIBUSB_ERROR_OVERFLOW; + break; + case LIBUSB_TRANSFER_ERROR: + case LIBUSB_TRANSFER_CANCELLED: + r = LIBUSB_ERROR_IO; + break; + default: + usbi_warn(HANDLE_CTX(dev_handle), + "unrecognised status code %d", transfer->status); + r = LIBUSB_ERROR_OTHER; + } + + libusb_free_transfer(transfer); + return r; +} + +static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, + int *transferred, unsigned int timeout, unsigned char type) +{ + struct libusb_transfer *transfer; + int completed = 0; + int r; + + if (usbi_handling_events(HANDLE_CTX(dev_handle))) + return LIBUSB_ERROR_BUSY; + + transfer = libusb_alloc_transfer(0); + if (!transfer) + return LIBUSB_ERROR_NO_MEM; + + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, + sync_transfer_cb, &completed, timeout); + transfer->type = type; + + r = libusb_submit_transfer(transfer); + if (r < 0) { + libusb_free_transfer(transfer); + return r; + } + + sync_transfer_wait_for_completion(transfer); + + if (transferred) + *transferred = transfer->actual_length; + + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + r = 0; + break; + case LIBUSB_TRANSFER_TIMED_OUT: + r = LIBUSB_ERROR_TIMEOUT; + break; + case LIBUSB_TRANSFER_STALL: + r = LIBUSB_ERROR_PIPE; + break; + case LIBUSB_TRANSFER_OVERFLOW: + r = LIBUSB_ERROR_OVERFLOW; + break; + case LIBUSB_TRANSFER_NO_DEVICE: + r = LIBUSB_ERROR_NO_DEVICE; + break; + case LIBUSB_TRANSFER_ERROR: + case LIBUSB_TRANSFER_CANCELLED: + r = LIBUSB_ERROR_IO; + break; + default: + usbi_warn(HANDLE_CTX(dev_handle), + "unrecognised status code %d", transfer->status); + r = LIBUSB_ERROR_OTHER; + } + + libusb_free_transfer(transfer); + return r; +} + +/** \ingroup libusb_syncio + * Perform a USB bulk transfer. The direction of the transfer is inferred from + * the direction bits of the endpoint address. + * + * For bulk reads, the length field indicates the maximum length of + * data you are expecting to receive. If less data arrives than expected, + * this function will return that data, so be sure to check the + * transferred output parameter. + * + * You should also check the transferred parameter for bulk writes. + * Not all of the data may have been written. + * + * Also check transferred when dealing with a timeout error code. + * libusb may have to split your transfer into a number of chunks to satisfy + * underlying O/S requirements, meaning that the timeout may expire after + * the first few chunks have completed. libusb is careful not to lose any data + * that may have been transferred; do not assume that timeout conditions + * indicate a complete lack of I/O. + * + * \param dev_handle a handle for the device to communicate with + * \param endpoint the address of a valid endpoint to communicate with + * \param data a suitably-sized data buffer for either input or output + * (depending on endpoint) + * \param length for bulk writes, the number of bytes from data to be sent. for + * bulk reads, the maximum number of bytes to receive into the data buffer. + * \param transferred output location for the number of bytes actually + * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), + * it is legal to pass a NULL pointer if you do not wish to receive this + * information. + * \param timeout timeout (in millseconds) that this function should wait + * before giving up due to no response being received. For an unlimited + * timeout, use value 0. + * + * \returns 0 on success (and populates transferred) + * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates + * transferred) + * \returns LIBUSB_ERROR_PIPE if the endpoint halted + * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see + * \ref libusb_packetoverflow + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_BUSY if called from event handling context + * \returns another LIBUSB_ERROR code on other failures + */ +int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, int *transferred, + unsigned int timeout) +{ + return do_sync_bulk_transfer(dev_handle, endpoint, data, length, + transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); +} + +/** \ingroup libusb_syncio + * Perform a USB interrupt transfer. The direction of the transfer is inferred + * from the direction bits of the endpoint address. + * + * For interrupt reads, the length field indicates the maximum length + * of data you are expecting to receive. If less data arrives than expected, + * this function will return that data, so be sure to check the + * transferred output parameter. + * + * You should also check the transferred parameter for interrupt + * writes. Not all of the data may have been written. + * + * Also check transferred when dealing with a timeout error code. + * libusb may have to split your transfer into a number of chunks to satisfy + * underlying O/S requirements, meaning that the timeout may expire after + * the first few chunks have completed. libusb is careful not to lose any data + * that may have been transferred; do not assume that timeout conditions + * indicate a complete lack of I/O. + * + * The default endpoint bInterval value is used as the polling interval. + * + * \param dev_handle a handle for the device to communicate with + * \param endpoint the address of a valid endpoint to communicate with + * \param data a suitably-sized data buffer for either input or output + * (depending on endpoint) + * \param length for bulk writes, the number of bytes from data to be sent. for + * bulk reads, the maximum number of bytes to receive into the data buffer. + * \param transferred output location for the number of bytes actually + * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), + * it is legal to pass a NULL pointer if you do not wish to receive this + * information. + * \param timeout timeout (in millseconds) that this function should wait + * before giving up due to no response being received. For an unlimited + * timeout, use value 0. + * + * \returns 0 on success (and populates transferred) + * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out + * \returns LIBUSB_ERROR_PIPE if the endpoint halted + * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see + * \ref libusb_packetoverflow + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_BUSY if called from event handling context + * \returns another LIBUSB_ERROR code on other error + */ +int API_EXPORTED libusb_interrupt_transfer( + struct libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *data, int length, int *transferred, unsigned int timeout) +{ + return do_sync_bulk_transfer(dev_handle, endpoint, data, length, + transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); +} diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/version.h b/vendor/github.com/karalabe/usb/libusb/libusb/version.h new file mode 100644 index 0000000000..c6dfe37093 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/version.h @@ -0,0 +1,18 @@ +/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */ +#include "version_nano.h" +#ifndef LIBUSB_MAJOR +#define LIBUSB_MAJOR 1 +#endif +#ifndef LIBUSB_MINOR +#define LIBUSB_MINOR 0 +#endif +#ifndef LIBUSB_MICRO +#define LIBUSB_MICRO 22 +#endif +#ifndef LIBUSB_NANO +#define LIBUSB_NANO 0 +#endif +/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ +#ifndef LIBUSB_RC +#define LIBUSB_RC "" +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h b/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h new file mode 100644 index 0000000000..90a782a6bf --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h @@ -0,0 +1 @@ +#define LIBUSB_NANO 11312 diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go new file mode 100644 index 0000000000..5d052781bc --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -0,0 +1,712 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +//go:generate go run gen.go +//go:generate go run gen.go -test + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "io/ioutil" + "math/rand" + "os" + "sort" + "strings" +) + +// identifier converts s to a Go exported identifier. +// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". +func identifier(s string) string { + b := make([]byte, 0, len(s)) + cap := true + for _, c := range s { + if c == '-' { + cap = true + continue + } + if cap && 'a' <= c && c <= 'z' { + c -= 'a' - 'A' + } + cap = false + b = append(b, byte(c)) + } + return string(b) +} + +var test = flag.Bool("test", false, "generate table_test.go") + +func genFile(name string, buf *bytes.Buffer) { + b, err := format.Source(buf.Bytes()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := ioutil.WriteFile(name, b, 0644); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func main() { + flag.Parse() + + var all []string + all = append(all, elements...) + all = append(all, attributes...) + all = append(all, eventHandlers...) + all = append(all, extra...) + sort.Strings(all) + + // uniq - lists have dups + w := 0 + for _, s := range all { + if w == 0 || all[w-1] != s { + all[w] = s + w++ + } + } + all = all[:w] + + if *test { + var buf bytes.Buffer + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") + fmt.Fprintln(&buf, "package atom\n") + fmt.Fprintln(&buf, "var testAtomList = []string{") + for _, s := range all { + fmt.Fprintf(&buf, "\t%q,\n", s) + } + fmt.Fprintln(&buf, "}") + + genFile("table_test.go", &buf) + return + } + + // Find hash that minimizes table size. + var best *table + for i := 0; i < 1000000; i++ { + if best != nil && 1<<(best.k-1) < len(all) { + break + } + h := rand.Uint32() + for k := uint(0); k <= 16; k++ { + if best != nil && k >= best.k { + break + } + var t table + if t.init(h, k, all) { + best = &t + break + } + } + } + if best == nil { + fmt.Fprintf(os.Stderr, "failed to construct string table\n") + os.Exit(1) + } + + // Lay out strings, using overlaps when possible. + layout := append([]string{}, all...) + + // Remove strings that are substrings of other strings + for changed := true; changed; { + changed = false + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i != j && t != "" && strings.Contains(s, t) { + changed = true + layout[j] = "" + } + } + } + } + + // Join strings where one suffix matches another prefix. + for { + // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], + // maximizing overlap length k. + besti := -1 + bestj := -1 + bestk := 0 + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i == j { + continue + } + for k := bestk + 1; k <= len(s) && k <= len(t); k++ { + if s[len(s)-k:] == t[:k] { + besti = i + bestj = j + bestk = k + } + } + } + } + if bestk > 0 { + layout[besti] += layout[bestj][bestk:] + layout[bestj] = "" + continue + } + break + } + + text := strings.Join(layout, "") + + atom := map[string]uint32{} + for _, s := range all { + off := strings.Index(text, s) + if off < 0 { + panic("lost string " + s) + } + atom[s] = uint32(off<<8 | len(s)) + } + + var buf bytes.Buffer + // Generate the Go code. + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go\n") + fmt.Fprintln(&buf, "package atom\n\nconst (") + + // compute max len + maxLen := 0 + for _, s := range all { + if maxLen < len(s) { + maxLen = len(s) + } + fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) + } + fmt.Fprintln(&buf, ")\n") + + fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) + fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) + + fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) + for i, s := range best.tab { + if s == "" { + continue + } + fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) + } + fmt.Fprintf(&buf, "}\n") + datasize := (1 << best.k) * 4 + + fmt.Fprintln(&buf, "const atomText =") + textsize := len(text) + for len(text) > 60 { + fmt.Fprintf(&buf, "\t%q +\n", text[:60]) + text = text[60:] + } + fmt.Fprintf(&buf, "\t%q\n\n", text) + + genFile("table.go", &buf) + + fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) +} + +type byLen []string + +func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } +func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x byLen) Len() int { return len(x) } + +// fnv computes the FNV hash with an arbitrary starting value h. +func fnv(h uint32, s string) uint32 { + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// A table represents an attempt at constructing the lookup table. +// The lookup table uses cuckoo hashing, meaning that each string +// can be found in one of two positions. +type table struct { + h0 uint32 + k uint + mask uint32 + tab []string +} + +// hash returns the two hashes for s. +func (t *table) hash(s string) (h1, h2 uint32) { + h := fnv(t.h0, s) + h1 = h & t.mask + h2 = (h >> 16) & t.mask + return +} + +// init initializes the table with the given parameters. +// h0 is the initial hash value, +// k is the number of bits of hash value to use, and +// x is the list of strings to store in the table. +// init returns false if the table cannot be constructed. +func (t *table) init(h0 uint32, k uint, x []string) bool { + t.h0 = h0 + t.k = k + t.tab = make([]string, 1< len(t.tab) { + return false + } + s := t.tab[i] + h1, h2 := t.hash(s) + j := h1 + h2 - i + if t.tab[j] != "" && !t.push(j, depth+1) { + return false + } + t.tab[j] = s + return true +} + +// The lists of element names and attribute keys were taken from +// https://html.spec.whatwg.org/multipage/indices.html#index +// as of the "HTML Living Standard - Last Updated 16 April 2018" version. + +// "command", "keygen" and "menuitem" have been removed from the spec, +// but are kept here for backwards compatibility. +var elements = []string{ + "a", + "abbr", + "address", + "area", + "article", + "aside", + "audio", + "b", + "base", + "bdi", + "bdo", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "cite", + "code", + "col", + "colgroup", + "command", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "main", + "map", + "mark", + "menu", + "menuitem", + "meta", + "meter", + "nav", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "picture", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "slot", + "small", + "source", + "span", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "u", + "ul", + "var", + "video", + "wbr", +} + +// https://html.spec.whatwg.org/multipage/indices.html#attributes-3 +// +// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", +// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, +// but are kept here for backwards compatibility. +var attributes = []string{ + "abbr", + "accept", + "accept-charset", + "accesskey", + "action", + "allowfullscreen", + "allowpaymentrequest", + "allowusermedia", + "alt", + "as", + "async", + "autocomplete", + "autofocus", + "autoplay", + "challenge", + "charset", + "checked", + "cite", + "class", + "color", + "cols", + "colspan", + "command", + "content", + "contenteditable", + "contextmenu", + "controls", + "coords", + "crossorigin", + "data", + "datetime", + "default", + "defer", + "dir", + "dirname", + "disabled", + "download", + "draggable", + "dropzone", + "enctype", + "for", + "form", + "formaction", + "formenctype", + "formmethod", + "formnovalidate", + "formtarget", + "headers", + "height", + "hidden", + "high", + "href", + "hreflang", + "http-equiv", + "icon", + "id", + "inputmode", + "integrity", + "is", + "ismap", + "itemid", + "itemprop", + "itemref", + "itemscope", + "itemtype", + "keytype", + "kind", + "label", + "lang", + "list", + "loop", + "low", + "manifest", + "max", + "maxlength", + "media", + "mediagroup", + "method", + "min", + "minlength", + "multiple", + "muted", + "name", + "nomodule", + "nonce", + "novalidate", + "open", + "optimum", + "pattern", + "ping", + "placeholder", + "playsinline", + "poster", + "preload", + "radiogroup", + "readonly", + "referrerpolicy", + "rel", + "required", + "reversed", + "rows", + "rowspan", + "sandbox", + "spellcheck", + "scope", + "scoped", + "seamless", + "selected", + "shape", + "size", + "sizes", + "sortable", + "sorted", + "slot", + "span", + "spellcheck", + "src", + "srcdoc", + "srclang", + "srcset", + "start", + "step", + "style", + "tabindex", + "target", + "title", + "translate", + "type", + "typemustmatch", + "updateviacache", + "usemap", + "value", + "width", + "workertype", + "wrap", +} + +// "onautocomplete", "onautocompleteerror", "onmousewheel", +// "onshow" and "onsort" have been removed from the spec, +// but are kept here for backwards compatibility. +var eventHandlers = []string{ + "onabort", + "onautocomplete", + "onautocompleteerror", + "onauxclick", + "onafterprint", + "onbeforeprint", + "onbeforeunload", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncopy", + "oncuechange", + "oncut", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragexit", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "onhashchange", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onlanguagechange", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadend", + "onloadstart", + "onmessage", + "onmessageerror", + "onmousedown", + "onmouseenter", + "onmouseleave", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onwheel", + "onoffline", + "ononline", + "onpagehide", + "onpageshow", + "onpaste", + "onpause", + "onplay", + "onplaying", + "onpopstate", + "onprogress", + "onratechange", + "onreset", + "onresize", + "onrejectionhandled", + "onscroll", + "onsecuritypolicyviolation", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onsort", + "onstalled", + "onstorage", + "onsubmit", + "onsuspend", + "ontimeupdate", + "ontoggle", + "onunhandledrejection", + "onunload", + "onvolumechange", + "onwaiting", +} + +// extra are ad-hoc values not covered by any of the lists above. +var extra = []string{ + "acronym", + "align", + "annotation", + "annotation-xml", + "applet", + "basefont", + "bgsound", + "big", + "blink", + "center", + "color", + "desc", + "face", + "font", + "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. + "foreignobject", + "frame", + "frameset", + "image", + "isindex", + "listing", + "malignmark", + "marquee", + "math", + "mglyph", + "mi", + "mn", + "mo", + "ms", + "mtext", + "nobr", + "noembed", + "noframes", + "plaintext", + "prompt", + "public", + "rb", + "rtc", + "spacer", + "strike", + "svg", + "system", + "tt", + "xmp", +} diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go index ae0d1b05cd..e3c01d7c90 100644 --- a/vendor/golang.org/x/net/html/token.go +++ b/vendor/golang.org/x/net/html/token.go @@ -347,7 +347,6 @@ loop: break loop } if c != '/' { - z.raw.end-- continue loop } if z.readRawEndTag() || z.err != nil { @@ -1068,11 +1067,6 @@ loop: // Raw returns the unmodified text of the current token. Calling Next, Token, // Text, TagName or TagAttr may change the contents of the returned slice. -// -// The token stream's raw bytes partition the byte stream (up until an -// ErrorToken). There are no overlaps or gaps between two consecutive token's -// raw bytes. One implication is that the byte offset of the current token is -// the sum of the lengths of all previous tokens' raw bytes. func (z *Tokenizer) Raw() []byte { return z.buf[z.raw.start:z.raw.end] } diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go index 97f17831fc..1565cf2702 100644 --- a/vendor/golang.org/x/net/http2/hpack/encode.go +++ b/vendor/golang.org/x/net/http2/hpack/encode.go @@ -150,7 +150,7 @@ func appendIndexed(dst []byte, i uint64) []byte { // extended buffer. // // If f.Sensitive is true, "Never Indexed" representation is used. If -// f.Sensitive is false and indexing is true, "Incremental Indexing" +// f.Sensitive is false and indexing is true, "Inremental Indexing" // representation is used. func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go index 2a5399ec4a..a6140099cb 100644 --- a/vendor/golang.org/x/net/http2/pipe.go +++ b/vendor/golang.org/x/net/http2/pipe.go @@ -17,7 +17,6 @@ type pipe struct { mu sync.Mutex c sync.Cond // c.L lazily initialized to &p.mu b pipeBuffer // nil when done reading - unread int // bytes unread when done err error // read error once empty. non-nil means closed. breakErr error // immediate read error (caller doesn't see rest of b) donec chan struct{} // closed on error @@ -34,7 +33,7 @@ func (p *pipe) Len() int { p.mu.Lock() defer p.mu.Unlock() if p.b == nil { - return p.unread + return 0 } return p.b.Len() } @@ -81,7 +80,6 @@ func (p *pipe) Write(d []byte) (n int, err error) { return 0, errClosedPipeWrite } if p.breakErr != nil { - p.unread += len(d) return len(d), nil // discard when there is no reader } return p.b.Write(d) @@ -119,9 +117,6 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) { } p.readFn = fn if dst == &p.breakErr { - if p.b != nil { - p.unread += p.b.Len() - } p.b = nil } *dst = err diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index d2ba820c70..57334dc79b 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -52,11 +52,10 @@ import ( ) const ( - prefaceTimeout = 10 * time.Second - firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway - handlerChunkWriteSize = 4 << 10 - defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? - maxQueuedControlFrames = 10000 + prefaceTimeout = 10 * time.Second + firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway + handlerChunkWriteSize = 4 << 10 + defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? ) var ( @@ -164,15 +163,6 @@ func (s *Server) maxConcurrentStreams() uint32 { return defaultMaxStreams } -// maxQueuedControlFrames is the maximum number of control frames like -// SETTINGS, PING and RST_STREAM that will be queued for writing before -// the connection is closed to prevent memory exhaustion attacks. -func (s *Server) maxQueuedControlFrames() int { - // TODO: if anybody asks, add a Server field, and remember to define the - // behavior of negative values. - return maxQueuedControlFrames -} - type serverInternalState struct { mu sync.Mutex activeConns map[*serverConn]struct{} @@ -322,7 +312,7 @@ type ServeConnOpts struct { } func (o *ServeConnOpts) context() context.Context { - if o != nil && o.Context != nil { + if o.Context != nil { return o.Context } return context.Background() @@ -516,7 +506,6 @@ type serverConn struct { sawFirstSettings bool // got the initial SETTINGS frame after the preface needToSendSettingsAck bool unackedSettings int // how many SETTINGS have we sent without ACKs? - queuedControlFrames int // control frames in the writeSched queue clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client @@ -905,14 +894,6 @@ func (sc *serverConn) serve() { } } - // If the peer is causing us to generate a lot of control frames, - // but not reading them from us, assume they are trying to make us - // run out of memory. - if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() { - sc.vlogf("http2: too many control frames in send queue, closing connection") - return - } - // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY // with no error code (graceful shutdown), don't start the timer until // all open streams have been completed. @@ -1112,14 +1093,6 @@ func (sc *serverConn) writeFrame(wr FrameWriteRequest) { } if !ignoreWrite { - if wr.isControl() { - sc.queuedControlFrames++ - // For extra safety, detect wraparounds, which should not happen, - // and pull the plug. - if sc.queuedControlFrames < 0 { - sc.conn.Close() - } - } sc.writeSched.Push(wr) } sc.scheduleFrameWrite() @@ -1237,8 +1210,10 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) { // If a frame is already being written, nothing happens. This will be called again // when the frame is done being written. // -// If a frame isn't being written and we need to send one, the best frame -// to send is selected by writeSched. +// If a frame isn't being written we need to send one, the best frame +// to send is selected, preferring first things that aren't +// stream-specific (e.g. ACKing settings), and then finding the +// highest priority stream. // // If a frame isn't being written and there's nothing else to send, we // flush the write buffer. @@ -1266,9 +1241,6 @@ func (sc *serverConn) scheduleFrameWrite() { } if !sc.inGoAway || sc.goAwayCode == ErrCodeNo { if wr, ok := sc.writeSched.Pop(); ok { - if wr.isControl() { - sc.queuedControlFrames-- - } sc.startFrameWrite(wr) continue } @@ -1561,8 +1533,6 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error { if err := f.ForeachSetting(sc.processSetting); err != nil { return err } - // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be - // acknowledged individually, even if multiple are received before the ACK. sc.needToSendSettingsAck = true sc.scheduleFrameWrite() return nil @@ -2415,11 +2385,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { clen = strconv.Itoa(len(p)) } _, hasContentType := rws.snapHeader["Content-Type"] - // If the Content-Encoding is non-blank, we shouldn't - // sniff the body. See Issue golang.org/issue/31753. - ce := rws.snapHeader.Get("Content-Encoding") - hasCE := len(ce) > 0 - if !hasCE && !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 { + if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 { ctype = http.DetectContentType(p) } var date string @@ -2528,7 +2494,7 @@ const TrailerPrefix = "Trailer:" // trailers. That worked for a while, until we found the first major // user of Trailers in the wild: gRPC (using them only over http2), // and gRPC libraries permit setting trailers mid-stream without -// predeclaring them. So: change of plans. We still permit the old +// predeclarnig them. So: change of plans. We still permit the old // way, but we also permit this hack: if a Header() key begins with // "Trailer:", the suffix of that key is a Trailer. Because ':' is an // invalid token byte anyway, there is no ambiguity. (And it's already @@ -2828,7 +2794,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) { // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that // is in either the "open" or "half-closed (remote)" state. if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { - // responseWriter.Push checks that the stream is peer-initiated. + // responseWriter.Push checks that the stream is peer-initiaed. msg.done <- errStreamClosed return } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 42ad181448..aeac7d8a51 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -603,7 +603,7 @@ func (t *Transport) expectContinueTimeout() time.Duration { } func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { - return t.newClientConn(c, t.disableKeepAlives()) + return t.newClientConn(c, false) } func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { @@ -1216,8 +1216,6 @@ var ( // abort request body write, but send stream reset of cancel. errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") - - errReqBodyTooLong = errors.New("http2: request body larger than specified content length") ) func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { @@ -1240,32 +1238,10 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) ( req := cs.req hasTrailers := req.Trailer != nil - remainLen := actualContentLength(req) - hasContentLen := remainLen != -1 var sawEOF bool for !sawEOF { - n, err := body.Read(buf[:len(buf)-1]) - if hasContentLen { - remainLen -= int64(n) - if remainLen == 0 && err == nil { - // The request body's Content-Length was predeclared and - // we just finished reading it all, but the underlying io.Reader - // returned the final chunk with a nil error (which is one of - // the two valid things a Reader can do at EOF). Because we'd prefer - // to send the END_STREAM bit early, double-check that we're actually - // at EOF. Subsequent reads should return (0, EOF) at this point. - // If either value is different, we return an error in one of two ways below. - var n1 int - n1, err = body.Read(buf[n:]) - remainLen -= int64(n1) - } - if remainLen < 0 { - err = errReqBodyTooLong - cc.writeStreamReset(cs.ID, ErrCodeCancel, err) - return err - } - } + n, err := body.Read(buf) if err == io.EOF { sawEOF = true err = nil @@ -1478,29 +1454,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail if vv[0] == "" { continue } - } else if strings.EqualFold(k, "cookie") { - // Per 8.1.2.5 To allow for better compression efficiency, the - // Cookie header field MAY be split into separate header fields, - // each with one or more cookie-pairs. - for _, v := range vv { - for { - p := strings.IndexByte(v, ';') - if p < 0 { - break - } - f("cookie", v[:p]) - p++ - // strip space after semicolon if any. - for p+1 <= len(v) && v[p] == ' ' { - p++ - } - v = v[p:] - } - if len(v) > 0 { - f("cookie", v) - } - } - continue + } for _, v := range vv { diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go index f24d2b1e7d..4fe3073073 100644 --- a/vendor/golang.org/x/net/http2/writesched.go +++ b/vendor/golang.org/x/net/http2/writesched.go @@ -32,7 +32,7 @@ type WriteScheduler interface { // Pop dequeues the next frame to write. Returns false if no frames can // be written. Frames with a given wr.StreamID() are Pop'd in the same - // order they are Push'd. No frames should be discarded except by CloseStream. + // order they are Push'd. Pop() (wr FrameWriteRequest, ok bool) } @@ -76,12 +76,6 @@ func (wr FrameWriteRequest) StreamID() uint32 { return wr.stream.id } -// isControl reports whether wr is a control frame for MaxQueuedControlFrames -// purposes. That includes non-stream frames and RST_STREAM frames. -func (wr FrameWriteRequest) isControl() bool { - return wr.stream == nil -} - // DataSize returns the number of flow control bytes that must be consumed // to write this entire frame. This is 0 for non-DATA frames. func (wr FrameWriteRequest) DataSize() int { diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go index 2618b2c11d..848fed6ec7 100644 --- a/vendor/golang.org/x/net/http2/writesched_priority.go +++ b/vendor/golang.org/x/net/http2/writesched_priority.go @@ -149,7 +149,7 @@ func (n *priorityNode) addBytes(b int64) { } // walkReadyInOrder iterates over the tree in priority order, calling f for each node -// with a non-empty write queue. When f returns true, this function returns true and the +// with a non-empty write queue. When f returns true, this funcion returns true and the // walk halts. tmp is used as scratch space for sorting. // // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true diff --git a/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go index 9a7b9e581c..36d7919f16 100644 --- a/vendor/golang.org/x/net/http2/writesched_random.go +++ b/vendor/golang.org/x/net/http2/writesched_random.go @@ -19,8 +19,7 @@ type randomWriteScheduler struct { zero writeQueue // sq contains the stream-specific queues, keyed by stream ID. - // When a stream is idle, closed, or emptied, it's deleted - // from the map. + // When a stream is idle or closed, it's deleted from the map. sq map[uint32]*writeQueue // pool of empty queues for reuse. @@ -64,12 +63,8 @@ func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) { return ws.zero.shift(), true } // Iterate over all non-idle streams until finding one that can be consumed. - for streamID, q := range ws.sq { + for _, q := range ws.sq { if wr, ok := q.consume(math.MaxInt32); ok { - if q.empty() { - delete(ws.sq, streamID) - ws.queuePool.put(q) - } return wr, true } } diff --git a/vendor/golang.org/x/net/idna/tables11.0.0.go b/vendor/golang.org/x/net/idna/tables11.0.0.go index 8ce0811fdf..c515d7ad2a 100644 --- a/vendor/golang.org/x/net/idna/tables11.0.0.go +++ b/vendor/golang.org/x/net/idna/tables11.0.0.go @@ -1,6 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. -// +build go1.13,!go1.14 +// +build go1.13 package idna diff --git a/vendor/golang.org/x/net/idna/tables12.00.go b/vendor/golang.org/x/net/idna/tables12.00.go deleted file mode 100644 index f4b8ea3638..0000000000 --- a/vendor/golang.org/x/net/idna/tables12.00.go +++ /dev/null @@ -1,4733 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -// +build go1.14 - -package idna - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "12.0.0" - -var mappings string = "" + // Size: 8178 bytes - "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" + - "\x053⁄4\x03i̇\x03l·\x03ʼn\x01s\x03dž\x03ⱥ\x03ⱦ\x01h\x01j\x01r\x01w\x01y" + - "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" + - "\x04եւ\x04اٴ\x04وٴ\x04ۇٴ\x04يٴ\x06क़\x06ख़\x06ग़\x06ज़\x06ड़\x06ढ़\x06फ़" + - "\x06य़\x06ড়\x06ঢ়\x06য়\x06ਲ਼\x06ਸ਼\x06ਖ਼\x06ਗ਼\x06ਜ਼\x06ਫ਼\x06ଡ଼\x06ଢ଼" + - "\x06ํา\x06ໍາ\x06ຫນ\x06ຫມ\x06གྷ\x06ཌྷ\x06དྷ\x06བྷ\x06ཛྷ\x06ཀྵ\x06ཱི\x06ཱུ" + - "\x06ྲྀ\x09ྲཱྀ\x06ླྀ\x09ླཱྀ\x06ཱྀ\x06ྒྷ\x06ྜྷ\x06ྡྷ\x06ྦྷ\x06ྫྷ\x06ྐྵ\x02" + - "в\x02д\x02о\x02с\x02т\x02ъ\x02ѣ\x02æ\x01b\x01d\x01e\x02ǝ\x01g\x01i\x01k" + - "\x01m\x01n\x02ȣ\x01p\x01t\x01u\x02ɐ\x02ɑ\x02ə\x02ɛ\x02ɜ\x02ŋ\x02ɔ\x02ɯ" + - "\x01v\x02β\x02γ\x02δ\x02φ\x02χ\x02ρ\x02н\x02ɒ\x01c\x02ɕ\x02ð\x01f\x02ɟ" + - "\x02ɡ\x02ɥ\x02ɨ\x02ɩ\x02ɪ\x02ʝ\x02ɭ\x02ʟ\x02ɱ\x02ɰ\x02ɲ\x02ɳ\x02ɴ\x02ɵ" + - "\x02ɸ\x02ʂ\x02ʃ\x02ƫ\x02ʉ\x02ʊ\x02ʋ\x02ʌ\x01z\x02ʐ\x02ʑ\x02ʒ\x02θ\x02ss" + - "\x02ά\x02έ\x02ή\x02ί\x02ό\x02ύ\x02ώ\x05ἀι\x05ἁι\x05ἂι\x05ἃι\x05ἄι\x05ἅι" + - "\x05ἆι\x05ἇι\x05ἠι\x05ἡι\x05ἢι\x05ἣι\x05ἤι\x05ἥι\x05ἦι\x05ἧι\x05ὠι\x05ὡι" + - "\x05ὢι\x05ὣι\x05ὤι\x05ὥι\x05ὦι\x05ὧι\x05ὰι\x04αι\x04άι\x05ᾶι\x02ι\x05 ̈͂" + - "\x05ὴι\x04ηι\x04ήι\x05ῆι\x05 ̓̀\x05 ̓́\x05 ̓͂\x02ΐ\x05 ̔̀\x05 ̔́\x05 ̔͂" + - "\x02ΰ\x05 ̈̀\x01`\x05ὼι\x04ωι\x04ώι\x05ῶι\x06′′\x09′′′\x06‵‵\x09‵‵‵\x02!" + - "!\x02??\x02?!\x02!?\x0c′′′′\x010\x014\x015\x016\x017\x018\x019\x01+\x01=" + - "\x01(\x01)\x02rs\x02ħ\x02no\x01q\x02sm\x02tm\x02ω\x02å\x02א\x02ב\x02ג" + - "\x02ד\x02π\x051⁄7\x051⁄9\x061⁄10\x051⁄3\x052⁄3\x051⁄5\x052⁄5\x053⁄5\x054" + - "⁄5\x051⁄6\x055⁄6\x051⁄8\x053⁄8\x055⁄8\x057⁄8\x041⁄\x02ii\x02iv\x02vi" + - "\x04viii\x02ix\x02xi\x050⁄3\x06∫∫\x09∫∫∫\x06∮∮\x09∮∮∮\x0210\x0211\x0212" + - "\x0213\x0214\x0215\x0216\x0217\x0218\x0219\x0220\x04(10)\x04(11)\x04(12)" + - "\x04(13)\x04(14)\x04(15)\x04(16)\x04(17)\x04(18)\x04(19)\x04(20)\x0c∫∫∫∫" + - "\x02==\x05⫝̸\x02ɫ\x02ɽ\x02ȿ\x02ɀ\x01.\x04 ゙\x04 ゚\x06より\x06コト\x05(ᄀ)\x05" + - "(ᄂ)\x05(ᄃ)\x05(ᄅ)\x05(ᄆ)\x05(ᄇ)\x05(ᄉ)\x05(ᄋ)\x05(ᄌ)\x05(ᄎ)\x05(ᄏ)\x05(ᄐ" + - ")\x05(ᄑ)\x05(ᄒ)\x05(가)\x05(나)\x05(다)\x05(라)\x05(마)\x05(바)\x05(사)\x05(아)" + - "\x05(자)\x05(차)\x05(카)\x05(타)\x05(파)\x05(하)\x05(주)\x08(오전)\x08(오후)\x05(一)" + - "\x05(二)\x05(三)\x05(四)\x05(五)\x05(六)\x05(七)\x05(八)\x05(九)\x05(十)\x05(月)" + - "\x05(火)\x05(水)\x05(木)\x05(金)\x05(土)\x05(日)\x05(株)\x05(有)\x05(社)\x05(名)" + - "\x05(特)\x05(財)\x05(祝)\x05(労)\x05(代)\x05(呼)\x05(学)\x05(監)\x05(企)\x05(資)" + - "\x05(協)\x05(祭)\x05(休)\x05(自)\x05(至)\x0221\x0222\x0223\x0224\x0225\x0226" + - "\x0227\x0228\x0229\x0230\x0231\x0232\x0233\x0234\x0235\x06참고\x06주의\x0236" + - "\x0237\x0238\x0239\x0240\x0241\x0242\x0243\x0244\x0245\x0246\x0247\x0248" + - "\x0249\x0250\x041月\x042月\x043月\x044月\x045月\x046月\x047月\x048月\x049月\x0510" + - "月\x0511月\x0512月\x02hg\x02ev\x0cアパート\x0cアルファ\x0cアンペア\x09アール\x0cイニング\x09" + - "インチ\x09ウォン\x0fエスクード\x0cエーカー\x09オンス\x09オーム\x09カイリ\x0cカラット\x0cカロリー\x09ガロ" + - "ン\x09ガンマ\x06ギガ\x09ギニー\x0cキュリー\x0cギルダー\x06キロ\x0fキログラム\x12キロメートル\x0fキロワッ" + - "ト\x09グラム\x0fグラムトン\x0fクルゼイロ\x0cクローネ\x09ケース\x09コルナ\x09コーポ\x0cサイクル\x0fサンチ" + - "ーム\x0cシリング\x09センチ\x09セント\x09ダース\x06デシ\x06ドル\x06トン\x06ナノ\x09ノット\x09ハイツ" + - "\x0fパーセント\x09パーツ\x0cバーレル\x0fピアストル\x09ピクル\x06ピコ\x06ビル\x0fファラッド\x0cフィート" + - "\x0fブッシェル\x09フラン\x0fヘクタール\x06ペソ\x09ペニヒ\x09ヘルツ\x09ペンス\x09ページ\x09ベータ\x0cポイ" + - "ント\x09ボルト\x06ホン\x09ポンド\x09ホール\x09ホーン\x0cマイクロ\x09マイル\x09マッハ\x09マルク\x0fマ" + - "ンション\x0cミクロン\x06ミリ\x0fミリバール\x06メガ\x0cメガトン\x0cメートル\x09ヤード\x09ヤール\x09ユアン" + - "\x0cリットル\x06リラ\x09ルピー\x0cルーブル\x06レム\x0fレントゲン\x09ワット\x040点\x041点\x042点" + - "\x043点\x044点\x045点\x046点\x047点\x048点\x049点\x0510点\x0511点\x0512点\x0513点" + - "\x0514点\x0515点\x0516点\x0517点\x0518点\x0519点\x0520点\x0521点\x0522点\x0523点" + - "\x0524点\x02da\x02au\x02ov\x02pc\x02dm\x02iu\x06平成\x06昭和\x06大正\x06明治\x0c株" + - "式会社\x02pa\x02na\x02ma\x02ka\x02kb\x02mb\x02gb\x04kcal\x02pf\x02nf\x02m" + - "g\x02kg\x02hz\x02ml\x02dl\x02kl\x02fm\x02nm\x02mm\x02cm\x02km\x02m2\x02m" + - "3\x05m∕s\x06m∕s2\x07rad∕s\x08rad∕s2\x02ps\x02ns\x02ms\x02pv\x02nv\x02mv" + - "\x02kv\x02pw\x02nw\x02mw\x02kw\x02bq\x02cc\x02cd\x06c∕kg\x02db\x02gy\x02" + - "ha\x02hp\x02in\x02kk\x02kt\x02lm\x02ln\x02lx\x02ph\x02pr\x02sr\x02sv\x02" + - "wb\x05v∕m\x05a∕m\x041日\x042日\x043日\x044日\x045日\x046日\x047日\x048日\x049日" + - "\x0510日\x0511日\x0512日\x0513日\x0514日\x0515日\x0516日\x0517日\x0518日\x0519日" + - "\x0520日\x0521日\x0522日\x0523日\x0524日\x0525日\x0526日\x0527日\x0528日\x0529日" + - "\x0530日\x0531日\x02ь\x02ɦ\x02ɬ\x02ʞ\x02ʇ\x02œ\x04𤋮\x04𢡊\x04𢡄\x04𣏕\x04𥉉" + - "\x04𥳐\x04𧻓\x02ff\x02fi\x02fl\x02st\x04մն\x04մե\x04մի\x04վն\x04մխ\x04יִ" + - "\x04ײַ\x02ע\x02ה\x02כ\x02ל\x02ם\x02ר\x02ת\x04שׁ\x04שׂ\x06שּׁ\x06שּׂ\x04א" + - "ַ\x04אָ\x04אּ\x04בּ\x04גּ\x04דּ\x04הּ\x04וּ\x04זּ\x04טּ\x04יּ\x04ךּ\x04" + - "כּ\x04לּ\x04מּ\x04נּ\x04סּ\x04ףּ\x04פּ\x04צּ\x04קּ\x04רּ\x04שּ\x04תּ" + - "\x04וֹ\x04בֿ\x04כֿ\x04פֿ\x04אל\x02ٱ\x02ٻ\x02پ\x02ڀ\x02ٺ\x02ٿ\x02ٹ\x02ڤ" + - "\x02ڦ\x02ڄ\x02ڃ\x02چ\x02ڇ\x02ڍ\x02ڌ\x02ڎ\x02ڈ\x02ژ\x02ڑ\x02ک\x02گ\x02ڳ" + - "\x02ڱ\x02ں\x02ڻ\x02ۀ\x02ہ\x02ھ\x02ے\x02ۓ\x02ڭ\x02ۇ\x02ۆ\x02ۈ\x02ۋ\x02ۅ" + - "\x02ۉ\x02ې\x02ى\x04ئا\x04ئە\x04ئو\x04ئۇ\x04ئۆ\x04ئۈ\x04ئې\x04ئى\x02ی\x04" + - "ئج\x04ئح\x04ئم\x04ئي\x04بج\x04بح\x04بخ\x04بم\x04بى\x04بي\x04تج\x04تح" + - "\x04تخ\x04تم\x04تى\x04تي\x04ثج\x04ثم\x04ثى\x04ثي\x04جح\x04جم\x04حج\x04حم" + - "\x04خج\x04خح\x04خم\x04سج\x04سح\x04سخ\x04سم\x04صح\x04صم\x04ضج\x04ضح\x04ضخ" + - "\x04ضم\x04طح\x04طم\x04ظم\x04عج\x04عم\x04غج\x04غم\x04فج\x04فح\x04فخ\x04فم" + - "\x04فى\x04في\x04قح\x04قم\x04قى\x04قي\x04كا\x04كج\x04كح\x04كخ\x04كل\x04كم" + - "\x04كى\x04كي\x04لج\x04لح\x04لخ\x04لم\x04لى\x04لي\x04مج\x04مح\x04مخ\x04مم" + - "\x04مى\x04مي\x04نج\x04نح\x04نخ\x04نم\x04نى\x04ني\x04هج\x04هم\x04هى\x04هي" + - "\x04يج\x04يح\x04يخ\x04يم\x04يى\x04يي\x04ذٰ\x04رٰ\x04ىٰ\x05 ٌّ\x05 ٍّ\x05" + - " َّ\x05 ُّ\x05 ِّ\x05 ّٰ\x04ئر\x04ئز\x04ئن\x04بر\x04بز\x04بن\x04تر\x04تز" + - "\x04تن\x04ثر\x04ثز\x04ثن\x04ما\x04نر\x04نز\x04نن\x04ير\x04يز\x04ين\x04ئخ" + - "\x04ئه\x04به\x04ته\x04صخ\x04له\x04نه\x04هٰ\x04يه\x04ثه\x04سه\x04شم\x04شه" + - "\x06ـَّ\x06ـُّ\x06ـِّ\x04طى\x04طي\x04عى\x04عي\x04غى\x04غي\x04سى\x04سي" + - "\x04شى\x04شي\x04حى\x04حي\x04جى\x04جي\x04خى\x04خي\x04صى\x04صي\x04ضى\x04ضي" + - "\x04شج\x04شح\x04شخ\x04شر\x04سر\x04صر\x04ضر\x04اً\x06تجم\x06تحج\x06تحم" + - "\x06تخم\x06تمج\x06تمح\x06تمخ\x06جمح\x06حمي\x06حمى\x06سحج\x06سجح\x06سجى" + - "\x06سمح\x06سمج\x06سمم\x06صحح\x06صمم\x06شحم\x06شجي\x06شمخ\x06شمم\x06ضحى" + - "\x06ضخم\x06طمح\x06طمم\x06طمي\x06عجم\x06عمم\x06عمى\x06غمم\x06غمي\x06غمى" + - "\x06فخم\x06قمح\x06قمم\x06لحم\x06لحي\x06لحى\x06لجج\x06لخم\x06لمح\x06محج" + - "\x06محم\x06محي\x06مجح\x06مجم\x06مخج\x06مخم\x06مجخ\x06همج\x06همم\x06نحم" + - "\x06نحى\x06نجم\x06نجى\x06نمي\x06نمى\x06يمم\x06بخي\x06تجي\x06تجى\x06تخي" + - "\x06تخى\x06تمي\x06تمى\x06جمي\x06جحى\x06جمى\x06سخى\x06صحي\x06شحي\x06ضحي" + - "\x06لجي\x06لمي\x06يحي\x06يجي\x06يمي\x06ممي\x06قمي\x06نحي\x06عمي\x06كمي" + - "\x06نجح\x06مخي\x06لجم\x06كمم\x06جحي\x06حجي\x06مجي\x06فمي\x06بحي\x06سخي" + - "\x06نجي\x06صلے\x06قلے\x08الله\x08اكبر\x08محمد\x08صلعم\x08رسول\x08عليه" + - "\x08وسلم\x06صلى!صلى الله عليه وسلم\x0fجل جلاله\x08ریال\x01,\x01:\x01!" + - "\x01?\x01_\x01{\x01}\x01[\x01]\x01#\x01&\x01*\x01-\x01<\x01>\x01\\\x01$" + - "\x01%\x01@\x04ـً\x04ـَ\x04ـُ\x04ـِ\x04ـّ\x04ـْ\x02ء\x02آ\x02أ\x02ؤ\x02إ" + - "\x02ئ\x02ا\x02ب\x02ة\x02ت\x02ث\x02ج\x02ح\x02خ\x02د\x02ذ\x02ر\x02ز\x02س" + - "\x02ش\x02ص\x02ض\x02ط\x02ظ\x02ع\x02غ\x02ف\x02ق\x02ك\x02ل\x02م\x02ن\x02ه" + - "\x02و\x02ي\x04لآ\x04لأ\x04لإ\x04لا\x01\x22\x01'\x01/\x01^\x01|\x01~\x02¢" + - "\x02£\x02¬\x02¦\x02¥\x08𝅗𝅥\x08𝅘𝅥\x0c𝅘𝅥𝅮\x0c𝅘𝅥𝅯\x0c𝅘𝅥𝅰\x0c𝅘𝅥𝅱\x0c𝅘𝅥𝅲\x08𝆹" + - "𝅥\x08𝆺𝅥\x0c𝆹𝅥𝅮\x0c𝆺𝅥𝅮\x0c𝆹𝅥𝅯\x0c𝆺𝅥𝅯\x02ı\x02ȷ\x02α\x02ε\x02ζ\x02η\x02" + - "κ\x02λ\x02μ\x02ν\x02ξ\x02ο\x02σ\x02τ\x02υ\x02ψ\x03∇\x03∂\x02ϝ\x02ٮ\x02ڡ" + - "\x02ٯ\x020,\x021,\x022,\x023,\x024,\x025,\x026,\x027,\x028,\x029,\x03(a)" + - "\x03(b)\x03(c)\x03(d)\x03(e)\x03(f)\x03(g)\x03(h)\x03(i)\x03(j)\x03(k)" + - "\x03(l)\x03(m)\x03(n)\x03(o)\x03(p)\x03(q)\x03(r)\x03(s)\x03(t)\x03(u)" + - "\x03(v)\x03(w)\x03(x)\x03(y)\x03(z)\x07〔s〕\x02wz\x02hv\x02sd\x03ppv\x02w" + - "c\x02mc\x02md\x02mr\x02dj\x06ほか\x06ココ\x03サ\x03手\x03字\x03双\x03デ\x03二\x03多" + - "\x03解\x03天\x03交\x03映\x03無\x03料\x03前\x03後\x03再\x03新\x03初\x03終\x03生\x03販" + - "\x03声\x03吹\x03演\x03投\x03捕\x03一\x03三\x03遊\x03左\x03中\x03右\x03指\x03走\x03打" + - "\x03禁\x03空\x03合\x03満\x03有\x03月\x03申\x03割\x03営\x03配\x09〔本〕\x09〔三〕\x09〔二〕" + - "\x09〔安〕\x09〔点〕\x09〔打〕\x09〔盗〕\x09〔勝〕\x09〔敗〕\x03得\x03可\x03丽\x03丸\x03乁\x03你" + - "\x03侮\x03侻\x03倂\x03偺\x03備\x03僧\x03像\x03㒞\x03免\x03兔\x03兤\x03具\x03㒹\x03內" + - "\x03冗\x03冤\x03仌\x03冬\x03况\x03凵\x03刃\x03㓟\x03刻\x03剆\x03剷\x03㔕\x03勇\x03勉" + - "\x03勤\x03勺\x03包\x03匆\x03北\x03卉\x03卑\x03博\x03即\x03卽\x03卿\x03灰\x03及\x03叟" + - "\x03叫\x03叱\x03吆\x03咞\x03吸\x03呈\x03周\x03咢\x03哶\x03唐\x03啓\x03啣\x03善\x03喙" + - "\x03喫\x03喳\x03嗂\x03圖\x03嘆\x03圗\x03噑\x03噴\x03切\x03壮\x03城\x03埴\x03堍\x03型" + - "\x03堲\x03報\x03墬\x03売\x03壷\x03夆\x03夢\x03奢\x03姬\x03娛\x03娧\x03姘\x03婦\x03㛮" + - "\x03嬈\x03嬾\x03寃\x03寘\x03寧\x03寳\x03寿\x03将\x03尢\x03㞁\x03屠\x03屮\x03峀\x03岍" + - "\x03嵃\x03嵮\x03嵫\x03嵼\x03巡\x03巢\x03㠯\x03巽\x03帨\x03帽\x03幩\x03㡢\x03㡼\x03庰" + - "\x03庳\x03庶\x03廊\x03廾\x03舁\x03弢\x03㣇\x03形\x03彫\x03㣣\x03徚\x03忍\x03志\x03忹" + - "\x03悁\x03㤺\x03㤜\x03悔\x03惇\x03慈\x03慌\x03慎\x03慺\x03憎\x03憲\x03憤\x03憯\x03懞" + - "\x03懲\x03懶\x03成\x03戛\x03扝\x03抱\x03拔\x03捐\x03挽\x03拼\x03捨\x03掃\x03揤\x03搢" + - "\x03揅\x03掩\x03㨮\x03摩\x03摾\x03撝\x03摷\x03㩬\x03敏\x03敬\x03旣\x03書\x03晉\x03㬙" + - "\x03暑\x03㬈\x03㫤\x03冒\x03冕\x03最\x03暜\x03肭\x03䏙\x03朗\x03望\x03朡\x03杞\x03杓" + - "\x03㭉\x03柺\x03枅\x03桒\x03梅\x03梎\x03栟\x03椔\x03㮝\x03楂\x03榣\x03槪\x03檨\x03櫛" + - "\x03㰘\x03次\x03歔\x03㱎\x03歲\x03殟\x03殺\x03殻\x03汎\x03沿\x03泍\x03汧\x03洖\x03派" + - "\x03海\x03流\x03浩\x03浸\x03涅\x03洴\x03港\x03湮\x03㴳\x03滋\x03滇\x03淹\x03潮\x03濆" + - "\x03瀹\x03瀞\x03瀛\x03㶖\x03灊\x03災\x03灷\x03炭\x03煅\x03熜\x03爨\x03爵\x03牐\x03犀" + - "\x03犕\x03獺\x03王\x03㺬\x03玥\x03㺸\x03瑇\x03瑜\x03瑱\x03璅\x03瓊\x03㼛\x03甤\x03甾" + - "\x03異\x03瘐\x03㿼\x03䀈\x03直\x03眞\x03真\x03睊\x03䀹\x03瞋\x03䁆\x03䂖\x03硎\x03碌" + - "\x03磌\x03䃣\x03祖\x03福\x03秫\x03䄯\x03穀\x03穊\x03穏\x03䈂\x03篆\x03築\x03䈧\x03糒" + - "\x03䊠\x03糨\x03糣\x03紀\x03絣\x03䌁\x03緇\x03縂\x03繅\x03䌴\x03䍙\x03罺\x03羕\x03翺" + - "\x03者\x03聠\x03聰\x03䏕\x03育\x03脃\x03䐋\x03脾\x03媵\x03舄\x03辞\x03䑫\x03芑\x03芋" + - "\x03芝\x03劳\x03花\x03芳\x03芽\x03苦\x03若\x03茝\x03荣\x03莭\x03茣\x03莽\x03菧\x03著" + - "\x03荓\x03菊\x03菌\x03菜\x03䔫\x03蓱\x03蓳\x03蔖\x03蕤\x03䕝\x03䕡\x03䕫\x03虐\x03虜" + - "\x03虧\x03虩\x03蚩\x03蚈\x03蜎\x03蛢\x03蝹\x03蜨\x03蝫\x03螆\x03蟡\x03蠁\x03䗹\x03衠" + - "\x03衣\x03裗\x03裞\x03䘵\x03裺\x03㒻\x03䚾\x03䛇\x03誠\x03諭\x03變\x03豕\x03貫\x03賁" + - "\x03贛\x03起\x03跋\x03趼\x03跰\x03軔\x03輸\x03邔\x03郱\x03鄑\x03鄛\x03鈸\x03鋗\x03鋘" + - "\x03鉼\x03鏹\x03鐕\x03開\x03䦕\x03閷\x03䧦\x03雃\x03嶲\x03霣\x03䩮\x03䩶\x03韠\x03䪲" + - "\x03頋\x03頩\x03飢\x03䬳\x03餩\x03馧\x03駂\x03駾\x03䯎\x03鬒\x03鱀\x03鳽\x03䳎\x03䳭" + - "\x03鵧\x03䳸\x03麻\x03䵖\x03黹\x03黾\x03鼅\x03鼏\x03鼖\x03鼻" - -var xorData string = "" + // Size: 4862 bytes - "\x02\x0c\x09\x02\xb0\xec\x02\xad\xd8\x02\xad\xd9\x02\x06\x07\x02\x0f\x12" + - "\x02\x0f\x1f\x02\x0f\x1d\x02\x01\x13\x02\x0f\x16\x02\x0f\x0b\x02\x0f3" + - "\x02\x0f7\x02\x0f?\x02\x0f/\x02\x0f*\x02\x0c&\x02\x0c*\x02\x0c;\x02\x0c9" + - "\x02\x0c%\x02\xab\xed\x02\xab\xe2\x02\xab\xe3\x02\xa9\xe0\x02\xa9\xe1" + - "\x02\xa9\xe6\x02\xa3\xcb\x02\xa3\xc8\x02\xa3\xc9\x02\x01#\x02\x01\x08" + - "\x02\x0e>\x02\x0e'\x02\x0f\x03\x02\x03\x0d\x02\x03\x09\x02\x03\x17\x02" + - "\x03\x0e\x02\x02\x03\x02\x011\x02\x01\x00\x02\x01\x10\x02\x03<\x02\x07" + - "\x0d\x02\x02\x0c\x02\x0c0\x02\x01\x03\x02\x01\x01\x02\x01 \x02\x01\x22" + - "\x02\x01)\x02\x01\x0a\x02\x01\x0c\x02\x02\x06\x02\x02\x02\x02\x03\x10" + - "\x03\x037 \x03\x0b+\x03\x021\x00\x02\x01\x04\x02\x01\x02\x02\x019\x02" + - "\x03\x1c\x02\x02$\x03\x80p$\x02\x03:\x02\x03\x0a\x03\xc1r.\x03\xc1r,\x03" + - "\xc1r\x02\x02\x02:\x02\x02>\x02\x02,\x02\x02\x10\x02\x02\x00\x03\xc1s<" + - "\x03\xc1s*\x03\xc2L$\x03\xc2L;\x02\x09)\x02\x0a\x19\x03\x83\xab\xe3\x03" + - "\x83\xab\xf2\x03 4\xe0\x03\x81\xab\xea\x03\x81\xab\xf3\x03 4\xef\x03\x96" + - "\xe1\xcd\x03\x84\xe5\xc3\x02\x0d\x11\x03\x8b\xec\xcb\x03\x94\xec\xcf\x03" + - "\x9a\xec\xc2\x03\x8b\xec\xdb\x03\x94\xec\xdf\x03\x9a\xec\xd2\x03\x01\x0c" + - "!\x03\x01\x0c#\x03ʠ\x9d\x03ʣ\x9c\x03ʢ\x9f\x03ʥ\x9e\x03ʤ\x91\x03ʧ\x90\x03" + - "ʦ\x93\x03ʩ\x92\x03ʨ\x95\x03\xca\xf3\xb5\x03\xca\xf0\xb4\x03\xca\xf1\xb7" + - "\x03\xca\xf6\xb6\x03\xca\xf7\x89\x03\xca\xf4\x88\x03\xca\xf5\x8b\x03\xca" + - "\xfa\x8a\x03\xca\xfb\x8d\x03\xca\xf8\x8c\x03\xca\xf9\x8f\x03\xca\xfe\x8e" + - "\x03\xca\xff\x81\x03\xca\xfc\x80\x03\xca\xfd\x83\x03\xca\xe2\x82\x03\xca" + - "\xe3\x85\x03\xca\xe0\x84\x03\xca\xe1\x87\x03\xca\xe6\x86\x03\xca\xe7\x99" + - "\x03\xca\xe4\x98\x03\xca\xe5\x9b\x03\xca\xea\x9a\x03\xca\xeb\x9d\x03\xca" + - "\xe8\x9c\x03ؓ\x89\x03ߔ\x8b\x02\x010\x03\x03\x04\x1e\x03\x04\x15\x12\x03" + - "\x0b\x05,\x03\x06\x04\x00\x03\x06\x04)\x03\x06\x044\x03\x06\x04<\x03\x06" + - "\x05\x1d\x03\x06\x06\x00\x03\x06\x06\x0a\x03\x06\x06'\x03\x06\x062\x03" + - "\x0786\x03\x079/\x03\x079 \x03\x07:\x0e\x03\x07:\x1b\x03\x07:%\x03\x07;/" + - "\x03\x07;%\x03\x074\x11\x03\x076\x09\x03\x077*\x03\x070\x01\x03\x070\x0f" + - "\x03\x070.\x03\x071\x16\x03\x071\x04\x03\x0710\x03\x072\x18\x03\x072-" + - "\x03\x073\x14\x03\x073>\x03\x07'\x09\x03\x07 \x00\x03\x07\x1f\x0b\x03" + - "\x07\x18#\x03\x07\x18(\x03\x07\x186\x03\x07\x18\x03\x03\x07\x19\x16\x03" + - "\x07\x116\x03\x07\x12'\x03\x07\x13\x10\x03\x07\x0c&\x03\x07\x0c\x08\x03" + - "\x07\x0c\x13\x03\x07\x0d\x02\x03\x07\x0d\x1c\x03\x07\x0b5\x03\x07\x0b" + - "\x0a\x03\x07\x0b\x01\x03\x07\x0b\x0f\x03\x07\x05\x00\x03\x07\x05\x09\x03" + - "\x07\x05\x0b\x03\x07\x07\x01\x03\x07\x07\x08\x03\x07\x00<\x03\x07\x00+" + - "\x03\x07\x01)\x03\x07\x01\x1b\x03\x07\x01\x08\x03\x07\x03?\x03\x0445\x03" + - "\x044\x08\x03\x0454\x03\x04)/\x03\x04)5\x03\x04+\x05\x03\x04+\x14\x03" + - "\x04+ \x03\x04+<\x03\x04*&\x03\x04*\x22\x03\x04&8\x03\x04!\x01\x03\x04!" + - "\x22\x03\x04\x11+\x03\x04\x10.\x03\x04\x104\x03\x04\x13=\x03\x04\x12\x04" + - "\x03\x04\x12\x0a\x03\x04\x0d\x1d\x03\x04\x0d\x07\x03\x04\x0d \x03\x05<>" + - "\x03\x055<\x03\x055!\x03\x055#\x03\x055&\x03\x054\x1d\x03\x054\x02\x03" + - "\x054\x07\x03\x0571\x03\x053\x1a\x03\x053\x16\x03\x05.<\x03\x05.\x07\x03" + - "\x05):\x03\x05)<\x03\x05)\x0c\x03\x05)\x15\x03\x05+-\x03\x05+5\x03\x05$" + - "\x1e\x03\x05$\x14\x03\x05'\x04\x03\x05'\x14\x03\x05&\x02\x03\x05\x226" + - "\x03\x05\x22\x0c\x03\x05\x22\x1c\x03\x05\x19\x0a\x03\x05\x1b\x09\x03\x05" + - "\x1b\x0c\x03\x05\x14\x07\x03\x05\x16?\x03\x05\x16\x0c\x03\x05\x0c\x05" + - "\x03\x05\x0e\x0f\x03\x05\x01\x0e\x03\x05\x00(\x03\x05\x030\x03\x05\x03" + - "\x06\x03\x0a==\x03\x0a=1\x03\x0a=,\x03\x0a=\x0c\x03\x0a??\x03\x0a<\x08" + - "\x03\x0a9!\x03\x0a9)\x03\x0a97\x03\x0a99\x03\x0a6\x0a\x03\x0a6\x1c\x03" + - "\x0a6\x17\x03\x0a7'\x03\x0a78\x03\x0a73\x03\x0a'\x01\x03\x0a'&\x03\x0a" + - "\x1f\x0e\x03\x0a\x1f\x03\x03\x0a\x1f3\x03\x0a\x1b/\x03\x0a\x18\x19\x03" + - "\x0a\x19\x01\x03\x0a\x16\x14\x03\x0a\x0e\x22\x03\x0a\x0f\x10\x03\x0a\x0f" + - "\x02\x03\x0a\x0f \x03\x0a\x0c\x04\x03\x0a\x0b>\x03\x0a\x0b+\x03\x0a\x08/" + - "\x03\x0a\x046\x03\x0a\x05\x14\x03\x0a\x00\x04\x03\x0a\x00\x10\x03\x0a" + - "\x00\x14\x03\x0b<3\x03\x0b;*\x03\x0b9\x22\x03\x0b9)\x03\x0b97\x03\x0b+" + - "\x10\x03\x0b((\x03\x0b&5\x03\x0b$\x1c\x03\x0b$\x12\x03\x0b%\x04\x03\x0b#" + - "<\x03\x0b#0\x03\x0b#\x0d\x03\x0b#\x19\x03\x0b!:\x03\x0b!\x1f\x03\x0b!" + - "\x00\x03\x0b\x1e5\x03\x0b\x1c\x1d\x03\x0b\x1d-\x03\x0b\x1d(\x03\x0b\x18." + - "\x03\x0b\x18 \x03\x0b\x18\x16\x03\x0b\x14\x13\x03\x0b\x15$\x03\x0b\x15" + - "\x22\x03\x0b\x12\x1b\x03\x0b\x12\x10\x03\x0b\x132\x03\x0b\x13=\x03\x0b" + - "\x12\x18\x03\x0b\x0c&\x03\x0b\x061\x03\x0b\x06:\x03\x0b\x05#\x03\x0b\x05" + - "<\x03\x0b\x04\x0b\x03\x0b\x04\x04\x03\x0b\x04\x1b\x03\x0b\x042\x03\x0b" + - "\x041\x03\x0b\x03\x03\x03\x0b\x03\x1d\x03\x0b\x03/\x03\x0b\x03+\x03\x0b" + - "\x02\x1b\x03\x0b\x02\x00\x03\x0b\x01\x1e\x03\x0b\x01\x08\x03\x0b\x015" + - "\x03\x06\x0d9\x03\x06\x0d=\x03\x06\x0d?\x03\x02\x001\x03\x02\x003\x03" + - "\x02\x02\x19\x03\x02\x006\x03\x02\x02\x1b\x03\x02\x004\x03\x02\x00<\x03" + - "\x02\x02\x0a\x03\x02\x02\x0e\x03\x02\x01\x1a\x03\x02\x01\x07\x03\x02\x01" + - "\x05\x03\x02\x01\x0b\x03\x02\x01%\x03\x02\x01\x0c\x03\x02\x01\x04\x03" + - "\x02\x01\x1c\x03\x02\x00.\x03\x02\x002\x03\x02\x00>\x03\x02\x00\x12\x03" + - "\x02\x00\x16\x03\x02\x011\x03\x02\x013\x03\x02\x02 \x03\x02\x02%\x03\x02" + - "\x02$\x03\x02\x028\x03\x02\x02;\x03\x02\x024\x03\x02\x012\x03\x02\x022" + - "\x03\x02\x02/\x03\x02\x01,\x03\x02\x01\x13\x03\x02\x01\x16\x03\x02\x01" + - "\x11\x03\x02\x01\x1e\x03\x02\x01\x15\x03\x02\x01\x17\x03\x02\x01\x0f\x03" + - "\x02\x01\x08\x03\x02\x00?\x03\x02\x03\x07\x03\x02\x03\x0d\x03\x02\x03" + - "\x13\x03\x02\x03\x1d\x03\x02\x03\x1f\x03\x02\x00\x03\x03\x02\x00\x0d\x03" + - "\x02\x00\x01\x03\x02\x00\x1b\x03\x02\x00\x19\x03\x02\x00\x18\x03\x02\x00" + - "\x13\x03\x02\x00/\x03\x07>\x12\x03\x07<\x1f\x03\x07>\x1d\x03\x06\x1d\x0e" + - "\x03\x07>\x1c\x03\x07>:\x03\x07>\x13\x03\x04\x12+\x03\x07?\x03\x03\x07>" + - "\x02\x03\x06\x224\x03\x06\x1a.\x03\x07<%\x03\x06\x1c\x0b\x03\x0609\x03" + - "\x05\x1f\x01\x03\x04'\x08\x03\x93\xfd\xf5\x03\x02\x0d \x03\x02\x0d#\x03" + - "\x02\x0d!\x03\x02\x0d&\x03\x02\x0d\x22\x03\x02\x0d/\x03\x02\x0d,\x03\x02" + - "\x0d$\x03\x02\x0d'\x03\x02\x0d%\x03\x02\x0d;\x03\x02\x0d=\x03\x02\x0d?" + - "\x03\x099.\x03\x08\x0b7\x03\x08\x02\x14\x03\x08\x14\x0d\x03\x08.:\x03" + - "\x089'\x03\x0f\x0b\x18\x03\x0f\x1c1\x03\x0f\x17&\x03\x0f9\x1f\x03\x0f0" + - "\x0c\x03\x0e\x0a9\x03\x0e\x056\x03\x0e\x1c#\x03\x0f\x13\x0e\x03\x072\x00" + - "\x03\x070\x0d\x03\x072\x0b\x03\x06\x11\x18\x03\x070\x10\x03\x06\x0f(\x03" + - "\x072\x05\x03\x06\x0f,\x03\x073\x15\x03\x06\x07\x08\x03\x05\x16\x02\x03" + - "\x04\x0b \x03\x05:8\x03\x05\x16%\x03\x0a\x0d\x1f\x03\x06\x16\x10\x03\x05" + - "\x1d5\x03\x05*;\x03\x05\x16\x1b\x03\x04.-\x03\x06\x1a\x19\x03\x04\x03," + - "\x03\x0b87\x03\x04/\x0a\x03\x06\x00,\x03\x04-\x01\x03\x04\x1e-\x03\x06/(" + - "\x03\x0a\x0b5\x03\x06\x0e7\x03\x06\x07.\x03\x0597\x03\x0a*%\x03\x0760" + - "\x03\x06\x0c;\x03\x05'\x00\x03\x072.\x03\x072\x08\x03\x06=\x01\x03\x06" + - "\x05\x1b\x03\x06\x06\x12\x03\x06$=\x03\x06'\x0d\x03\x04\x11\x0f\x03\x076" + - ",\x03\x06\x07;\x03\x06.,\x03\x86\xf9\xea\x03\x8f\xff\xeb\x02\x092\x02" + - "\x095\x02\x094\x02\x09;\x02\x09>\x02\x098\x02\x09*\x02\x09/\x02\x09,\x02" + - "\x09%\x02\x09&\x02\x09#\x02\x09 \x02\x08!\x02\x08%\x02\x08$\x02\x08+\x02" + - "\x08.\x02\x08*\x02\x08&\x02\x088\x02\x08>\x02\x084\x02\x086\x02\x080\x02" + - "\x08\x10\x02\x08\x17\x02\x08\x12\x02\x08\x1d\x02\x08\x1f\x02\x08\x13\x02" + - "\x08\x15\x02\x08\x14\x02\x08\x0c\x03\x8b\xfd\xd0\x03\x81\xec\xc6\x03\x87" + - "\xe0\x8a\x03-2\xe3\x03\x80\xef\xe4\x03-2\xea\x03\x88\xe6\xeb\x03\x8e\xe6" + - "\xe8\x03\x84\xe6\xe9\x03\x97\xe6\xee\x03-2\xf9\x03-2\xf6\x03\x8e\xe3\xad" + - "\x03\x80\xe3\x92\x03\x88\xe3\x90\x03\x8e\xe3\x90\x03\x80\xe3\x97\x03\x88" + - "\xe3\x95\x03\x88\xfe\xcb\x03\x8e\xfe\xca\x03\x84\xfe\xcd\x03\x91\xef\xc9" + - "\x03-2\xc1\x03-2\xc0\x03-2\xcb\x03\x88@\x09\x03\x8e@\x08\x03\x8f\xe0\xf5" + - "\x03\x8e\xe6\xf9\x03\x8e\xe0\xfa\x03\x93\xff\xf4\x03\x84\xee\xd3\x03\x0b" + - "(\x04\x023 \x03\x0b)\x08\x021;\x02\x01*\x03\x0b#\x10\x03\x0b 0\x03\x0b!" + - "\x10\x03\x0b!0\x03\x07\x15\x08\x03\x09?5\x03\x07\x1f\x08\x03\x07\x17\x0b" + - "\x03\x09\x1f\x15\x03\x0b\x1c7\x03\x0a+#\x03\x06\x1a\x1b\x03\x06\x1a\x14" + - "\x03\x0a\x01\x18\x03\x06#\x1b\x03\x0a2\x0c\x03\x0a\x01\x04\x03\x09#;\x03" + - "\x08='\x03\x08\x1a\x0a\x03\x07\x03\x0a\x111\x03\x09\x1b\x09\x03\x073.\x03\x07" + - "\x01\x00\x03\x09/,\x03\x07#>\x03\x07\x048\x03\x0a\x1f\x22\x03\x098>\x03" + - "\x09\x11\x00\x03\x08/\x17\x03\x06'\x22\x03\x0b\x1a+\x03\x0a\x22\x19\x03" + - "\x0a/1\x03\x0974\x03\x09\x0f\x22\x03\x08,\x22\x03\x08?\x14\x03\x07$5\x03" + - "\x07<3\x03\x07=*\x03\x07\x13\x18\x03\x068\x0a\x03\x06\x09\x16\x03\x06" + - "\x13\x00\x03\x08\x067\x03\x08\x01\x03\x03\x08\x12\x1d\x03\x07+7\x03\x06(" + - ";\x03\x06\x1c?\x03\x07\x0e\x17\x03\x0a\x06\x1d\x03\x0a\x19\x07\x03\x08" + - "\x14$\x03\x07$;\x03\x08,$\x03\x08\x06\x0d\x03\x07\x16\x0a\x03\x06>>\x03" + - "\x0a\x06\x12\x03\x0a\x14)\x03\x09\x0d\x1f\x03\x09\x12\x17\x03\x09\x19" + - "\x01\x03\x08\x11 \x03\x08\x1d'\x03\x06<\x1a\x03\x0a.\x00\x03\x07'\x18" + - "\x03\x0a\x22\x08\x03\x08\x0d\x0a\x03\x08\x13)\x03\x07*)\x03\x06<,\x03" + - "\x07\x0b\x1a\x03\x09.\x14\x03\x09\x0d\x1e\x03\x07\x0e#\x03\x0b\x1d'\x03" + - "\x0a\x0a8\x03\x09%2\x03\x08+&\x03\x080\x12\x03\x0a)4\x03\x08\x06\x1f\x03" + - "\x0b\x1b\x1a\x03\x0a\x1b\x0f\x03\x0b\x1d*\x03\x09\x16$\x03\x090\x11\x03" + - "\x08\x11\x08\x03\x0a*(\x03\x0a\x042\x03\x089,\x03\x074'\x03\x07\x0f\x05" + - "\x03\x09\x0b\x0a\x03\x07\x1b\x01\x03\x09\x17:\x03\x09.\x0d\x03\x07.\x11" + - "\x03\x09+\x15\x03\x080\x13\x03\x0b\x1f\x19\x03\x0a \x11\x03\x0a\x220\x03" + - "\x09\x07;\x03\x08\x16\x1c\x03\x07,\x13\x03\x07\x0e/\x03\x06\x221\x03\x0a" + - ".\x0a\x03\x0a7\x02\x03\x0a\x032\x03\x0a\x1d.\x03\x091\x06\x03\x09\x19:" + - "\x03\x08\x02/\x03\x060+\x03\x06\x0f-\x03\x06\x1c\x1f\x03\x06\x1d\x07\x03" + - "\x0a,\x11\x03\x09=\x0d\x03\x09\x0b;\x03\x07\x1b/\x03\x0a\x1f:\x03\x09 " + - "\x1f\x03\x09.\x10\x03\x094\x0b\x03\x09\x1a1\x03\x08#\x1a\x03\x084\x1d" + - "\x03\x08\x01\x1f\x03\x08\x11\x22\x03\x07'8\x03\x07\x1a>\x03\x0757\x03" + - "\x06&9\x03\x06+\x11\x03\x0a.\x0b\x03\x0a,>\x03\x0a4#\x03\x08%\x17\x03" + - "\x07\x05\x22\x03\x07\x0c\x0b\x03\x0a\x1d+\x03\x0a\x19\x16\x03\x09+\x1f" + - "\x03\x09\x08\x0b\x03\x08\x16\x18\x03\x08+\x12\x03\x0b\x1d\x0c\x03\x0a=" + - "\x10\x03\x0a\x09\x0d\x03\x0a\x10\x11\x03\x09&0\x03\x08(\x1f\x03\x087\x07" + - "\x03\x08\x185\x03\x07'6\x03\x06.\x05\x03\x06=\x04\x03\x06;;\x03\x06\x06," + - "\x03\x0b\x18>\x03\x08\x00\x18\x03\x06 \x03\x03\x06<\x00\x03\x09%\x18\x03" + - "\x0b\x1c<\x03\x0a%!\x03\x0a\x09\x12\x03\x0a\x16\x02\x03\x090'\x03\x09" + - "\x0e=\x03\x08 \x0e\x03\x08>\x03\x03\x074>\x03\x06&?\x03\x06\x19\x09\x03" + - "\x06?(\x03\x0a-\x0e\x03\x09:3\x03\x098:\x03\x09\x12\x0b\x03\x09\x1d\x17" + - "\x03\x087\x05\x03\x082\x14\x03\x08\x06%\x03\x08\x13\x1f\x03\x06\x06\x0e" + - "\x03\x0a\x22<\x03\x09/<\x03\x06>+\x03\x0a'?\x03\x0a\x13\x0c\x03\x09\x10<" + - "\x03\x07\x1b=\x03\x0a\x19\x13\x03\x09\x22\x1d\x03\x09\x07\x0d\x03\x08)" + - "\x1c\x03\x06=\x1a\x03\x0a/4\x03\x0a7\x11\x03\x0a\x16:\x03\x09?3\x03\x09:" + - "/\x03\x09\x05\x0a\x03\x09\x14\x06\x03\x087\x22\x03\x080\x07\x03\x08\x1a" + - "\x1f\x03\x07\x04(\x03\x07\x04\x09\x03\x06 %\x03\x06<\x08\x03\x0a+\x14" + - "\x03\x09\x1d\x16\x03\x0a70\x03\x08 >\x03\x0857\x03\x070\x0a\x03\x06=\x12" + - "\x03\x06\x16%\x03\x06\x1d,\x03\x099#\x03\x09\x10>\x03\x07 \x1e\x03\x08" + - "\x0c<\x03\x08\x0b\x18\x03\x08\x15+\x03\x08,:\x03\x08%\x22\x03\x07\x0a$" + - "\x03\x0b\x1c=\x03\x07+\x08\x03\x0a/\x05\x03\x0a \x07\x03\x0a\x12'\x03" + - "\x09#\x11\x03\x08\x1b\x15\x03\x0a\x06\x01\x03\x09\x1c\x1b\x03\x0922\x03" + - "\x07\x14<\x03\x07\x09\x04\x03\x061\x04\x03\x07\x0e\x01\x03\x0a\x13\x18" + - "\x03\x0a-\x0c\x03\x0a?\x0d\x03\x0a\x09\x0a\x03\x091&\x03\x0a/\x0b\x03" + - "\x08$<\x03\x083\x1d\x03\x08\x0c$\x03\x08\x0d\x07\x03\x08\x0d?\x03\x08" + - "\x0e\x14\x03\x065\x0a\x03\x08\x1a#\x03\x08\x16#\x03\x0702\x03\x07\x03" + - "\x1a\x03\x06(\x1d\x03\x06+\x1b\x03\x06\x0b\x05\x03\x06\x0b\x17\x03\x06" + - "\x0c\x04\x03\x06\x1e\x19\x03\x06+0\x03\x062\x18\x03\x0b\x16\x1e\x03\x0a+" + - "\x16\x03\x0a-?\x03\x0a#:\x03\x0a#\x10\x03\x0a%$\x03\x0a>+\x03\x0a01\x03" + - "\x0a1\x10\x03\x0a\x099\x03\x0a\x0a\x12\x03\x0a\x19\x1f\x03\x0a\x19\x12" + - "\x03\x09*)\x03\x09-\x16\x03\x09.1\x03\x09.2\x03\x09<\x0e\x03\x09> \x03" + - "\x093\x12\x03\x09\x0b\x01\x03\x09\x1c2\x03\x09\x11\x1c\x03\x09\x15%\x03" + - "\x08,&\x03\x08!\x22\x03\x089(\x03\x08\x0b\x1a\x03\x08\x0d2\x03\x08\x0c" + - "\x04\x03\x08\x0c\x06\x03\x08\x0c\x1f\x03\x08\x0c\x0c\x03\x08\x0f\x1f\x03" + - "\x08\x0f\x1d\x03\x08\x00\x14\x03\x08\x03\x14\x03\x08\x06\x16\x03\x08\x1e" + - "#\x03\x08\x11\x11\x03\x08\x10\x18\x03\x08\x14(\x03\x07)\x1e\x03\x07.1" + - "\x03\x07 $\x03\x07 '\x03\x078\x08\x03\x07\x0d0\x03\x07\x0f7\x03\x07\x05#" + - "\x03\x07\x05\x1a\x03\x07\x1a7\x03\x07\x1d-\x03\x07\x17\x10\x03\x06)\x1f" + - "\x03\x062\x0b\x03\x066\x16\x03\x06\x09\x11\x03\x09(\x1e\x03\x07!5\x03" + - "\x0b\x11\x16\x03\x0a/\x04\x03\x0a,\x1a\x03\x0b\x173\x03\x0a,1\x03\x0a/5" + - "\x03\x0a\x221\x03\x0a\x22\x0d\x03\x0a?%\x03\x0a<,\x03\x0a?#\x03\x0a>\x19" + - "\x03\x0a\x08&\x03\x0a\x0b\x0e\x03\x0a\x0c:\x03\x0a\x0c+\x03\x0a\x03\x22" + - "\x03\x0a\x06)\x03\x0a\x11\x10\x03\x0a\x11\x1a\x03\x0a\x17-\x03\x0a\x14(" + - "\x03\x09)\x1e\x03\x09/\x09\x03\x09.\x00\x03\x09,\x07\x03\x09/*\x03\x09-9" + - "\x03\x09\x228\x03\x09%\x09\x03\x09:\x12\x03\x09;\x1d\x03\x09?\x06\x03" + - "\x093%\x03\x096\x05\x03\x096\x08\x03\x097\x02\x03\x09\x07,\x03\x09\x04," + - "\x03\x09\x1f\x16\x03\x09\x11\x03\x03\x09\x11\x12\x03\x09\x168\x03\x08*" + - "\x05\x03\x08/2\x03\x084:\x03\x08\x22+\x03\x08 0\x03\x08&\x0a\x03\x08;" + - "\x10\x03\x08>$\x03\x08>\x18\x03\x0829\x03\x082:\x03\x081,\x03\x081<\x03" + - "\x081\x1c\x03\x087#\x03\x087*\x03\x08\x09'\x03\x08\x00\x1d\x03\x08\x05-" + - "\x03\x08\x1f4\x03\x08\x1d\x04\x03\x08\x16\x0f\x03\x07*7\x03\x07'!\x03" + - "\x07%\x1b\x03\x077\x0c\x03\x07\x0c1\x03\x07\x0c.\x03\x07\x00\x06\x03\x07" + - "\x01\x02\x03\x07\x010\x03\x07\x06=\x03\x07\x01\x03\x03\x07\x01\x13\x03" + - "\x07\x06\x06\x03\x07\x05\x0a\x03\x07\x1f\x09\x03\x07\x17:\x03\x06*1\x03" + - "\x06-\x1d\x03\x06\x223\x03\x062:\x03\x060$\x03\x066\x1e\x03\x064\x12\x03" + - "\x0645\x03\x06\x0b\x00\x03\x06\x0b7\x03\x06\x07\x1f\x03\x06\x15\x12\x03" + - "\x0c\x05\x0f\x03\x0b+\x0b\x03\x0b+-\x03\x06\x16\x1b\x03\x06\x15\x17\x03" + - "\x89\xca\xea\x03\x89\xca\xe8\x03\x0c8\x10\x03\x0c8\x01\x03\x0c8\x0f\x03" + - "\x0d8%\x03\x0d8!\x03\x0c8-\x03\x0c8/\x03\x0c8+\x03\x0c87\x03\x0c85\x03" + - "\x0c9\x09\x03\x0c9\x0d\x03\x0c9\x0f\x03\x0c9\x0b\x03\xcfu\x0c\x03\xcfu" + - "\x0f\x03\xcfu\x0e\x03\xcfu\x09\x03\x0c9\x10\x03\x0d9\x0c\x03\xcf`;\x03" + - "\xcf`>\x03\xcf`9\x03\xcf`8\x03\xcf`7\x03\xcf`*\x03\xcf`-\x03\xcf`,\x03" + - "\x0d\x1b\x1a\x03\x0d\x1b&\x03\x0c=.\x03\x0c=%\x03\x0c>\x1e\x03\x0c>\x14" + - "\x03\x0c?\x06\x03\x0c?\x0b\x03\x0c?\x0c\x03\x0c?\x0d\x03\x0c?\x02\x03" + - "\x0c>\x0f\x03\x0c>\x08\x03\x0c>\x09\x03\x0c>,\x03\x0c>\x0c\x03\x0c?\x13" + - "\x03\x0c?\x16\x03\x0c?\x15\x03\x0c?\x1c\x03\x0c?\x1f\x03\x0c?\x1d\x03" + - "\x0c?\x1a\x03\x0c?\x17\x03\x0c?\x08\x03\x0c?\x09\x03\x0c?\x0e\x03\x0c?" + - "\x04\x03\x0c?\x05\x03\x0c" + - "\x03\x0c=2\x03\x0c=6\x03\x0c<\x07\x03\x0c<\x05\x03\x0e:!\x03\x0e:#\x03" + - "\x0e8\x09\x03\x0e:&\x03\x0e8\x0b\x03\x0e:$\x03\x0e:,\x03\x0e8\x1a\x03" + - "\x0e8\x1e\x03\x0e:*\x03\x0e:7\x03\x0e:5\x03\x0e:;\x03\x0e:\x15\x03\x0e:<" + - "\x03\x0e:4\x03\x0e:'\x03\x0e:-\x03\x0e:%\x03\x0e:?\x03\x0e:=\x03\x0e:)" + - "\x03\x0e:/\x03\xcfs'\x03\x0d=\x0f\x03\x0d+*\x03\x0d99\x03\x0d9;\x03\x0d9" + - "?\x03\x0d)\x0d\x03\x0d(%\x02\x01\x18\x02\x01(\x02\x01\x1e\x03\x0f$!\x03" + - "\x0f87\x03\x0f4\x0e\x03\x0f5\x1d\x03\x06'\x03\x03\x0f\x08\x18\x03\x0f" + - "\x0d\x1b\x03\x0e2=\x03\x0e;\x08\x03\x0e:\x0b\x03\x0e\x06$\x03\x0e\x0d)" + - "\x03\x0e\x16\x1f\x03\x0e\x16\x1b\x03\x0d$\x0a\x03\x05,\x1d\x03\x0d. \x03" + - "\x0d.#\x03\x0c(/\x03\x09%\x02\x03\x0d90\x03\x0d\x0e4\x03\x0d\x0d\x0f\x03" + - "\x0c#\x00\x03\x0c,\x1e\x03\x0c2\x0e\x03\x0c\x01\x17\x03\x0c\x09:\x03\x0e" + - "\x173\x03\x0c\x08\x03\x03\x0c\x11\x07\x03\x0c\x10\x18\x03\x0c\x1f\x1c" + - "\x03\x0c\x19\x0e\x03\x0c\x1a\x1f\x03\x0f0>\x03\x0b->\x03\x0b<+\x03\x0b8" + - "\x13\x03\x0b\x043\x03\x0b\x14\x03\x03\x0b\x16%\x03\x0d\x22&\x03\x0b\x1a" + - "\x1a\x03\x0b\x1a\x04\x03\x0a%9\x03\x0a&2\x03\x0a&0\x03\x0a!\x1a\x03\x0a!" + - "7\x03\x0a5\x10\x03\x0a=4\x03\x0a?\x0e\x03\x0a>\x10\x03\x0a\x00 \x03\x0a" + - "\x0f:\x03\x0a\x0f9\x03\x0a\x0b\x0a\x03\x0a\x17%\x03\x0a\x1b-\x03\x09-" + - "\x1a\x03\x09,4\x03\x09.,\x03\x09)\x09\x03\x096!\x03\x091\x1f\x03\x093" + - "\x16\x03\x0c+\x1f\x03\x098 \x03\x098=\x03\x0c(\x1a\x03\x0c(\x16\x03\x09" + - "\x0a+\x03\x09\x16\x12\x03\x09\x13\x0e\x03\x09\x153\x03\x08)!\x03\x09\x1a" + - "\x01\x03\x09\x18\x01\x03\x08%#\x03\x08>\x22\x03\x08\x05%\x03\x08\x02*" + - "\x03\x08\x15;\x03\x08\x1b7\x03\x0f\x07\x1d\x03\x0f\x04\x03\x03\x070\x0c" + - "\x03\x07;\x0b\x03\x07\x08\x17\x03\x07\x12\x06\x03\x06/-\x03\x0671\x03" + - "\x065+\x03\x06>7\x03\x06\x049\x03\x05+\x1e\x03\x05,\x17\x03\x05 \x1d\x03" + - "\x05\x22\x05\x03\x050\x1d" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *idnaTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return idnaValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = idnaIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = idnaIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = idnaIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *idnaTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return idnaValues[c0] - } - i := idnaIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = idnaIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = idnaIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *idnaTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return idnaValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = idnaIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := idnaIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = idnaIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = idnaIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *idnaTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return idnaValues[c0] - } - i := idnaIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = idnaIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = idnaIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// idnaTrie. Total size: 29708 bytes (29.01 KiB). Checksum: c3ecc76d8fffa6e6. -type idnaTrie struct{} - -func newIdnaTrie(i int) *idnaTrie { - return &idnaTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *idnaTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 125: - return uint16(idnaValues[n<<6+uint32(b)]) - default: - n -= 125 - return uint16(idnaSparse.lookup(n, b)) - } -} - -// idnaValues: 127 blocks, 8128 entries, 16256 bytes -// The third block is the zero block. -var idnaValues = [8128]uint16{ - // Block 0x0, offset 0x0 - 0x00: 0x0080, 0x01: 0x0080, 0x02: 0x0080, 0x03: 0x0080, 0x04: 0x0080, 0x05: 0x0080, - 0x06: 0x0080, 0x07: 0x0080, 0x08: 0x0080, 0x09: 0x0080, 0x0a: 0x0080, 0x0b: 0x0080, - 0x0c: 0x0080, 0x0d: 0x0080, 0x0e: 0x0080, 0x0f: 0x0080, 0x10: 0x0080, 0x11: 0x0080, - 0x12: 0x0080, 0x13: 0x0080, 0x14: 0x0080, 0x15: 0x0080, 0x16: 0x0080, 0x17: 0x0080, - 0x18: 0x0080, 0x19: 0x0080, 0x1a: 0x0080, 0x1b: 0x0080, 0x1c: 0x0080, 0x1d: 0x0080, - 0x1e: 0x0080, 0x1f: 0x0080, 0x20: 0x0080, 0x21: 0x0080, 0x22: 0x0080, 0x23: 0x0080, - 0x24: 0x0080, 0x25: 0x0080, 0x26: 0x0080, 0x27: 0x0080, 0x28: 0x0080, 0x29: 0x0080, - 0x2a: 0x0080, 0x2b: 0x0080, 0x2c: 0x0080, 0x2d: 0x0008, 0x2e: 0x0008, 0x2f: 0x0080, - 0x30: 0x0008, 0x31: 0x0008, 0x32: 0x0008, 0x33: 0x0008, 0x34: 0x0008, 0x35: 0x0008, - 0x36: 0x0008, 0x37: 0x0008, 0x38: 0x0008, 0x39: 0x0008, 0x3a: 0x0080, 0x3b: 0x0080, - 0x3c: 0x0080, 0x3d: 0x0080, 0x3e: 0x0080, 0x3f: 0x0080, - // Block 0x1, offset 0x40 - 0x40: 0x0080, 0x41: 0xe105, 0x42: 0xe105, 0x43: 0xe105, 0x44: 0xe105, 0x45: 0xe105, - 0x46: 0xe105, 0x47: 0xe105, 0x48: 0xe105, 0x49: 0xe105, 0x4a: 0xe105, 0x4b: 0xe105, - 0x4c: 0xe105, 0x4d: 0xe105, 0x4e: 0xe105, 0x4f: 0xe105, 0x50: 0xe105, 0x51: 0xe105, - 0x52: 0xe105, 0x53: 0xe105, 0x54: 0xe105, 0x55: 0xe105, 0x56: 0xe105, 0x57: 0xe105, - 0x58: 0xe105, 0x59: 0xe105, 0x5a: 0xe105, 0x5b: 0x0080, 0x5c: 0x0080, 0x5d: 0x0080, - 0x5e: 0x0080, 0x5f: 0x0080, 0x60: 0x0080, 0x61: 0x0008, 0x62: 0x0008, 0x63: 0x0008, - 0x64: 0x0008, 0x65: 0x0008, 0x66: 0x0008, 0x67: 0x0008, 0x68: 0x0008, 0x69: 0x0008, - 0x6a: 0x0008, 0x6b: 0x0008, 0x6c: 0x0008, 0x6d: 0x0008, 0x6e: 0x0008, 0x6f: 0x0008, - 0x70: 0x0008, 0x71: 0x0008, 0x72: 0x0008, 0x73: 0x0008, 0x74: 0x0008, 0x75: 0x0008, - 0x76: 0x0008, 0x77: 0x0008, 0x78: 0x0008, 0x79: 0x0008, 0x7a: 0x0008, 0x7b: 0x0080, - 0x7c: 0x0080, 0x7d: 0x0080, 0x7e: 0x0080, 0x7f: 0x0080, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0040, 0xc1: 0x0040, 0xc2: 0x0040, 0xc3: 0x0040, 0xc4: 0x0040, 0xc5: 0x0040, - 0xc6: 0x0040, 0xc7: 0x0040, 0xc8: 0x0040, 0xc9: 0x0040, 0xca: 0x0040, 0xcb: 0x0040, - 0xcc: 0x0040, 0xcd: 0x0040, 0xce: 0x0040, 0xcf: 0x0040, 0xd0: 0x0040, 0xd1: 0x0040, - 0xd2: 0x0040, 0xd3: 0x0040, 0xd4: 0x0040, 0xd5: 0x0040, 0xd6: 0x0040, 0xd7: 0x0040, - 0xd8: 0x0040, 0xd9: 0x0040, 0xda: 0x0040, 0xdb: 0x0040, 0xdc: 0x0040, 0xdd: 0x0040, - 0xde: 0x0040, 0xdf: 0x0040, 0xe0: 0x000a, 0xe1: 0x0018, 0xe2: 0x0018, 0xe3: 0x0018, - 0xe4: 0x0018, 0xe5: 0x0018, 0xe6: 0x0018, 0xe7: 0x0018, 0xe8: 0x001a, 0xe9: 0x0018, - 0xea: 0x0039, 0xeb: 0x0018, 0xec: 0x0018, 0xed: 0x03c0, 0xee: 0x0018, 0xef: 0x004a, - 0xf0: 0x0018, 0xf1: 0x0018, 0xf2: 0x0069, 0xf3: 0x0079, 0xf4: 0x008a, 0xf5: 0x0005, - 0xf6: 0x0018, 0xf7: 0x0008, 0xf8: 0x00aa, 0xf9: 0x00c9, 0xfa: 0x00d9, 0xfb: 0x0018, - 0xfc: 0x00e9, 0xfd: 0x0119, 0xfe: 0x0149, 0xff: 0x0018, - // Block 0x4, offset 0x100 - 0x100: 0xe00d, 0x101: 0x0008, 0x102: 0xe00d, 0x103: 0x0008, 0x104: 0xe00d, 0x105: 0x0008, - 0x106: 0xe00d, 0x107: 0x0008, 0x108: 0xe00d, 0x109: 0x0008, 0x10a: 0xe00d, 0x10b: 0x0008, - 0x10c: 0xe00d, 0x10d: 0x0008, 0x10e: 0xe00d, 0x10f: 0x0008, 0x110: 0xe00d, 0x111: 0x0008, - 0x112: 0xe00d, 0x113: 0x0008, 0x114: 0xe00d, 0x115: 0x0008, 0x116: 0xe00d, 0x117: 0x0008, - 0x118: 0xe00d, 0x119: 0x0008, 0x11a: 0xe00d, 0x11b: 0x0008, 0x11c: 0xe00d, 0x11d: 0x0008, - 0x11e: 0xe00d, 0x11f: 0x0008, 0x120: 0xe00d, 0x121: 0x0008, 0x122: 0xe00d, 0x123: 0x0008, - 0x124: 0xe00d, 0x125: 0x0008, 0x126: 0xe00d, 0x127: 0x0008, 0x128: 0xe00d, 0x129: 0x0008, - 0x12a: 0xe00d, 0x12b: 0x0008, 0x12c: 0xe00d, 0x12d: 0x0008, 0x12e: 0xe00d, 0x12f: 0x0008, - 0x130: 0x0179, 0x131: 0x0008, 0x132: 0x0035, 0x133: 0x004d, 0x134: 0xe00d, 0x135: 0x0008, - 0x136: 0xe00d, 0x137: 0x0008, 0x138: 0x0008, 0x139: 0xe01d, 0x13a: 0x0008, 0x13b: 0xe03d, - 0x13c: 0x0008, 0x13d: 0xe01d, 0x13e: 0x0008, 0x13f: 0x0199, - // Block 0x5, offset 0x140 - 0x140: 0x0199, 0x141: 0xe01d, 0x142: 0x0008, 0x143: 0xe03d, 0x144: 0x0008, 0x145: 0xe01d, - 0x146: 0x0008, 0x147: 0xe07d, 0x148: 0x0008, 0x149: 0x01b9, 0x14a: 0xe00d, 0x14b: 0x0008, - 0x14c: 0xe00d, 0x14d: 0x0008, 0x14e: 0xe00d, 0x14f: 0x0008, 0x150: 0xe00d, 0x151: 0x0008, - 0x152: 0xe00d, 0x153: 0x0008, 0x154: 0xe00d, 0x155: 0x0008, 0x156: 0xe00d, 0x157: 0x0008, - 0x158: 0xe00d, 0x159: 0x0008, 0x15a: 0xe00d, 0x15b: 0x0008, 0x15c: 0xe00d, 0x15d: 0x0008, - 0x15e: 0xe00d, 0x15f: 0x0008, 0x160: 0xe00d, 0x161: 0x0008, 0x162: 0xe00d, 0x163: 0x0008, - 0x164: 0xe00d, 0x165: 0x0008, 0x166: 0xe00d, 0x167: 0x0008, 0x168: 0xe00d, 0x169: 0x0008, - 0x16a: 0xe00d, 0x16b: 0x0008, 0x16c: 0xe00d, 0x16d: 0x0008, 0x16e: 0xe00d, 0x16f: 0x0008, - 0x170: 0xe00d, 0x171: 0x0008, 0x172: 0xe00d, 0x173: 0x0008, 0x174: 0xe00d, 0x175: 0x0008, - 0x176: 0xe00d, 0x177: 0x0008, 0x178: 0x0065, 0x179: 0xe01d, 0x17a: 0x0008, 0x17b: 0xe03d, - 0x17c: 0x0008, 0x17d: 0xe01d, 0x17e: 0x0008, 0x17f: 0x01d9, - // Block 0x6, offset 0x180 - 0x180: 0x0008, 0x181: 0x007d, 0x182: 0xe00d, 0x183: 0x0008, 0x184: 0xe00d, 0x185: 0x0008, - 0x186: 0x007d, 0x187: 0xe07d, 0x188: 0x0008, 0x189: 0x0095, 0x18a: 0x00ad, 0x18b: 0xe03d, - 0x18c: 0x0008, 0x18d: 0x0008, 0x18e: 0x00c5, 0x18f: 0x00dd, 0x190: 0x00f5, 0x191: 0xe01d, - 0x192: 0x0008, 0x193: 0x010d, 0x194: 0x0125, 0x195: 0x0008, 0x196: 0x013d, 0x197: 0x013d, - 0x198: 0xe00d, 0x199: 0x0008, 0x19a: 0x0008, 0x19b: 0x0008, 0x19c: 0x010d, 0x19d: 0x0155, - 0x19e: 0x0008, 0x19f: 0x016d, 0x1a0: 0xe00d, 0x1a1: 0x0008, 0x1a2: 0xe00d, 0x1a3: 0x0008, - 0x1a4: 0xe00d, 0x1a5: 0x0008, 0x1a6: 0x0185, 0x1a7: 0xe07d, 0x1a8: 0x0008, 0x1a9: 0x019d, - 0x1aa: 0x0008, 0x1ab: 0x0008, 0x1ac: 0xe00d, 0x1ad: 0x0008, 0x1ae: 0x0185, 0x1af: 0xe0fd, - 0x1b0: 0x0008, 0x1b1: 0x01b5, 0x1b2: 0x01cd, 0x1b3: 0xe03d, 0x1b4: 0x0008, 0x1b5: 0xe01d, - 0x1b6: 0x0008, 0x1b7: 0x01e5, 0x1b8: 0xe00d, 0x1b9: 0x0008, 0x1ba: 0x0008, 0x1bb: 0x0008, - 0x1bc: 0xe00d, 0x1bd: 0x0008, 0x1be: 0x0008, 0x1bf: 0x0008, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0008, 0x1c1: 0x0008, 0x1c2: 0x0008, 0x1c3: 0x0008, 0x1c4: 0x01e9, 0x1c5: 0x01e9, - 0x1c6: 0x01e9, 0x1c7: 0x01fd, 0x1c8: 0x0215, 0x1c9: 0x022d, 0x1ca: 0x0245, 0x1cb: 0x025d, - 0x1cc: 0x0275, 0x1cd: 0xe01d, 0x1ce: 0x0008, 0x1cf: 0xe0fd, 0x1d0: 0x0008, 0x1d1: 0xe01d, - 0x1d2: 0x0008, 0x1d3: 0xe03d, 0x1d4: 0x0008, 0x1d5: 0xe01d, 0x1d6: 0x0008, 0x1d7: 0xe07d, - 0x1d8: 0x0008, 0x1d9: 0xe01d, 0x1da: 0x0008, 0x1db: 0xe03d, 0x1dc: 0x0008, 0x1dd: 0x0008, - 0x1de: 0xe00d, 0x1df: 0x0008, 0x1e0: 0xe00d, 0x1e1: 0x0008, 0x1e2: 0xe00d, 0x1e3: 0x0008, - 0x1e4: 0xe00d, 0x1e5: 0x0008, 0x1e6: 0xe00d, 0x1e7: 0x0008, 0x1e8: 0xe00d, 0x1e9: 0x0008, - 0x1ea: 0xe00d, 0x1eb: 0x0008, 0x1ec: 0xe00d, 0x1ed: 0x0008, 0x1ee: 0xe00d, 0x1ef: 0x0008, - 0x1f0: 0x0008, 0x1f1: 0x028d, 0x1f2: 0x02a5, 0x1f3: 0x02bd, 0x1f4: 0xe00d, 0x1f5: 0x0008, - 0x1f6: 0x02d5, 0x1f7: 0x02ed, 0x1f8: 0xe00d, 0x1f9: 0x0008, 0x1fa: 0xe00d, 0x1fb: 0x0008, - 0x1fc: 0xe00d, 0x1fd: 0x0008, 0x1fe: 0xe00d, 0x1ff: 0x0008, - // Block 0x8, offset 0x200 - 0x200: 0xe00d, 0x201: 0x0008, 0x202: 0xe00d, 0x203: 0x0008, 0x204: 0xe00d, 0x205: 0x0008, - 0x206: 0xe00d, 0x207: 0x0008, 0x208: 0xe00d, 0x209: 0x0008, 0x20a: 0xe00d, 0x20b: 0x0008, - 0x20c: 0xe00d, 0x20d: 0x0008, 0x20e: 0xe00d, 0x20f: 0x0008, 0x210: 0xe00d, 0x211: 0x0008, - 0x212: 0xe00d, 0x213: 0x0008, 0x214: 0xe00d, 0x215: 0x0008, 0x216: 0xe00d, 0x217: 0x0008, - 0x218: 0xe00d, 0x219: 0x0008, 0x21a: 0xe00d, 0x21b: 0x0008, 0x21c: 0xe00d, 0x21d: 0x0008, - 0x21e: 0xe00d, 0x21f: 0x0008, 0x220: 0x0305, 0x221: 0x0008, 0x222: 0xe00d, 0x223: 0x0008, - 0x224: 0xe00d, 0x225: 0x0008, 0x226: 0xe00d, 0x227: 0x0008, 0x228: 0xe00d, 0x229: 0x0008, - 0x22a: 0xe00d, 0x22b: 0x0008, 0x22c: 0xe00d, 0x22d: 0x0008, 0x22e: 0xe00d, 0x22f: 0x0008, - 0x230: 0xe00d, 0x231: 0x0008, 0x232: 0xe00d, 0x233: 0x0008, 0x234: 0x0008, 0x235: 0x0008, - 0x236: 0x0008, 0x237: 0x0008, 0x238: 0x0008, 0x239: 0x0008, 0x23a: 0x0209, 0x23b: 0xe03d, - 0x23c: 0x0008, 0x23d: 0x031d, 0x23e: 0x0229, 0x23f: 0x0008, - // Block 0x9, offset 0x240 - 0x240: 0x0008, 0x241: 0x0008, 0x242: 0x0018, 0x243: 0x0018, 0x244: 0x0018, 0x245: 0x0018, - 0x246: 0x0008, 0x247: 0x0008, 0x248: 0x0008, 0x249: 0x0008, 0x24a: 0x0008, 0x24b: 0x0008, - 0x24c: 0x0008, 0x24d: 0x0008, 0x24e: 0x0008, 0x24f: 0x0008, 0x250: 0x0008, 0x251: 0x0008, - 0x252: 0x0018, 0x253: 0x0018, 0x254: 0x0018, 0x255: 0x0018, 0x256: 0x0018, 0x257: 0x0018, - 0x258: 0x029a, 0x259: 0x02ba, 0x25a: 0x02da, 0x25b: 0x02fa, 0x25c: 0x031a, 0x25d: 0x033a, - 0x25e: 0x0018, 0x25f: 0x0018, 0x260: 0x03ad, 0x261: 0x0359, 0x262: 0x01d9, 0x263: 0x0369, - 0x264: 0x03c5, 0x265: 0x0018, 0x266: 0x0018, 0x267: 0x0018, 0x268: 0x0018, 0x269: 0x0018, - 0x26a: 0x0018, 0x26b: 0x0018, 0x26c: 0x0008, 0x26d: 0x0018, 0x26e: 0x0008, 0x26f: 0x0018, - 0x270: 0x0018, 0x271: 0x0018, 0x272: 0x0018, 0x273: 0x0018, 0x274: 0x0018, 0x275: 0x0018, - 0x276: 0x0018, 0x277: 0x0018, 0x278: 0x0018, 0x279: 0x0018, 0x27a: 0x0018, 0x27b: 0x0018, - 0x27c: 0x0018, 0x27d: 0x0018, 0x27e: 0x0018, 0x27f: 0x0018, - // Block 0xa, offset 0x280 - 0x280: 0x03dd, 0x281: 0x03dd, 0x282: 0x3308, 0x283: 0x03f5, 0x284: 0x0379, 0x285: 0x040d, - 0x286: 0x3308, 0x287: 0x3308, 0x288: 0x3308, 0x289: 0x3308, 0x28a: 0x3308, 0x28b: 0x3308, - 0x28c: 0x3308, 0x28d: 0x3308, 0x28e: 0x3308, 0x28f: 0x33c0, 0x290: 0x3308, 0x291: 0x3308, - 0x292: 0x3308, 0x293: 0x3308, 0x294: 0x3308, 0x295: 0x3308, 0x296: 0x3308, 0x297: 0x3308, - 0x298: 0x3308, 0x299: 0x3308, 0x29a: 0x3308, 0x29b: 0x3308, 0x29c: 0x3308, 0x29d: 0x3308, - 0x29e: 0x3308, 0x29f: 0x3308, 0x2a0: 0x3308, 0x2a1: 0x3308, 0x2a2: 0x3308, 0x2a3: 0x3308, - 0x2a4: 0x3308, 0x2a5: 0x3308, 0x2a6: 0x3308, 0x2a7: 0x3308, 0x2a8: 0x3308, 0x2a9: 0x3308, - 0x2aa: 0x3308, 0x2ab: 0x3308, 0x2ac: 0x3308, 0x2ad: 0x3308, 0x2ae: 0x3308, 0x2af: 0x3308, - 0x2b0: 0xe00d, 0x2b1: 0x0008, 0x2b2: 0xe00d, 0x2b3: 0x0008, 0x2b4: 0x0425, 0x2b5: 0x0008, - 0x2b6: 0xe00d, 0x2b7: 0x0008, 0x2b8: 0x0040, 0x2b9: 0x0040, 0x2ba: 0x03a2, 0x2bb: 0x0008, - 0x2bc: 0x0008, 0x2bd: 0x0008, 0x2be: 0x03c2, 0x2bf: 0x043d, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x0040, 0x2c1: 0x0040, 0x2c2: 0x0040, 0x2c3: 0x0040, 0x2c4: 0x008a, 0x2c5: 0x03d2, - 0x2c6: 0xe155, 0x2c7: 0x0455, 0x2c8: 0xe12d, 0x2c9: 0xe13d, 0x2ca: 0xe12d, 0x2cb: 0x0040, - 0x2cc: 0x03dd, 0x2cd: 0x0040, 0x2ce: 0x046d, 0x2cf: 0x0485, 0x2d0: 0x0008, 0x2d1: 0xe105, - 0x2d2: 0xe105, 0x2d3: 0xe105, 0x2d4: 0xe105, 0x2d5: 0xe105, 0x2d6: 0xe105, 0x2d7: 0xe105, - 0x2d8: 0xe105, 0x2d9: 0xe105, 0x2da: 0xe105, 0x2db: 0xe105, 0x2dc: 0xe105, 0x2dd: 0xe105, - 0x2de: 0xe105, 0x2df: 0xe105, 0x2e0: 0x049d, 0x2e1: 0x049d, 0x2e2: 0x0040, 0x2e3: 0x049d, - 0x2e4: 0x049d, 0x2e5: 0x049d, 0x2e6: 0x049d, 0x2e7: 0x049d, 0x2e8: 0x049d, 0x2e9: 0x049d, - 0x2ea: 0x049d, 0x2eb: 0x049d, 0x2ec: 0x0008, 0x2ed: 0x0008, 0x2ee: 0x0008, 0x2ef: 0x0008, - 0x2f0: 0x0008, 0x2f1: 0x0008, 0x2f2: 0x0008, 0x2f3: 0x0008, 0x2f4: 0x0008, 0x2f5: 0x0008, - 0x2f6: 0x0008, 0x2f7: 0x0008, 0x2f8: 0x0008, 0x2f9: 0x0008, 0x2fa: 0x0008, 0x2fb: 0x0008, - 0x2fc: 0x0008, 0x2fd: 0x0008, 0x2fe: 0x0008, 0x2ff: 0x0008, - // Block 0xc, offset 0x300 - 0x300: 0x0008, 0x301: 0x0008, 0x302: 0xe00f, 0x303: 0x0008, 0x304: 0x0008, 0x305: 0x0008, - 0x306: 0x0008, 0x307: 0x0008, 0x308: 0x0008, 0x309: 0x0008, 0x30a: 0x0008, 0x30b: 0x0008, - 0x30c: 0x0008, 0x30d: 0x0008, 0x30e: 0x0008, 0x30f: 0xe0c5, 0x310: 0x04b5, 0x311: 0x04cd, - 0x312: 0xe0bd, 0x313: 0xe0f5, 0x314: 0xe0fd, 0x315: 0xe09d, 0x316: 0xe0b5, 0x317: 0x0008, - 0x318: 0xe00d, 0x319: 0x0008, 0x31a: 0xe00d, 0x31b: 0x0008, 0x31c: 0xe00d, 0x31d: 0x0008, - 0x31e: 0xe00d, 0x31f: 0x0008, 0x320: 0xe00d, 0x321: 0x0008, 0x322: 0xe00d, 0x323: 0x0008, - 0x324: 0xe00d, 0x325: 0x0008, 0x326: 0xe00d, 0x327: 0x0008, 0x328: 0xe00d, 0x329: 0x0008, - 0x32a: 0xe00d, 0x32b: 0x0008, 0x32c: 0xe00d, 0x32d: 0x0008, 0x32e: 0xe00d, 0x32f: 0x0008, - 0x330: 0x04e5, 0x331: 0xe185, 0x332: 0xe18d, 0x333: 0x0008, 0x334: 0x04fd, 0x335: 0x03dd, - 0x336: 0x0018, 0x337: 0xe07d, 0x338: 0x0008, 0x339: 0xe1d5, 0x33a: 0xe00d, 0x33b: 0x0008, - 0x33c: 0x0008, 0x33d: 0x0515, 0x33e: 0x052d, 0x33f: 0x052d, - // Block 0xd, offset 0x340 - 0x340: 0x0008, 0x341: 0x0008, 0x342: 0x0008, 0x343: 0x0008, 0x344: 0x0008, 0x345: 0x0008, - 0x346: 0x0008, 0x347: 0x0008, 0x348: 0x0008, 0x349: 0x0008, 0x34a: 0x0008, 0x34b: 0x0008, - 0x34c: 0x0008, 0x34d: 0x0008, 0x34e: 0x0008, 0x34f: 0x0008, 0x350: 0x0008, 0x351: 0x0008, - 0x352: 0x0008, 0x353: 0x0008, 0x354: 0x0008, 0x355: 0x0008, 0x356: 0x0008, 0x357: 0x0008, - 0x358: 0x0008, 0x359: 0x0008, 0x35a: 0x0008, 0x35b: 0x0008, 0x35c: 0x0008, 0x35d: 0x0008, - 0x35e: 0x0008, 0x35f: 0x0008, 0x360: 0xe00d, 0x361: 0x0008, 0x362: 0xe00d, 0x363: 0x0008, - 0x364: 0xe00d, 0x365: 0x0008, 0x366: 0xe00d, 0x367: 0x0008, 0x368: 0xe00d, 0x369: 0x0008, - 0x36a: 0xe00d, 0x36b: 0x0008, 0x36c: 0xe00d, 0x36d: 0x0008, 0x36e: 0xe00d, 0x36f: 0x0008, - 0x370: 0xe00d, 0x371: 0x0008, 0x372: 0xe00d, 0x373: 0x0008, 0x374: 0xe00d, 0x375: 0x0008, - 0x376: 0xe00d, 0x377: 0x0008, 0x378: 0xe00d, 0x379: 0x0008, 0x37a: 0xe00d, 0x37b: 0x0008, - 0x37c: 0xe00d, 0x37d: 0x0008, 0x37e: 0xe00d, 0x37f: 0x0008, - // Block 0xe, offset 0x380 - 0x380: 0xe00d, 0x381: 0x0008, 0x382: 0x0018, 0x383: 0x3308, 0x384: 0x3308, 0x385: 0x3308, - 0x386: 0x3308, 0x387: 0x3308, 0x388: 0x3318, 0x389: 0x3318, 0x38a: 0xe00d, 0x38b: 0x0008, - 0x38c: 0xe00d, 0x38d: 0x0008, 0x38e: 0xe00d, 0x38f: 0x0008, 0x390: 0xe00d, 0x391: 0x0008, - 0x392: 0xe00d, 0x393: 0x0008, 0x394: 0xe00d, 0x395: 0x0008, 0x396: 0xe00d, 0x397: 0x0008, - 0x398: 0xe00d, 0x399: 0x0008, 0x39a: 0xe00d, 0x39b: 0x0008, 0x39c: 0xe00d, 0x39d: 0x0008, - 0x39e: 0xe00d, 0x39f: 0x0008, 0x3a0: 0xe00d, 0x3a1: 0x0008, 0x3a2: 0xe00d, 0x3a3: 0x0008, - 0x3a4: 0xe00d, 0x3a5: 0x0008, 0x3a6: 0xe00d, 0x3a7: 0x0008, 0x3a8: 0xe00d, 0x3a9: 0x0008, - 0x3aa: 0xe00d, 0x3ab: 0x0008, 0x3ac: 0xe00d, 0x3ad: 0x0008, 0x3ae: 0xe00d, 0x3af: 0x0008, - 0x3b0: 0xe00d, 0x3b1: 0x0008, 0x3b2: 0xe00d, 0x3b3: 0x0008, 0x3b4: 0xe00d, 0x3b5: 0x0008, - 0x3b6: 0xe00d, 0x3b7: 0x0008, 0x3b8: 0xe00d, 0x3b9: 0x0008, 0x3ba: 0xe00d, 0x3bb: 0x0008, - 0x3bc: 0xe00d, 0x3bd: 0x0008, 0x3be: 0xe00d, 0x3bf: 0x0008, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x0040, 0x3c1: 0xe01d, 0x3c2: 0x0008, 0x3c3: 0xe03d, 0x3c4: 0x0008, 0x3c5: 0xe01d, - 0x3c6: 0x0008, 0x3c7: 0xe07d, 0x3c8: 0x0008, 0x3c9: 0xe01d, 0x3ca: 0x0008, 0x3cb: 0xe03d, - 0x3cc: 0x0008, 0x3cd: 0xe01d, 0x3ce: 0x0008, 0x3cf: 0x0008, 0x3d0: 0xe00d, 0x3d1: 0x0008, - 0x3d2: 0xe00d, 0x3d3: 0x0008, 0x3d4: 0xe00d, 0x3d5: 0x0008, 0x3d6: 0xe00d, 0x3d7: 0x0008, - 0x3d8: 0xe00d, 0x3d9: 0x0008, 0x3da: 0xe00d, 0x3db: 0x0008, 0x3dc: 0xe00d, 0x3dd: 0x0008, - 0x3de: 0xe00d, 0x3df: 0x0008, 0x3e0: 0xe00d, 0x3e1: 0x0008, 0x3e2: 0xe00d, 0x3e3: 0x0008, - 0x3e4: 0xe00d, 0x3e5: 0x0008, 0x3e6: 0xe00d, 0x3e7: 0x0008, 0x3e8: 0xe00d, 0x3e9: 0x0008, - 0x3ea: 0xe00d, 0x3eb: 0x0008, 0x3ec: 0xe00d, 0x3ed: 0x0008, 0x3ee: 0xe00d, 0x3ef: 0x0008, - 0x3f0: 0xe00d, 0x3f1: 0x0008, 0x3f2: 0xe00d, 0x3f3: 0x0008, 0x3f4: 0xe00d, 0x3f5: 0x0008, - 0x3f6: 0xe00d, 0x3f7: 0x0008, 0x3f8: 0xe00d, 0x3f9: 0x0008, 0x3fa: 0xe00d, 0x3fb: 0x0008, - 0x3fc: 0xe00d, 0x3fd: 0x0008, 0x3fe: 0xe00d, 0x3ff: 0x0008, - // Block 0x10, offset 0x400 - 0x400: 0xe00d, 0x401: 0x0008, 0x402: 0xe00d, 0x403: 0x0008, 0x404: 0xe00d, 0x405: 0x0008, - 0x406: 0xe00d, 0x407: 0x0008, 0x408: 0xe00d, 0x409: 0x0008, 0x40a: 0xe00d, 0x40b: 0x0008, - 0x40c: 0xe00d, 0x40d: 0x0008, 0x40e: 0xe00d, 0x40f: 0x0008, 0x410: 0xe00d, 0x411: 0x0008, - 0x412: 0xe00d, 0x413: 0x0008, 0x414: 0xe00d, 0x415: 0x0008, 0x416: 0xe00d, 0x417: 0x0008, - 0x418: 0xe00d, 0x419: 0x0008, 0x41a: 0xe00d, 0x41b: 0x0008, 0x41c: 0xe00d, 0x41d: 0x0008, - 0x41e: 0xe00d, 0x41f: 0x0008, 0x420: 0xe00d, 0x421: 0x0008, 0x422: 0xe00d, 0x423: 0x0008, - 0x424: 0xe00d, 0x425: 0x0008, 0x426: 0xe00d, 0x427: 0x0008, 0x428: 0xe00d, 0x429: 0x0008, - 0x42a: 0xe00d, 0x42b: 0x0008, 0x42c: 0xe00d, 0x42d: 0x0008, 0x42e: 0xe00d, 0x42f: 0x0008, - 0x430: 0x0040, 0x431: 0x03f5, 0x432: 0x03f5, 0x433: 0x03f5, 0x434: 0x03f5, 0x435: 0x03f5, - 0x436: 0x03f5, 0x437: 0x03f5, 0x438: 0x03f5, 0x439: 0x03f5, 0x43a: 0x03f5, 0x43b: 0x03f5, - 0x43c: 0x03f5, 0x43d: 0x03f5, 0x43e: 0x03f5, 0x43f: 0x03f5, - // Block 0x11, offset 0x440 - 0x440: 0x0840, 0x441: 0x0840, 0x442: 0x0840, 0x443: 0x0840, 0x444: 0x0840, 0x445: 0x0840, - 0x446: 0x0018, 0x447: 0x0018, 0x448: 0x0818, 0x449: 0x0018, 0x44a: 0x0018, 0x44b: 0x0818, - 0x44c: 0x0018, 0x44d: 0x0818, 0x44e: 0x0018, 0x44f: 0x0018, 0x450: 0x3308, 0x451: 0x3308, - 0x452: 0x3308, 0x453: 0x3308, 0x454: 0x3308, 0x455: 0x3308, 0x456: 0x3308, 0x457: 0x3308, - 0x458: 0x3308, 0x459: 0x3308, 0x45a: 0x3308, 0x45b: 0x0818, 0x45c: 0x0b40, 0x45d: 0x0040, - 0x45e: 0x0818, 0x45f: 0x0818, 0x460: 0x0a08, 0x461: 0x0808, 0x462: 0x0c08, 0x463: 0x0c08, - 0x464: 0x0c08, 0x465: 0x0c08, 0x466: 0x0a08, 0x467: 0x0c08, 0x468: 0x0a08, 0x469: 0x0c08, - 0x46a: 0x0a08, 0x46b: 0x0a08, 0x46c: 0x0a08, 0x46d: 0x0a08, 0x46e: 0x0a08, 0x46f: 0x0c08, - 0x470: 0x0c08, 0x471: 0x0c08, 0x472: 0x0c08, 0x473: 0x0a08, 0x474: 0x0a08, 0x475: 0x0a08, - 0x476: 0x0a08, 0x477: 0x0a08, 0x478: 0x0a08, 0x479: 0x0a08, 0x47a: 0x0a08, 0x47b: 0x0a08, - 0x47c: 0x0a08, 0x47d: 0x0a08, 0x47e: 0x0a08, 0x47f: 0x0a08, - // Block 0x12, offset 0x480 - 0x480: 0x0818, 0x481: 0x0a08, 0x482: 0x0a08, 0x483: 0x0a08, 0x484: 0x0a08, 0x485: 0x0a08, - 0x486: 0x0a08, 0x487: 0x0a08, 0x488: 0x0c08, 0x489: 0x0a08, 0x48a: 0x0a08, 0x48b: 0x3308, - 0x48c: 0x3308, 0x48d: 0x3308, 0x48e: 0x3308, 0x48f: 0x3308, 0x490: 0x3308, 0x491: 0x3308, - 0x492: 0x3308, 0x493: 0x3308, 0x494: 0x3308, 0x495: 0x3308, 0x496: 0x3308, 0x497: 0x3308, - 0x498: 0x3308, 0x499: 0x3308, 0x49a: 0x3308, 0x49b: 0x3308, 0x49c: 0x3308, 0x49d: 0x3308, - 0x49e: 0x3308, 0x49f: 0x3308, 0x4a0: 0x0808, 0x4a1: 0x0808, 0x4a2: 0x0808, 0x4a3: 0x0808, - 0x4a4: 0x0808, 0x4a5: 0x0808, 0x4a6: 0x0808, 0x4a7: 0x0808, 0x4a8: 0x0808, 0x4a9: 0x0808, - 0x4aa: 0x0018, 0x4ab: 0x0818, 0x4ac: 0x0818, 0x4ad: 0x0818, 0x4ae: 0x0a08, 0x4af: 0x0a08, - 0x4b0: 0x3308, 0x4b1: 0x0c08, 0x4b2: 0x0c08, 0x4b3: 0x0c08, 0x4b4: 0x0808, 0x4b5: 0x0429, - 0x4b6: 0x0451, 0x4b7: 0x0479, 0x4b8: 0x04a1, 0x4b9: 0x0a08, 0x4ba: 0x0a08, 0x4bb: 0x0a08, - 0x4bc: 0x0a08, 0x4bd: 0x0a08, 0x4be: 0x0a08, 0x4bf: 0x0a08, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x0c08, 0x4c1: 0x0a08, 0x4c2: 0x0a08, 0x4c3: 0x0c08, 0x4c4: 0x0c08, 0x4c5: 0x0c08, - 0x4c6: 0x0c08, 0x4c7: 0x0c08, 0x4c8: 0x0c08, 0x4c9: 0x0c08, 0x4ca: 0x0c08, 0x4cb: 0x0c08, - 0x4cc: 0x0a08, 0x4cd: 0x0c08, 0x4ce: 0x0a08, 0x4cf: 0x0c08, 0x4d0: 0x0a08, 0x4d1: 0x0a08, - 0x4d2: 0x0c08, 0x4d3: 0x0c08, 0x4d4: 0x0818, 0x4d5: 0x0c08, 0x4d6: 0x3308, 0x4d7: 0x3308, - 0x4d8: 0x3308, 0x4d9: 0x3308, 0x4da: 0x3308, 0x4db: 0x3308, 0x4dc: 0x3308, 0x4dd: 0x0840, - 0x4de: 0x0018, 0x4df: 0x3308, 0x4e0: 0x3308, 0x4e1: 0x3308, 0x4e2: 0x3308, 0x4e3: 0x3308, - 0x4e4: 0x3308, 0x4e5: 0x0808, 0x4e6: 0x0808, 0x4e7: 0x3308, 0x4e8: 0x3308, 0x4e9: 0x0018, - 0x4ea: 0x3308, 0x4eb: 0x3308, 0x4ec: 0x3308, 0x4ed: 0x3308, 0x4ee: 0x0c08, 0x4ef: 0x0c08, - 0x4f0: 0x0008, 0x4f1: 0x0008, 0x4f2: 0x0008, 0x4f3: 0x0008, 0x4f4: 0x0008, 0x4f5: 0x0008, - 0x4f6: 0x0008, 0x4f7: 0x0008, 0x4f8: 0x0008, 0x4f9: 0x0008, 0x4fa: 0x0a08, 0x4fb: 0x0a08, - 0x4fc: 0x0a08, 0x4fd: 0x0808, 0x4fe: 0x0808, 0x4ff: 0x0a08, - // Block 0x14, offset 0x500 - 0x500: 0x0818, 0x501: 0x0818, 0x502: 0x0818, 0x503: 0x0818, 0x504: 0x0818, 0x505: 0x0818, - 0x506: 0x0818, 0x507: 0x0818, 0x508: 0x0818, 0x509: 0x0818, 0x50a: 0x0818, 0x50b: 0x0818, - 0x50c: 0x0818, 0x50d: 0x0818, 0x50e: 0x0040, 0x50f: 0x0b40, 0x510: 0x0c08, 0x511: 0x3308, - 0x512: 0x0a08, 0x513: 0x0a08, 0x514: 0x0a08, 0x515: 0x0c08, 0x516: 0x0c08, 0x517: 0x0c08, - 0x518: 0x0c08, 0x519: 0x0c08, 0x51a: 0x0a08, 0x51b: 0x0a08, 0x51c: 0x0a08, 0x51d: 0x0a08, - 0x51e: 0x0c08, 0x51f: 0x0a08, 0x520: 0x0a08, 0x521: 0x0a08, 0x522: 0x0a08, 0x523: 0x0a08, - 0x524: 0x0a08, 0x525: 0x0a08, 0x526: 0x0a08, 0x527: 0x0a08, 0x528: 0x0c08, 0x529: 0x0a08, - 0x52a: 0x0c08, 0x52b: 0x0a08, 0x52c: 0x0c08, 0x52d: 0x0a08, 0x52e: 0x0a08, 0x52f: 0x0c08, - 0x530: 0x3308, 0x531: 0x3308, 0x532: 0x3308, 0x533: 0x3308, 0x534: 0x3308, 0x535: 0x3308, - 0x536: 0x3308, 0x537: 0x3308, 0x538: 0x3308, 0x539: 0x3308, 0x53a: 0x3308, 0x53b: 0x3308, - 0x53c: 0x3308, 0x53d: 0x3308, 0x53e: 0x3308, 0x53f: 0x3308, - // Block 0x15, offset 0x540 - 0x540: 0x0c08, 0x541: 0x0a08, 0x542: 0x0a08, 0x543: 0x0a08, 0x544: 0x0a08, 0x545: 0x0a08, - 0x546: 0x0c08, 0x547: 0x0c08, 0x548: 0x0a08, 0x549: 0x0c08, 0x54a: 0x0a08, 0x54b: 0x0a08, - 0x54c: 0x0a08, 0x54d: 0x0a08, 0x54e: 0x0a08, 0x54f: 0x0a08, 0x550: 0x0a08, 0x551: 0x0a08, - 0x552: 0x0a08, 0x553: 0x0a08, 0x554: 0x0c08, 0x555: 0x0a08, 0x556: 0x0808, 0x557: 0x0808, - 0x558: 0x0808, 0x559: 0x3308, 0x55a: 0x3308, 0x55b: 0x3308, 0x55c: 0x0040, 0x55d: 0x0040, - 0x55e: 0x0818, 0x55f: 0x0040, 0x560: 0x0a08, 0x561: 0x0808, 0x562: 0x0a08, 0x563: 0x0a08, - 0x564: 0x0a08, 0x565: 0x0a08, 0x566: 0x0808, 0x567: 0x0c08, 0x568: 0x0a08, 0x569: 0x0c08, - 0x56a: 0x0c08, 0x56b: 0x0040, 0x56c: 0x0040, 0x56d: 0x0040, 0x56e: 0x0040, 0x56f: 0x0040, - 0x570: 0x0040, 0x571: 0x0040, 0x572: 0x0040, 0x573: 0x0040, 0x574: 0x0040, 0x575: 0x0040, - 0x576: 0x0040, 0x577: 0x0040, 0x578: 0x0040, 0x579: 0x0040, 0x57a: 0x0040, 0x57b: 0x0040, - 0x57c: 0x0040, 0x57d: 0x0040, 0x57e: 0x0040, 0x57f: 0x0040, - // Block 0x16, offset 0x580 - 0x580: 0x3008, 0x581: 0x3308, 0x582: 0x3308, 0x583: 0x3308, 0x584: 0x3308, 0x585: 0x3308, - 0x586: 0x3308, 0x587: 0x3308, 0x588: 0x3308, 0x589: 0x3008, 0x58a: 0x3008, 0x58b: 0x3008, - 0x58c: 0x3008, 0x58d: 0x3b08, 0x58e: 0x3008, 0x58f: 0x3008, 0x590: 0x0008, 0x591: 0x3308, - 0x592: 0x3308, 0x593: 0x3308, 0x594: 0x3308, 0x595: 0x3308, 0x596: 0x3308, 0x597: 0x3308, - 0x598: 0x04c9, 0x599: 0x0501, 0x59a: 0x0539, 0x59b: 0x0571, 0x59c: 0x05a9, 0x59d: 0x05e1, - 0x59e: 0x0619, 0x59f: 0x0651, 0x5a0: 0x0008, 0x5a1: 0x0008, 0x5a2: 0x3308, 0x5a3: 0x3308, - 0x5a4: 0x0018, 0x5a5: 0x0018, 0x5a6: 0x0008, 0x5a7: 0x0008, 0x5a8: 0x0008, 0x5a9: 0x0008, - 0x5aa: 0x0008, 0x5ab: 0x0008, 0x5ac: 0x0008, 0x5ad: 0x0008, 0x5ae: 0x0008, 0x5af: 0x0008, - 0x5b0: 0x0018, 0x5b1: 0x0008, 0x5b2: 0x0008, 0x5b3: 0x0008, 0x5b4: 0x0008, 0x5b5: 0x0008, - 0x5b6: 0x0008, 0x5b7: 0x0008, 0x5b8: 0x0008, 0x5b9: 0x0008, 0x5ba: 0x0008, 0x5bb: 0x0008, - 0x5bc: 0x0008, 0x5bd: 0x0008, 0x5be: 0x0008, 0x5bf: 0x0008, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x0008, 0x5c1: 0x3308, 0x5c2: 0x3008, 0x5c3: 0x3008, 0x5c4: 0x0040, 0x5c5: 0x0008, - 0x5c6: 0x0008, 0x5c7: 0x0008, 0x5c8: 0x0008, 0x5c9: 0x0008, 0x5ca: 0x0008, 0x5cb: 0x0008, - 0x5cc: 0x0008, 0x5cd: 0x0040, 0x5ce: 0x0040, 0x5cf: 0x0008, 0x5d0: 0x0008, 0x5d1: 0x0040, - 0x5d2: 0x0040, 0x5d3: 0x0008, 0x5d4: 0x0008, 0x5d5: 0x0008, 0x5d6: 0x0008, 0x5d7: 0x0008, - 0x5d8: 0x0008, 0x5d9: 0x0008, 0x5da: 0x0008, 0x5db: 0x0008, 0x5dc: 0x0008, 0x5dd: 0x0008, - 0x5de: 0x0008, 0x5df: 0x0008, 0x5e0: 0x0008, 0x5e1: 0x0008, 0x5e2: 0x0008, 0x5e3: 0x0008, - 0x5e4: 0x0008, 0x5e5: 0x0008, 0x5e6: 0x0008, 0x5e7: 0x0008, 0x5e8: 0x0008, 0x5e9: 0x0040, - 0x5ea: 0x0008, 0x5eb: 0x0008, 0x5ec: 0x0008, 0x5ed: 0x0008, 0x5ee: 0x0008, 0x5ef: 0x0008, - 0x5f0: 0x0008, 0x5f1: 0x0040, 0x5f2: 0x0008, 0x5f3: 0x0040, 0x5f4: 0x0040, 0x5f5: 0x0040, - 0x5f6: 0x0008, 0x5f7: 0x0008, 0x5f8: 0x0008, 0x5f9: 0x0008, 0x5fa: 0x0040, 0x5fb: 0x0040, - 0x5fc: 0x3308, 0x5fd: 0x0008, 0x5fe: 0x3008, 0x5ff: 0x3008, - // Block 0x18, offset 0x600 - 0x600: 0x3008, 0x601: 0x3308, 0x602: 0x3308, 0x603: 0x3308, 0x604: 0x3308, 0x605: 0x0040, - 0x606: 0x0040, 0x607: 0x3008, 0x608: 0x3008, 0x609: 0x0040, 0x60a: 0x0040, 0x60b: 0x3008, - 0x60c: 0x3008, 0x60d: 0x3b08, 0x60e: 0x0008, 0x60f: 0x0040, 0x610: 0x0040, 0x611: 0x0040, - 0x612: 0x0040, 0x613: 0x0040, 0x614: 0x0040, 0x615: 0x0040, 0x616: 0x0040, 0x617: 0x3008, - 0x618: 0x0040, 0x619: 0x0040, 0x61a: 0x0040, 0x61b: 0x0040, 0x61c: 0x0689, 0x61d: 0x06c1, - 0x61e: 0x0040, 0x61f: 0x06f9, 0x620: 0x0008, 0x621: 0x0008, 0x622: 0x3308, 0x623: 0x3308, - 0x624: 0x0040, 0x625: 0x0040, 0x626: 0x0008, 0x627: 0x0008, 0x628: 0x0008, 0x629: 0x0008, - 0x62a: 0x0008, 0x62b: 0x0008, 0x62c: 0x0008, 0x62d: 0x0008, 0x62e: 0x0008, 0x62f: 0x0008, - 0x630: 0x0008, 0x631: 0x0008, 0x632: 0x0018, 0x633: 0x0018, 0x634: 0x0018, 0x635: 0x0018, - 0x636: 0x0018, 0x637: 0x0018, 0x638: 0x0018, 0x639: 0x0018, 0x63a: 0x0018, 0x63b: 0x0018, - 0x63c: 0x0008, 0x63d: 0x0018, 0x63e: 0x3308, 0x63f: 0x0040, - // Block 0x19, offset 0x640 - 0x640: 0x0040, 0x641: 0x3308, 0x642: 0x3308, 0x643: 0x3008, 0x644: 0x0040, 0x645: 0x0008, - 0x646: 0x0008, 0x647: 0x0008, 0x648: 0x0008, 0x649: 0x0008, 0x64a: 0x0008, 0x64b: 0x0040, - 0x64c: 0x0040, 0x64d: 0x0040, 0x64e: 0x0040, 0x64f: 0x0008, 0x650: 0x0008, 0x651: 0x0040, - 0x652: 0x0040, 0x653: 0x0008, 0x654: 0x0008, 0x655: 0x0008, 0x656: 0x0008, 0x657: 0x0008, - 0x658: 0x0008, 0x659: 0x0008, 0x65a: 0x0008, 0x65b: 0x0008, 0x65c: 0x0008, 0x65d: 0x0008, - 0x65e: 0x0008, 0x65f: 0x0008, 0x660: 0x0008, 0x661: 0x0008, 0x662: 0x0008, 0x663: 0x0008, - 0x664: 0x0008, 0x665: 0x0008, 0x666: 0x0008, 0x667: 0x0008, 0x668: 0x0008, 0x669: 0x0040, - 0x66a: 0x0008, 0x66b: 0x0008, 0x66c: 0x0008, 0x66d: 0x0008, 0x66e: 0x0008, 0x66f: 0x0008, - 0x670: 0x0008, 0x671: 0x0040, 0x672: 0x0008, 0x673: 0x0731, 0x674: 0x0040, 0x675: 0x0008, - 0x676: 0x0769, 0x677: 0x0040, 0x678: 0x0008, 0x679: 0x0008, 0x67a: 0x0040, 0x67b: 0x0040, - 0x67c: 0x3308, 0x67d: 0x0040, 0x67e: 0x3008, 0x67f: 0x3008, - // Block 0x1a, offset 0x680 - 0x680: 0x3008, 0x681: 0x3308, 0x682: 0x3308, 0x683: 0x0040, 0x684: 0x0040, 0x685: 0x0040, - 0x686: 0x0040, 0x687: 0x3308, 0x688: 0x3308, 0x689: 0x0040, 0x68a: 0x0040, 0x68b: 0x3308, - 0x68c: 0x3308, 0x68d: 0x3b08, 0x68e: 0x0040, 0x68f: 0x0040, 0x690: 0x0040, 0x691: 0x3308, - 0x692: 0x0040, 0x693: 0x0040, 0x694: 0x0040, 0x695: 0x0040, 0x696: 0x0040, 0x697: 0x0040, - 0x698: 0x0040, 0x699: 0x07a1, 0x69a: 0x07d9, 0x69b: 0x0811, 0x69c: 0x0008, 0x69d: 0x0040, - 0x69e: 0x0849, 0x69f: 0x0040, 0x6a0: 0x0040, 0x6a1: 0x0040, 0x6a2: 0x0040, 0x6a3: 0x0040, - 0x6a4: 0x0040, 0x6a5: 0x0040, 0x6a6: 0x0008, 0x6a7: 0x0008, 0x6a8: 0x0008, 0x6a9: 0x0008, - 0x6aa: 0x0008, 0x6ab: 0x0008, 0x6ac: 0x0008, 0x6ad: 0x0008, 0x6ae: 0x0008, 0x6af: 0x0008, - 0x6b0: 0x3308, 0x6b1: 0x3308, 0x6b2: 0x0008, 0x6b3: 0x0008, 0x6b4: 0x0008, 0x6b5: 0x3308, - 0x6b6: 0x0018, 0x6b7: 0x0040, 0x6b8: 0x0040, 0x6b9: 0x0040, 0x6ba: 0x0040, 0x6bb: 0x0040, - 0x6bc: 0x0040, 0x6bd: 0x0040, 0x6be: 0x0040, 0x6bf: 0x0040, - // Block 0x1b, offset 0x6c0 - 0x6c0: 0x0040, 0x6c1: 0x3308, 0x6c2: 0x3308, 0x6c3: 0x3008, 0x6c4: 0x0040, 0x6c5: 0x0008, - 0x6c6: 0x0008, 0x6c7: 0x0008, 0x6c8: 0x0008, 0x6c9: 0x0008, 0x6ca: 0x0008, 0x6cb: 0x0008, - 0x6cc: 0x0008, 0x6cd: 0x0008, 0x6ce: 0x0040, 0x6cf: 0x0008, 0x6d0: 0x0008, 0x6d1: 0x0008, - 0x6d2: 0x0040, 0x6d3: 0x0008, 0x6d4: 0x0008, 0x6d5: 0x0008, 0x6d6: 0x0008, 0x6d7: 0x0008, - 0x6d8: 0x0008, 0x6d9: 0x0008, 0x6da: 0x0008, 0x6db: 0x0008, 0x6dc: 0x0008, 0x6dd: 0x0008, - 0x6de: 0x0008, 0x6df: 0x0008, 0x6e0: 0x0008, 0x6e1: 0x0008, 0x6e2: 0x0008, 0x6e3: 0x0008, - 0x6e4: 0x0008, 0x6e5: 0x0008, 0x6e6: 0x0008, 0x6e7: 0x0008, 0x6e8: 0x0008, 0x6e9: 0x0040, - 0x6ea: 0x0008, 0x6eb: 0x0008, 0x6ec: 0x0008, 0x6ed: 0x0008, 0x6ee: 0x0008, 0x6ef: 0x0008, - 0x6f0: 0x0008, 0x6f1: 0x0040, 0x6f2: 0x0008, 0x6f3: 0x0008, 0x6f4: 0x0040, 0x6f5: 0x0008, - 0x6f6: 0x0008, 0x6f7: 0x0008, 0x6f8: 0x0008, 0x6f9: 0x0008, 0x6fa: 0x0040, 0x6fb: 0x0040, - 0x6fc: 0x3308, 0x6fd: 0x0008, 0x6fe: 0x3008, 0x6ff: 0x3008, - // Block 0x1c, offset 0x700 - 0x700: 0x3008, 0x701: 0x3308, 0x702: 0x3308, 0x703: 0x3308, 0x704: 0x3308, 0x705: 0x3308, - 0x706: 0x0040, 0x707: 0x3308, 0x708: 0x3308, 0x709: 0x3008, 0x70a: 0x0040, 0x70b: 0x3008, - 0x70c: 0x3008, 0x70d: 0x3b08, 0x70e: 0x0040, 0x70f: 0x0040, 0x710: 0x0008, 0x711: 0x0040, - 0x712: 0x0040, 0x713: 0x0040, 0x714: 0x0040, 0x715: 0x0040, 0x716: 0x0040, 0x717: 0x0040, - 0x718: 0x0040, 0x719: 0x0040, 0x71a: 0x0040, 0x71b: 0x0040, 0x71c: 0x0040, 0x71d: 0x0040, - 0x71e: 0x0040, 0x71f: 0x0040, 0x720: 0x0008, 0x721: 0x0008, 0x722: 0x3308, 0x723: 0x3308, - 0x724: 0x0040, 0x725: 0x0040, 0x726: 0x0008, 0x727: 0x0008, 0x728: 0x0008, 0x729: 0x0008, - 0x72a: 0x0008, 0x72b: 0x0008, 0x72c: 0x0008, 0x72d: 0x0008, 0x72e: 0x0008, 0x72f: 0x0008, - 0x730: 0x0018, 0x731: 0x0018, 0x732: 0x0040, 0x733: 0x0040, 0x734: 0x0040, 0x735: 0x0040, - 0x736: 0x0040, 0x737: 0x0040, 0x738: 0x0040, 0x739: 0x0008, 0x73a: 0x3308, 0x73b: 0x3308, - 0x73c: 0x3308, 0x73d: 0x3308, 0x73e: 0x3308, 0x73f: 0x3308, - // Block 0x1d, offset 0x740 - 0x740: 0x0040, 0x741: 0x3308, 0x742: 0x3008, 0x743: 0x3008, 0x744: 0x0040, 0x745: 0x0008, - 0x746: 0x0008, 0x747: 0x0008, 0x748: 0x0008, 0x749: 0x0008, 0x74a: 0x0008, 0x74b: 0x0008, - 0x74c: 0x0008, 0x74d: 0x0040, 0x74e: 0x0040, 0x74f: 0x0008, 0x750: 0x0008, 0x751: 0x0040, - 0x752: 0x0040, 0x753: 0x0008, 0x754: 0x0008, 0x755: 0x0008, 0x756: 0x0008, 0x757: 0x0008, - 0x758: 0x0008, 0x759: 0x0008, 0x75a: 0x0008, 0x75b: 0x0008, 0x75c: 0x0008, 0x75d: 0x0008, - 0x75e: 0x0008, 0x75f: 0x0008, 0x760: 0x0008, 0x761: 0x0008, 0x762: 0x0008, 0x763: 0x0008, - 0x764: 0x0008, 0x765: 0x0008, 0x766: 0x0008, 0x767: 0x0008, 0x768: 0x0008, 0x769: 0x0040, - 0x76a: 0x0008, 0x76b: 0x0008, 0x76c: 0x0008, 0x76d: 0x0008, 0x76e: 0x0008, 0x76f: 0x0008, - 0x770: 0x0008, 0x771: 0x0040, 0x772: 0x0008, 0x773: 0x0008, 0x774: 0x0040, 0x775: 0x0008, - 0x776: 0x0008, 0x777: 0x0008, 0x778: 0x0008, 0x779: 0x0008, 0x77a: 0x0040, 0x77b: 0x0040, - 0x77c: 0x3308, 0x77d: 0x0008, 0x77e: 0x3008, 0x77f: 0x3308, - // Block 0x1e, offset 0x780 - 0x780: 0x3008, 0x781: 0x3308, 0x782: 0x3308, 0x783: 0x3308, 0x784: 0x3308, 0x785: 0x0040, - 0x786: 0x0040, 0x787: 0x3008, 0x788: 0x3008, 0x789: 0x0040, 0x78a: 0x0040, 0x78b: 0x3008, - 0x78c: 0x3008, 0x78d: 0x3b08, 0x78e: 0x0040, 0x78f: 0x0040, 0x790: 0x0040, 0x791: 0x0040, - 0x792: 0x0040, 0x793: 0x0040, 0x794: 0x0040, 0x795: 0x0040, 0x796: 0x3308, 0x797: 0x3008, - 0x798: 0x0040, 0x799: 0x0040, 0x79a: 0x0040, 0x79b: 0x0040, 0x79c: 0x0881, 0x79d: 0x08b9, - 0x79e: 0x0040, 0x79f: 0x0008, 0x7a0: 0x0008, 0x7a1: 0x0008, 0x7a2: 0x3308, 0x7a3: 0x3308, - 0x7a4: 0x0040, 0x7a5: 0x0040, 0x7a6: 0x0008, 0x7a7: 0x0008, 0x7a8: 0x0008, 0x7a9: 0x0008, - 0x7aa: 0x0008, 0x7ab: 0x0008, 0x7ac: 0x0008, 0x7ad: 0x0008, 0x7ae: 0x0008, 0x7af: 0x0008, - 0x7b0: 0x0018, 0x7b1: 0x0008, 0x7b2: 0x0018, 0x7b3: 0x0018, 0x7b4: 0x0018, 0x7b5: 0x0018, - 0x7b6: 0x0018, 0x7b7: 0x0018, 0x7b8: 0x0040, 0x7b9: 0x0040, 0x7ba: 0x0040, 0x7bb: 0x0040, - 0x7bc: 0x0040, 0x7bd: 0x0040, 0x7be: 0x0040, 0x7bf: 0x0040, - // Block 0x1f, offset 0x7c0 - 0x7c0: 0x0040, 0x7c1: 0x0040, 0x7c2: 0x3308, 0x7c3: 0x0008, 0x7c4: 0x0040, 0x7c5: 0x0008, - 0x7c6: 0x0008, 0x7c7: 0x0008, 0x7c8: 0x0008, 0x7c9: 0x0008, 0x7ca: 0x0008, 0x7cb: 0x0040, - 0x7cc: 0x0040, 0x7cd: 0x0040, 0x7ce: 0x0008, 0x7cf: 0x0008, 0x7d0: 0x0008, 0x7d1: 0x0040, - 0x7d2: 0x0008, 0x7d3: 0x0008, 0x7d4: 0x0008, 0x7d5: 0x0008, 0x7d6: 0x0040, 0x7d7: 0x0040, - 0x7d8: 0x0040, 0x7d9: 0x0008, 0x7da: 0x0008, 0x7db: 0x0040, 0x7dc: 0x0008, 0x7dd: 0x0040, - 0x7de: 0x0008, 0x7df: 0x0008, 0x7e0: 0x0040, 0x7e1: 0x0040, 0x7e2: 0x0040, 0x7e3: 0x0008, - 0x7e4: 0x0008, 0x7e5: 0x0040, 0x7e6: 0x0040, 0x7e7: 0x0040, 0x7e8: 0x0008, 0x7e9: 0x0008, - 0x7ea: 0x0008, 0x7eb: 0x0040, 0x7ec: 0x0040, 0x7ed: 0x0040, 0x7ee: 0x0008, 0x7ef: 0x0008, - 0x7f0: 0x0008, 0x7f1: 0x0008, 0x7f2: 0x0008, 0x7f3: 0x0008, 0x7f4: 0x0008, 0x7f5: 0x0008, - 0x7f6: 0x0008, 0x7f7: 0x0008, 0x7f8: 0x0008, 0x7f9: 0x0008, 0x7fa: 0x0040, 0x7fb: 0x0040, - 0x7fc: 0x0040, 0x7fd: 0x0040, 0x7fe: 0x3008, 0x7ff: 0x3008, - // Block 0x20, offset 0x800 - 0x800: 0x3308, 0x801: 0x3008, 0x802: 0x3008, 0x803: 0x3008, 0x804: 0x3008, 0x805: 0x0040, - 0x806: 0x3308, 0x807: 0x3308, 0x808: 0x3308, 0x809: 0x0040, 0x80a: 0x3308, 0x80b: 0x3308, - 0x80c: 0x3308, 0x80d: 0x3b08, 0x80e: 0x0040, 0x80f: 0x0040, 0x810: 0x0040, 0x811: 0x0040, - 0x812: 0x0040, 0x813: 0x0040, 0x814: 0x0040, 0x815: 0x3308, 0x816: 0x3308, 0x817: 0x0040, - 0x818: 0x0008, 0x819: 0x0008, 0x81a: 0x0008, 0x81b: 0x0040, 0x81c: 0x0040, 0x81d: 0x0040, - 0x81e: 0x0040, 0x81f: 0x0040, 0x820: 0x0008, 0x821: 0x0008, 0x822: 0x3308, 0x823: 0x3308, - 0x824: 0x0040, 0x825: 0x0040, 0x826: 0x0008, 0x827: 0x0008, 0x828: 0x0008, 0x829: 0x0008, - 0x82a: 0x0008, 0x82b: 0x0008, 0x82c: 0x0008, 0x82d: 0x0008, 0x82e: 0x0008, 0x82f: 0x0008, - 0x830: 0x0040, 0x831: 0x0040, 0x832: 0x0040, 0x833: 0x0040, 0x834: 0x0040, 0x835: 0x0040, - 0x836: 0x0040, 0x837: 0x0018, 0x838: 0x0018, 0x839: 0x0018, 0x83a: 0x0018, 0x83b: 0x0018, - 0x83c: 0x0018, 0x83d: 0x0018, 0x83e: 0x0018, 0x83f: 0x0018, - // Block 0x21, offset 0x840 - 0x840: 0x0008, 0x841: 0x3308, 0x842: 0x3008, 0x843: 0x3008, 0x844: 0x0018, 0x845: 0x0008, - 0x846: 0x0008, 0x847: 0x0008, 0x848: 0x0008, 0x849: 0x0008, 0x84a: 0x0008, 0x84b: 0x0008, - 0x84c: 0x0008, 0x84d: 0x0040, 0x84e: 0x0008, 0x84f: 0x0008, 0x850: 0x0008, 0x851: 0x0040, - 0x852: 0x0008, 0x853: 0x0008, 0x854: 0x0008, 0x855: 0x0008, 0x856: 0x0008, 0x857: 0x0008, - 0x858: 0x0008, 0x859: 0x0008, 0x85a: 0x0008, 0x85b: 0x0008, 0x85c: 0x0008, 0x85d: 0x0008, - 0x85e: 0x0008, 0x85f: 0x0008, 0x860: 0x0008, 0x861: 0x0008, 0x862: 0x0008, 0x863: 0x0008, - 0x864: 0x0008, 0x865: 0x0008, 0x866: 0x0008, 0x867: 0x0008, 0x868: 0x0008, 0x869: 0x0040, - 0x86a: 0x0008, 0x86b: 0x0008, 0x86c: 0x0008, 0x86d: 0x0008, 0x86e: 0x0008, 0x86f: 0x0008, - 0x870: 0x0008, 0x871: 0x0008, 0x872: 0x0008, 0x873: 0x0008, 0x874: 0x0040, 0x875: 0x0008, - 0x876: 0x0008, 0x877: 0x0008, 0x878: 0x0008, 0x879: 0x0008, 0x87a: 0x0040, 0x87b: 0x0040, - 0x87c: 0x3308, 0x87d: 0x0008, 0x87e: 0x3008, 0x87f: 0x3308, - // Block 0x22, offset 0x880 - 0x880: 0x3008, 0x881: 0x3008, 0x882: 0x3008, 0x883: 0x3008, 0x884: 0x3008, 0x885: 0x0040, - 0x886: 0x3308, 0x887: 0x3008, 0x888: 0x3008, 0x889: 0x0040, 0x88a: 0x3008, 0x88b: 0x3008, - 0x88c: 0x3308, 0x88d: 0x3b08, 0x88e: 0x0040, 0x88f: 0x0040, 0x890: 0x0040, 0x891: 0x0040, - 0x892: 0x0040, 0x893: 0x0040, 0x894: 0x0040, 0x895: 0x3008, 0x896: 0x3008, 0x897: 0x0040, - 0x898: 0x0040, 0x899: 0x0040, 0x89a: 0x0040, 0x89b: 0x0040, 0x89c: 0x0040, 0x89d: 0x0040, - 0x89e: 0x0008, 0x89f: 0x0040, 0x8a0: 0x0008, 0x8a1: 0x0008, 0x8a2: 0x3308, 0x8a3: 0x3308, - 0x8a4: 0x0040, 0x8a5: 0x0040, 0x8a6: 0x0008, 0x8a7: 0x0008, 0x8a8: 0x0008, 0x8a9: 0x0008, - 0x8aa: 0x0008, 0x8ab: 0x0008, 0x8ac: 0x0008, 0x8ad: 0x0008, 0x8ae: 0x0008, 0x8af: 0x0008, - 0x8b0: 0x0040, 0x8b1: 0x0008, 0x8b2: 0x0008, 0x8b3: 0x0040, 0x8b4: 0x0040, 0x8b5: 0x0040, - 0x8b6: 0x0040, 0x8b7: 0x0040, 0x8b8: 0x0040, 0x8b9: 0x0040, 0x8ba: 0x0040, 0x8bb: 0x0040, - 0x8bc: 0x0040, 0x8bd: 0x0040, 0x8be: 0x0040, 0x8bf: 0x0040, - // Block 0x23, offset 0x8c0 - 0x8c0: 0x3008, 0x8c1: 0x3308, 0x8c2: 0x3308, 0x8c3: 0x3308, 0x8c4: 0x3308, 0x8c5: 0x0040, - 0x8c6: 0x3008, 0x8c7: 0x3008, 0x8c8: 0x3008, 0x8c9: 0x0040, 0x8ca: 0x3008, 0x8cb: 0x3008, - 0x8cc: 0x3008, 0x8cd: 0x3b08, 0x8ce: 0x0008, 0x8cf: 0x0018, 0x8d0: 0x0040, 0x8d1: 0x0040, - 0x8d2: 0x0040, 0x8d3: 0x0040, 0x8d4: 0x0008, 0x8d5: 0x0008, 0x8d6: 0x0008, 0x8d7: 0x3008, - 0x8d8: 0x0018, 0x8d9: 0x0018, 0x8da: 0x0018, 0x8db: 0x0018, 0x8dc: 0x0018, 0x8dd: 0x0018, - 0x8de: 0x0018, 0x8df: 0x0008, 0x8e0: 0x0008, 0x8e1: 0x0008, 0x8e2: 0x3308, 0x8e3: 0x3308, - 0x8e4: 0x0040, 0x8e5: 0x0040, 0x8e6: 0x0008, 0x8e7: 0x0008, 0x8e8: 0x0008, 0x8e9: 0x0008, - 0x8ea: 0x0008, 0x8eb: 0x0008, 0x8ec: 0x0008, 0x8ed: 0x0008, 0x8ee: 0x0008, 0x8ef: 0x0008, - 0x8f0: 0x0018, 0x8f1: 0x0018, 0x8f2: 0x0018, 0x8f3: 0x0018, 0x8f4: 0x0018, 0x8f5: 0x0018, - 0x8f6: 0x0018, 0x8f7: 0x0018, 0x8f8: 0x0018, 0x8f9: 0x0018, 0x8fa: 0x0008, 0x8fb: 0x0008, - 0x8fc: 0x0008, 0x8fd: 0x0008, 0x8fe: 0x0008, 0x8ff: 0x0008, - // Block 0x24, offset 0x900 - 0x900: 0x0040, 0x901: 0x0008, 0x902: 0x0008, 0x903: 0x0040, 0x904: 0x0008, 0x905: 0x0040, - 0x906: 0x0008, 0x907: 0x0008, 0x908: 0x0008, 0x909: 0x0008, 0x90a: 0x0008, 0x90b: 0x0040, - 0x90c: 0x0008, 0x90d: 0x0008, 0x90e: 0x0008, 0x90f: 0x0008, 0x910: 0x0008, 0x911: 0x0008, - 0x912: 0x0008, 0x913: 0x0008, 0x914: 0x0008, 0x915: 0x0008, 0x916: 0x0008, 0x917: 0x0008, - 0x918: 0x0008, 0x919: 0x0008, 0x91a: 0x0008, 0x91b: 0x0008, 0x91c: 0x0008, 0x91d: 0x0008, - 0x91e: 0x0008, 0x91f: 0x0008, 0x920: 0x0008, 0x921: 0x0008, 0x922: 0x0008, 0x923: 0x0008, - 0x924: 0x0040, 0x925: 0x0008, 0x926: 0x0040, 0x927: 0x0008, 0x928: 0x0008, 0x929: 0x0008, - 0x92a: 0x0008, 0x92b: 0x0008, 0x92c: 0x0008, 0x92d: 0x0008, 0x92e: 0x0008, 0x92f: 0x0008, - 0x930: 0x0008, 0x931: 0x3308, 0x932: 0x0008, 0x933: 0x0929, 0x934: 0x3308, 0x935: 0x3308, - 0x936: 0x3308, 0x937: 0x3308, 0x938: 0x3308, 0x939: 0x3308, 0x93a: 0x3b08, 0x93b: 0x3308, - 0x93c: 0x3308, 0x93d: 0x0008, 0x93e: 0x0040, 0x93f: 0x0040, - // Block 0x25, offset 0x940 - 0x940: 0x0008, 0x941: 0x0008, 0x942: 0x0008, 0x943: 0x09d1, 0x944: 0x0008, 0x945: 0x0008, - 0x946: 0x0008, 0x947: 0x0008, 0x948: 0x0040, 0x949: 0x0008, 0x94a: 0x0008, 0x94b: 0x0008, - 0x94c: 0x0008, 0x94d: 0x0a09, 0x94e: 0x0008, 0x94f: 0x0008, 0x950: 0x0008, 0x951: 0x0008, - 0x952: 0x0a41, 0x953: 0x0008, 0x954: 0x0008, 0x955: 0x0008, 0x956: 0x0008, 0x957: 0x0a79, - 0x958: 0x0008, 0x959: 0x0008, 0x95a: 0x0008, 0x95b: 0x0008, 0x95c: 0x0ab1, 0x95d: 0x0008, - 0x95e: 0x0008, 0x95f: 0x0008, 0x960: 0x0008, 0x961: 0x0008, 0x962: 0x0008, 0x963: 0x0008, - 0x964: 0x0008, 0x965: 0x0008, 0x966: 0x0008, 0x967: 0x0008, 0x968: 0x0008, 0x969: 0x0ae9, - 0x96a: 0x0008, 0x96b: 0x0008, 0x96c: 0x0008, 0x96d: 0x0040, 0x96e: 0x0040, 0x96f: 0x0040, - 0x970: 0x0040, 0x971: 0x3308, 0x972: 0x3308, 0x973: 0x0b21, 0x974: 0x3308, 0x975: 0x0b59, - 0x976: 0x0b91, 0x977: 0x0bc9, 0x978: 0x0c19, 0x979: 0x0c51, 0x97a: 0x3308, 0x97b: 0x3308, - 0x97c: 0x3308, 0x97d: 0x3308, 0x97e: 0x3308, 0x97f: 0x3008, - // Block 0x26, offset 0x980 - 0x980: 0x3308, 0x981: 0x0ca1, 0x982: 0x3308, 0x983: 0x3308, 0x984: 0x3b08, 0x985: 0x0018, - 0x986: 0x3308, 0x987: 0x3308, 0x988: 0x0008, 0x989: 0x0008, 0x98a: 0x0008, 0x98b: 0x0008, - 0x98c: 0x0008, 0x98d: 0x3308, 0x98e: 0x3308, 0x98f: 0x3308, 0x990: 0x3308, 0x991: 0x3308, - 0x992: 0x3308, 0x993: 0x0cd9, 0x994: 0x3308, 0x995: 0x3308, 0x996: 0x3308, 0x997: 0x3308, - 0x998: 0x0040, 0x999: 0x3308, 0x99a: 0x3308, 0x99b: 0x3308, 0x99c: 0x3308, 0x99d: 0x0d11, - 0x99e: 0x3308, 0x99f: 0x3308, 0x9a0: 0x3308, 0x9a1: 0x3308, 0x9a2: 0x0d49, 0x9a3: 0x3308, - 0x9a4: 0x3308, 0x9a5: 0x3308, 0x9a6: 0x3308, 0x9a7: 0x0d81, 0x9a8: 0x3308, 0x9a9: 0x3308, - 0x9aa: 0x3308, 0x9ab: 0x3308, 0x9ac: 0x0db9, 0x9ad: 0x3308, 0x9ae: 0x3308, 0x9af: 0x3308, - 0x9b0: 0x3308, 0x9b1: 0x3308, 0x9b2: 0x3308, 0x9b3: 0x3308, 0x9b4: 0x3308, 0x9b5: 0x3308, - 0x9b6: 0x3308, 0x9b7: 0x3308, 0x9b8: 0x3308, 0x9b9: 0x0df1, 0x9ba: 0x3308, 0x9bb: 0x3308, - 0x9bc: 0x3308, 0x9bd: 0x0040, 0x9be: 0x0018, 0x9bf: 0x0018, - // Block 0x27, offset 0x9c0 - 0x9c0: 0x0008, 0x9c1: 0x0008, 0x9c2: 0x0008, 0x9c3: 0x0008, 0x9c4: 0x0008, 0x9c5: 0x0008, - 0x9c6: 0x0008, 0x9c7: 0x0008, 0x9c8: 0x0008, 0x9c9: 0x0008, 0x9ca: 0x0008, 0x9cb: 0x0008, - 0x9cc: 0x0008, 0x9cd: 0x0008, 0x9ce: 0x0008, 0x9cf: 0x0008, 0x9d0: 0x0008, 0x9d1: 0x0008, - 0x9d2: 0x0008, 0x9d3: 0x0008, 0x9d4: 0x0008, 0x9d5: 0x0008, 0x9d6: 0x0008, 0x9d7: 0x0008, - 0x9d8: 0x0008, 0x9d9: 0x0008, 0x9da: 0x0008, 0x9db: 0x0008, 0x9dc: 0x0008, 0x9dd: 0x0008, - 0x9de: 0x0008, 0x9df: 0x0008, 0x9e0: 0x0008, 0x9e1: 0x0008, 0x9e2: 0x0008, 0x9e3: 0x0008, - 0x9e4: 0x0008, 0x9e5: 0x0008, 0x9e6: 0x0008, 0x9e7: 0x0008, 0x9e8: 0x0008, 0x9e9: 0x0008, - 0x9ea: 0x0008, 0x9eb: 0x0008, 0x9ec: 0x0039, 0x9ed: 0x0ed1, 0x9ee: 0x0ee9, 0x9ef: 0x0008, - 0x9f0: 0x0ef9, 0x9f1: 0x0f09, 0x9f2: 0x0f19, 0x9f3: 0x0f31, 0x9f4: 0x0249, 0x9f5: 0x0f41, - 0x9f6: 0x0259, 0x9f7: 0x0f51, 0x9f8: 0x0359, 0x9f9: 0x0f61, 0x9fa: 0x0f71, 0x9fb: 0x0008, - 0x9fc: 0x00d9, 0x9fd: 0x0f81, 0x9fe: 0x0f99, 0x9ff: 0x0269, - // Block 0x28, offset 0xa00 - 0xa00: 0x0fa9, 0xa01: 0x0fb9, 0xa02: 0x0279, 0xa03: 0x0039, 0xa04: 0x0fc9, 0xa05: 0x0fe1, - 0xa06: 0x05b5, 0xa07: 0x0ee9, 0xa08: 0x0ef9, 0xa09: 0x0f09, 0xa0a: 0x0ff9, 0xa0b: 0x1011, - 0xa0c: 0x1029, 0xa0d: 0x0f31, 0xa0e: 0x0008, 0xa0f: 0x0f51, 0xa10: 0x0f61, 0xa11: 0x1041, - 0xa12: 0x00d9, 0xa13: 0x1059, 0xa14: 0x05cd, 0xa15: 0x05cd, 0xa16: 0x0f99, 0xa17: 0x0fa9, - 0xa18: 0x0fb9, 0xa19: 0x05b5, 0xa1a: 0x1071, 0xa1b: 0x1089, 0xa1c: 0x05e5, 0xa1d: 0x1099, - 0xa1e: 0x10b1, 0xa1f: 0x10c9, 0xa20: 0x10e1, 0xa21: 0x10f9, 0xa22: 0x0f41, 0xa23: 0x0269, - 0xa24: 0x0fb9, 0xa25: 0x1089, 0xa26: 0x1099, 0xa27: 0x10b1, 0xa28: 0x1111, 0xa29: 0x10e1, - 0xa2a: 0x10f9, 0xa2b: 0x0008, 0xa2c: 0x0008, 0xa2d: 0x0008, 0xa2e: 0x0008, 0xa2f: 0x0008, - 0xa30: 0x0008, 0xa31: 0x0008, 0xa32: 0x0008, 0xa33: 0x0008, 0xa34: 0x0008, 0xa35: 0x0008, - 0xa36: 0x0008, 0xa37: 0x0008, 0xa38: 0x1129, 0xa39: 0x0008, 0xa3a: 0x0008, 0xa3b: 0x0008, - 0xa3c: 0x0008, 0xa3d: 0x0008, 0xa3e: 0x0008, 0xa3f: 0x0008, - // Block 0x29, offset 0xa40 - 0xa40: 0x0008, 0xa41: 0x0008, 0xa42: 0x0008, 0xa43: 0x0008, 0xa44: 0x0008, 0xa45: 0x0008, - 0xa46: 0x0008, 0xa47: 0x0008, 0xa48: 0x0008, 0xa49: 0x0008, 0xa4a: 0x0008, 0xa4b: 0x0008, - 0xa4c: 0x0008, 0xa4d: 0x0008, 0xa4e: 0x0008, 0xa4f: 0x0008, 0xa50: 0x0008, 0xa51: 0x0008, - 0xa52: 0x0008, 0xa53: 0x0008, 0xa54: 0x0008, 0xa55: 0x0008, 0xa56: 0x0008, 0xa57: 0x0008, - 0xa58: 0x0008, 0xa59: 0x0008, 0xa5a: 0x0008, 0xa5b: 0x1141, 0xa5c: 0x1159, 0xa5d: 0x1169, - 0xa5e: 0x1181, 0xa5f: 0x1029, 0xa60: 0x1199, 0xa61: 0x11a9, 0xa62: 0x11c1, 0xa63: 0x11d9, - 0xa64: 0x11f1, 0xa65: 0x1209, 0xa66: 0x1221, 0xa67: 0x05fd, 0xa68: 0x1239, 0xa69: 0x1251, - 0xa6a: 0xe17d, 0xa6b: 0x1269, 0xa6c: 0x1281, 0xa6d: 0x1299, 0xa6e: 0x12b1, 0xa6f: 0x12c9, - 0xa70: 0x12e1, 0xa71: 0x12f9, 0xa72: 0x1311, 0xa73: 0x1329, 0xa74: 0x1341, 0xa75: 0x1359, - 0xa76: 0x1371, 0xa77: 0x1389, 0xa78: 0x0615, 0xa79: 0x13a1, 0xa7a: 0x13b9, 0xa7b: 0x13d1, - 0xa7c: 0x13e1, 0xa7d: 0x13f9, 0xa7e: 0x1411, 0xa7f: 0x1429, - // Block 0x2a, offset 0xa80 - 0xa80: 0xe00d, 0xa81: 0x0008, 0xa82: 0xe00d, 0xa83: 0x0008, 0xa84: 0xe00d, 0xa85: 0x0008, - 0xa86: 0xe00d, 0xa87: 0x0008, 0xa88: 0xe00d, 0xa89: 0x0008, 0xa8a: 0xe00d, 0xa8b: 0x0008, - 0xa8c: 0xe00d, 0xa8d: 0x0008, 0xa8e: 0xe00d, 0xa8f: 0x0008, 0xa90: 0xe00d, 0xa91: 0x0008, - 0xa92: 0xe00d, 0xa93: 0x0008, 0xa94: 0xe00d, 0xa95: 0x0008, 0xa96: 0xe00d, 0xa97: 0x0008, - 0xa98: 0xe00d, 0xa99: 0x0008, 0xa9a: 0xe00d, 0xa9b: 0x0008, 0xa9c: 0xe00d, 0xa9d: 0x0008, - 0xa9e: 0xe00d, 0xa9f: 0x0008, 0xaa0: 0xe00d, 0xaa1: 0x0008, 0xaa2: 0xe00d, 0xaa3: 0x0008, - 0xaa4: 0xe00d, 0xaa5: 0x0008, 0xaa6: 0xe00d, 0xaa7: 0x0008, 0xaa8: 0xe00d, 0xaa9: 0x0008, - 0xaaa: 0xe00d, 0xaab: 0x0008, 0xaac: 0xe00d, 0xaad: 0x0008, 0xaae: 0xe00d, 0xaaf: 0x0008, - 0xab0: 0xe00d, 0xab1: 0x0008, 0xab2: 0xe00d, 0xab3: 0x0008, 0xab4: 0xe00d, 0xab5: 0x0008, - 0xab6: 0xe00d, 0xab7: 0x0008, 0xab8: 0xe00d, 0xab9: 0x0008, 0xaba: 0xe00d, 0xabb: 0x0008, - 0xabc: 0xe00d, 0xabd: 0x0008, 0xabe: 0xe00d, 0xabf: 0x0008, - // Block 0x2b, offset 0xac0 - 0xac0: 0xe00d, 0xac1: 0x0008, 0xac2: 0xe00d, 0xac3: 0x0008, 0xac4: 0xe00d, 0xac5: 0x0008, - 0xac6: 0xe00d, 0xac7: 0x0008, 0xac8: 0xe00d, 0xac9: 0x0008, 0xaca: 0xe00d, 0xacb: 0x0008, - 0xacc: 0xe00d, 0xacd: 0x0008, 0xace: 0xe00d, 0xacf: 0x0008, 0xad0: 0xe00d, 0xad1: 0x0008, - 0xad2: 0xe00d, 0xad3: 0x0008, 0xad4: 0xe00d, 0xad5: 0x0008, 0xad6: 0x0008, 0xad7: 0x0008, - 0xad8: 0x0008, 0xad9: 0x0008, 0xada: 0x062d, 0xadb: 0x064d, 0xadc: 0x0008, 0xadd: 0x0008, - 0xade: 0x1441, 0xadf: 0x0008, 0xae0: 0xe00d, 0xae1: 0x0008, 0xae2: 0xe00d, 0xae3: 0x0008, - 0xae4: 0xe00d, 0xae5: 0x0008, 0xae6: 0xe00d, 0xae7: 0x0008, 0xae8: 0xe00d, 0xae9: 0x0008, - 0xaea: 0xe00d, 0xaeb: 0x0008, 0xaec: 0xe00d, 0xaed: 0x0008, 0xaee: 0xe00d, 0xaef: 0x0008, - 0xaf0: 0xe00d, 0xaf1: 0x0008, 0xaf2: 0xe00d, 0xaf3: 0x0008, 0xaf4: 0xe00d, 0xaf5: 0x0008, - 0xaf6: 0xe00d, 0xaf7: 0x0008, 0xaf8: 0xe00d, 0xaf9: 0x0008, 0xafa: 0xe00d, 0xafb: 0x0008, - 0xafc: 0xe00d, 0xafd: 0x0008, 0xafe: 0xe00d, 0xaff: 0x0008, - // Block 0x2c, offset 0xb00 - 0xb00: 0x0008, 0xb01: 0x0008, 0xb02: 0x0008, 0xb03: 0x0008, 0xb04: 0x0008, 0xb05: 0x0008, - 0xb06: 0x0040, 0xb07: 0x0040, 0xb08: 0xe045, 0xb09: 0xe045, 0xb0a: 0xe045, 0xb0b: 0xe045, - 0xb0c: 0xe045, 0xb0d: 0xe045, 0xb0e: 0x0040, 0xb0f: 0x0040, 0xb10: 0x0008, 0xb11: 0x0008, - 0xb12: 0x0008, 0xb13: 0x0008, 0xb14: 0x0008, 0xb15: 0x0008, 0xb16: 0x0008, 0xb17: 0x0008, - 0xb18: 0x0040, 0xb19: 0xe045, 0xb1a: 0x0040, 0xb1b: 0xe045, 0xb1c: 0x0040, 0xb1d: 0xe045, - 0xb1e: 0x0040, 0xb1f: 0xe045, 0xb20: 0x0008, 0xb21: 0x0008, 0xb22: 0x0008, 0xb23: 0x0008, - 0xb24: 0x0008, 0xb25: 0x0008, 0xb26: 0x0008, 0xb27: 0x0008, 0xb28: 0xe045, 0xb29: 0xe045, - 0xb2a: 0xe045, 0xb2b: 0xe045, 0xb2c: 0xe045, 0xb2d: 0xe045, 0xb2e: 0xe045, 0xb2f: 0xe045, - 0xb30: 0x0008, 0xb31: 0x1459, 0xb32: 0x0008, 0xb33: 0x1471, 0xb34: 0x0008, 0xb35: 0x1489, - 0xb36: 0x0008, 0xb37: 0x14a1, 0xb38: 0x0008, 0xb39: 0x14b9, 0xb3a: 0x0008, 0xb3b: 0x14d1, - 0xb3c: 0x0008, 0xb3d: 0x14e9, 0xb3e: 0x0040, 0xb3f: 0x0040, - // Block 0x2d, offset 0xb40 - 0xb40: 0x1501, 0xb41: 0x1531, 0xb42: 0x1561, 0xb43: 0x1591, 0xb44: 0x15c1, 0xb45: 0x15f1, - 0xb46: 0x1621, 0xb47: 0x1651, 0xb48: 0x1501, 0xb49: 0x1531, 0xb4a: 0x1561, 0xb4b: 0x1591, - 0xb4c: 0x15c1, 0xb4d: 0x15f1, 0xb4e: 0x1621, 0xb4f: 0x1651, 0xb50: 0x1681, 0xb51: 0x16b1, - 0xb52: 0x16e1, 0xb53: 0x1711, 0xb54: 0x1741, 0xb55: 0x1771, 0xb56: 0x17a1, 0xb57: 0x17d1, - 0xb58: 0x1681, 0xb59: 0x16b1, 0xb5a: 0x16e1, 0xb5b: 0x1711, 0xb5c: 0x1741, 0xb5d: 0x1771, - 0xb5e: 0x17a1, 0xb5f: 0x17d1, 0xb60: 0x1801, 0xb61: 0x1831, 0xb62: 0x1861, 0xb63: 0x1891, - 0xb64: 0x18c1, 0xb65: 0x18f1, 0xb66: 0x1921, 0xb67: 0x1951, 0xb68: 0x1801, 0xb69: 0x1831, - 0xb6a: 0x1861, 0xb6b: 0x1891, 0xb6c: 0x18c1, 0xb6d: 0x18f1, 0xb6e: 0x1921, 0xb6f: 0x1951, - 0xb70: 0x0008, 0xb71: 0x0008, 0xb72: 0x1981, 0xb73: 0x19b1, 0xb74: 0x19d9, 0xb75: 0x0040, - 0xb76: 0x0008, 0xb77: 0x1a01, 0xb78: 0xe045, 0xb79: 0xe045, 0xb7a: 0x0665, 0xb7b: 0x1459, - 0xb7c: 0x19b1, 0xb7d: 0x067e, 0xb7e: 0x1a31, 0xb7f: 0x069e, - // Block 0x2e, offset 0xb80 - 0xb80: 0x06be, 0xb81: 0x1a4a, 0xb82: 0x1a79, 0xb83: 0x1aa9, 0xb84: 0x1ad1, 0xb85: 0x0040, - 0xb86: 0x0008, 0xb87: 0x1af9, 0xb88: 0x06dd, 0xb89: 0x1471, 0xb8a: 0x06f5, 0xb8b: 0x1489, - 0xb8c: 0x1aa9, 0xb8d: 0x1b2a, 0xb8e: 0x1b5a, 0xb8f: 0x1b8a, 0xb90: 0x0008, 0xb91: 0x0008, - 0xb92: 0x0008, 0xb93: 0x1bb9, 0xb94: 0x0040, 0xb95: 0x0040, 0xb96: 0x0008, 0xb97: 0x0008, - 0xb98: 0xe045, 0xb99: 0xe045, 0xb9a: 0x070d, 0xb9b: 0x14a1, 0xb9c: 0x0040, 0xb9d: 0x1bd2, - 0xb9e: 0x1c02, 0xb9f: 0x1c32, 0xba0: 0x0008, 0xba1: 0x0008, 0xba2: 0x0008, 0xba3: 0x1c61, - 0xba4: 0x0008, 0xba5: 0x0008, 0xba6: 0x0008, 0xba7: 0x0008, 0xba8: 0xe045, 0xba9: 0xe045, - 0xbaa: 0x0725, 0xbab: 0x14d1, 0xbac: 0xe04d, 0xbad: 0x1c7a, 0xbae: 0x03d2, 0xbaf: 0x1caa, - 0xbb0: 0x0040, 0xbb1: 0x0040, 0xbb2: 0x1cb9, 0xbb3: 0x1ce9, 0xbb4: 0x1d11, 0xbb5: 0x0040, - 0xbb6: 0x0008, 0xbb7: 0x1d39, 0xbb8: 0x073d, 0xbb9: 0x14b9, 0xbba: 0x0515, 0xbbb: 0x14e9, - 0xbbc: 0x1ce9, 0xbbd: 0x0756, 0xbbe: 0x0776, 0xbbf: 0x0040, - // Block 0x2f, offset 0xbc0 - 0xbc0: 0x000a, 0xbc1: 0x000a, 0xbc2: 0x000a, 0xbc3: 0x000a, 0xbc4: 0x000a, 0xbc5: 0x000a, - 0xbc6: 0x000a, 0xbc7: 0x000a, 0xbc8: 0x000a, 0xbc9: 0x000a, 0xbca: 0x000a, 0xbcb: 0x03c0, - 0xbcc: 0x0003, 0xbcd: 0x0003, 0xbce: 0x0340, 0xbcf: 0x0b40, 0xbd0: 0x0018, 0xbd1: 0xe00d, - 0xbd2: 0x0018, 0xbd3: 0x0018, 0xbd4: 0x0018, 0xbd5: 0x0018, 0xbd6: 0x0018, 0xbd7: 0x0796, - 0xbd8: 0x0018, 0xbd9: 0x0018, 0xbda: 0x0018, 0xbdb: 0x0018, 0xbdc: 0x0018, 0xbdd: 0x0018, - 0xbde: 0x0018, 0xbdf: 0x0018, 0xbe0: 0x0018, 0xbe1: 0x0018, 0xbe2: 0x0018, 0xbe3: 0x0018, - 0xbe4: 0x0040, 0xbe5: 0x0040, 0xbe6: 0x0040, 0xbe7: 0x0018, 0xbe8: 0x0040, 0xbe9: 0x0040, - 0xbea: 0x0340, 0xbeb: 0x0340, 0xbec: 0x0340, 0xbed: 0x0340, 0xbee: 0x0340, 0xbef: 0x000a, - 0xbf0: 0x0018, 0xbf1: 0x0018, 0xbf2: 0x0018, 0xbf3: 0x1d69, 0xbf4: 0x1da1, 0xbf5: 0x0018, - 0xbf6: 0x1df1, 0xbf7: 0x1e29, 0xbf8: 0x0018, 0xbf9: 0x0018, 0xbfa: 0x0018, 0xbfb: 0x0018, - 0xbfc: 0x1e7a, 0xbfd: 0x0018, 0xbfe: 0x07b6, 0xbff: 0x0018, - // Block 0x30, offset 0xc00 - 0xc00: 0x0018, 0xc01: 0x0018, 0xc02: 0x0018, 0xc03: 0x0018, 0xc04: 0x0018, 0xc05: 0x0018, - 0xc06: 0x0018, 0xc07: 0x1e92, 0xc08: 0x1eaa, 0xc09: 0x1ec2, 0xc0a: 0x0018, 0xc0b: 0x0018, - 0xc0c: 0x0018, 0xc0d: 0x0018, 0xc0e: 0x0018, 0xc0f: 0x0018, 0xc10: 0x0018, 0xc11: 0x0018, - 0xc12: 0x0018, 0xc13: 0x0018, 0xc14: 0x0018, 0xc15: 0x0018, 0xc16: 0x0018, 0xc17: 0x1ed9, - 0xc18: 0x0018, 0xc19: 0x0018, 0xc1a: 0x0018, 0xc1b: 0x0018, 0xc1c: 0x0018, 0xc1d: 0x0018, - 0xc1e: 0x0018, 0xc1f: 0x000a, 0xc20: 0x03c0, 0xc21: 0x0340, 0xc22: 0x0340, 0xc23: 0x0340, - 0xc24: 0x03c0, 0xc25: 0x0040, 0xc26: 0x0040, 0xc27: 0x0040, 0xc28: 0x0040, 0xc29: 0x0040, - 0xc2a: 0x0340, 0xc2b: 0x0340, 0xc2c: 0x0340, 0xc2d: 0x0340, 0xc2e: 0x0340, 0xc2f: 0x0340, - 0xc30: 0x1f41, 0xc31: 0x0f41, 0xc32: 0x0040, 0xc33: 0x0040, 0xc34: 0x1f51, 0xc35: 0x1f61, - 0xc36: 0x1f71, 0xc37: 0x1f81, 0xc38: 0x1f91, 0xc39: 0x1fa1, 0xc3a: 0x1fb2, 0xc3b: 0x07d5, - 0xc3c: 0x1fc2, 0xc3d: 0x1fd2, 0xc3e: 0x1fe2, 0xc3f: 0x0f71, - // Block 0x31, offset 0xc40 - 0xc40: 0x1f41, 0xc41: 0x00c9, 0xc42: 0x0069, 0xc43: 0x0079, 0xc44: 0x1f51, 0xc45: 0x1f61, - 0xc46: 0x1f71, 0xc47: 0x1f81, 0xc48: 0x1f91, 0xc49: 0x1fa1, 0xc4a: 0x1fb2, 0xc4b: 0x07ed, - 0xc4c: 0x1fc2, 0xc4d: 0x1fd2, 0xc4e: 0x1fe2, 0xc4f: 0x0040, 0xc50: 0x0039, 0xc51: 0x0f09, - 0xc52: 0x00d9, 0xc53: 0x0369, 0xc54: 0x0ff9, 0xc55: 0x0249, 0xc56: 0x0f51, 0xc57: 0x0359, - 0xc58: 0x0f61, 0xc59: 0x0f71, 0xc5a: 0x0f99, 0xc5b: 0x01d9, 0xc5c: 0x0fa9, 0xc5d: 0x0040, - 0xc5e: 0x0040, 0xc5f: 0x0040, 0xc60: 0x0018, 0xc61: 0x0018, 0xc62: 0x0018, 0xc63: 0x0018, - 0xc64: 0x0018, 0xc65: 0x0018, 0xc66: 0x0018, 0xc67: 0x0018, 0xc68: 0x1ff1, 0xc69: 0x0018, - 0xc6a: 0x0018, 0xc6b: 0x0018, 0xc6c: 0x0018, 0xc6d: 0x0018, 0xc6e: 0x0018, 0xc6f: 0x0018, - 0xc70: 0x0018, 0xc71: 0x0018, 0xc72: 0x0018, 0xc73: 0x0018, 0xc74: 0x0018, 0xc75: 0x0018, - 0xc76: 0x0018, 0xc77: 0x0018, 0xc78: 0x0018, 0xc79: 0x0018, 0xc7a: 0x0018, 0xc7b: 0x0018, - 0xc7c: 0x0018, 0xc7d: 0x0018, 0xc7e: 0x0018, 0xc7f: 0x0018, - // Block 0x32, offset 0xc80 - 0xc80: 0x0806, 0xc81: 0x0826, 0xc82: 0x1159, 0xc83: 0x0845, 0xc84: 0x0018, 0xc85: 0x0866, - 0xc86: 0x0886, 0xc87: 0x1011, 0xc88: 0x0018, 0xc89: 0x08a5, 0xc8a: 0x0f31, 0xc8b: 0x0249, - 0xc8c: 0x0249, 0xc8d: 0x0249, 0xc8e: 0x0249, 0xc8f: 0x2009, 0xc90: 0x0f41, 0xc91: 0x0f41, - 0xc92: 0x0359, 0xc93: 0x0359, 0xc94: 0x0018, 0xc95: 0x0f71, 0xc96: 0x2021, 0xc97: 0x0018, - 0xc98: 0x0018, 0xc99: 0x0f99, 0xc9a: 0x2039, 0xc9b: 0x0269, 0xc9c: 0x0269, 0xc9d: 0x0269, - 0xc9e: 0x0018, 0xc9f: 0x0018, 0xca0: 0x2049, 0xca1: 0x08c5, 0xca2: 0x2061, 0xca3: 0x0018, - 0xca4: 0x13d1, 0xca5: 0x0018, 0xca6: 0x2079, 0xca7: 0x0018, 0xca8: 0x13d1, 0xca9: 0x0018, - 0xcaa: 0x0f51, 0xcab: 0x2091, 0xcac: 0x0ee9, 0xcad: 0x1159, 0xcae: 0x0018, 0xcaf: 0x0f09, - 0xcb0: 0x0f09, 0xcb1: 0x1199, 0xcb2: 0x0040, 0xcb3: 0x0f61, 0xcb4: 0x00d9, 0xcb5: 0x20a9, - 0xcb6: 0x20c1, 0xcb7: 0x20d9, 0xcb8: 0x20f1, 0xcb9: 0x0f41, 0xcba: 0x0018, 0xcbb: 0x08e5, - 0xcbc: 0x2109, 0xcbd: 0x10b1, 0xcbe: 0x10b1, 0xcbf: 0x2109, - // Block 0x33, offset 0xcc0 - 0xcc0: 0x0905, 0xcc1: 0x0018, 0xcc2: 0x0018, 0xcc3: 0x0018, 0xcc4: 0x0018, 0xcc5: 0x0ef9, - 0xcc6: 0x0ef9, 0xcc7: 0x0f09, 0xcc8: 0x0f41, 0xcc9: 0x0259, 0xcca: 0x0018, 0xccb: 0x0018, - 0xccc: 0x0018, 0xccd: 0x0018, 0xcce: 0x0008, 0xccf: 0x0018, 0xcd0: 0x2121, 0xcd1: 0x2151, - 0xcd2: 0x2181, 0xcd3: 0x21b9, 0xcd4: 0x21e9, 0xcd5: 0x2219, 0xcd6: 0x2249, 0xcd7: 0x2279, - 0xcd8: 0x22a9, 0xcd9: 0x22d9, 0xcda: 0x2309, 0xcdb: 0x2339, 0xcdc: 0x2369, 0xcdd: 0x2399, - 0xcde: 0x23c9, 0xcdf: 0x23f9, 0xce0: 0x0f41, 0xce1: 0x2421, 0xce2: 0x091d, 0xce3: 0x2439, - 0xce4: 0x1089, 0xce5: 0x2451, 0xce6: 0x093d, 0xce7: 0x2469, 0xce8: 0x2491, 0xce9: 0x0369, - 0xcea: 0x24a9, 0xceb: 0x095d, 0xcec: 0x0359, 0xced: 0x1159, 0xcee: 0x0ef9, 0xcef: 0x0f61, - 0xcf0: 0x0f41, 0xcf1: 0x2421, 0xcf2: 0x097d, 0xcf3: 0x2439, 0xcf4: 0x1089, 0xcf5: 0x2451, - 0xcf6: 0x099d, 0xcf7: 0x2469, 0xcf8: 0x2491, 0xcf9: 0x0369, 0xcfa: 0x24a9, 0xcfb: 0x09bd, - 0xcfc: 0x0359, 0xcfd: 0x1159, 0xcfe: 0x0ef9, 0xcff: 0x0f61, - // Block 0x34, offset 0xd00 - 0xd00: 0x0018, 0xd01: 0x0018, 0xd02: 0x0018, 0xd03: 0x0018, 0xd04: 0x0018, 0xd05: 0x0018, - 0xd06: 0x0018, 0xd07: 0x0018, 0xd08: 0x0018, 0xd09: 0x0018, 0xd0a: 0x0018, 0xd0b: 0x0040, - 0xd0c: 0x0040, 0xd0d: 0x0040, 0xd0e: 0x0040, 0xd0f: 0x0040, 0xd10: 0x0040, 0xd11: 0x0040, - 0xd12: 0x0040, 0xd13: 0x0040, 0xd14: 0x0040, 0xd15: 0x0040, 0xd16: 0x0040, 0xd17: 0x0040, - 0xd18: 0x0040, 0xd19: 0x0040, 0xd1a: 0x0040, 0xd1b: 0x0040, 0xd1c: 0x0040, 0xd1d: 0x0040, - 0xd1e: 0x0040, 0xd1f: 0x0040, 0xd20: 0x00c9, 0xd21: 0x0069, 0xd22: 0x0079, 0xd23: 0x1f51, - 0xd24: 0x1f61, 0xd25: 0x1f71, 0xd26: 0x1f81, 0xd27: 0x1f91, 0xd28: 0x1fa1, 0xd29: 0x2601, - 0xd2a: 0x2619, 0xd2b: 0x2631, 0xd2c: 0x2649, 0xd2d: 0x2661, 0xd2e: 0x2679, 0xd2f: 0x2691, - 0xd30: 0x26a9, 0xd31: 0x26c1, 0xd32: 0x26d9, 0xd33: 0x26f1, 0xd34: 0x0a1e, 0xd35: 0x0a3e, - 0xd36: 0x0a5e, 0xd37: 0x0a7e, 0xd38: 0x0a9e, 0xd39: 0x0abe, 0xd3a: 0x0ade, 0xd3b: 0x0afe, - 0xd3c: 0x0b1e, 0xd3d: 0x270a, 0xd3e: 0x2732, 0xd3f: 0x275a, - // Block 0x35, offset 0xd40 - 0xd40: 0x2782, 0xd41: 0x27aa, 0xd42: 0x27d2, 0xd43: 0x27fa, 0xd44: 0x2822, 0xd45: 0x284a, - 0xd46: 0x2872, 0xd47: 0x289a, 0xd48: 0x0040, 0xd49: 0x0040, 0xd4a: 0x0040, 0xd4b: 0x0040, - 0xd4c: 0x0040, 0xd4d: 0x0040, 0xd4e: 0x0040, 0xd4f: 0x0040, 0xd50: 0x0040, 0xd51: 0x0040, - 0xd52: 0x0040, 0xd53: 0x0040, 0xd54: 0x0040, 0xd55: 0x0040, 0xd56: 0x0040, 0xd57: 0x0040, - 0xd58: 0x0040, 0xd59: 0x0040, 0xd5a: 0x0040, 0xd5b: 0x0040, 0xd5c: 0x0b3e, 0xd5d: 0x0b5e, - 0xd5e: 0x0b7e, 0xd5f: 0x0b9e, 0xd60: 0x0bbe, 0xd61: 0x0bde, 0xd62: 0x0bfe, 0xd63: 0x0c1e, - 0xd64: 0x0c3e, 0xd65: 0x0c5e, 0xd66: 0x0c7e, 0xd67: 0x0c9e, 0xd68: 0x0cbe, 0xd69: 0x0cde, - 0xd6a: 0x0cfe, 0xd6b: 0x0d1e, 0xd6c: 0x0d3e, 0xd6d: 0x0d5e, 0xd6e: 0x0d7e, 0xd6f: 0x0d9e, - 0xd70: 0x0dbe, 0xd71: 0x0dde, 0xd72: 0x0dfe, 0xd73: 0x0e1e, 0xd74: 0x0e3e, 0xd75: 0x0e5e, - 0xd76: 0x0039, 0xd77: 0x0ee9, 0xd78: 0x1159, 0xd79: 0x0ef9, 0xd7a: 0x0f09, 0xd7b: 0x1199, - 0xd7c: 0x0f31, 0xd7d: 0x0249, 0xd7e: 0x0f41, 0xd7f: 0x0259, - // Block 0x36, offset 0xd80 - 0xd80: 0x0f51, 0xd81: 0x0359, 0xd82: 0x0f61, 0xd83: 0x0f71, 0xd84: 0x00d9, 0xd85: 0x0f99, - 0xd86: 0x2039, 0xd87: 0x0269, 0xd88: 0x01d9, 0xd89: 0x0fa9, 0xd8a: 0x0fb9, 0xd8b: 0x1089, - 0xd8c: 0x0279, 0xd8d: 0x0369, 0xd8e: 0x0289, 0xd8f: 0x13d1, 0xd90: 0x0039, 0xd91: 0x0ee9, - 0xd92: 0x1159, 0xd93: 0x0ef9, 0xd94: 0x0f09, 0xd95: 0x1199, 0xd96: 0x0f31, 0xd97: 0x0249, - 0xd98: 0x0f41, 0xd99: 0x0259, 0xd9a: 0x0f51, 0xd9b: 0x0359, 0xd9c: 0x0f61, 0xd9d: 0x0f71, - 0xd9e: 0x00d9, 0xd9f: 0x0f99, 0xda0: 0x2039, 0xda1: 0x0269, 0xda2: 0x01d9, 0xda3: 0x0fa9, - 0xda4: 0x0fb9, 0xda5: 0x1089, 0xda6: 0x0279, 0xda7: 0x0369, 0xda8: 0x0289, 0xda9: 0x13d1, - 0xdaa: 0x1f41, 0xdab: 0x0018, 0xdac: 0x0018, 0xdad: 0x0018, 0xdae: 0x0018, 0xdaf: 0x0018, - 0xdb0: 0x0018, 0xdb1: 0x0018, 0xdb2: 0x0018, 0xdb3: 0x0018, 0xdb4: 0x0018, 0xdb5: 0x0018, - 0xdb6: 0x0018, 0xdb7: 0x0018, 0xdb8: 0x0018, 0xdb9: 0x0018, 0xdba: 0x0018, 0xdbb: 0x0018, - 0xdbc: 0x0018, 0xdbd: 0x0018, 0xdbe: 0x0018, 0xdbf: 0x0018, - // Block 0x37, offset 0xdc0 - 0xdc0: 0x0008, 0xdc1: 0x0008, 0xdc2: 0x0008, 0xdc3: 0x0008, 0xdc4: 0x0008, 0xdc5: 0x0008, - 0xdc6: 0x0008, 0xdc7: 0x0008, 0xdc8: 0x0008, 0xdc9: 0x0008, 0xdca: 0x0008, 0xdcb: 0x0008, - 0xdcc: 0x0008, 0xdcd: 0x0008, 0xdce: 0x0008, 0xdcf: 0x0008, 0xdd0: 0x0008, 0xdd1: 0x0008, - 0xdd2: 0x0008, 0xdd3: 0x0008, 0xdd4: 0x0008, 0xdd5: 0x0008, 0xdd6: 0x0008, 0xdd7: 0x0008, - 0xdd8: 0x0008, 0xdd9: 0x0008, 0xdda: 0x0008, 0xddb: 0x0008, 0xddc: 0x0008, 0xddd: 0x0008, - 0xdde: 0x0008, 0xddf: 0x0040, 0xde0: 0xe00d, 0xde1: 0x0008, 0xde2: 0x2971, 0xde3: 0x0ed5, - 0xde4: 0x2989, 0xde5: 0x0008, 0xde6: 0x0008, 0xde7: 0xe07d, 0xde8: 0x0008, 0xde9: 0xe01d, - 0xdea: 0x0008, 0xdeb: 0xe03d, 0xdec: 0x0008, 0xded: 0x0fe1, 0xdee: 0x1281, 0xdef: 0x0fc9, - 0xdf0: 0x1141, 0xdf1: 0x0008, 0xdf2: 0xe00d, 0xdf3: 0x0008, 0xdf4: 0x0008, 0xdf5: 0xe01d, - 0xdf6: 0x0008, 0xdf7: 0x0008, 0xdf8: 0x0008, 0xdf9: 0x0008, 0xdfa: 0x0008, 0xdfb: 0x0008, - 0xdfc: 0x0259, 0xdfd: 0x1089, 0xdfe: 0x29a1, 0xdff: 0x29b9, - // Block 0x38, offset 0xe00 - 0xe00: 0xe00d, 0xe01: 0x0008, 0xe02: 0xe00d, 0xe03: 0x0008, 0xe04: 0xe00d, 0xe05: 0x0008, - 0xe06: 0xe00d, 0xe07: 0x0008, 0xe08: 0xe00d, 0xe09: 0x0008, 0xe0a: 0xe00d, 0xe0b: 0x0008, - 0xe0c: 0xe00d, 0xe0d: 0x0008, 0xe0e: 0xe00d, 0xe0f: 0x0008, 0xe10: 0xe00d, 0xe11: 0x0008, - 0xe12: 0xe00d, 0xe13: 0x0008, 0xe14: 0xe00d, 0xe15: 0x0008, 0xe16: 0xe00d, 0xe17: 0x0008, - 0xe18: 0xe00d, 0xe19: 0x0008, 0xe1a: 0xe00d, 0xe1b: 0x0008, 0xe1c: 0xe00d, 0xe1d: 0x0008, - 0xe1e: 0xe00d, 0xe1f: 0x0008, 0xe20: 0xe00d, 0xe21: 0x0008, 0xe22: 0xe00d, 0xe23: 0x0008, - 0xe24: 0x0008, 0xe25: 0x0018, 0xe26: 0x0018, 0xe27: 0x0018, 0xe28: 0x0018, 0xe29: 0x0018, - 0xe2a: 0x0018, 0xe2b: 0xe03d, 0xe2c: 0x0008, 0xe2d: 0xe01d, 0xe2e: 0x0008, 0xe2f: 0x3308, - 0xe30: 0x3308, 0xe31: 0x3308, 0xe32: 0xe00d, 0xe33: 0x0008, 0xe34: 0x0040, 0xe35: 0x0040, - 0xe36: 0x0040, 0xe37: 0x0040, 0xe38: 0x0040, 0xe39: 0x0018, 0xe3a: 0x0018, 0xe3b: 0x0018, - 0xe3c: 0x0018, 0xe3d: 0x0018, 0xe3e: 0x0018, 0xe3f: 0x0018, - // Block 0x39, offset 0xe40 - 0xe40: 0x2715, 0xe41: 0x2735, 0xe42: 0x2755, 0xe43: 0x2775, 0xe44: 0x2795, 0xe45: 0x27b5, - 0xe46: 0x27d5, 0xe47: 0x27f5, 0xe48: 0x2815, 0xe49: 0x2835, 0xe4a: 0x2855, 0xe4b: 0x2875, - 0xe4c: 0x2895, 0xe4d: 0x28b5, 0xe4e: 0x28d5, 0xe4f: 0x28f5, 0xe50: 0x2915, 0xe51: 0x2935, - 0xe52: 0x2955, 0xe53: 0x2975, 0xe54: 0x2995, 0xe55: 0x29b5, 0xe56: 0x0040, 0xe57: 0x0040, - 0xe58: 0x0040, 0xe59: 0x0040, 0xe5a: 0x0040, 0xe5b: 0x0040, 0xe5c: 0x0040, 0xe5d: 0x0040, - 0xe5e: 0x0040, 0xe5f: 0x0040, 0xe60: 0x0040, 0xe61: 0x0040, 0xe62: 0x0040, 0xe63: 0x0040, - 0xe64: 0x0040, 0xe65: 0x0040, 0xe66: 0x0040, 0xe67: 0x0040, 0xe68: 0x0040, 0xe69: 0x0040, - 0xe6a: 0x0040, 0xe6b: 0x0040, 0xe6c: 0x0040, 0xe6d: 0x0040, 0xe6e: 0x0040, 0xe6f: 0x0040, - 0xe70: 0x0040, 0xe71: 0x0040, 0xe72: 0x0040, 0xe73: 0x0040, 0xe74: 0x0040, 0xe75: 0x0040, - 0xe76: 0x0040, 0xe77: 0x0040, 0xe78: 0x0040, 0xe79: 0x0040, 0xe7a: 0x0040, 0xe7b: 0x0040, - 0xe7c: 0x0040, 0xe7d: 0x0040, 0xe7e: 0x0040, 0xe7f: 0x0040, - // Block 0x3a, offset 0xe80 - 0xe80: 0x000a, 0xe81: 0x0018, 0xe82: 0x29d1, 0xe83: 0x0018, 0xe84: 0x0018, 0xe85: 0x0008, - 0xe86: 0x0008, 0xe87: 0x0008, 0xe88: 0x0018, 0xe89: 0x0018, 0xe8a: 0x0018, 0xe8b: 0x0018, - 0xe8c: 0x0018, 0xe8d: 0x0018, 0xe8e: 0x0018, 0xe8f: 0x0018, 0xe90: 0x0018, 0xe91: 0x0018, - 0xe92: 0x0018, 0xe93: 0x0018, 0xe94: 0x0018, 0xe95: 0x0018, 0xe96: 0x0018, 0xe97: 0x0018, - 0xe98: 0x0018, 0xe99: 0x0018, 0xe9a: 0x0018, 0xe9b: 0x0018, 0xe9c: 0x0018, 0xe9d: 0x0018, - 0xe9e: 0x0018, 0xe9f: 0x0018, 0xea0: 0x0018, 0xea1: 0x0018, 0xea2: 0x0018, 0xea3: 0x0018, - 0xea4: 0x0018, 0xea5: 0x0018, 0xea6: 0x0018, 0xea7: 0x0018, 0xea8: 0x0018, 0xea9: 0x0018, - 0xeaa: 0x3308, 0xeab: 0x3308, 0xeac: 0x3308, 0xead: 0x3308, 0xeae: 0x3018, 0xeaf: 0x3018, - 0xeb0: 0x0018, 0xeb1: 0x0018, 0xeb2: 0x0018, 0xeb3: 0x0018, 0xeb4: 0x0018, 0xeb5: 0x0018, - 0xeb6: 0xe125, 0xeb7: 0x0018, 0xeb8: 0x29d5, 0xeb9: 0x29f5, 0xeba: 0x2a15, 0xebb: 0x0018, - 0xebc: 0x0008, 0xebd: 0x0018, 0xebe: 0x0018, 0xebf: 0x0018, - // Block 0x3b, offset 0xec0 - 0xec0: 0x2b55, 0xec1: 0x2b75, 0xec2: 0x2b95, 0xec3: 0x2bb5, 0xec4: 0x2bd5, 0xec5: 0x2bf5, - 0xec6: 0x2bf5, 0xec7: 0x2bf5, 0xec8: 0x2c15, 0xec9: 0x2c15, 0xeca: 0x2c15, 0xecb: 0x2c15, - 0xecc: 0x2c35, 0xecd: 0x2c35, 0xece: 0x2c35, 0xecf: 0x2c55, 0xed0: 0x2c75, 0xed1: 0x2c75, - 0xed2: 0x2a95, 0xed3: 0x2a95, 0xed4: 0x2c75, 0xed5: 0x2c75, 0xed6: 0x2c95, 0xed7: 0x2c95, - 0xed8: 0x2c75, 0xed9: 0x2c75, 0xeda: 0x2a95, 0xedb: 0x2a95, 0xedc: 0x2c75, 0xedd: 0x2c75, - 0xede: 0x2c55, 0xedf: 0x2c55, 0xee0: 0x2cb5, 0xee1: 0x2cb5, 0xee2: 0x2cd5, 0xee3: 0x2cd5, - 0xee4: 0x0040, 0xee5: 0x2cf5, 0xee6: 0x2d15, 0xee7: 0x2d35, 0xee8: 0x2d35, 0xee9: 0x2d55, - 0xeea: 0x2d75, 0xeeb: 0x2d95, 0xeec: 0x2db5, 0xeed: 0x2dd5, 0xeee: 0x2df5, 0xeef: 0x2e15, - 0xef0: 0x2e35, 0xef1: 0x2e55, 0xef2: 0x2e55, 0xef3: 0x2e75, 0xef4: 0x2e95, 0xef5: 0x2e95, - 0xef6: 0x2eb5, 0xef7: 0x2ed5, 0xef8: 0x2e75, 0xef9: 0x2ef5, 0xefa: 0x2f15, 0xefb: 0x2ef5, - 0xefc: 0x2e75, 0xefd: 0x2f35, 0xefe: 0x2f55, 0xeff: 0x2f75, - // Block 0x3c, offset 0xf00 - 0xf00: 0x2f95, 0xf01: 0x2fb5, 0xf02: 0x2d15, 0xf03: 0x2cf5, 0xf04: 0x2fd5, 0xf05: 0x2ff5, - 0xf06: 0x3015, 0xf07: 0x3035, 0xf08: 0x3055, 0xf09: 0x3075, 0xf0a: 0x3095, 0xf0b: 0x30b5, - 0xf0c: 0x30d5, 0xf0d: 0x30f5, 0xf0e: 0x3115, 0xf0f: 0x0040, 0xf10: 0x0018, 0xf11: 0x0018, - 0xf12: 0x3135, 0xf13: 0x3155, 0xf14: 0x3175, 0xf15: 0x3195, 0xf16: 0x31b5, 0xf17: 0x31d5, - 0xf18: 0x31f5, 0xf19: 0x3215, 0xf1a: 0x3235, 0xf1b: 0x3255, 0xf1c: 0x3175, 0xf1d: 0x3275, - 0xf1e: 0x3295, 0xf1f: 0x32b5, 0xf20: 0x0008, 0xf21: 0x0008, 0xf22: 0x0008, 0xf23: 0x0008, - 0xf24: 0x0008, 0xf25: 0x0008, 0xf26: 0x0008, 0xf27: 0x0008, 0xf28: 0x0008, 0xf29: 0x0008, - 0xf2a: 0x0008, 0xf2b: 0x0008, 0xf2c: 0x0008, 0xf2d: 0x0008, 0xf2e: 0x0008, 0xf2f: 0x0008, - 0xf30: 0x0008, 0xf31: 0x0008, 0xf32: 0x0008, 0xf33: 0x0008, 0xf34: 0x0008, 0xf35: 0x0008, - 0xf36: 0x0008, 0xf37: 0x0008, 0xf38: 0x0008, 0xf39: 0x0008, 0xf3a: 0x0008, 0xf3b: 0x0040, - 0xf3c: 0x0040, 0xf3d: 0x0040, 0xf3e: 0x0040, 0xf3f: 0x0040, - // Block 0x3d, offset 0xf40 - 0xf40: 0x36a2, 0xf41: 0x36d2, 0xf42: 0x3702, 0xf43: 0x3732, 0xf44: 0x32d5, 0xf45: 0x32f5, - 0xf46: 0x3315, 0xf47: 0x3335, 0xf48: 0x0018, 0xf49: 0x0018, 0xf4a: 0x0018, 0xf4b: 0x0018, - 0xf4c: 0x0018, 0xf4d: 0x0018, 0xf4e: 0x0018, 0xf4f: 0x0018, 0xf50: 0x3355, 0xf51: 0x3761, - 0xf52: 0x3779, 0xf53: 0x3791, 0xf54: 0x37a9, 0xf55: 0x37c1, 0xf56: 0x37d9, 0xf57: 0x37f1, - 0xf58: 0x3809, 0xf59: 0x3821, 0xf5a: 0x3839, 0xf5b: 0x3851, 0xf5c: 0x3869, 0xf5d: 0x3881, - 0xf5e: 0x3899, 0xf5f: 0x38b1, 0xf60: 0x3375, 0xf61: 0x3395, 0xf62: 0x33b5, 0xf63: 0x33d5, - 0xf64: 0x33f5, 0xf65: 0x33f5, 0xf66: 0x3415, 0xf67: 0x3435, 0xf68: 0x3455, 0xf69: 0x3475, - 0xf6a: 0x3495, 0xf6b: 0x34b5, 0xf6c: 0x34d5, 0xf6d: 0x34f5, 0xf6e: 0x3515, 0xf6f: 0x3535, - 0xf70: 0x3555, 0xf71: 0x3575, 0xf72: 0x3595, 0xf73: 0x35b5, 0xf74: 0x35d5, 0xf75: 0x35f5, - 0xf76: 0x3615, 0xf77: 0x3635, 0xf78: 0x3655, 0xf79: 0x3675, 0xf7a: 0x3695, 0xf7b: 0x36b5, - 0xf7c: 0x38c9, 0xf7d: 0x3901, 0xf7e: 0x36d5, 0xf7f: 0x0018, - // Block 0x3e, offset 0xf80 - 0xf80: 0x36f5, 0xf81: 0x3715, 0xf82: 0x3735, 0xf83: 0x3755, 0xf84: 0x3775, 0xf85: 0x3795, - 0xf86: 0x37b5, 0xf87: 0x37d5, 0xf88: 0x37f5, 0xf89: 0x3815, 0xf8a: 0x3835, 0xf8b: 0x3855, - 0xf8c: 0x3875, 0xf8d: 0x3895, 0xf8e: 0x38b5, 0xf8f: 0x38d5, 0xf90: 0x38f5, 0xf91: 0x3915, - 0xf92: 0x3935, 0xf93: 0x3955, 0xf94: 0x3975, 0xf95: 0x3995, 0xf96: 0x39b5, 0xf97: 0x39d5, - 0xf98: 0x39f5, 0xf99: 0x3a15, 0xf9a: 0x3a35, 0xf9b: 0x3a55, 0xf9c: 0x3a75, 0xf9d: 0x3a95, - 0xf9e: 0x3ab5, 0xf9f: 0x3ad5, 0xfa0: 0x3af5, 0xfa1: 0x3b15, 0xfa2: 0x3b35, 0xfa3: 0x3b55, - 0xfa4: 0x3b75, 0xfa5: 0x3b95, 0xfa6: 0x1295, 0xfa7: 0x3bb5, 0xfa8: 0x3bd5, 0xfa9: 0x3bf5, - 0xfaa: 0x3c15, 0xfab: 0x3c35, 0xfac: 0x3c55, 0xfad: 0x3c75, 0xfae: 0x23b5, 0xfaf: 0x3c95, - 0xfb0: 0x3cb5, 0xfb1: 0x3939, 0xfb2: 0x3951, 0xfb3: 0x3969, 0xfb4: 0x3981, 0xfb5: 0x3999, - 0xfb6: 0x39b1, 0xfb7: 0x39c9, 0xfb8: 0x39e1, 0xfb9: 0x39f9, 0xfba: 0x3a11, 0xfbb: 0x3a29, - 0xfbc: 0x3a41, 0xfbd: 0x3a59, 0xfbe: 0x3a71, 0xfbf: 0x3a89, - // Block 0x3f, offset 0xfc0 - 0xfc0: 0x3aa1, 0xfc1: 0x3ac9, 0xfc2: 0x3af1, 0xfc3: 0x3b19, 0xfc4: 0x3b41, 0xfc5: 0x3b69, - 0xfc6: 0x3b91, 0xfc7: 0x3bb9, 0xfc8: 0x3be1, 0xfc9: 0x3c09, 0xfca: 0x3c39, 0xfcb: 0x3c69, - 0xfcc: 0x3c99, 0xfcd: 0x3cd5, 0xfce: 0x3cb1, 0xfcf: 0x3cf5, 0xfd0: 0x3d15, 0xfd1: 0x3d2d, - 0xfd2: 0x3d45, 0xfd3: 0x3d5d, 0xfd4: 0x3d75, 0xfd5: 0x3d75, 0xfd6: 0x3d5d, 0xfd7: 0x3d8d, - 0xfd8: 0x07d5, 0xfd9: 0x3da5, 0xfda: 0x3dbd, 0xfdb: 0x3dd5, 0xfdc: 0x3ded, 0xfdd: 0x3e05, - 0xfde: 0x3e1d, 0xfdf: 0x3e35, 0xfe0: 0x3e4d, 0xfe1: 0x3e65, 0xfe2: 0x3e7d, 0xfe3: 0x3e95, - 0xfe4: 0x3ead, 0xfe5: 0x3ead, 0xfe6: 0x3ec5, 0xfe7: 0x3ec5, 0xfe8: 0x3edd, 0xfe9: 0x3edd, - 0xfea: 0x3ef5, 0xfeb: 0x3f0d, 0xfec: 0x3f25, 0xfed: 0x3f3d, 0xfee: 0x3f55, 0xfef: 0x3f55, - 0xff0: 0x3f6d, 0xff1: 0x3f6d, 0xff2: 0x3f6d, 0xff3: 0x3f85, 0xff4: 0x3f9d, 0xff5: 0x3fb5, - 0xff6: 0x3fcd, 0xff7: 0x3fb5, 0xff8: 0x3fe5, 0xff9: 0x3ffd, 0xffa: 0x3f85, 0xffb: 0x4015, - 0xffc: 0x402d, 0xffd: 0x402d, 0xffe: 0x402d, 0xfff: 0x0040, - // Block 0x40, offset 0x1000 - 0x1000: 0x3cc9, 0x1001: 0x3d31, 0x1002: 0x3d99, 0x1003: 0x3e01, 0x1004: 0x3e51, 0x1005: 0x3eb9, - 0x1006: 0x3f09, 0x1007: 0x3f59, 0x1008: 0x3fd9, 0x1009: 0x4041, 0x100a: 0x4091, 0x100b: 0x40e1, - 0x100c: 0x4131, 0x100d: 0x4199, 0x100e: 0x4201, 0x100f: 0x4251, 0x1010: 0x42a1, 0x1011: 0x42d9, - 0x1012: 0x4329, 0x1013: 0x4391, 0x1014: 0x43f9, 0x1015: 0x4431, 0x1016: 0x44b1, 0x1017: 0x4549, - 0x1018: 0x45c9, 0x1019: 0x4619, 0x101a: 0x4699, 0x101b: 0x4719, 0x101c: 0x4781, 0x101d: 0x47d1, - 0x101e: 0x4821, 0x101f: 0x4871, 0x1020: 0x48d9, 0x1021: 0x4959, 0x1022: 0x49c1, 0x1023: 0x4a11, - 0x1024: 0x4a61, 0x1025: 0x4ab1, 0x1026: 0x4ae9, 0x1027: 0x4b21, 0x1028: 0x4b59, 0x1029: 0x4b91, - 0x102a: 0x4be1, 0x102b: 0x4c31, 0x102c: 0x4cb1, 0x102d: 0x4d01, 0x102e: 0x4d69, 0x102f: 0x4de9, - 0x1030: 0x4e39, 0x1031: 0x4e71, 0x1032: 0x4ea9, 0x1033: 0x4f29, 0x1034: 0x4f91, 0x1035: 0x5011, - 0x1036: 0x5061, 0x1037: 0x50e1, 0x1038: 0x5119, 0x1039: 0x5169, 0x103a: 0x51b9, 0x103b: 0x5209, - 0x103c: 0x5259, 0x103d: 0x52a9, 0x103e: 0x5311, 0x103f: 0x5361, - // Block 0x41, offset 0x1040 - 0x1040: 0x5399, 0x1041: 0x53e9, 0x1042: 0x5439, 0x1043: 0x5489, 0x1044: 0x54f1, 0x1045: 0x5541, - 0x1046: 0x5591, 0x1047: 0x55e1, 0x1048: 0x5661, 0x1049: 0x56c9, 0x104a: 0x5701, 0x104b: 0x5781, - 0x104c: 0x57b9, 0x104d: 0x5821, 0x104e: 0x5889, 0x104f: 0x58d9, 0x1050: 0x5929, 0x1051: 0x5979, - 0x1052: 0x59e1, 0x1053: 0x5a19, 0x1054: 0x5a69, 0x1055: 0x5ad1, 0x1056: 0x5b09, 0x1057: 0x5b89, - 0x1058: 0x5bd9, 0x1059: 0x5c01, 0x105a: 0x5c29, 0x105b: 0x5c51, 0x105c: 0x5c79, 0x105d: 0x5ca1, - 0x105e: 0x5cc9, 0x105f: 0x5cf1, 0x1060: 0x5d19, 0x1061: 0x5d41, 0x1062: 0x5d69, 0x1063: 0x5d99, - 0x1064: 0x5dc9, 0x1065: 0x5df9, 0x1066: 0x5e29, 0x1067: 0x5e59, 0x1068: 0x5e89, 0x1069: 0x5eb9, - 0x106a: 0x5ee9, 0x106b: 0x5f19, 0x106c: 0x5f49, 0x106d: 0x5f79, 0x106e: 0x5fa9, 0x106f: 0x5fd9, - 0x1070: 0x6009, 0x1071: 0x4045, 0x1072: 0x6039, 0x1073: 0x6051, 0x1074: 0x4065, 0x1075: 0x6069, - 0x1076: 0x6081, 0x1077: 0x6099, 0x1078: 0x4085, 0x1079: 0x4085, 0x107a: 0x60b1, 0x107b: 0x60c9, - 0x107c: 0x6101, 0x107d: 0x6139, 0x107e: 0x6171, 0x107f: 0x61a9, - // Block 0x42, offset 0x1080 - 0x1080: 0x6211, 0x1081: 0x6229, 0x1082: 0x40a5, 0x1083: 0x6241, 0x1084: 0x6259, 0x1085: 0x6271, - 0x1086: 0x6289, 0x1087: 0x62a1, 0x1088: 0x40c5, 0x1089: 0x62b9, 0x108a: 0x62e1, 0x108b: 0x62f9, - 0x108c: 0x40e5, 0x108d: 0x40e5, 0x108e: 0x6311, 0x108f: 0x6329, 0x1090: 0x6341, 0x1091: 0x4105, - 0x1092: 0x4125, 0x1093: 0x4145, 0x1094: 0x4165, 0x1095: 0x4185, 0x1096: 0x6359, 0x1097: 0x6371, - 0x1098: 0x6389, 0x1099: 0x63a1, 0x109a: 0x63b9, 0x109b: 0x41a5, 0x109c: 0x63d1, 0x109d: 0x63e9, - 0x109e: 0x6401, 0x109f: 0x41c5, 0x10a0: 0x41e5, 0x10a1: 0x6419, 0x10a2: 0x4205, 0x10a3: 0x4225, - 0x10a4: 0x4245, 0x10a5: 0x6431, 0x10a6: 0x4265, 0x10a7: 0x6449, 0x10a8: 0x6479, 0x10a9: 0x6211, - 0x10aa: 0x4285, 0x10ab: 0x42a5, 0x10ac: 0x42c5, 0x10ad: 0x42e5, 0x10ae: 0x64b1, 0x10af: 0x64f1, - 0x10b0: 0x6539, 0x10b1: 0x6551, 0x10b2: 0x4305, 0x10b3: 0x6569, 0x10b4: 0x6581, 0x10b5: 0x6599, - 0x10b6: 0x4325, 0x10b7: 0x65b1, 0x10b8: 0x65c9, 0x10b9: 0x65b1, 0x10ba: 0x65e1, 0x10bb: 0x65f9, - 0x10bc: 0x4345, 0x10bd: 0x6611, 0x10be: 0x6629, 0x10bf: 0x6611, - // Block 0x43, offset 0x10c0 - 0x10c0: 0x4365, 0x10c1: 0x4385, 0x10c2: 0x0040, 0x10c3: 0x6641, 0x10c4: 0x6659, 0x10c5: 0x6671, - 0x10c6: 0x6689, 0x10c7: 0x0040, 0x10c8: 0x66c1, 0x10c9: 0x66d9, 0x10ca: 0x66f1, 0x10cb: 0x6709, - 0x10cc: 0x6721, 0x10cd: 0x6739, 0x10ce: 0x6401, 0x10cf: 0x6751, 0x10d0: 0x6769, 0x10d1: 0x6781, - 0x10d2: 0x43a5, 0x10d3: 0x6799, 0x10d4: 0x6289, 0x10d5: 0x43c5, 0x10d6: 0x43e5, 0x10d7: 0x67b1, - 0x10d8: 0x0040, 0x10d9: 0x4405, 0x10da: 0x67c9, 0x10db: 0x67e1, 0x10dc: 0x67f9, 0x10dd: 0x6811, - 0x10de: 0x6829, 0x10df: 0x6859, 0x10e0: 0x6889, 0x10e1: 0x68b1, 0x10e2: 0x68d9, 0x10e3: 0x6901, - 0x10e4: 0x6929, 0x10e5: 0x6951, 0x10e6: 0x6979, 0x10e7: 0x69a1, 0x10e8: 0x69c9, 0x10e9: 0x69f1, - 0x10ea: 0x6a21, 0x10eb: 0x6a51, 0x10ec: 0x6a81, 0x10ed: 0x6ab1, 0x10ee: 0x6ae1, 0x10ef: 0x6b11, - 0x10f0: 0x6b41, 0x10f1: 0x6b71, 0x10f2: 0x6ba1, 0x10f3: 0x6bd1, 0x10f4: 0x6c01, 0x10f5: 0x6c31, - 0x10f6: 0x6c61, 0x10f7: 0x6c91, 0x10f8: 0x6cc1, 0x10f9: 0x6cf1, 0x10fa: 0x6d21, 0x10fb: 0x6d51, - 0x10fc: 0x6d81, 0x10fd: 0x6db1, 0x10fe: 0x6de1, 0x10ff: 0x4425, - // Block 0x44, offset 0x1100 - 0x1100: 0xe00d, 0x1101: 0x0008, 0x1102: 0xe00d, 0x1103: 0x0008, 0x1104: 0xe00d, 0x1105: 0x0008, - 0x1106: 0xe00d, 0x1107: 0x0008, 0x1108: 0xe00d, 0x1109: 0x0008, 0x110a: 0xe00d, 0x110b: 0x0008, - 0x110c: 0xe00d, 0x110d: 0x0008, 0x110e: 0xe00d, 0x110f: 0x0008, 0x1110: 0xe00d, 0x1111: 0x0008, - 0x1112: 0xe00d, 0x1113: 0x0008, 0x1114: 0xe00d, 0x1115: 0x0008, 0x1116: 0xe00d, 0x1117: 0x0008, - 0x1118: 0xe00d, 0x1119: 0x0008, 0x111a: 0xe00d, 0x111b: 0x0008, 0x111c: 0xe00d, 0x111d: 0x0008, - 0x111e: 0xe00d, 0x111f: 0x0008, 0x1120: 0xe00d, 0x1121: 0x0008, 0x1122: 0xe00d, 0x1123: 0x0008, - 0x1124: 0xe00d, 0x1125: 0x0008, 0x1126: 0xe00d, 0x1127: 0x0008, 0x1128: 0xe00d, 0x1129: 0x0008, - 0x112a: 0xe00d, 0x112b: 0x0008, 0x112c: 0xe00d, 0x112d: 0x0008, 0x112e: 0x0008, 0x112f: 0x3308, - 0x1130: 0x3318, 0x1131: 0x3318, 0x1132: 0x3318, 0x1133: 0x0018, 0x1134: 0x3308, 0x1135: 0x3308, - 0x1136: 0x3308, 0x1137: 0x3308, 0x1138: 0x3308, 0x1139: 0x3308, 0x113a: 0x3308, 0x113b: 0x3308, - 0x113c: 0x3308, 0x113d: 0x3308, 0x113e: 0x0018, 0x113f: 0x0008, - // Block 0x45, offset 0x1140 - 0x1140: 0xe00d, 0x1141: 0x0008, 0x1142: 0xe00d, 0x1143: 0x0008, 0x1144: 0xe00d, 0x1145: 0x0008, - 0x1146: 0xe00d, 0x1147: 0x0008, 0x1148: 0xe00d, 0x1149: 0x0008, 0x114a: 0xe00d, 0x114b: 0x0008, - 0x114c: 0xe00d, 0x114d: 0x0008, 0x114e: 0xe00d, 0x114f: 0x0008, 0x1150: 0xe00d, 0x1151: 0x0008, - 0x1152: 0xe00d, 0x1153: 0x0008, 0x1154: 0xe00d, 0x1155: 0x0008, 0x1156: 0xe00d, 0x1157: 0x0008, - 0x1158: 0xe00d, 0x1159: 0x0008, 0x115a: 0xe00d, 0x115b: 0x0008, 0x115c: 0x0ea1, 0x115d: 0x6e11, - 0x115e: 0x3308, 0x115f: 0x3308, 0x1160: 0x0008, 0x1161: 0x0008, 0x1162: 0x0008, 0x1163: 0x0008, - 0x1164: 0x0008, 0x1165: 0x0008, 0x1166: 0x0008, 0x1167: 0x0008, 0x1168: 0x0008, 0x1169: 0x0008, - 0x116a: 0x0008, 0x116b: 0x0008, 0x116c: 0x0008, 0x116d: 0x0008, 0x116e: 0x0008, 0x116f: 0x0008, - 0x1170: 0x0008, 0x1171: 0x0008, 0x1172: 0x0008, 0x1173: 0x0008, 0x1174: 0x0008, 0x1175: 0x0008, - 0x1176: 0x0008, 0x1177: 0x0008, 0x1178: 0x0008, 0x1179: 0x0008, 0x117a: 0x0008, 0x117b: 0x0008, - 0x117c: 0x0008, 0x117d: 0x0008, 0x117e: 0x0008, 0x117f: 0x0008, - // Block 0x46, offset 0x1180 - 0x1180: 0x0018, 0x1181: 0x0018, 0x1182: 0x0018, 0x1183: 0x0018, 0x1184: 0x0018, 0x1185: 0x0018, - 0x1186: 0x0018, 0x1187: 0x0018, 0x1188: 0x0018, 0x1189: 0x0018, 0x118a: 0x0018, 0x118b: 0x0018, - 0x118c: 0x0018, 0x118d: 0x0018, 0x118e: 0x0018, 0x118f: 0x0018, 0x1190: 0x0018, 0x1191: 0x0018, - 0x1192: 0x0018, 0x1193: 0x0018, 0x1194: 0x0018, 0x1195: 0x0018, 0x1196: 0x0018, 0x1197: 0x0008, - 0x1198: 0x0008, 0x1199: 0x0008, 0x119a: 0x0008, 0x119b: 0x0008, 0x119c: 0x0008, 0x119d: 0x0008, - 0x119e: 0x0008, 0x119f: 0x0008, 0x11a0: 0x0018, 0x11a1: 0x0018, 0x11a2: 0xe00d, 0x11a3: 0x0008, - 0x11a4: 0xe00d, 0x11a5: 0x0008, 0x11a6: 0xe00d, 0x11a7: 0x0008, 0x11a8: 0xe00d, 0x11a9: 0x0008, - 0x11aa: 0xe00d, 0x11ab: 0x0008, 0x11ac: 0xe00d, 0x11ad: 0x0008, 0x11ae: 0xe00d, 0x11af: 0x0008, - 0x11b0: 0x0008, 0x11b1: 0x0008, 0x11b2: 0xe00d, 0x11b3: 0x0008, 0x11b4: 0xe00d, 0x11b5: 0x0008, - 0x11b6: 0xe00d, 0x11b7: 0x0008, 0x11b8: 0xe00d, 0x11b9: 0x0008, 0x11ba: 0xe00d, 0x11bb: 0x0008, - 0x11bc: 0xe00d, 0x11bd: 0x0008, 0x11be: 0xe00d, 0x11bf: 0x0008, - // Block 0x47, offset 0x11c0 - 0x11c0: 0xe00d, 0x11c1: 0x0008, 0x11c2: 0xe00d, 0x11c3: 0x0008, 0x11c4: 0xe00d, 0x11c5: 0x0008, - 0x11c6: 0xe00d, 0x11c7: 0x0008, 0x11c8: 0xe00d, 0x11c9: 0x0008, 0x11ca: 0xe00d, 0x11cb: 0x0008, - 0x11cc: 0xe00d, 0x11cd: 0x0008, 0x11ce: 0xe00d, 0x11cf: 0x0008, 0x11d0: 0xe00d, 0x11d1: 0x0008, - 0x11d2: 0xe00d, 0x11d3: 0x0008, 0x11d4: 0xe00d, 0x11d5: 0x0008, 0x11d6: 0xe00d, 0x11d7: 0x0008, - 0x11d8: 0xe00d, 0x11d9: 0x0008, 0x11da: 0xe00d, 0x11db: 0x0008, 0x11dc: 0xe00d, 0x11dd: 0x0008, - 0x11de: 0xe00d, 0x11df: 0x0008, 0x11e0: 0xe00d, 0x11e1: 0x0008, 0x11e2: 0xe00d, 0x11e3: 0x0008, - 0x11e4: 0xe00d, 0x11e5: 0x0008, 0x11e6: 0xe00d, 0x11e7: 0x0008, 0x11e8: 0xe00d, 0x11e9: 0x0008, - 0x11ea: 0xe00d, 0x11eb: 0x0008, 0x11ec: 0xe00d, 0x11ed: 0x0008, 0x11ee: 0xe00d, 0x11ef: 0x0008, - 0x11f0: 0xe0fd, 0x11f1: 0x0008, 0x11f2: 0x0008, 0x11f3: 0x0008, 0x11f4: 0x0008, 0x11f5: 0x0008, - 0x11f6: 0x0008, 0x11f7: 0x0008, 0x11f8: 0x0008, 0x11f9: 0xe01d, 0x11fa: 0x0008, 0x11fb: 0xe03d, - 0x11fc: 0x0008, 0x11fd: 0x4445, 0x11fe: 0xe00d, 0x11ff: 0x0008, - // Block 0x48, offset 0x1200 - 0x1200: 0xe00d, 0x1201: 0x0008, 0x1202: 0xe00d, 0x1203: 0x0008, 0x1204: 0xe00d, 0x1205: 0x0008, - 0x1206: 0xe00d, 0x1207: 0x0008, 0x1208: 0x0008, 0x1209: 0x0018, 0x120a: 0x0018, 0x120b: 0xe03d, - 0x120c: 0x0008, 0x120d: 0x11d9, 0x120e: 0x0008, 0x120f: 0x0008, 0x1210: 0xe00d, 0x1211: 0x0008, - 0x1212: 0xe00d, 0x1213: 0x0008, 0x1214: 0x0008, 0x1215: 0x0008, 0x1216: 0xe00d, 0x1217: 0x0008, - 0x1218: 0xe00d, 0x1219: 0x0008, 0x121a: 0xe00d, 0x121b: 0x0008, 0x121c: 0xe00d, 0x121d: 0x0008, - 0x121e: 0xe00d, 0x121f: 0x0008, 0x1220: 0xe00d, 0x1221: 0x0008, 0x1222: 0xe00d, 0x1223: 0x0008, - 0x1224: 0xe00d, 0x1225: 0x0008, 0x1226: 0xe00d, 0x1227: 0x0008, 0x1228: 0xe00d, 0x1229: 0x0008, - 0x122a: 0x6e29, 0x122b: 0x1029, 0x122c: 0x11c1, 0x122d: 0x6e41, 0x122e: 0x1221, 0x122f: 0x0008, - 0x1230: 0x6e59, 0x1231: 0x6e71, 0x1232: 0x1239, 0x1233: 0x4465, 0x1234: 0xe00d, 0x1235: 0x0008, - 0x1236: 0xe00d, 0x1237: 0x0008, 0x1238: 0xe00d, 0x1239: 0x0008, 0x123a: 0xe00d, 0x123b: 0x0008, - 0x123c: 0xe00d, 0x123d: 0x0008, 0x123e: 0xe00d, 0x123f: 0x0008, - // Block 0x49, offset 0x1240 - 0x1240: 0x650d, 0x1241: 0x652d, 0x1242: 0x654d, 0x1243: 0x656d, 0x1244: 0x658d, 0x1245: 0x65ad, - 0x1246: 0x65cd, 0x1247: 0x65ed, 0x1248: 0x660d, 0x1249: 0x662d, 0x124a: 0x664d, 0x124b: 0x666d, - 0x124c: 0x668d, 0x124d: 0x66ad, 0x124e: 0x0008, 0x124f: 0x0008, 0x1250: 0x66cd, 0x1251: 0x0008, - 0x1252: 0x66ed, 0x1253: 0x0008, 0x1254: 0x0008, 0x1255: 0x670d, 0x1256: 0x672d, 0x1257: 0x674d, - 0x1258: 0x676d, 0x1259: 0x678d, 0x125a: 0x67ad, 0x125b: 0x67cd, 0x125c: 0x67ed, 0x125d: 0x680d, - 0x125e: 0x682d, 0x125f: 0x0008, 0x1260: 0x684d, 0x1261: 0x0008, 0x1262: 0x686d, 0x1263: 0x0008, - 0x1264: 0x0008, 0x1265: 0x688d, 0x1266: 0x68ad, 0x1267: 0x0008, 0x1268: 0x0008, 0x1269: 0x0008, - 0x126a: 0x68cd, 0x126b: 0x68ed, 0x126c: 0x690d, 0x126d: 0x692d, 0x126e: 0x694d, 0x126f: 0x696d, - 0x1270: 0x698d, 0x1271: 0x69ad, 0x1272: 0x69cd, 0x1273: 0x69ed, 0x1274: 0x6a0d, 0x1275: 0x6a2d, - 0x1276: 0x6a4d, 0x1277: 0x6a6d, 0x1278: 0x6a8d, 0x1279: 0x6aad, 0x127a: 0x6acd, 0x127b: 0x6aed, - 0x127c: 0x6b0d, 0x127d: 0x6b2d, 0x127e: 0x6b4d, 0x127f: 0x6b6d, - // Block 0x4a, offset 0x1280 - 0x1280: 0x7acd, 0x1281: 0x7aed, 0x1282: 0x7b0d, 0x1283: 0x7b2d, 0x1284: 0x7b4d, 0x1285: 0x7b6d, - 0x1286: 0x7b8d, 0x1287: 0x7bad, 0x1288: 0x7bcd, 0x1289: 0x7bed, 0x128a: 0x7c0d, 0x128b: 0x7c2d, - 0x128c: 0x7c4d, 0x128d: 0x7c6d, 0x128e: 0x7c8d, 0x128f: 0x6ec9, 0x1290: 0x6ef1, 0x1291: 0x6f19, - 0x1292: 0x7cad, 0x1293: 0x7ccd, 0x1294: 0x7ced, 0x1295: 0x6f41, 0x1296: 0x6f69, 0x1297: 0x6f91, - 0x1298: 0x7d0d, 0x1299: 0x7d2d, 0x129a: 0x0040, 0x129b: 0x0040, 0x129c: 0x0040, 0x129d: 0x0040, - 0x129e: 0x0040, 0x129f: 0x0040, 0x12a0: 0x0040, 0x12a1: 0x0040, 0x12a2: 0x0040, 0x12a3: 0x0040, - 0x12a4: 0x0040, 0x12a5: 0x0040, 0x12a6: 0x0040, 0x12a7: 0x0040, 0x12a8: 0x0040, 0x12a9: 0x0040, - 0x12aa: 0x0040, 0x12ab: 0x0040, 0x12ac: 0x0040, 0x12ad: 0x0040, 0x12ae: 0x0040, 0x12af: 0x0040, - 0x12b0: 0x0040, 0x12b1: 0x0040, 0x12b2: 0x0040, 0x12b3: 0x0040, 0x12b4: 0x0040, 0x12b5: 0x0040, - 0x12b6: 0x0040, 0x12b7: 0x0040, 0x12b8: 0x0040, 0x12b9: 0x0040, 0x12ba: 0x0040, 0x12bb: 0x0040, - 0x12bc: 0x0040, 0x12bd: 0x0040, 0x12be: 0x0040, 0x12bf: 0x0040, - // Block 0x4b, offset 0x12c0 - 0x12c0: 0x6fb9, 0x12c1: 0x6fd1, 0x12c2: 0x6fe9, 0x12c3: 0x7d4d, 0x12c4: 0x7d6d, 0x12c5: 0x7001, - 0x12c6: 0x7001, 0x12c7: 0x0040, 0x12c8: 0x0040, 0x12c9: 0x0040, 0x12ca: 0x0040, 0x12cb: 0x0040, - 0x12cc: 0x0040, 0x12cd: 0x0040, 0x12ce: 0x0040, 0x12cf: 0x0040, 0x12d0: 0x0040, 0x12d1: 0x0040, - 0x12d2: 0x0040, 0x12d3: 0x7019, 0x12d4: 0x7041, 0x12d5: 0x7069, 0x12d6: 0x7091, 0x12d7: 0x70b9, - 0x12d8: 0x0040, 0x12d9: 0x0040, 0x12da: 0x0040, 0x12db: 0x0040, 0x12dc: 0x0040, 0x12dd: 0x70e1, - 0x12de: 0x3308, 0x12df: 0x7109, 0x12e0: 0x7131, 0x12e1: 0x20a9, 0x12e2: 0x20f1, 0x12e3: 0x7149, - 0x12e4: 0x7161, 0x12e5: 0x7179, 0x12e6: 0x7191, 0x12e7: 0x71a9, 0x12e8: 0x71c1, 0x12e9: 0x1fb2, - 0x12ea: 0x71d9, 0x12eb: 0x7201, 0x12ec: 0x7229, 0x12ed: 0x7261, 0x12ee: 0x7299, 0x12ef: 0x72c1, - 0x12f0: 0x72e9, 0x12f1: 0x7311, 0x12f2: 0x7339, 0x12f3: 0x7361, 0x12f4: 0x7389, 0x12f5: 0x73b1, - 0x12f6: 0x73d9, 0x12f7: 0x0040, 0x12f8: 0x7401, 0x12f9: 0x7429, 0x12fa: 0x7451, 0x12fb: 0x7479, - 0x12fc: 0x74a1, 0x12fd: 0x0040, 0x12fe: 0x74c9, 0x12ff: 0x0040, - // Block 0x4c, offset 0x1300 - 0x1300: 0x74f1, 0x1301: 0x7519, 0x1302: 0x0040, 0x1303: 0x7541, 0x1304: 0x7569, 0x1305: 0x0040, - 0x1306: 0x7591, 0x1307: 0x75b9, 0x1308: 0x75e1, 0x1309: 0x7609, 0x130a: 0x7631, 0x130b: 0x7659, - 0x130c: 0x7681, 0x130d: 0x76a9, 0x130e: 0x76d1, 0x130f: 0x76f9, 0x1310: 0x7721, 0x1311: 0x7721, - 0x1312: 0x7739, 0x1313: 0x7739, 0x1314: 0x7739, 0x1315: 0x7739, 0x1316: 0x7751, 0x1317: 0x7751, - 0x1318: 0x7751, 0x1319: 0x7751, 0x131a: 0x7769, 0x131b: 0x7769, 0x131c: 0x7769, 0x131d: 0x7769, - 0x131e: 0x7781, 0x131f: 0x7781, 0x1320: 0x7781, 0x1321: 0x7781, 0x1322: 0x7799, 0x1323: 0x7799, - 0x1324: 0x7799, 0x1325: 0x7799, 0x1326: 0x77b1, 0x1327: 0x77b1, 0x1328: 0x77b1, 0x1329: 0x77b1, - 0x132a: 0x77c9, 0x132b: 0x77c9, 0x132c: 0x77c9, 0x132d: 0x77c9, 0x132e: 0x77e1, 0x132f: 0x77e1, - 0x1330: 0x77e1, 0x1331: 0x77e1, 0x1332: 0x77f9, 0x1333: 0x77f9, 0x1334: 0x77f9, 0x1335: 0x77f9, - 0x1336: 0x7811, 0x1337: 0x7811, 0x1338: 0x7811, 0x1339: 0x7811, 0x133a: 0x7829, 0x133b: 0x7829, - 0x133c: 0x7829, 0x133d: 0x7829, 0x133e: 0x7841, 0x133f: 0x7841, - // Block 0x4d, offset 0x1340 - 0x1340: 0x7841, 0x1341: 0x7841, 0x1342: 0x7859, 0x1343: 0x7859, 0x1344: 0x7871, 0x1345: 0x7871, - 0x1346: 0x7889, 0x1347: 0x7889, 0x1348: 0x78a1, 0x1349: 0x78a1, 0x134a: 0x78b9, 0x134b: 0x78b9, - 0x134c: 0x78d1, 0x134d: 0x78d1, 0x134e: 0x78e9, 0x134f: 0x78e9, 0x1350: 0x78e9, 0x1351: 0x78e9, - 0x1352: 0x7901, 0x1353: 0x7901, 0x1354: 0x7901, 0x1355: 0x7901, 0x1356: 0x7919, 0x1357: 0x7919, - 0x1358: 0x7919, 0x1359: 0x7919, 0x135a: 0x7931, 0x135b: 0x7931, 0x135c: 0x7931, 0x135d: 0x7931, - 0x135e: 0x7949, 0x135f: 0x7949, 0x1360: 0x7961, 0x1361: 0x7961, 0x1362: 0x7961, 0x1363: 0x7961, - 0x1364: 0x7979, 0x1365: 0x7979, 0x1366: 0x7991, 0x1367: 0x7991, 0x1368: 0x7991, 0x1369: 0x7991, - 0x136a: 0x79a9, 0x136b: 0x79a9, 0x136c: 0x79a9, 0x136d: 0x79a9, 0x136e: 0x79c1, 0x136f: 0x79c1, - 0x1370: 0x79d9, 0x1371: 0x79d9, 0x1372: 0x0818, 0x1373: 0x0818, 0x1374: 0x0818, 0x1375: 0x0818, - 0x1376: 0x0818, 0x1377: 0x0818, 0x1378: 0x0818, 0x1379: 0x0818, 0x137a: 0x0818, 0x137b: 0x0818, - 0x137c: 0x0818, 0x137d: 0x0818, 0x137e: 0x0818, 0x137f: 0x0818, - // Block 0x4e, offset 0x1380 - 0x1380: 0x0818, 0x1381: 0x0818, 0x1382: 0x0040, 0x1383: 0x0040, 0x1384: 0x0040, 0x1385: 0x0040, - 0x1386: 0x0040, 0x1387: 0x0040, 0x1388: 0x0040, 0x1389: 0x0040, 0x138a: 0x0040, 0x138b: 0x0040, - 0x138c: 0x0040, 0x138d: 0x0040, 0x138e: 0x0040, 0x138f: 0x0040, 0x1390: 0x0040, 0x1391: 0x0040, - 0x1392: 0x0040, 0x1393: 0x79f1, 0x1394: 0x79f1, 0x1395: 0x79f1, 0x1396: 0x79f1, 0x1397: 0x7a09, - 0x1398: 0x7a09, 0x1399: 0x7a21, 0x139a: 0x7a21, 0x139b: 0x7a39, 0x139c: 0x7a39, 0x139d: 0x0479, - 0x139e: 0x7a51, 0x139f: 0x7a51, 0x13a0: 0x7a69, 0x13a1: 0x7a69, 0x13a2: 0x7a81, 0x13a3: 0x7a81, - 0x13a4: 0x7a99, 0x13a5: 0x7a99, 0x13a6: 0x7a99, 0x13a7: 0x7a99, 0x13a8: 0x7ab1, 0x13a9: 0x7ab1, - 0x13aa: 0x7ac9, 0x13ab: 0x7ac9, 0x13ac: 0x7af1, 0x13ad: 0x7af1, 0x13ae: 0x7b19, 0x13af: 0x7b19, - 0x13b0: 0x7b41, 0x13b1: 0x7b41, 0x13b2: 0x7b69, 0x13b3: 0x7b69, 0x13b4: 0x7b91, 0x13b5: 0x7b91, - 0x13b6: 0x7bb9, 0x13b7: 0x7bb9, 0x13b8: 0x7bb9, 0x13b9: 0x7be1, 0x13ba: 0x7be1, 0x13bb: 0x7be1, - 0x13bc: 0x7c09, 0x13bd: 0x7c09, 0x13be: 0x7c09, 0x13bf: 0x7c09, - // Block 0x4f, offset 0x13c0 - 0x13c0: 0x85f9, 0x13c1: 0x8621, 0x13c2: 0x8649, 0x13c3: 0x8671, 0x13c4: 0x8699, 0x13c5: 0x86c1, - 0x13c6: 0x86e9, 0x13c7: 0x8711, 0x13c8: 0x8739, 0x13c9: 0x8761, 0x13ca: 0x8789, 0x13cb: 0x87b1, - 0x13cc: 0x87d9, 0x13cd: 0x8801, 0x13ce: 0x8829, 0x13cf: 0x8851, 0x13d0: 0x8879, 0x13d1: 0x88a1, - 0x13d2: 0x88c9, 0x13d3: 0x88f1, 0x13d4: 0x8919, 0x13d5: 0x8941, 0x13d6: 0x8969, 0x13d7: 0x8991, - 0x13d8: 0x89b9, 0x13d9: 0x89e1, 0x13da: 0x8a09, 0x13db: 0x8a31, 0x13dc: 0x8a59, 0x13dd: 0x8a81, - 0x13de: 0x8aaa, 0x13df: 0x8ada, 0x13e0: 0x8b0a, 0x13e1: 0x8b3a, 0x13e2: 0x8b6a, 0x13e3: 0x8b9a, - 0x13e4: 0x8bc9, 0x13e5: 0x8bf1, 0x13e6: 0x7c71, 0x13e7: 0x8c19, 0x13e8: 0x7be1, 0x13e9: 0x7c99, - 0x13ea: 0x8c41, 0x13eb: 0x8c69, 0x13ec: 0x7d39, 0x13ed: 0x8c91, 0x13ee: 0x7d61, 0x13ef: 0x7d89, - 0x13f0: 0x8cb9, 0x13f1: 0x8ce1, 0x13f2: 0x7e29, 0x13f3: 0x8d09, 0x13f4: 0x7e51, 0x13f5: 0x7e79, - 0x13f6: 0x8d31, 0x13f7: 0x8d59, 0x13f8: 0x7ec9, 0x13f9: 0x8d81, 0x13fa: 0x7ef1, 0x13fb: 0x7f19, - 0x13fc: 0x83a1, 0x13fd: 0x83c9, 0x13fe: 0x8441, 0x13ff: 0x8469, - // Block 0x50, offset 0x1400 - 0x1400: 0x8491, 0x1401: 0x8531, 0x1402: 0x8559, 0x1403: 0x8581, 0x1404: 0x85a9, 0x1405: 0x8649, - 0x1406: 0x8671, 0x1407: 0x8699, 0x1408: 0x8da9, 0x1409: 0x8739, 0x140a: 0x8dd1, 0x140b: 0x8df9, - 0x140c: 0x8829, 0x140d: 0x8e21, 0x140e: 0x8851, 0x140f: 0x8879, 0x1410: 0x8a81, 0x1411: 0x8e49, - 0x1412: 0x8e71, 0x1413: 0x89b9, 0x1414: 0x8e99, 0x1415: 0x89e1, 0x1416: 0x8a09, 0x1417: 0x7c21, - 0x1418: 0x7c49, 0x1419: 0x8ec1, 0x141a: 0x7c71, 0x141b: 0x8ee9, 0x141c: 0x7cc1, 0x141d: 0x7ce9, - 0x141e: 0x7d11, 0x141f: 0x7d39, 0x1420: 0x8f11, 0x1421: 0x7db1, 0x1422: 0x7dd9, 0x1423: 0x7e01, - 0x1424: 0x7e29, 0x1425: 0x8f39, 0x1426: 0x7ec9, 0x1427: 0x7f41, 0x1428: 0x7f69, 0x1429: 0x7f91, - 0x142a: 0x7fb9, 0x142b: 0x7fe1, 0x142c: 0x8031, 0x142d: 0x8059, 0x142e: 0x8081, 0x142f: 0x80a9, - 0x1430: 0x80d1, 0x1431: 0x80f9, 0x1432: 0x8f61, 0x1433: 0x8121, 0x1434: 0x8149, 0x1435: 0x8171, - 0x1436: 0x8199, 0x1437: 0x81c1, 0x1438: 0x81e9, 0x1439: 0x8239, 0x143a: 0x8261, 0x143b: 0x8289, - 0x143c: 0x82b1, 0x143d: 0x82d9, 0x143e: 0x8301, 0x143f: 0x8329, - // Block 0x51, offset 0x1440 - 0x1440: 0x8351, 0x1441: 0x8379, 0x1442: 0x83f1, 0x1443: 0x8419, 0x1444: 0x84b9, 0x1445: 0x84e1, - 0x1446: 0x8509, 0x1447: 0x8531, 0x1448: 0x8559, 0x1449: 0x85d1, 0x144a: 0x85f9, 0x144b: 0x8621, - 0x144c: 0x8649, 0x144d: 0x8f89, 0x144e: 0x86c1, 0x144f: 0x86e9, 0x1450: 0x8711, 0x1451: 0x8739, - 0x1452: 0x87b1, 0x1453: 0x87d9, 0x1454: 0x8801, 0x1455: 0x8829, 0x1456: 0x8fb1, 0x1457: 0x88a1, - 0x1458: 0x88c9, 0x1459: 0x8fd9, 0x145a: 0x8941, 0x145b: 0x8969, 0x145c: 0x8991, 0x145d: 0x89b9, - 0x145e: 0x9001, 0x145f: 0x7c71, 0x1460: 0x8ee9, 0x1461: 0x7d39, 0x1462: 0x8f11, 0x1463: 0x7e29, - 0x1464: 0x8f39, 0x1465: 0x7ec9, 0x1466: 0x9029, 0x1467: 0x80d1, 0x1468: 0x9051, 0x1469: 0x9079, - 0x146a: 0x90a1, 0x146b: 0x8531, 0x146c: 0x8559, 0x146d: 0x8649, 0x146e: 0x8829, 0x146f: 0x8fb1, - 0x1470: 0x89b9, 0x1471: 0x9001, 0x1472: 0x90c9, 0x1473: 0x9101, 0x1474: 0x9139, 0x1475: 0x9171, - 0x1476: 0x9199, 0x1477: 0x91c1, 0x1478: 0x91e9, 0x1479: 0x9211, 0x147a: 0x9239, 0x147b: 0x9261, - 0x147c: 0x9289, 0x147d: 0x92b1, 0x147e: 0x92d9, 0x147f: 0x9301, - // Block 0x52, offset 0x1480 - 0x1480: 0x9329, 0x1481: 0x9351, 0x1482: 0x9379, 0x1483: 0x93a1, 0x1484: 0x93c9, 0x1485: 0x93f1, - 0x1486: 0x9419, 0x1487: 0x9441, 0x1488: 0x9469, 0x1489: 0x9491, 0x148a: 0x94b9, 0x148b: 0x94e1, - 0x148c: 0x9079, 0x148d: 0x9509, 0x148e: 0x9531, 0x148f: 0x9559, 0x1490: 0x9581, 0x1491: 0x9171, - 0x1492: 0x9199, 0x1493: 0x91c1, 0x1494: 0x91e9, 0x1495: 0x9211, 0x1496: 0x9239, 0x1497: 0x9261, - 0x1498: 0x9289, 0x1499: 0x92b1, 0x149a: 0x92d9, 0x149b: 0x9301, 0x149c: 0x9329, 0x149d: 0x9351, - 0x149e: 0x9379, 0x149f: 0x93a1, 0x14a0: 0x93c9, 0x14a1: 0x93f1, 0x14a2: 0x9419, 0x14a3: 0x9441, - 0x14a4: 0x9469, 0x14a5: 0x9491, 0x14a6: 0x94b9, 0x14a7: 0x94e1, 0x14a8: 0x9079, 0x14a9: 0x9509, - 0x14aa: 0x9531, 0x14ab: 0x9559, 0x14ac: 0x9581, 0x14ad: 0x9491, 0x14ae: 0x94b9, 0x14af: 0x94e1, - 0x14b0: 0x9079, 0x14b1: 0x9051, 0x14b2: 0x90a1, 0x14b3: 0x8211, 0x14b4: 0x8059, 0x14b5: 0x8081, - 0x14b6: 0x80a9, 0x14b7: 0x9491, 0x14b8: 0x94b9, 0x14b9: 0x94e1, 0x14ba: 0x8211, 0x14bb: 0x8239, - 0x14bc: 0x95a9, 0x14bd: 0x95a9, 0x14be: 0x0018, 0x14bf: 0x0018, - // Block 0x53, offset 0x14c0 - 0x14c0: 0x0040, 0x14c1: 0x0040, 0x14c2: 0x0040, 0x14c3: 0x0040, 0x14c4: 0x0040, 0x14c5: 0x0040, - 0x14c6: 0x0040, 0x14c7: 0x0040, 0x14c8: 0x0040, 0x14c9: 0x0040, 0x14ca: 0x0040, 0x14cb: 0x0040, - 0x14cc: 0x0040, 0x14cd: 0x0040, 0x14ce: 0x0040, 0x14cf: 0x0040, 0x14d0: 0x95d1, 0x14d1: 0x9609, - 0x14d2: 0x9609, 0x14d3: 0x9641, 0x14d4: 0x9679, 0x14d5: 0x96b1, 0x14d6: 0x96e9, 0x14d7: 0x9721, - 0x14d8: 0x9759, 0x14d9: 0x9759, 0x14da: 0x9791, 0x14db: 0x97c9, 0x14dc: 0x9801, 0x14dd: 0x9839, - 0x14de: 0x9871, 0x14df: 0x98a9, 0x14e0: 0x98a9, 0x14e1: 0x98e1, 0x14e2: 0x9919, 0x14e3: 0x9919, - 0x14e4: 0x9951, 0x14e5: 0x9951, 0x14e6: 0x9989, 0x14e7: 0x99c1, 0x14e8: 0x99c1, 0x14e9: 0x99f9, - 0x14ea: 0x9a31, 0x14eb: 0x9a31, 0x14ec: 0x9a69, 0x14ed: 0x9a69, 0x14ee: 0x9aa1, 0x14ef: 0x9ad9, - 0x14f0: 0x9ad9, 0x14f1: 0x9b11, 0x14f2: 0x9b11, 0x14f3: 0x9b49, 0x14f4: 0x9b81, 0x14f5: 0x9bb9, - 0x14f6: 0x9bf1, 0x14f7: 0x9bf1, 0x14f8: 0x9c29, 0x14f9: 0x9c61, 0x14fa: 0x9c99, 0x14fb: 0x9cd1, - 0x14fc: 0x9d09, 0x14fd: 0x9d09, 0x14fe: 0x9d41, 0x14ff: 0x9d79, - // Block 0x54, offset 0x1500 - 0x1500: 0xa949, 0x1501: 0xa981, 0x1502: 0xa9b9, 0x1503: 0xa8a1, 0x1504: 0x9bb9, 0x1505: 0x9989, - 0x1506: 0xa9f1, 0x1507: 0xaa29, 0x1508: 0x0040, 0x1509: 0x0040, 0x150a: 0x0040, 0x150b: 0x0040, - 0x150c: 0x0040, 0x150d: 0x0040, 0x150e: 0x0040, 0x150f: 0x0040, 0x1510: 0x0040, 0x1511: 0x0040, - 0x1512: 0x0040, 0x1513: 0x0040, 0x1514: 0x0040, 0x1515: 0x0040, 0x1516: 0x0040, 0x1517: 0x0040, - 0x1518: 0x0040, 0x1519: 0x0040, 0x151a: 0x0040, 0x151b: 0x0040, 0x151c: 0x0040, 0x151d: 0x0040, - 0x151e: 0x0040, 0x151f: 0x0040, 0x1520: 0x0040, 0x1521: 0x0040, 0x1522: 0x0040, 0x1523: 0x0040, - 0x1524: 0x0040, 0x1525: 0x0040, 0x1526: 0x0040, 0x1527: 0x0040, 0x1528: 0x0040, 0x1529: 0x0040, - 0x152a: 0x0040, 0x152b: 0x0040, 0x152c: 0x0040, 0x152d: 0x0040, 0x152e: 0x0040, 0x152f: 0x0040, - 0x1530: 0xaa61, 0x1531: 0xaa99, 0x1532: 0xaad1, 0x1533: 0xab19, 0x1534: 0xab61, 0x1535: 0xaba9, - 0x1536: 0xabf1, 0x1537: 0xac39, 0x1538: 0xac81, 0x1539: 0xacc9, 0x153a: 0xad02, 0x153b: 0xae12, - 0x153c: 0xae91, 0x153d: 0x0018, 0x153e: 0x0040, 0x153f: 0x0040, - // Block 0x55, offset 0x1540 - 0x1540: 0x33c0, 0x1541: 0x33c0, 0x1542: 0x33c0, 0x1543: 0x33c0, 0x1544: 0x33c0, 0x1545: 0x33c0, - 0x1546: 0x33c0, 0x1547: 0x33c0, 0x1548: 0x33c0, 0x1549: 0x33c0, 0x154a: 0x33c0, 0x154b: 0x33c0, - 0x154c: 0x33c0, 0x154d: 0x33c0, 0x154e: 0x33c0, 0x154f: 0x33c0, 0x1550: 0xaeda, 0x1551: 0x7d8d, - 0x1552: 0x0040, 0x1553: 0xaeea, 0x1554: 0x03c2, 0x1555: 0xaefa, 0x1556: 0xaf0a, 0x1557: 0x7dad, - 0x1558: 0x7dcd, 0x1559: 0x0040, 0x155a: 0x0040, 0x155b: 0x0040, 0x155c: 0x0040, 0x155d: 0x0040, - 0x155e: 0x0040, 0x155f: 0x0040, 0x1560: 0x3308, 0x1561: 0x3308, 0x1562: 0x3308, 0x1563: 0x3308, - 0x1564: 0x3308, 0x1565: 0x3308, 0x1566: 0x3308, 0x1567: 0x3308, 0x1568: 0x3308, 0x1569: 0x3308, - 0x156a: 0x3308, 0x156b: 0x3308, 0x156c: 0x3308, 0x156d: 0x3308, 0x156e: 0x3308, 0x156f: 0x3308, - 0x1570: 0x0040, 0x1571: 0x7ded, 0x1572: 0x7e0d, 0x1573: 0xaf1a, 0x1574: 0xaf1a, 0x1575: 0x1fd2, - 0x1576: 0x1fe2, 0x1577: 0xaf2a, 0x1578: 0xaf3a, 0x1579: 0x7e2d, 0x157a: 0x7e4d, 0x157b: 0x7e6d, - 0x157c: 0x7e2d, 0x157d: 0x7e8d, 0x157e: 0x7ead, 0x157f: 0x7e8d, - // Block 0x56, offset 0x1580 - 0x1580: 0x7ecd, 0x1581: 0x7eed, 0x1582: 0x7f0d, 0x1583: 0x7eed, 0x1584: 0x7f2d, 0x1585: 0x0018, - 0x1586: 0x0018, 0x1587: 0xaf4a, 0x1588: 0xaf5a, 0x1589: 0x7f4e, 0x158a: 0x7f6e, 0x158b: 0x7f8e, - 0x158c: 0x7fae, 0x158d: 0xaf1a, 0x158e: 0xaf1a, 0x158f: 0xaf1a, 0x1590: 0xaeda, 0x1591: 0x7fcd, - 0x1592: 0x0040, 0x1593: 0x0040, 0x1594: 0x03c2, 0x1595: 0xaeea, 0x1596: 0xaf0a, 0x1597: 0xaefa, - 0x1598: 0x7fed, 0x1599: 0x1fd2, 0x159a: 0x1fe2, 0x159b: 0xaf2a, 0x159c: 0xaf3a, 0x159d: 0x7ecd, - 0x159e: 0x7f2d, 0x159f: 0xaf6a, 0x15a0: 0xaf7a, 0x15a1: 0xaf8a, 0x15a2: 0x1fb2, 0x15a3: 0xaf99, - 0x15a4: 0xafaa, 0x15a5: 0xafba, 0x15a6: 0x1fc2, 0x15a7: 0x0040, 0x15a8: 0xafca, 0x15a9: 0xafda, - 0x15aa: 0xafea, 0x15ab: 0xaffa, 0x15ac: 0x0040, 0x15ad: 0x0040, 0x15ae: 0x0040, 0x15af: 0x0040, - 0x15b0: 0x800e, 0x15b1: 0xb009, 0x15b2: 0x802e, 0x15b3: 0x0808, 0x15b4: 0x804e, 0x15b5: 0x0040, - 0x15b6: 0x806e, 0x15b7: 0xb031, 0x15b8: 0x808e, 0x15b9: 0xb059, 0x15ba: 0x80ae, 0x15bb: 0xb081, - 0x15bc: 0x80ce, 0x15bd: 0xb0a9, 0x15be: 0x80ee, 0x15bf: 0xb0d1, - // Block 0x57, offset 0x15c0 - 0x15c0: 0xb0f9, 0x15c1: 0xb111, 0x15c2: 0xb111, 0x15c3: 0xb129, 0x15c4: 0xb129, 0x15c5: 0xb141, - 0x15c6: 0xb141, 0x15c7: 0xb159, 0x15c8: 0xb159, 0x15c9: 0xb171, 0x15ca: 0xb171, 0x15cb: 0xb171, - 0x15cc: 0xb171, 0x15cd: 0xb189, 0x15ce: 0xb189, 0x15cf: 0xb1a1, 0x15d0: 0xb1a1, 0x15d1: 0xb1a1, - 0x15d2: 0xb1a1, 0x15d3: 0xb1b9, 0x15d4: 0xb1b9, 0x15d5: 0xb1d1, 0x15d6: 0xb1d1, 0x15d7: 0xb1d1, - 0x15d8: 0xb1d1, 0x15d9: 0xb1e9, 0x15da: 0xb1e9, 0x15db: 0xb1e9, 0x15dc: 0xb1e9, 0x15dd: 0xb201, - 0x15de: 0xb201, 0x15df: 0xb201, 0x15e0: 0xb201, 0x15e1: 0xb219, 0x15e2: 0xb219, 0x15e3: 0xb219, - 0x15e4: 0xb219, 0x15e5: 0xb231, 0x15e6: 0xb231, 0x15e7: 0xb231, 0x15e8: 0xb231, 0x15e9: 0xb249, - 0x15ea: 0xb249, 0x15eb: 0xb261, 0x15ec: 0xb261, 0x15ed: 0xb279, 0x15ee: 0xb279, 0x15ef: 0xb291, - 0x15f0: 0xb291, 0x15f1: 0xb2a9, 0x15f2: 0xb2a9, 0x15f3: 0xb2a9, 0x15f4: 0xb2a9, 0x15f5: 0xb2c1, - 0x15f6: 0xb2c1, 0x15f7: 0xb2c1, 0x15f8: 0xb2c1, 0x15f9: 0xb2d9, 0x15fa: 0xb2d9, 0x15fb: 0xb2d9, - 0x15fc: 0xb2d9, 0x15fd: 0xb2f1, 0x15fe: 0xb2f1, 0x15ff: 0xb2f1, - // Block 0x58, offset 0x1600 - 0x1600: 0xb2f1, 0x1601: 0xb309, 0x1602: 0xb309, 0x1603: 0xb309, 0x1604: 0xb309, 0x1605: 0xb321, - 0x1606: 0xb321, 0x1607: 0xb321, 0x1608: 0xb321, 0x1609: 0xb339, 0x160a: 0xb339, 0x160b: 0xb339, - 0x160c: 0xb339, 0x160d: 0xb351, 0x160e: 0xb351, 0x160f: 0xb351, 0x1610: 0xb351, 0x1611: 0xb369, - 0x1612: 0xb369, 0x1613: 0xb369, 0x1614: 0xb369, 0x1615: 0xb381, 0x1616: 0xb381, 0x1617: 0xb381, - 0x1618: 0xb381, 0x1619: 0xb399, 0x161a: 0xb399, 0x161b: 0xb399, 0x161c: 0xb399, 0x161d: 0xb3b1, - 0x161e: 0xb3b1, 0x161f: 0xb3b1, 0x1620: 0xb3b1, 0x1621: 0xb3c9, 0x1622: 0xb3c9, 0x1623: 0xb3c9, - 0x1624: 0xb3c9, 0x1625: 0xb3e1, 0x1626: 0xb3e1, 0x1627: 0xb3e1, 0x1628: 0xb3e1, 0x1629: 0xb3f9, - 0x162a: 0xb3f9, 0x162b: 0xb3f9, 0x162c: 0xb3f9, 0x162d: 0xb411, 0x162e: 0xb411, 0x162f: 0x7ab1, - 0x1630: 0x7ab1, 0x1631: 0xb429, 0x1632: 0xb429, 0x1633: 0xb429, 0x1634: 0xb429, 0x1635: 0xb441, - 0x1636: 0xb441, 0x1637: 0xb469, 0x1638: 0xb469, 0x1639: 0xb491, 0x163a: 0xb491, 0x163b: 0xb4b9, - 0x163c: 0xb4b9, 0x163d: 0x0040, 0x163e: 0x0040, 0x163f: 0x03c0, - // Block 0x59, offset 0x1640 - 0x1640: 0x0040, 0x1641: 0xaefa, 0x1642: 0xb4e2, 0x1643: 0xaf6a, 0x1644: 0xafda, 0x1645: 0xafea, - 0x1646: 0xaf7a, 0x1647: 0xb4f2, 0x1648: 0x1fd2, 0x1649: 0x1fe2, 0x164a: 0xaf8a, 0x164b: 0x1fb2, - 0x164c: 0xaeda, 0x164d: 0xaf99, 0x164e: 0x29d1, 0x164f: 0xb502, 0x1650: 0x1f41, 0x1651: 0x00c9, - 0x1652: 0x0069, 0x1653: 0x0079, 0x1654: 0x1f51, 0x1655: 0x1f61, 0x1656: 0x1f71, 0x1657: 0x1f81, - 0x1658: 0x1f91, 0x1659: 0x1fa1, 0x165a: 0xaeea, 0x165b: 0x03c2, 0x165c: 0xafaa, 0x165d: 0x1fc2, - 0x165e: 0xafba, 0x165f: 0xaf0a, 0x1660: 0xaffa, 0x1661: 0x0039, 0x1662: 0x0ee9, 0x1663: 0x1159, - 0x1664: 0x0ef9, 0x1665: 0x0f09, 0x1666: 0x1199, 0x1667: 0x0f31, 0x1668: 0x0249, 0x1669: 0x0f41, - 0x166a: 0x0259, 0x166b: 0x0f51, 0x166c: 0x0359, 0x166d: 0x0f61, 0x166e: 0x0f71, 0x166f: 0x00d9, - 0x1670: 0x0f99, 0x1671: 0x2039, 0x1672: 0x0269, 0x1673: 0x01d9, 0x1674: 0x0fa9, 0x1675: 0x0fb9, - 0x1676: 0x1089, 0x1677: 0x0279, 0x1678: 0x0369, 0x1679: 0x0289, 0x167a: 0x13d1, 0x167b: 0xaf4a, - 0x167c: 0xafca, 0x167d: 0xaf5a, 0x167e: 0xb512, 0x167f: 0xaf1a, - // Block 0x5a, offset 0x1680 - 0x1680: 0x1caa, 0x1681: 0x0039, 0x1682: 0x0ee9, 0x1683: 0x1159, 0x1684: 0x0ef9, 0x1685: 0x0f09, - 0x1686: 0x1199, 0x1687: 0x0f31, 0x1688: 0x0249, 0x1689: 0x0f41, 0x168a: 0x0259, 0x168b: 0x0f51, - 0x168c: 0x0359, 0x168d: 0x0f61, 0x168e: 0x0f71, 0x168f: 0x00d9, 0x1690: 0x0f99, 0x1691: 0x2039, - 0x1692: 0x0269, 0x1693: 0x01d9, 0x1694: 0x0fa9, 0x1695: 0x0fb9, 0x1696: 0x1089, 0x1697: 0x0279, - 0x1698: 0x0369, 0x1699: 0x0289, 0x169a: 0x13d1, 0x169b: 0xaf2a, 0x169c: 0xb522, 0x169d: 0xaf3a, - 0x169e: 0xb532, 0x169f: 0x810d, 0x16a0: 0x812d, 0x16a1: 0x29d1, 0x16a2: 0x814d, 0x16a3: 0x814d, - 0x16a4: 0x816d, 0x16a5: 0x818d, 0x16a6: 0x81ad, 0x16a7: 0x81cd, 0x16a8: 0x81ed, 0x16a9: 0x820d, - 0x16aa: 0x822d, 0x16ab: 0x824d, 0x16ac: 0x826d, 0x16ad: 0x828d, 0x16ae: 0x82ad, 0x16af: 0x82cd, - 0x16b0: 0x82ed, 0x16b1: 0x830d, 0x16b2: 0x832d, 0x16b3: 0x834d, 0x16b4: 0x836d, 0x16b5: 0x838d, - 0x16b6: 0x83ad, 0x16b7: 0x83cd, 0x16b8: 0x83ed, 0x16b9: 0x840d, 0x16ba: 0x842d, 0x16bb: 0x844d, - 0x16bc: 0x81ed, 0x16bd: 0x846d, 0x16be: 0x848d, 0x16bf: 0x824d, - // Block 0x5b, offset 0x16c0 - 0x16c0: 0x84ad, 0x16c1: 0x84cd, 0x16c2: 0x84ed, 0x16c3: 0x850d, 0x16c4: 0x852d, 0x16c5: 0x854d, - 0x16c6: 0x856d, 0x16c7: 0x858d, 0x16c8: 0x850d, 0x16c9: 0x85ad, 0x16ca: 0x850d, 0x16cb: 0x85cd, - 0x16cc: 0x85cd, 0x16cd: 0x85ed, 0x16ce: 0x85ed, 0x16cf: 0x860d, 0x16d0: 0x854d, 0x16d1: 0x862d, - 0x16d2: 0x864d, 0x16d3: 0x862d, 0x16d4: 0x866d, 0x16d5: 0x864d, 0x16d6: 0x868d, 0x16d7: 0x868d, - 0x16d8: 0x86ad, 0x16d9: 0x86ad, 0x16da: 0x86cd, 0x16db: 0x86cd, 0x16dc: 0x864d, 0x16dd: 0x814d, - 0x16de: 0x86ed, 0x16df: 0x870d, 0x16e0: 0x0040, 0x16e1: 0x872d, 0x16e2: 0x874d, 0x16e3: 0x876d, - 0x16e4: 0x878d, 0x16e5: 0x876d, 0x16e6: 0x87ad, 0x16e7: 0x87cd, 0x16e8: 0x87ed, 0x16e9: 0x87ed, - 0x16ea: 0x880d, 0x16eb: 0x880d, 0x16ec: 0x882d, 0x16ed: 0x882d, 0x16ee: 0x880d, 0x16ef: 0x880d, - 0x16f0: 0x884d, 0x16f1: 0x886d, 0x16f2: 0x888d, 0x16f3: 0x88ad, 0x16f4: 0x88cd, 0x16f5: 0x88ed, - 0x16f6: 0x88ed, 0x16f7: 0x88ed, 0x16f8: 0x890d, 0x16f9: 0x890d, 0x16fa: 0x890d, 0x16fb: 0x890d, - 0x16fc: 0x87ed, 0x16fd: 0x87ed, 0x16fe: 0x87ed, 0x16ff: 0x0040, - // Block 0x5c, offset 0x1700 - 0x1700: 0x0040, 0x1701: 0x0040, 0x1702: 0x874d, 0x1703: 0x872d, 0x1704: 0x892d, 0x1705: 0x872d, - 0x1706: 0x874d, 0x1707: 0x872d, 0x1708: 0x0040, 0x1709: 0x0040, 0x170a: 0x894d, 0x170b: 0x874d, - 0x170c: 0x896d, 0x170d: 0x892d, 0x170e: 0x896d, 0x170f: 0x874d, 0x1710: 0x0040, 0x1711: 0x0040, - 0x1712: 0x898d, 0x1713: 0x89ad, 0x1714: 0x88ad, 0x1715: 0x896d, 0x1716: 0x892d, 0x1717: 0x896d, - 0x1718: 0x0040, 0x1719: 0x0040, 0x171a: 0x89cd, 0x171b: 0x89ed, 0x171c: 0x89cd, 0x171d: 0x0040, - 0x171e: 0x0040, 0x171f: 0x0040, 0x1720: 0xb541, 0x1721: 0xb559, 0x1722: 0xb571, 0x1723: 0x8a0e, - 0x1724: 0xb589, 0x1725: 0xb5a1, 0x1726: 0x8a2d, 0x1727: 0x0040, 0x1728: 0x8a4d, 0x1729: 0x8a6d, - 0x172a: 0x8a8d, 0x172b: 0x8a6d, 0x172c: 0x8aad, 0x172d: 0x8acd, 0x172e: 0x8aed, 0x172f: 0x0040, - 0x1730: 0x0040, 0x1731: 0x0040, 0x1732: 0x0040, 0x1733: 0x0040, 0x1734: 0x0040, 0x1735: 0x0040, - 0x1736: 0x0040, 0x1737: 0x0040, 0x1738: 0x0040, 0x1739: 0x0340, 0x173a: 0x0340, 0x173b: 0x0340, - 0x173c: 0x0040, 0x173d: 0x0040, 0x173e: 0x0040, 0x173f: 0x0040, - // Block 0x5d, offset 0x1740 - 0x1740: 0x0a08, 0x1741: 0x0a08, 0x1742: 0x0a08, 0x1743: 0x0a08, 0x1744: 0x0a08, 0x1745: 0x0c08, - 0x1746: 0x0808, 0x1747: 0x0c08, 0x1748: 0x0818, 0x1749: 0x0c08, 0x174a: 0x0c08, 0x174b: 0x0808, - 0x174c: 0x0808, 0x174d: 0x0908, 0x174e: 0x0c08, 0x174f: 0x0c08, 0x1750: 0x0c08, 0x1751: 0x0c08, - 0x1752: 0x0c08, 0x1753: 0x0a08, 0x1754: 0x0a08, 0x1755: 0x0a08, 0x1756: 0x0a08, 0x1757: 0x0908, - 0x1758: 0x0a08, 0x1759: 0x0a08, 0x175a: 0x0a08, 0x175b: 0x0a08, 0x175c: 0x0a08, 0x175d: 0x0c08, - 0x175e: 0x0a08, 0x175f: 0x0a08, 0x1760: 0x0a08, 0x1761: 0x0c08, 0x1762: 0x0808, 0x1763: 0x0808, - 0x1764: 0x0c08, 0x1765: 0x3308, 0x1766: 0x3308, 0x1767: 0x0040, 0x1768: 0x0040, 0x1769: 0x0040, - 0x176a: 0x0040, 0x176b: 0x0a18, 0x176c: 0x0a18, 0x176d: 0x0a18, 0x176e: 0x0a18, 0x176f: 0x0c18, - 0x1770: 0x0818, 0x1771: 0x0818, 0x1772: 0x0818, 0x1773: 0x0818, 0x1774: 0x0818, 0x1775: 0x0818, - 0x1776: 0x0818, 0x1777: 0x0040, 0x1778: 0x0040, 0x1779: 0x0040, 0x177a: 0x0040, 0x177b: 0x0040, - 0x177c: 0x0040, 0x177d: 0x0040, 0x177e: 0x0040, 0x177f: 0x0040, - // Block 0x5e, offset 0x1780 - 0x1780: 0x0a08, 0x1781: 0x0c08, 0x1782: 0x0a08, 0x1783: 0x0c08, 0x1784: 0x0c08, 0x1785: 0x0c08, - 0x1786: 0x0a08, 0x1787: 0x0a08, 0x1788: 0x0a08, 0x1789: 0x0c08, 0x178a: 0x0a08, 0x178b: 0x0a08, - 0x178c: 0x0c08, 0x178d: 0x0a08, 0x178e: 0x0c08, 0x178f: 0x0c08, 0x1790: 0x0a08, 0x1791: 0x0c08, - 0x1792: 0x0040, 0x1793: 0x0040, 0x1794: 0x0040, 0x1795: 0x0040, 0x1796: 0x0040, 0x1797: 0x0040, - 0x1798: 0x0040, 0x1799: 0x0818, 0x179a: 0x0818, 0x179b: 0x0818, 0x179c: 0x0818, 0x179d: 0x0040, - 0x179e: 0x0040, 0x179f: 0x0040, 0x17a0: 0x0040, 0x17a1: 0x0040, 0x17a2: 0x0040, 0x17a3: 0x0040, - 0x17a4: 0x0040, 0x17a5: 0x0040, 0x17a6: 0x0040, 0x17a7: 0x0040, 0x17a8: 0x0040, 0x17a9: 0x0c18, - 0x17aa: 0x0c18, 0x17ab: 0x0c18, 0x17ac: 0x0c18, 0x17ad: 0x0a18, 0x17ae: 0x0a18, 0x17af: 0x0818, - 0x17b0: 0x0040, 0x17b1: 0x0040, 0x17b2: 0x0040, 0x17b3: 0x0040, 0x17b4: 0x0040, 0x17b5: 0x0040, - 0x17b6: 0x0040, 0x17b7: 0x0040, 0x17b8: 0x0040, 0x17b9: 0x0040, 0x17ba: 0x0040, 0x17bb: 0x0040, - 0x17bc: 0x0040, 0x17bd: 0x0040, 0x17be: 0x0040, 0x17bf: 0x0040, - // Block 0x5f, offset 0x17c0 - 0x17c0: 0x3308, 0x17c1: 0x3308, 0x17c2: 0x3008, 0x17c3: 0x3008, 0x17c4: 0x0040, 0x17c5: 0x0008, - 0x17c6: 0x0008, 0x17c7: 0x0008, 0x17c8: 0x0008, 0x17c9: 0x0008, 0x17ca: 0x0008, 0x17cb: 0x0008, - 0x17cc: 0x0008, 0x17cd: 0x0040, 0x17ce: 0x0040, 0x17cf: 0x0008, 0x17d0: 0x0008, 0x17d1: 0x0040, - 0x17d2: 0x0040, 0x17d3: 0x0008, 0x17d4: 0x0008, 0x17d5: 0x0008, 0x17d6: 0x0008, 0x17d7: 0x0008, - 0x17d8: 0x0008, 0x17d9: 0x0008, 0x17da: 0x0008, 0x17db: 0x0008, 0x17dc: 0x0008, 0x17dd: 0x0008, - 0x17de: 0x0008, 0x17df: 0x0008, 0x17e0: 0x0008, 0x17e1: 0x0008, 0x17e2: 0x0008, 0x17e3: 0x0008, - 0x17e4: 0x0008, 0x17e5: 0x0008, 0x17e6: 0x0008, 0x17e7: 0x0008, 0x17e8: 0x0008, 0x17e9: 0x0040, - 0x17ea: 0x0008, 0x17eb: 0x0008, 0x17ec: 0x0008, 0x17ed: 0x0008, 0x17ee: 0x0008, 0x17ef: 0x0008, - 0x17f0: 0x0008, 0x17f1: 0x0040, 0x17f2: 0x0008, 0x17f3: 0x0008, 0x17f4: 0x0040, 0x17f5: 0x0008, - 0x17f6: 0x0008, 0x17f7: 0x0008, 0x17f8: 0x0008, 0x17f9: 0x0008, 0x17fa: 0x0040, 0x17fb: 0x3308, - 0x17fc: 0x3308, 0x17fd: 0x0008, 0x17fe: 0x3008, 0x17ff: 0x3008, - // Block 0x60, offset 0x1800 - 0x1800: 0x3308, 0x1801: 0x3008, 0x1802: 0x3008, 0x1803: 0x3008, 0x1804: 0x3008, 0x1805: 0x0040, - 0x1806: 0x0040, 0x1807: 0x3008, 0x1808: 0x3008, 0x1809: 0x0040, 0x180a: 0x0040, 0x180b: 0x3008, - 0x180c: 0x3008, 0x180d: 0x3808, 0x180e: 0x0040, 0x180f: 0x0040, 0x1810: 0x0008, 0x1811: 0x0040, - 0x1812: 0x0040, 0x1813: 0x0040, 0x1814: 0x0040, 0x1815: 0x0040, 0x1816: 0x0040, 0x1817: 0x3008, - 0x1818: 0x0040, 0x1819: 0x0040, 0x181a: 0x0040, 0x181b: 0x0040, 0x181c: 0x0040, 0x181d: 0x0008, - 0x181e: 0x0008, 0x181f: 0x0008, 0x1820: 0x0008, 0x1821: 0x0008, 0x1822: 0x3008, 0x1823: 0x3008, - 0x1824: 0x0040, 0x1825: 0x0040, 0x1826: 0x3308, 0x1827: 0x3308, 0x1828: 0x3308, 0x1829: 0x3308, - 0x182a: 0x3308, 0x182b: 0x3308, 0x182c: 0x3308, 0x182d: 0x0040, 0x182e: 0x0040, 0x182f: 0x0040, - 0x1830: 0x3308, 0x1831: 0x3308, 0x1832: 0x3308, 0x1833: 0x3308, 0x1834: 0x3308, 0x1835: 0x0040, - 0x1836: 0x0040, 0x1837: 0x0040, 0x1838: 0x0040, 0x1839: 0x0040, 0x183a: 0x0040, 0x183b: 0x0040, - 0x183c: 0x0040, 0x183d: 0x0040, 0x183e: 0x0040, 0x183f: 0x0040, - // Block 0x61, offset 0x1840 - 0x1840: 0x0039, 0x1841: 0x0ee9, 0x1842: 0x1159, 0x1843: 0x0ef9, 0x1844: 0x0f09, 0x1845: 0x1199, - 0x1846: 0x0f31, 0x1847: 0x0249, 0x1848: 0x0f41, 0x1849: 0x0259, 0x184a: 0x0f51, 0x184b: 0x0359, - 0x184c: 0x0f61, 0x184d: 0x0f71, 0x184e: 0x00d9, 0x184f: 0x0f99, 0x1850: 0x2039, 0x1851: 0x0269, - 0x1852: 0x01d9, 0x1853: 0x0fa9, 0x1854: 0x0fb9, 0x1855: 0x1089, 0x1856: 0x0279, 0x1857: 0x0369, - 0x1858: 0x0289, 0x1859: 0x13d1, 0x185a: 0x0039, 0x185b: 0x0ee9, 0x185c: 0x1159, 0x185d: 0x0ef9, - 0x185e: 0x0f09, 0x185f: 0x1199, 0x1860: 0x0f31, 0x1861: 0x0249, 0x1862: 0x0f41, 0x1863: 0x0259, - 0x1864: 0x0f51, 0x1865: 0x0359, 0x1866: 0x0f61, 0x1867: 0x0f71, 0x1868: 0x00d9, 0x1869: 0x0f99, - 0x186a: 0x2039, 0x186b: 0x0269, 0x186c: 0x01d9, 0x186d: 0x0fa9, 0x186e: 0x0fb9, 0x186f: 0x1089, - 0x1870: 0x0279, 0x1871: 0x0369, 0x1872: 0x0289, 0x1873: 0x13d1, 0x1874: 0x0039, 0x1875: 0x0ee9, - 0x1876: 0x1159, 0x1877: 0x0ef9, 0x1878: 0x0f09, 0x1879: 0x1199, 0x187a: 0x0f31, 0x187b: 0x0249, - 0x187c: 0x0f41, 0x187d: 0x0259, 0x187e: 0x0f51, 0x187f: 0x0359, - // Block 0x62, offset 0x1880 - 0x1880: 0x0f61, 0x1881: 0x0f71, 0x1882: 0x00d9, 0x1883: 0x0f99, 0x1884: 0x2039, 0x1885: 0x0269, - 0x1886: 0x01d9, 0x1887: 0x0fa9, 0x1888: 0x0fb9, 0x1889: 0x1089, 0x188a: 0x0279, 0x188b: 0x0369, - 0x188c: 0x0289, 0x188d: 0x13d1, 0x188e: 0x0039, 0x188f: 0x0ee9, 0x1890: 0x1159, 0x1891: 0x0ef9, - 0x1892: 0x0f09, 0x1893: 0x1199, 0x1894: 0x0f31, 0x1895: 0x0040, 0x1896: 0x0f41, 0x1897: 0x0259, - 0x1898: 0x0f51, 0x1899: 0x0359, 0x189a: 0x0f61, 0x189b: 0x0f71, 0x189c: 0x00d9, 0x189d: 0x0f99, - 0x189e: 0x2039, 0x189f: 0x0269, 0x18a0: 0x01d9, 0x18a1: 0x0fa9, 0x18a2: 0x0fb9, 0x18a3: 0x1089, - 0x18a4: 0x0279, 0x18a5: 0x0369, 0x18a6: 0x0289, 0x18a7: 0x13d1, 0x18a8: 0x0039, 0x18a9: 0x0ee9, - 0x18aa: 0x1159, 0x18ab: 0x0ef9, 0x18ac: 0x0f09, 0x18ad: 0x1199, 0x18ae: 0x0f31, 0x18af: 0x0249, - 0x18b0: 0x0f41, 0x18b1: 0x0259, 0x18b2: 0x0f51, 0x18b3: 0x0359, 0x18b4: 0x0f61, 0x18b5: 0x0f71, - 0x18b6: 0x00d9, 0x18b7: 0x0f99, 0x18b8: 0x2039, 0x18b9: 0x0269, 0x18ba: 0x01d9, 0x18bb: 0x0fa9, - 0x18bc: 0x0fb9, 0x18bd: 0x1089, 0x18be: 0x0279, 0x18bf: 0x0369, - // Block 0x63, offset 0x18c0 - 0x18c0: 0x0289, 0x18c1: 0x13d1, 0x18c2: 0x0039, 0x18c3: 0x0ee9, 0x18c4: 0x1159, 0x18c5: 0x0ef9, - 0x18c6: 0x0f09, 0x18c7: 0x1199, 0x18c8: 0x0f31, 0x18c9: 0x0249, 0x18ca: 0x0f41, 0x18cb: 0x0259, - 0x18cc: 0x0f51, 0x18cd: 0x0359, 0x18ce: 0x0f61, 0x18cf: 0x0f71, 0x18d0: 0x00d9, 0x18d1: 0x0f99, - 0x18d2: 0x2039, 0x18d3: 0x0269, 0x18d4: 0x01d9, 0x18d5: 0x0fa9, 0x18d6: 0x0fb9, 0x18d7: 0x1089, - 0x18d8: 0x0279, 0x18d9: 0x0369, 0x18da: 0x0289, 0x18db: 0x13d1, 0x18dc: 0x0039, 0x18dd: 0x0040, - 0x18de: 0x1159, 0x18df: 0x0ef9, 0x18e0: 0x0040, 0x18e1: 0x0040, 0x18e2: 0x0f31, 0x18e3: 0x0040, - 0x18e4: 0x0040, 0x18e5: 0x0259, 0x18e6: 0x0f51, 0x18e7: 0x0040, 0x18e8: 0x0040, 0x18e9: 0x0f71, - 0x18ea: 0x00d9, 0x18eb: 0x0f99, 0x18ec: 0x2039, 0x18ed: 0x0040, 0x18ee: 0x01d9, 0x18ef: 0x0fa9, - 0x18f0: 0x0fb9, 0x18f1: 0x1089, 0x18f2: 0x0279, 0x18f3: 0x0369, 0x18f4: 0x0289, 0x18f5: 0x13d1, - 0x18f6: 0x0039, 0x18f7: 0x0ee9, 0x18f8: 0x1159, 0x18f9: 0x0ef9, 0x18fa: 0x0040, 0x18fb: 0x1199, - 0x18fc: 0x0040, 0x18fd: 0x0249, 0x18fe: 0x0f41, 0x18ff: 0x0259, - // Block 0x64, offset 0x1900 - 0x1900: 0x0f51, 0x1901: 0x0359, 0x1902: 0x0f61, 0x1903: 0x0f71, 0x1904: 0x0040, 0x1905: 0x0f99, - 0x1906: 0x2039, 0x1907: 0x0269, 0x1908: 0x01d9, 0x1909: 0x0fa9, 0x190a: 0x0fb9, 0x190b: 0x1089, - 0x190c: 0x0279, 0x190d: 0x0369, 0x190e: 0x0289, 0x190f: 0x13d1, 0x1910: 0x0039, 0x1911: 0x0ee9, - 0x1912: 0x1159, 0x1913: 0x0ef9, 0x1914: 0x0f09, 0x1915: 0x1199, 0x1916: 0x0f31, 0x1917: 0x0249, - 0x1918: 0x0f41, 0x1919: 0x0259, 0x191a: 0x0f51, 0x191b: 0x0359, 0x191c: 0x0f61, 0x191d: 0x0f71, - 0x191e: 0x00d9, 0x191f: 0x0f99, 0x1920: 0x2039, 0x1921: 0x0269, 0x1922: 0x01d9, 0x1923: 0x0fa9, - 0x1924: 0x0fb9, 0x1925: 0x1089, 0x1926: 0x0279, 0x1927: 0x0369, 0x1928: 0x0289, 0x1929: 0x13d1, - 0x192a: 0x0039, 0x192b: 0x0ee9, 0x192c: 0x1159, 0x192d: 0x0ef9, 0x192e: 0x0f09, 0x192f: 0x1199, - 0x1930: 0x0f31, 0x1931: 0x0249, 0x1932: 0x0f41, 0x1933: 0x0259, 0x1934: 0x0f51, 0x1935: 0x0359, - 0x1936: 0x0f61, 0x1937: 0x0f71, 0x1938: 0x00d9, 0x1939: 0x0f99, 0x193a: 0x2039, 0x193b: 0x0269, - 0x193c: 0x01d9, 0x193d: 0x0fa9, 0x193e: 0x0fb9, 0x193f: 0x1089, - // Block 0x65, offset 0x1940 - 0x1940: 0x0279, 0x1941: 0x0369, 0x1942: 0x0289, 0x1943: 0x13d1, 0x1944: 0x0039, 0x1945: 0x0ee9, - 0x1946: 0x0040, 0x1947: 0x0ef9, 0x1948: 0x0f09, 0x1949: 0x1199, 0x194a: 0x0f31, 0x194b: 0x0040, - 0x194c: 0x0040, 0x194d: 0x0259, 0x194e: 0x0f51, 0x194f: 0x0359, 0x1950: 0x0f61, 0x1951: 0x0f71, - 0x1952: 0x00d9, 0x1953: 0x0f99, 0x1954: 0x2039, 0x1955: 0x0040, 0x1956: 0x01d9, 0x1957: 0x0fa9, - 0x1958: 0x0fb9, 0x1959: 0x1089, 0x195a: 0x0279, 0x195b: 0x0369, 0x195c: 0x0289, 0x195d: 0x0040, - 0x195e: 0x0039, 0x195f: 0x0ee9, 0x1960: 0x1159, 0x1961: 0x0ef9, 0x1962: 0x0f09, 0x1963: 0x1199, - 0x1964: 0x0f31, 0x1965: 0x0249, 0x1966: 0x0f41, 0x1967: 0x0259, 0x1968: 0x0f51, 0x1969: 0x0359, - 0x196a: 0x0f61, 0x196b: 0x0f71, 0x196c: 0x00d9, 0x196d: 0x0f99, 0x196e: 0x2039, 0x196f: 0x0269, - 0x1970: 0x01d9, 0x1971: 0x0fa9, 0x1972: 0x0fb9, 0x1973: 0x1089, 0x1974: 0x0279, 0x1975: 0x0369, - 0x1976: 0x0289, 0x1977: 0x13d1, 0x1978: 0x0039, 0x1979: 0x0ee9, 0x197a: 0x0040, 0x197b: 0x0ef9, - 0x197c: 0x0f09, 0x197d: 0x1199, 0x197e: 0x0f31, 0x197f: 0x0040, - // Block 0x66, offset 0x1980 - 0x1980: 0x0f41, 0x1981: 0x0259, 0x1982: 0x0f51, 0x1983: 0x0359, 0x1984: 0x0f61, 0x1985: 0x0040, - 0x1986: 0x00d9, 0x1987: 0x0040, 0x1988: 0x0040, 0x1989: 0x0040, 0x198a: 0x01d9, 0x198b: 0x0fa9, - 0x198c: 0x0fb9, 0x198d: 0x1089, 0x198e: 0x0279, 0x198f: 0x0369, 0x1990: 0x0289, 0x1991: 0x0040, - 0x1992: 0x0039, 0x1993: 0x0ee9, 0x1994: 0x1159, 0x1995: 0x0ef9, 0x1996: 0x0f09, 0x1997: 0x1199, - 0x1998: 0x0f31, 0x1999: 0x0249, 0x199a: 0x0f41, 0x199b: 0x0259, 0x199c: 0x0f51, 0x199d: 0x0359, - 0x199e: 0x0f61, 0x199f: 0x0f71, 0x19a0: 0x00d9, 0x19a1: 0x0f99, 0x19a2: 0x2039, 0x19a3: 0x0269, - 0x19a4: 0x01d9, 0x19a5: 0x0fa9, 0x19a6: 0x0fb9, 0x19a7: 0x1089, 0x19a8: 0x0279, 0x19a9: 0x0369, - 0x19aa: 0x0289, 0x19ab: 0x13d1, 0x19ac: 0x0039, 0x19ad: 0x0ee9, 0x19ae: 0x1159, 0x19af: 0x0ef9, - 0x19b0: 0x0f09, 0x19b1: 0x1199, 0x19b2: 0x0f31, 0x19b3: 0x0249, 0x19b4: 0x0f41, 0x19b5: 0x0259, - 0x19b6: 0x0f51, 0x19b7: 0x0359, 0x19b8: 0x0f61, 0x19b9: 0x0f71, 0x19ba: 0x00d9, 0x19bb: 0x0f99, - 0x19bc: 0x2039, 0x19bd: 0x0269, 0x19be: 0x01d9, 0x19bf: 0x0fa9, - // Block 0x67, offset 0x19c0 - 0x19c0: 0x0fb9, 0x19c1: 0x1089, 0x19c2: 0x0279, 0x19c3: 0x0369, 0x19c4: 0x0289, 0x19c5: 0x13d1, - 0x19c6: 0x0039, 0x19c7: 0x0ee9, 0x19c8: 0x1159, 0x19c9: 0x0ef9, 0x19ca: 0x0f09, 0x19cb: 0x1199, - 0x19cc: 0x0f31, 0x19cd: 0x0249, 0x19ce: 0x0f41, 0x19cf: 0x0259, 0x19d0: 0x0f51, 0x19d1: 0x0359, - 0x19d2: 0x0f61, 0x19d3: 0x0f71, 0x19d4: 0x00d9, 0x19d5: 0x0f99, 0x19d6: 0x2039, 0x19d7: 0x0269, - 0x19d8: 0x01d9, 0x19d9: 0x0fa9, 0x19da: 0x0fb9, 0x19db: 0x1089, 0x19dc: 0x0279, 0x19dd: 0x0369, - 0x19de: 0x0289, 0x19df: 0x13d1, 0x19e0: 0x0039, 0x19e1: 0x0ee9, 0x19e2: 0x1159, 0x19e3: 0x0ef9, - 0x19e4: 0x0f09, 0x19e5: 0x1199, 0x19e6: 0x0f31, 0x19e7: 0x0249, 0x19e8: 0x0f41, 0x19e9: 0x0259, - 0x19ea: 0x0f51, 0x19eb: 0x0359, 0x19ec: 0x0f61, 0x19ed: 0x0f71, 0x19ee: 0x00d9, 0x19ef: 0x0f99, - 0x19f0: 0x2039, 0x19f1: 0x0269, 0x19f2: 0x01d9, 0x19f3: 0x0fa9, 0x19f4: 0x0fb9, 0x19f5: 0x1089, - 0x19f6: 0x0279, 0x19f7: 0x0369, 0x19f8: 0x0289, 0x19f9: 0x13d1, 0x19fa: 0x0039, 0x19fb: 0x0ee9, - 0x19fc: 0x1159, 0x19fd: 0x0ef9, 0x19fe: 0x0f09, 0x19ff: 0x1199, - // Block 0x68, offset 0x1a00 - 0x1a00: 0x0f31, 0x1a01: 0x0249, 0x1a02: 0x0f41, 0x1a03: 0x0259, 0x1a04: 0x0f51, 0x1a05: 0x0359, - 0x1a06: 0x0f61, 0x1a07: 0x0f71, 0x1a08: 0x00d9, 0x1a09: 0x0f99, 0x1a0a: 0x2039, 0x1a0b: 0x0269, - 0x1a0c: 0x01d9, 0x1a0d: 0x0fa9, 0x1a0e: 0x0fb9, 0x1a0f: 0x1089, 0x1a10: 0x0279, 0x1a11: 0x0369, - 0x1a12: 0x0289, 0x1a13: 0x13d1, 0x1a14: 0x0039, 0x1a15: 0x0ee9, 0x1a16: 0x1159, 0x1a17: 0x0ef9, - 0x1a18: 0x0f09, 0x1a19: 0x1199, 0x1a1a: 0x0f31, 0x1a1b: 0x0249, 0x1a1c: 0x0f41, 0x1a1d: 0x0259, - 0x1a1e: 0x0f51, 0x1a1f: 0x0359, 0x1a20: 0x0f61, 0x1a21: 0x0f71, 0x1a22: 0x00d9, 0x1a23: 0x0f99, - 0x1a24: 0x2039, 0x1a25: 0x0269, 0x1a26: 0x01d9, 0x1a27: 0x0fa9, 0x1a28: 0x0fb9, 0x1a29: 0x1089, - 0x1a2a: 0x0279, 0x1a2b: 0x0369, 0x1a2c: 0x0289, 0x1a2d: 0x13d1, 0x1a2e: 0x0039, 0x1a2f: 0x0ee9, - 0x1a30: 0x1159, 0x1a31: 0x0ef9, 0x1a32: 0x0f09, 0x1a33: 0x1199, 0x1a34: 0x0f31, 0x1a35: 0x0249, - 0x1a36: 0x0f41, 0x1a37: 0x0259, 0x1a38: 0x0f51, 0x1a39: 0x0359, 0x1a3a: 0x0f61, 0x1a3b: 0x0f71, - 0x1a3c: 0x00d9, 0x1a3d: 0x0f99, 0x1a3e: 0x2039, 0x1a3f: 0x0269, - // Block 0x69, offset 0x1a40 - 0x1a40: 0x01d9, 0x1a41: 0x0fa9, 0x1a42: 0x0fb9, 0x1a43: 0x1089, 0x1a44: 0x0279, 0x1a45: 0x0369, - 0x1a46: 0x0289, 0x1a47: 0x13d1, 0x1a48: 0x0039, 0x1a49: 0x0ee9, 0x1a4a: 0x1159, 0x1a4b: 0x0ef9, - 0x1a4c: 0x0f09, 0x1a4d: 0x1199, 0x1a4e: 0x0f31, 0x1a4f: 0x0249, 0x1a50: 0x0f41, 0x1a51: 0x0259, - 0x1a52: 0x0f51, 0x1a53: 0x0359, 0x1a54: 0x0f61, 0x1a55: 0x0f71, 0x1a56: 0x00d9, 0x1a57: 0x0f99, - 0x1a58: 0x2039, 0x1a59: 0x0269, 0x1a5a: 0x01d9, 0x1a5b: 0x0fa9, 0x1a5c: 0x0fb9, 0x1a5d: 0x1089, - 0x1a5e: 0x0279, 0x1a5f: 0x0369, 0x1a60: 0x0289, 0x1a61: 0x13d1, 0x1a62: 0x0039, 0x1a63: 0x0ee9, - 0x1a64: 0x1159, 0x1a65: 0x0ef9, 0x1a66: 0x0f09, 0x1a67: 0x1199, 0x1a68: 0x0f31, 0x1a69: 0x0249, - 0x1a6a: 0x0f41, 0x1a6b: 0x0259, 0x1a6c: 0x0f51, 0x1a6d: 0x0359, 0x1a6e: 0x0f61, 0x1a6f: 0x0f71, - 0x1a70: 0x00d9, 0x1a71: 0x0f99, 0x1a72: 0x2039, 0x1a73: 0x0269, 0x1a74: 0x01d9, 0x1a75: 0x0fa9, - 0x1a76: 0x0fb9, 0x1a77: 0x1089, 0x1a78: 0x0279, 0x1a79: 0x0369, 0x1a7a: 0x0289, 0x1a7b: 0x13d1, - 0x1a7c: 0x0039, 0x1a7d: 0x0ee9, 0x1a7e: 0x1159, 0x1a7f: 0x0ef9, - // Block 0x6a, offset 0x1a80 - 0x1a80: 0x0f09, 0x1a81: 0x1199, 0x1a82: 0x0f31, 0x1a83: 0x0249, 0x1a84: 0x0f41, 0x1a85: 0x0259, - 0x1a86: 0x0f51, 0x1a87: 0x0359, 0x1a88: 0x0f61, 0x1a89: 0x0f71, 0x1a8a: 0x00d9, 0x1a8b: 0x0f99, - 0x1a8c: 0x2039, 0x1a8d: 0x0269, 0x1a8e: 0x01d9, 0x1a8f: 0x0fa9, 0x1a90: 0x0fb9, 0x1a91: 0x1089, - 0x1a92: 0x0279, 0x1a93: 0x0369, 0x1a94: 0x0289, 0x1a95: 0x13d1, 0x1a96: 0x0039, 0x1a97: 0x0ee9, - 0x1a98: 0x1159, 0x1a99: 0x0ef9, 0x1a9a: 0x0f09, 0x1a9b: 0x1199, 0x1a9c: 0x0f31, 0x1a9d: 0x0249, - 0x1a9e: 0x0f41, 0x1a9f: 0x0259, 0x1aa0: 0x0f51, 0x1aa1: 0x0359, 0x1aa2: 0x0f61, 0x1aa3: 0x0f71, - 0x1aa4: 0x00d9, 0x1aa5: 0x0f99, 0x1aa6: 0x2039, 0x1aa7: 0x0269, 0x1aa8: 0x01d9, 0x1aa9: 0x0fa9, - 0x1aaa: 0x0fb9, 0x1aab: 0x1089, 0x1aac: 0x0279, 0x1aad: 0x0369, 0x1aae: 0x0289, 0x1aaf: 0x13d1, - 0x1ab0: 0x0039, 0x1ab1: 0x0ee9, 0x1ab2: 0x1159, 0x1ab3: 0x0ef9, 0x1ab4: 0x0f09, 0x1ab5: 0x1199, - 0x1ab6: 0x0f31, 0x1ab7: 0x0249, 0x1ab8: 0x0f41, 0x1ab9: 0x0259, 0x1aba: 0x0f51, 0x1abb: 0x0359, - 0x1abc: 0x0f61, 0x1abd: 0x0f71, 0x1abe: 0x00d9, 0x1abf: 0x0f99, - // Block 0x6b, offset 0x1ac0 - 0x1ac0: 0x2039, 0x1ac1: 0x0269, 0x1ac2: 0x01d9, 0x1ac3: 0x0fa9, 0x1ac4: 0x0fb9, 0x1ac5: 0x1089, - 0x1ac6: 0x0279, 0x1ac7: 0x0369, 0x1ac8: 0x0289, 0x1ac9: 0x13d1, 0x1aca: 0x0039, 0x1acb: 0x0ee9, - 0x1acc: 0x1159, 0x1acd: 0x0ef9, 0x1ace: 0x0f09, 0x1acf: 0x1199, 0x1ad0: 0x0f31, 0x1ad1: 0x0249, - 0x1ad2: 0x0f41, 0x1ad3: 0x0259, 0x1ad4: 0x0f51, 0x1ad5: 0x0359, 0x1ad6: 0x0f61, 0x1ad7: 0x0f71, - 0x1ad8: 0x00d9, 0x1ad9: 0x0f99, 0x1ada: 0x2039, 0x1adb: 0x0269, 0x1adc: 0x01d9, 0x1add: 0x0fa9, - 0x1ade: 0x0fb9, 0x1adf: 0x1089, 0x1ae0: 0x0279, 0x1ae1: 0x0369, 0x1ae2: 0x0289, 0x1ae3: 0x13d1, - 0x1ae4: 0xba81, 0x1ae5: 0xba99, 0x1ae6: 0x0040, 0x1ae7: 0x0040, 0x1ae8: 0xbab1, 0x1ae9: 0x1099, - 0x1aea: 0x10b1, 0x1aeb: 0x10c9, 0x1aec: 0xbac9, 0x1aed: 0xbae1, 0x1aee: 0xbaf9, 0x1aef: 0x1429, - 0x1af0: 0x1a31, 0x1af1: 0xbb11, 0x1af2: 0xbb29, 0x1af3: 0xbb41, 0x1af4: 0xbb59, 0x1af5: 0xbb71, - 0x1af6: 0xbb89, 0x1af7: 0x2109, 0x1af8: 0x1111, 0x1af9: 0x1429, 0x1afa: 0xbba1, 0x1afb: 0xbbb9, - 0x1afc: 0xbbd1, 0x1afd: 0x10e1, 0x1afe: 0x10f9, 0x1aff: 0xbbe9, - // Block 0x6c, offset 0x1b00 - 0x1b00: 0x2079, 0x1b01: 0xbc01, 0x1b02: 0xbab1, 0x1b03: 0x1099, 0x1b04: 0x10b1, 0x1b05: 0x10c9, - 0x1b06: 0xbac9, 0x1b07: 0xbae1, 0x1b08: 0xbaf9, 0x1b09: 0x1429, 0x1b0a: 0x1a31, 0x1b0b: 0xbb11, - 0x1b0c: 0xbb29, 0x1b0d: 0xbb41, 0x1b0e: 0xbb59, 0x1b0f: 0xbb71, 0x1b10: 0xbb89, 0x1b11: 0x2109, - 0x1b12: 0x1111, 0x1b13: 0xbba1, 0x1b14: 0xbba1, 0x1b15: 0xbbb9, 0x1b16: 0xbbd1, 0x1b17: 0x10e1, - 0x1b18: 0x10f9, 0x1b19: 0xbbe9, 0x1b1a: 0x2079, 0x1b1b: 0xbc21, 0x1b1c: 0xbac9, 0x1b1d: 0x1429, - 0x1b1e: 0xbb11, 0x1b1f: 0x10e1, 0x1b20: 0x1111, 0x1b21: 0x2109, 0x1b22: 0xbab1, 0x1b23: 0x1099, - 0x1b24: 0x10b1, 0x1b25: 0x10c9, 0x1b26: 0xbac9, 0x1b27: 0xbae1, 0x1b28: 0xbaf9, 0x1b29: 0x1429, - 0x1b2a: 0x1a31, 0x1b2b: 0xbb11, 0x1b2c: 0xbb29, 0x1b2d: 0xbb41, 0x1b2e: 0xbb59, 0x1b2f: 0xbb71, - 0x1b30: 0xbb89, 0x1b31: 0x2109, 0x1b32: 0x1111, 0x1b33: 0x1429, 0x1b34: 0xbba1, 0x1b35: 0xbbb9, - 0x1b36: 0xbbd1, 0x1b37: 0x10e1, 0x1b38: 0x10f9, 0x1b39: 0xbbe9, 0x1b3a: 0x2079, 0x1b3b: 0xbc01, - 0x1b3c: 0xbab1, 0x1b3d: 0x1099, 0x1b3e: 0x10b1, 0x1b3f: 0x10c9, - // Block 0x6d, offset 0x1b40 - 0x1b40: 0xbac9, 0x1b41: 0xbae1, 0x1b42: 0xbaf9, 0x1b43: 0x1429, 0x1b44: 0x1a31, 0x1b45: 0xbb11, - 0x1b46: 0xbb29, 0x1b47: 0xbb41, 0x1b48: 0xbb59, 0x1b49: 0xbb71, 0x1b4a: 0xbb89, 0x1b4b: 0x2109, - 0x1b4c: 0x1111, 0x1b4d: 0xbba1, 0x1b4e: 0xbba1, 0x1b4f: 0xbbb9, 0x1b50: 0xbbd1, 0x1b51: 0x10e1, - 0x1b52: 0x10f9, 0x1b53: 0xbbe9, 0x1b54: 0x2079, 0x1b55: 0xbc21, 0x1b56: 0xbac9, 0x1b57: 0x1429, - 0x1b58: 0xbb11, 0x1b59: 0x10e1, 0x1b5a: 0x1111, 0x1b5b: 0x2109, 0x1b5c: 0xbab1, 0x1b5d: 0x1099, - 0x1b5e: 0x10b1, 0x1b5f: 0x10c9, 0x1b60: 0xbac9, 0x1b61: 0xbae1, 0x1b62: 0xbaf9, 0x1b63: 0x1429, - 0x1b64: 0x1a31, 0x1b65: 0xbb11, 0x1b66: 0xbb29, 0x1b67: 0xbb41, 0x1b68: 0xbb59, 0x1b69: 0xbb71, - 0x1b6a: 0xbb89, 0x1b6b: 0x2109, 0x1b6c: 0x1111, 0x1b6d: 0x1429, 0x1b6e: 0xbba1, 0x1b6f: 0xbbb9, - 0x1b70: 0xbbd1, 0x1b71: 0x10e1, 0x1b72: 0x10f9, 0x1b73: 0xbbe9, 0x1b74: 0x2079, 0x1b75: 0xbc01, - 0x1b76: 0xbab1, 0x1b77: 0x1099, 0x1b78: 0x10b1, 0x1b79: 0x10c9, 0x1b7a: 0xbac9, 0x1b7b: 0xbae1, - 0x1b7c: 0xbaf9, 0x1b7d: 0x1429, 0x1b7e: 0x1a31, 0x1b7f: 0xbb11, - // Block 0x6e, offset 0x1b80 - 0x1b80: 0xbb29, 0x1b81: 0xbb41, 0x1b82: 0xbb59, 0x1b83: 0xbb71, 0x1b84: 0xbb89, 0x1b85: 0x2109, - 0x1b86: 0x1111, 0x1b87: 0xbba1, 0x1b88: 0xbba1, 0x1b89: 0xbbb9, 0x1b8a: 0xbbd1, 0x1b8b: 0x10e1, - 0x1b8c: 0x10f9, 0x1b8d: 0xbbe9, 0x1b8e: 0x2079, 0x1b8f: 0xbc21, 0x1b90: 0xbac9, 0x1b91: 0x1429, - 0x1b92: 0xbb11, 0x1b93: 0x10e1, 0x1b94: 0x1111, 0x1b95: 0x2109, 0x1b96: 0xbab1, 0x1b97: 0x1099, - 0x1b98: 0x10b1, 0x1b99: 0x10c9, 0x1b9a: 0xbac9, 0x1b9b: 0xbae1, 0x1b9c: 0xbaf9, 0x1b9d: 0x1429, - 0x1b9e: 0x1a31, 0x1b9f: 0xbb11, 0x1ba0: 0xbb29, 0x1ba1: 0xbb41, 0x1ba2: 0xbb59, 0x1ba3: 0xbb71, - 0x1ba4: 0xbb89, 0x1ba5: 0x2109, 0x1ba6: 0x1111, 0x1ba7: 0x1429, 0x1ba8: 0xbba1, 0x1ba9: 0xbbb9, - 0x1baa: 0xbbd1, 0x1bab: 0x10e1, 0x1bac: 0x10f9, 0x1bad: 0xbbe9, 0x1bae: 0x2079, 0x1baf: 0xbc01, - 0x1bb0: 0xbab1, 0x1bb1: 0x1099, 0x1bb2: 0x10b1, 0x1bb3: 0x10c9, 0x1bb4: 0xbac9, 0x1bb5: 0xbae1, - 0x1bb6: 0xbaf9, 0x1bb7: 0x1429, 0x1bb8: 0x1a31, 0x1bb9: 0xbb11, 0x1bba: 0xbb29, 0x1bbb: 0xbb41, - 0x1bbc: 0xbb59, 0x1bbd: 0xbb71, 0x1bbe: 0xbb89, 0x1bbf: 0x2109, - // Block 0x6f, offset 0x1bc0 - 0x1bc0: 0x1111, 0x1bc1: 0xbba1, 0x1bc2: 0xbba1, 0x1bc3: 0xbbb9, 0x1bc4: 0xbbd1, 0x1bc5: 0x10e1, - 0x1bc6: 0x10f9, 0x1bc7: 0xbbe9, 0x1bc8: 0x2079, 0x1bc9: 0xbc21, 0x1bca: 0xbac9, 0x1bcb: 0x1429, - 0x1bcc: 0xbb11, 0x1bcd: 0x10e1, 0x1bce: 0x1111, 0x1bcf: 0x2109, 0x1bd0: 0xbab1, 0x1bd1: 0x1099, - 0x1bd2: 0x10b1, 0x1bd3: 0x10c9, 0x1bd4: 0xbac9, 0x1bd5: 0xbae1, 0x1bd6: 0xbaf9, 0x1bd7: 0x1429, - 0x1bd8: 0x1a31, 0x1bd9: 0xbb11, 0x1bda: 0xbb29, 0x1bdb: 0xbb41, 0x1bdc: 0xbb59, 0x1bdd: 0xbb71, - 0x1bde: 0xbb89, 0x1bdf: 0x2109, 0x1be0: 0x1111, 0x1be1: 0x1429, 0x1be2: 0xbba1, 0x1be3: 0xbbb9, - 0x1be4: 0xbbd1, 0x1be5: 0x10e1, 0x1be6: 0x10f9, 0x1be7: 0xbbe9, 0x1be8: 0x2079, 0x1be9: 0xbc01, - 0x1bea: 0xbab1, 0x1beb: 0x1099, 0x1bec: 0x10b1, 0x1bed: 0x10c9, 0x1bee: 0xbac9, 0x1bef: 0xbae1, - 0x1bf0: 0xbaf9, 0x1bf1: 0x1429, 0x1bf2: 0x1a31, 0x1bf3: 0xbb11, 0x1bf4: 0xbb29, 0x1bf5: 0xbb41, - 0x1bf6: 0xbb59, 0x1bf7: 0xbb71, 0x1bf8: 0xbb89, 0x1bf9: 0x2109, 0x1bfa: 0x1111, 0x1bfb: 0xbba1, - 0x1bfc: 0xbba1, 0x1bfd: 0xbbb9, 0x1bfe: 0xbbd1, 0x1bff: 0x10e1, - // Block 0x70, offset 0x1c00 - 0x1c00: 0x10f9, 0x1c01: 0xbbe9, 0x1c02: 0x2079, 0x1c03: 0xbc21, 0x1c04: 0xbac9, 0x1c05: 0x1429, - 0x1c06: 0xbb11, 0x1c07: 0x10e1, 0x1c08: 0x1111, 0x1c09: 0x2109, 0x1c0a: 0xbc41, 0x1c0b: 0xbc41, - 0x1c0c: 0x0040, 0x1c0d: 0x0040, 0x1c0e: 0x1f41, 0x1c0f: 0x00c9, 0x1c10: 0x0069, 0x1c11: 0x0079, - 0x1c12: 0x1f51, 0x1c13: 0x1f61, 0x1c14: 0x1f71, 0x1c15: 0x1f81, 0x1c16: 0x1f91, 0x1c17: 0x1fa1, - 0x1c18: 0x1f41, 0x1c19: 0x00c9, 0x1c1a: 0x0069, 0x1c1b: 0x0079, 0x1c1c: 0x1f51, 0x1c1d: 0x1f61, - 0x1c1e: 0x1f71, 0x1c1f: 0x1f81, 0x1c20: 0x1f91, 0x1c21: 0x1fa1, 0x1c22: 0x1f41, 0x1c23: 0x00c9, - 0x1c24: 0x0069, 0x1c25: 0x0079, 0x1c26: 0x1f51, 0x1c27: 0x1f61, 0x1c28: 0x1f71, 0x1c29: 0x1f81, - 0x1c2a: 0x1f91, 0x1c2b: 0x1fa1, 0x1c2c: 0x1f41, 0x1c2d: 0x00c9, 0x1c2e: 0x0069, 0x1c2f: 0x0079, - 0x1c30: 0x1f51, 0x1c31: 0x1f61, 0x1c32: 0x1f71, 0x1c33: 0x1f81, 0x1c34: 0x1f91, 0x1c35: 0x1fa1, - 0x1c36: 0x1f41, 0x1c37: 0x00c9, 0x1c38: 0x0069, 0x1c39: 0x0079, 0x1c3a: 0x1f51, 0x1c3b: 0x1f61, - 0x1c3c: 0x1f71, 0x1c3d: 0x1f81, 0x1c3e: 0x1f91, 0x1c3f: 0x1fa1, - // Block 0x71, offset 0x1c40 - 0x1c40: 0xe115, 0x1c41: 0xe115, 0x1c42: 0xe135, 0x1c43: 0xe135, 0x1c44: 0xe115, 0x1c45: 0xe115, - 0x1c46: 0xe175, 0x1c47: 0xe175, 0x1c48: 0xe115, 0x1c49: 0xe115, 0x1c4a: 0xe135, 0x1c4b: 0xe135, - 0x1c4c: 0xe115, 0x1c4d: 0xe115, 0x1c4e: 0xe1f5, 0x1c4f: 0xe1f5, 0x1c50: 0xe115, 0x1c51: 0xe115, - 0x1c52: 0xe135, 0x1c53: 0xe135, 0x1c54: 0xe115, 0x1c55: 0xe115, 0x1c56: 0xe175, 0x1c57: 0xe175, - 0x1c58: 0xe115, 0x1c59: 0xe115, 0x1c5a: 0xe135, 0x1c5b: 0xe135, 0x1c5c: 0xe115, 0x1c5d: 0xe115, - 0x1c5e: 0x8b3d, 0x1c5f: 0x8b3d, 0x1c60: 0x04b5, 0x1c61: 0x04b5, 0x1c62: 0x0a08, 0x1c63: 0x0a08, - 0x1c64: 0x0a08, 0x1c65: 0x0a08, 0x1c66: 0x0a08, 0x1c67: 0x0a08, 0x1c68: 0x0a08, 0x1c69: 0x0a08, - 0x1c6a: 0x0a08, 0x1c6b: 0x0a08, 0x1c6c: 0x0a08, 0x1c6d: 0x0a08, 0x1c6e: 0x0a08, 0x1c6f: 0x0a08, - 0x1c70: 0x0a08, 0x1c71: 0x0a08, 0x1c72: 0x0a08, 0x1c73: 0x0a08, 0x1c74: 0x0a08, 0x1c75: 0x0a08, - 0x1c76: 0x0a08, 0x1c77: 0x0a08, 0x1c78: 0x0a08, 0x1c79: 0x0a08, 0x1c7a: 0x0a08, 0x1c7b: 0x0a08, - 0x1c7c: 0x0a08, 0x1c7d: 0x0a08, 0x1c7e: 0x0a08, 0x1c7f: 0x0a08, - // Block 0x72, offset 0x1c80 - 0x1c80: 0xb189, 0x1c81: 0xb1a1, 0x1c82: 0xb201, 0x1c83: 0xb249, 0x1c84: 0x0040, 0x1c85: 0xb411, - 0x1c86: 0xb291, 0x1c87: 0xb219, 0x1c88: 0xb309, 0x1c89: 0xb429, 0x1c8a: 0xb399, 0x1c8b: 0xb3b1, - 0x1c8c: 0xb3c9, 0x1c8d: 0xb3e1, 0x1c8e: 0xb2a9, 0x1c8f: 0xb339, 0x1c90: 0xb369, 0x1c91: 0xb2d9, - 0x1c92: 0xb381, 0x1c93: 0xb279, 0x1c94: 0xb2c1, 0x1c95: 0xb1d1, 0x1c96: 0xb1e9, 0x1c97: 0xb231, - 0x1c98: 0xb261, 0x1c99: 0xb2f1, 0x1c9a: 0xb321, 0x1c9b: 0xb351, 0x1c9c: 0xbc59, 0x1c9d: 0x7949, - 0x1c9e: 0xbc71, 0x1c9f: 0xbc89, 0x1ca0: 0x0040, 0x1ca1: 0xb1a1, 0x1ca2: 0xb201, 0x1ca3: 0x0040, - 0x1ca4: 0xb3f9, 0x1ca5: 0x0040, 0x1ca6: 0x0040, 0x1ca7: 0xb219, 0x1ca8: 0x0040, 0x1ca9: 0xb429, - 0x1caa: 0xb399, 0x1cab: 0xb3b1, 0x1cac: 0xb3c9, 0x1cad: 0xb3e1, 0x1cae: 0xb2a9, 0x1caf: 0xb339, - 0x1cb0: 0xb369, 0x1cb1: 0xb2d9, 0x1cb2: 0xb381, 0x1cb3: 0x0040, 0x1cb4: 0xb2c1, 0x1cb5: 0xb1d1, - 0x1cb6: 0xb1e9, 0x1cb7: 0xb231, 0x1cb8: 0x0040, 0x1cb9: 0xb2f1, 0x1cba: 0x0040, 0x1cbb: 0xb351, - 0x1cbc: 0x0040, 0x1cbd: 0x0040, 0x1cbe: 0x0040, 0x1cbf: 0x0040, - // Block 0x73, offset 0x1cc0 - 0x1cc0: 0x0040, 0x1cc1: 0x0040, 0x1cc2: 0xb201, 0x1cc3: 0x0040, 0x1cc4: 0x0040, 0x1cc5: 0x0040, - 0x1cc6: 0x0040, 0x1cc7: 0xb219, 0x1cc8: 0x0040, 0x1cc9: 0xb429, 0x1cca: 0x0040, 0x1ccb: 0xb3b1, - 0x1ccc: 0x0040, 0x1ccd: 0xb3e1, 0x1cce: 0xb2a9, 0x1ccf: 0xb339, 0x1cd0: 0x0040, 0x1cd1: 0xb2d9, - 0x1cd2: 0xb381, 0x1cd3: 0x0040, 0x1cd4: 0xb2c1, 0x1cd5: 0x0040, 0x1cd6: 0x0040, 0x1cd7: 0xb231, - 0x1cd8: 0x0040, 0x1cd9: 0xb2f1, 0x1cda: 0x0040, 0x1cdb: 0xb351, 0x1cdc: 0x0040, 0x1cdd: 0x7949, - 0x1cde: 0x0040, 0x1cdf: 0xbc89, 0x1ce0: 0x0040, 0x1ce1: 0xb1a1, 0x1ce2: 0xb201, 0x1ce3: 0x0040, - 0x1ce4: 0xb3f9, 0x1ce5: 0x0040, 0x1ce6: 0x0040, 0x1ce7: 0xb219, 0x1ce8: 0xb309, 0x1ce9: 0xb429, - 0x1cea: 0xb399, 0x1ceb: 0x0040, 0x1cec: 0xb3c9, 0x1ced: 0xb3e1, 0x1cee: 0xb2a9, 0x1cef: 0xb339, - 0x1cf0: 0xb369, 0x1cf1: 0xb2d9, 0x1cf2: 0xb381, 0x1cf3: 0x0040, 0x1cf4: 0xb2c1, 0x1cf5: 0xb1d1, - 0x1cf6: 0xb1e9, 0x1cf7: 0xb231, 0x1cf8: 0x0040, 0x1cf9: 0xb2f1, 0x1cfa: 0xb321, 0x1cfb: 0xb351, - 0x1cfc: 0xbc59, 0x1cfd: 0x0040, 0x1cfe: 0xbc71, 0x1cff: 0x0040, - // Block 0x74, offset 0x1d00 - 0x1d00: 0xb189, 0x1d01: 0xb1a1, 0x1d02: 0xb201, 0x1d03: 0xb249, 0x1d04: 0xb3f9, 0x1d05: 0xb411, - 0x1d06: 0xb291, 0x1d07: 0xb219, 0x1d08: 0xb309, 0x1d09: 0xb429, 0x1d0a: 0x0040, 0x1d0b: 0xb3b1, - 0x1d0c: 0xb3c9, 0x1d0d: 0xb3e1, 0x1d0e: 0xb2a9, 0x1d0f: 0xb339, 0x1d10: 0xb369, 0x1d11: 0xb2d9, - 0x1d12: 0xb381, 0x1d13: 0xb279, 0x1d14: 0xb2c1, 0x1d15: 0xb1d1, 0x1d16: 0xb1e9, 0x1d17: 0xb231, - 0x1d18: 0xb261, 0x1d19: 0xb2f1, 0x1d1a: 0xb321, 0x1d1b: 0xb351, 0x1d1c: 0x0040, 0x1d1d: 0x0040, - 0x1d1e: 0x0040, 0x1d1f: 0x0040, 0x1d20: 0x0040, 0x1d21: 0xb1a1, 0x1d22: 0xb201, 0x1d23: 0xb249, - 0x1d24: 0x0040, 0x1d25: 0xb411, 0x1d26: 0xb291, 0x1d27: 0xb219, 0x1d28: 0xb309, 0x1d29: 0xb429, - 0x1d2a: 0x0040, 0x1d2b: 0xb3b1, 0x1d2c: 0xb3c9, 0x1d2d: 0xb3e1, 0x1d2e: 0xb2a9, 0x1d2f: 0xb339, - 0x1d30: 0xb369, 0x1d31: 0xb2d9, 0x1d32: 0xb381, 0x1d33: 0xb279, 0x1d34: 0xb2c1, 0x1d35: 0xb1d1, - 0x1d36: 0xb1e9, 0x1d37: 0xb231, 0x1d38: 0xb261, 0x1d39: 0xb2f1, 0x1d3a: 0xb321, 0x1d3b: 0xb351, - 0x1d3c: 0x0040, 0x1d3d: 0x0040, 0x1d3e: 0x0040, 0x1d3f: 0x0040, - // Block 0x75, offset 0x1d40 - 0x1d40: 0x0040, 0x1d41: 0xbca2, 0x1d42: 0xbcba, 0x1d43: 0xbcd2, 0x1d44: 0xbcea, 0x1d45: 0xbd02, - 0x1d46: 0xbd1a, 0x1d47: 0xbd32, 0x1d48: 0xbd4a, 0x1d49: 0xbd62, 0x1d4a: 0xbd7a, 0x1d4b: 0x0018, - 0x1d4c: 0x0018, 0x1d4d: 0x0040, 0x1d4e: 0x0040, 0x1d4f: 0x0040, 0x1d50: 0xbd92, 0x1d51: 0xbdb2, - 0x1d52: 0xbdd2, 0x1d53: 0xbdf2, 0x1d54: 0xbe12, 0x1d55: 0xbe32, 0x1d56: 0xbe52, 0x1d57: 0xbe72, - 0x1d58: 0xbe92, 0x1d59: 0xbeb2, 0x1d5a: 0xbed2, 0x1d5b: 0xbef2, 0x1d5c: 0xbf12, 0x1d5d: 0xbf32, - 0x1d5e: 0xbf52, 0x1d5f: 0xbf72, 0x1d60: 0xbf92, 0x1d61: 0xbfb2, 0x1d62: 0xbfd2, 0x1d63: 0xbff2, - 0x1d64: 0xc012, 0x1d65: 0xc032, 0x1d66: 0xc052, 0x1d67: 0xc072, 0x1d68: 0xc092, 0x1d69: 0xc0b2, - 0x1d6a: 0xc0d1, 0x1d6b: 0x1159, 0x1d6c: 0x0269, 0x1d6d: 0x6671, 0x1d6e: 0xc111, 0x1d6f: 0x0018, - 0x1d70: 0x0039, 0x1d71: 0x0ee9, 0x1d72: 0x1159, 0x1d73: 0x0ef9, 0x1d74: 0x0f09, 0x1d75: 0x1199, - 0x1d76: 0x0f31, 0x1d77: 0x0249, 0x1d78: 0x0f41, 0x1d79: 0x0259, 0x1d7a: 0x0f51, 0x1d7b: 0x0359, - 0x1d7c: 0x0f61, 0x1d7d: 0x0f71, 0x1d7e: 0x00d9, 0x1d7f: 0x0f99, - // Block 0x76, offset 0x1d80 - 0x1d80: 0x2039, 0x1d81: 0x0269, 0x1d82: 0x01d9, 0x1d83: 0x0fa9, 0x1d84: 0x0fb9, 0x1d85: 0x1089, - 0x1d86: 0x0279, 0x1d87: 0x0369, 0x1d88: 0x0289, 0x1d89: 0x13d1, 0x1d8a: 0xc129, 0x1d8b: 0x65b1, - 0x1d8c: 0xc141, 0x1d8d: 0x1441, 0x1d8e: 0xc159, 0x1d8f: 0xc179, 0x1d90: 0x0018, 0x1d91: 0x0018, - 0x1d92: 0x0018, 0x1d93: 0x0018, 0x1d94: 0x0018, 0x1d95: 0x0018, 0x1d96: 0x0018, 0x1d97: 0x0018, - 0x1d98: 0x0018, 0x1d99: 0x0018, 0x1d9a: 0x0018, 0x1d9b: 0x0018, 0x1d9c: 0x0018, 0x1d9d: 0x0018, - 0x1d9e: 0x0018, 0x1d9f: 0x0018, 0x1da0: 0x0018, 0x1da1: 0x0018, 0x1da2: 0x0018, 0x1da3: 0x0018, - 0x1da4: 0x0018, 0x1da5: 0x0018, 0x1da6: 0x0018, 0x1da7: 0x0018, 0x1da8: 0x0018, 0x1da9: 0x0018, - 0x1daa: 0xc191, 0x1dab: 0xc1a9, 0x1dac: 0xc1c1, 0x1dad: 0x0040, 0x1dae: 0x0040, 0x1daf: 0x0040, - 0x1db0: 0x0018, 0x1db1: 0x0018, 0x1db2: 0x0018, 0x1db3: 0x0018, 0x1db4: 0x0018, 0x1db5: 0x0018, - 0x1db6: 0x0018, 0x1db7: 0x0018, 0x1db8: 0x0018, 0x1db9: 0x0018, 0x1dba: 0x0018, 0x1dbb: 0x0018, - 0x1dbc: 0x0018, 0x1dbd: 0x0018, 0x1dbe: 0x0018, 0x1dbf: 0x0018, - // Block 0x77, offset 0x1dc0 - 0x1dc0: 0xc1f1, 0x1dc1: 0xc229, 0x1dc2: 0xc261, 0x1dc3: 0x0040, 0x1dc4: 0x0040, 0x1dc5: 0x0040, - 0x1dc6: 0x0040, 0x1dc7: 0x0040, 0x1dc8: 0x0040, 0x1dc9: 0x0040, 0x1dca: 0x0040, 0x1dcb: 0x0040, - 0x1dcc: 0x0040, 0x1dcd: 0x0040, 0x1dce: 0x0040, 0x1dcf: 0x0040, 0x1dd0: 0xc281, 0x1dd1: 0xc2a1, - 0x1dd2: 0xc2c1, 0x1dd3: 0xc2e1, 0x1dd4: 0xc301, 0x1dd5: 0xc321, 0x1dd6: 0xc341, 0x1dd7: 0xc361, - 0x1dd8: 0xc381, 0x1dd9: 0xc3a1, 0x1dda: 0xc3c1, 0x1ddb: 0xc3e1, 0x1ddc: 0xc401, 0x1ddd: 0xc421, - 0x1dde: 0xc441, 0x1ddf: 0xc461, 0x1de0: 0xc481, 0x1de1: 0xc4a1, 0x1de2: 0xc4c1, 0x1de3: 0xc4e1, - 0x1de4: 0xc501, 0x1de5: 0xc521, 0x1de6: 0xc541, 0x1de7: 0xc561, 0x1de8: 0xc581, 0x1de9: 0xc5a1, - 0x1dea: 0xc5c1, 0x1deb: 0xc5e1, 0x1dec: 0xc601, 0x1ded: 0xc621, 0x1dee: 0xc641, 0x1def: 0xc661, - 0x1df0: 0xc681, 0x1df1: 0xc6a1, 0x1df2: 0xc6c1, 0x1df3: 0xc6e1, 0x1df4: 0xc701, 0x1df5: 0xc721, - 0x1df6: 0xc741, 0x1df7: 0xc761, 0x1df8: 0xc781, 0x1df9: 0xc7a1, 0x1dfa: 0xc7c1, 0x1dfb: 0xc7e1, - 0x1dfc: 0x0040, 0x1dfd: 0x0040, 0x1dfe: 0x0040, 0x1dff: 0x0040, - // Block 0x78, offset 0x1e00 - 0x1e00: 0xcb11, 0x1e01: 0xcb31, 0x1e02: 0xcb51, 0x1e03: 0x8b55, 0x1e04: 0xcb71, 0x1e05: 0xcb91, - 0x1e06: 0xcbb1, 0x1e07: 0xcbd1, 0x1e08: 0xcbf1, 0x1e09: 0xcc11, 0x1e0a: 0xcc31, 0x1e0b: 0xcc51, - 0x1e0c: 0xcc71, 0x1e0d: 0x8b75, 0x1e0e: 0xcc91, 0x1e0f: 0xccb1, 0x1e10: 0xccd1, 0x1e11: 0xccf1, - 0x1e12: 0x8b95, 0x1e13: 0xcd11, 0x1e14: 0xcd31, 0x1e15: 0xc441, 0x1e16: 0x8bb5, 0x1e17: 0xcd51, - 0x1e18: 0xcd71, 0x1e19: 0xcd91, 0x1e1a: 0xcdb1, 0x1e1b: 0xcdd1, 0x1e1c: 0x8bd5, 0x1e1d: 0xcdf1, - 0x1e1e: 0xce11, 0x1e1f: 0xce31, 0x1e20: 0xce51, 0x1e21: 0xce71, 0x1e22: 0xc7a1, 0x1e23: 0xce91, - 0x1e24: 0xceb1, 0x1e25: 0xced1, 0x1e26: 0xcef1, 0x1e27: 0xcf11, 0x1e28: 0xcf31, 0x1e29: 0xcf51, - 0x1e2a: 0xcf71, 0x1e2b: 0xcf91, 0x1e2c: 0xcfb1, 0x1e2d: 0xcfd1, 0x1e2e: 0xcff1, 0x1e2f: 0xd011, - 0x1e30: 0xd031, 0x1e31: 0xd051, 0x1e32: 0xd051, 0x1e33: 0xd051, 0x1e34: 0x8bf5, 0x1e35: 0xd071, - 0x1e36: 0xd091, 0x1e37: 0xd0b1, 0x1e38: 0x8c15, 0x1e39: 0xd0d1, 0x1e3a: 0xd0f1, 0x1e3b: 0xd111, - 0x1e3c: 0xd131, 0x1e3d: 0xd151, 0x1e3e: 0xd171, 0x1e3f: 0xd191, - // Block 0x79, offset 0x1e40 - 0x1e40: 0xd1b1, 0x1e41: 0xd1d1, 0x1e42: 0xd1f1, 0x1e43: 0xd211, 0x1e44: 0xd231, 0x1e45: 0xd251, - 0x1e46: 0xd251, 0x1e47: 0xd271, 0x1e48: 0xd291, 0x1e49: 0xd2b1, 0x1e4a: 0xd2d1, 0x1e4b: 0xd2f1, - 0x1e4c: 0xd311, 0x1e4d: 0xd331, 0x1e4e: 0xd351, 0x1e4f: 0xd371, 0x1e50: 0xd391, 0x1e51: 0xd3b1, - 0x1e52: 0xd3d1, 0x1e53: 0xd3f1, 0x1e54: 0xd411, 0x1e55: 0xd431, 0x1e56: 0xd451, 0x1e57: 0xd471, - 0x1e58: 0xd491, 0x1e59: 0x8c35, 0x1e5a: 0xd4b1, 0x1e5b: 0xd4d1, 0x1e5c: 0xd4f1, 0x1e5d: 0xc321, - 0x1e5e: 0xd511, 0x1e5f: 0xd531, 0x1e60: 0x8c55, 0x1e61: 0x8c75, 0x1e62: 0xd551, 0x1e63: 0xd571, - 0x1e64: 0xd591, 0x1e65: 0xd5b1, 0x1e66: 0xd5d1, 0x1e67: 0xd5f1, 0x1e68: 0x2040, 0x1e69: 0xd611, - 0x1e6a: 0xd631, 0x1e6b: 0xd631, 0x1e6c: 0x8c95, 0x1e6d: 0xd651, 0x1e6e: 0xd671, 0x1e6f: 0xd691, - 0x1e70: 0xd6b1, 0x1e71: 0x8cb5, 0x1e72: 0xd6d1, 0x1e73: 0xd6f1, 0x1e74: 0x2040, 0x1e75: 0xd711, - 0x1e76: 0xd731, 0x1e77: 0xd751, 0x1e78: 0xd771, 0x1e79: 0xd791, 0x1e7a: 0xd7b1, 0x1e7b: 0x8cd5, - 0x1e7c: 0xd7d1, 0x1e7d: 0x8cf5, 0x1e7e: 0xd7f1, 0x1e7f: 0xd811, - // Block 0x7a, offset 0x1e80 - 0x1e80: 0xd831, 0x1e81: 0xd851, 0x1e82: 0xd871, 0x1e83: 0xd891, 0x1e84: 0xd8b1, 0x1e85: 0xd8d1, - 0x1e86: 0xd8f1, 0x1e87: 0xd911, 0x1e88: 0xd931, 0x1e89: 0x8d15, 0x1e8a: 0xd951, 0x1e8b: 0xd971, - 0x1e8c: 0xd991, 0x1e8d: 0xd9b1, 0x1e8e: 0xd9d1, 0x1e8f: 0x8d35, 0x1e90: 0xd9f1, 0x1e91: 0x8d55, - 0x1e92: 0x8d75, 0x1e93: 0xda11, 0x1e94: 0xda31, 0x1e95: 0xda31, 0x1e96: 0xda51, 0x1e97: 0x8d95, - 0x1e98: 0x8db5, 0x1e99: 0xda71, 0x1e9a: 0xda91, 0x1e9b: 0xdab1, 0x1e9c: 0xdad1, 0x1e9d: 0xdaf1, - 0x1e9e: 0xdb11, 0x1e9f: 0xdb31, 0x1ea0: 0xdb51, 0x1ea1: 0xdb71, 0x1ea2: 0xdb91, 0x1ea3: 0xdbb1, - 0x1ea4: 0x8dd5, 0x1ea5: 0xdbd1, 0x1ea6: 0xdbf1, 0x1ea7: 0xdc11, 0x1ea8: 0xdc31, 0x1ea9: 0xdc11, - 0x1eaa: 0xdc51, 0x1eab: 0xdc71, 0x1eac: 0xdc91, 0x1ead: 0xdcb1, 0x1eae: 0xdcd1, 0x1eaf: 0xdcf1, - 0x1eb0: 0xdd11, 0x1eb1: 0xdd31, 0x1eb2: 0xdd51, 0x1eb3: 0xdd71, 0x1eb4: 0xdd91, 0x1eb5: 0xddb1, - 0x1eb6: 0xddd1, 0x1eb7: 0xddf1, 0x1eb8: 0x8df5, 0x1eb9: 0xde11, 0x1eba: 0xde31, 0x1ebb: 0xde51, - 0x1ebc: 0xde71, 0x1ebd: 0xde91, 0x1ebe: 0x8e15, 0x1ebf: 0xdeb1, - // Block 0x7b, offset 0x1ec0 - 0x1ec0: 0xe5b1, 0x1ec1: 0xe5d1, 0x1ec2: 0xe5f1, 0x1ec3: 0xe611, 0x1ec4: 0xe631, 0x1ec5: 0xe651, - 0x1ec6: 0x8f35, 0x1ec7: 0xe671, 0x1ec8: 0xe691, 0x1ec9: 0xe6b1, 0x1eca: 0xe6d1, 0x1ecb: 0xe6f1, - 0x1ecc: 0xe711, 0x1ecd: 0x8f55, 0x1ece: 0xe731, 0x1ecf: 0xe751, 0x1ed0: 0x8f75, 0x1ed1: 0x8f95, - 0x1ed2: 0xe771, 0x1ed3: 0xe791, 0x1ed4: 0xe7b1, 0x1ed5: 0xe7d1, 0x1ed6: 0xe7f1, 0x1ed7: 0xe811, - 0x1ed8: 0xe831, 0x1ed9: 0xe851, 0x1eda: 0xe871, 0x1edb: 0x8fb5, 0x1edc: 0xe891, 0x1edd: 0x8fd5, - 0x1ede: 0xe8b1, 0x1edf: 0x2040, 0x1ee0: 0xe8d1, 0x1ee1: 0xe8f1, 0x1ee2: 0xe911, 0x1ee3: 0x8ff5, - 0x1ee4: 0xe931, 0x1ee5: 0xe951, 0x1ee6: 0x9015, 0x1ee7: 0x9035, 0x1ee8: 0xe971, 0x1ee9: 0xe991, - 0x1eea: 0xe9b1, 0x1eeb: 0xe9d1, 0x1eec: 0xe9f1, 0x1eed: 0xe9f1, 0x1eee: 0xea11, 0x1eef: 0xea31, - 0x1ef0: 0xea51, 0x1ef1: 0xea71, 0x1ef2: 0xea91, 0x1ef3: 0xeab1, 0x1ef4: 0xead1, 0x1ef5: 0x9055, - 0x1ef6: 0xeaf1, 0x1ef7: 0x9075, 0x1ef8: 0xeb11, 0x1ef9: 0x9095, 0x1efa: 0xeb31, 0x1efb: 0x90b5, - 0x1efc: 0x90d5, 0x1efd: 0x90f5, 0x1efe: 0xeb51, 0x1eff: 0xeb71, - // Block 0x7c, offset 0x1f00 - 0x1f00: 0xeb91, 0x1f01: 0x9115, 0x1f02: 0x9135, 0x1f03: 0x9155, 0x1f04: 0x9175, 0x1f05: 0xebb1, - 0x1f06: 0xebd1, 0x1f07: 0xebd1, 0x1f08: 0xebf1, 0x1f09: 0xec11, 0x1f0a: 0xec31, 0x1f0b: 0xec51, - 0x1f0c: 0xec71, 0x1f0d: 0x9195, 0x1f0e: 0xec91, 0x1f0f: 0xecb1, 0x1f10: 0xecd1, 0x1f11: 0xecf1, - 0x1f12: 0x91b5, 0x1f13: 0xed11, 0x1f14: 0x91d5, 0x1f15: 0x91f5, 0x1f16: 0xed31, 0x1f17: 0xed51, - 0x1f18: 0xed71, 0x1f19: 0xed91, 0x1f1a: 0xedb1, 0x1f1b: 0xedd1, 0x1f1c: 0x9215, 0x1f1d: 0x9235, - 0x1f1e: 0x9255, 0x1f1f: 0x2040, 0x1f20: 0xedf1, 0x1f21: 0x9275, 0x1f22: 0xee11, 0x1f23: 0xee31, - 0x1f24: 0xee51, 0x1f25: 0x9295, 0x1f26: 0xee71, 0x1f27: 0xee91, 0x1f28: 0xeeb1, 0x1f29: 0xeed1, - 0x1f2a: 0xeef1, 0x1f2b: 0x92b5, 0x1f2c: 0xef11, 0x1f2d: 0xef31, 0x1f2e: 0xef51, 0x1f2f: 0xef71, - 0x1f30: 0xef91, 0x1f31: 0xefb1, 0x1f32: 0x92d5, 0x1f33: 0x92f5, 0x1f34: 0xefd1, 0x1f35: 0x9315, - 0x1f36: 0xeff1, 0x1f37: 0x9335, 0x1f38: 0xf011, 0x1f39: 0xf031, 0x1f3a: 0xf051, 0x1f3b: 0x9355, - 0x1f3c: 0x9375, 0x1f3d: 0xf071, 0x1f3e: 0x9395, 0x1f3f: 0xf091, - // Block 0x7d, offset 0x1f40 - 0x1f40: 0xf6d1, 0x1f41: 0xf6f1, 0x1f42: 0xf711, 0x1f43: 0xf731, 0x1f44: 0xf751, 0x1f45: 0x9555, - 0x1f46: 0xf771, 0x1f47: 0xf791, 0x1f48: 0xf7b1, 0x1f49: 0xf7d1, 0x1f4a: 0xf7f1, 0x1f4b: 0x9575, - 0x1f4c: 0x9595, 0x1f4d: 0xf811, 0x1f4e: 0xf831, 0x1f4f: 0xf851, 0x1f50: 0xf871, 0x1f51: 0xf891, - 0x1f52: 0xf8b1, 0x1f53: 0x95b5, 0x1f54: 0xf8d1, 0x1f55: 0xf8f1, 0x1f56: 0xf911, 0x1f57: 0xf931, - 0x1f58: 0x95d5, 0x1f59: 0x95f5, 0x1f5a: 0xf951, 0x1f5b: 0xf971, 0x1f5c: 0xf991, 0x1f5d: 0x9615, - 0x1f5e: 0xf9b1, 0x1f5f: 0xf9d1, 0x1f60: 0x684d, 0x1f61: 0x9635, 0x1f62: 0xf9f1, 0x1f63: 0xfa11, - 0x1f64: 0xfa31, 0x1f65: 0x9655, 0x1f66: 0xfa51, 0x1f67: 0xfa71, 0x1f68: 0xfa91, 0x1f69: 0xfab1, - 0x1f6a: 0xfad1, 0x1f6b: 0xfaf1, 0x1f6c: 0xfb11, 0x1f6d: 0x9675, 0x1f6e: 0xfb31, 0x1f6f: 0xfb51, - 0x1f70: 0xfb71, 0x1f71: 0x9695, 0x1f72: 0xfb91, 0x1f73: 0xfbb1, 0x1f74: 0xfbd1, 0x1f75: 0xfbf1, - 0x1f76: 0x7b6d, 0x1f77: 0x96b5, 0x1f78: 0xfc11, 0x1f79: 0xfc31, 0x1f7a: 0xfc51, 0x1f7b: 0x96d5, - 0x1f7c: 0xfc71, 0x1f7d: 0x96f5, 0x1f7e: 0xfc91, 0x1f7f: 0xfc91, - // Block 0x7e, offset 0x1f80 - 0x1f80: 0xfcb1, 0x1f81: 0x9715, 0x1f82: 0xfcd1, 0x1f83: 0xfcf1, 0x1f84: 0xfd11, 0x1f85: 0xfd31, - 0x1f86: 0xfd51, 0x1f87: 0xfd71, 0x1f88: 0xfd91, 0x1f89: 0x9735, 0x1f8a: 0xfdb1, 0x1f8b: 0xfdd1, - 0x1f8c: 0xfdf1, 0x1f8d: 0xfe11, 0x1f8e: 0xfe31, 0x1f8f: 0xfe51, 0x1f90: 0x9755, 0x1f91: 0xfe71, - 0x1f92: 0x9775, 0x1f93: 0x9795, 0x1f94: 0x97b5, 0x1f95: 0xfe91, 0x1f96: 0xfeb1, 0x1f97: 0xfed1, - 0x1f98: 0xfef1, 0x1f99: 0xff11, 0x1f9a: 0xff31, 0x1f9b: 0xff51, 0x1f9c: 0xff71, 0x1f9d: 0x97d5, - 0x1f9e: 0x0040, 0x1f9f: 0x0040, 0x1fa0: 0x0040, 0x1fa1: 0x0040, 0x1fa2: 0x0040, 0x1fa3: 0x0040, - 0x1fa4: 0x0040, 0x1fa5: 0x0040, 0x1fa6: 0x0040, 0x1fa7: 0x0040, 0x1fa8: 0x0040, 0x1fa9: 0x0040, - 0x1faa: 0x0040, 0x1fab: 0x0040, 0x1fac: 0x0040, 0x1fad: 0x0040, 0x1fae: 0x0040, 0x1faf: 0x0040, - 0x1fb0: 0x0040, 0x1fb1: 0x0040, 0x1fb2: 0x0040, 0x1fb3: 0x0040, 0x1fb4: 0x0040, 0x1fb5: 0x0040, - 0x1fb6: 0x0040, 0x1fb7: 0x0040, 0x1fb8: 0x0040, 0x1fb9: 0x0040, 0x1fba: 0x0040, 0x1fbb: 0x0040, - 0x1fbc: 0x0040, 0x1fbd: 0x0040, 0x1fbe: 0x0040, 0x1fbf: 0x0040, -} - -// idnaIndex: 36 blocks, 2304 entries, 4608 bytes -// Block 0 is the zero block. -var idnaIndex = [2304]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x01, 0xc3: 0x7d, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x04, 0xc7: 0x05, - 0xc8: 0x06, 0xc9: 0x7e, 0xca: 0x7f, 0xcb: 0x07, 0xcc: 0x80, 0xcd: 0x08, 0xce: 0x09, 0xcf: 0x0a, - 0xd0: 0x81, 0xd1: 0x0b, 0xd2: 0x0c, 0xd3: 0x0d, 0xd4: 0x0e, 0xd5: 0x82, 0xd6: 0x83, 0xd7: 0x84, - 0xd8: 0x0f, 0xd9: 0x10, 0xda: 0x85, 0xdb: 0x11, 0xdc: 0x12, 0xdd: 0x86, 0xde: 0x87, 0xdf: 0x88, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe5: 0x07, 0xe6: 0x07, 0xe7: 0x07, - 0xe8: 0x07, 0xe9: 0x08, 0xea: 0x09, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x0a, 0xee: 0x0b, 0xef: 0x0c, - 0xf0: 0x1d, 0xf1: 0x1e, 0xf2: 0x1e, 0xf3: 0x20, 0xf4: 0x21, - // Block 0x4, offset 0x100 - 0x120: 0x89, 0x121: 0x13, 0x122: 0x8a, 0x123: 0x8b, 0x124: 0x8c, 0x125: 0x14, 0x126: 0x15, 0x127: 0x16, - 0x128: 0x17, 0x129: 0x18, 0x12a: 0x19, 0x12b: 0x1a, 0x12c: 0x1b, 0x12d: 0x1c, 0x12e: 0x1d, 0x12f: 0x8d, - 0x130: 0x8e, 0x131: 0x1e, 0x132: 0x1f, 0x133: 0x20, 0x134: 0x8f, 0x135: 0x21, 0x136: 0x90, 0x137: 0x91, - 0x138: 0x92, 0x139: 0x93, 0x13a: 0x22, 0x13b: 0x94, 0x13c: 0x95, 0x13d: 0x23, 0x13e: 0x24, 0x13f: 0x96, - // Block 0x5, offset 0x140 - 0x140: 0x97, 0x141: 0x98, 0x142: 0x99, 0x143: 0x9a, 0x144: 0x9b, 0x145: 0x9c, 0x146: 0x9d, 0x147: 0x9e, - 0x148: 0x9f, 0x149: 0xa0, 0x14a: 0xa1, 0x14b: 0xa2, 0x14c: 0xa3, 0x14d: 0xa4, 0x14e: 0xa5, 0x14f: 0xa6, - 0x150: 0xa7, 0x151: 0x9f, 0x152: 0x9f, 0x153: 0x9f, 0x154: 0x9f, 0x155: 0x9f, 0x156: 0x9f, 0x157: 0x9f, - 0x158: 0x9f, 0x159: 0xa8, 0x15a: 0xa9, 0x15b: 0xaa, 0x15c: 0xab, 0x15d: 0xac, 0x15e: 0xad, 0x15f: 0xae, - 0x160: 0xaf, 0x161: 0xb0, 0x162: 0xb1, 0x163: 0xb2, 0x164: 0xb3, 0x165: 0xb4, 0x166: 0xb5, 0x167: 0xb6, - 0x168: 0xb7, 0x169: 0xb8, 0x16a: 0xb9, 0x16b: 0xba, 0x16c: 0xbb, 0x16d: 0xbc, 0x16e: 0xbd, 0x16f: 0xbe, - 0x170: 0xbf, 0x171: 0xc0, 0x172: 0xc1, 0x173: 0xc2, 0x174: 0x25, 0x175: 0x26, 0x176: 0x27, 0x177: 0xc3, - 0x178: 0x28, 0x179: 0x28, 0x17a: 0x29, 0x17b: 0x28, 0x17c: 0xc4, 0x17d: 0x2a, 0x17e: 0x2b, 0x17f: 0x2c, - // Block 0x6, offset 0x180 - 0x180: 0x2d, 0x181: 0x2e, 0x182: 0x2f, 0x183: 0xc5, 0x184: 0x30, 0x185: 0x31, 0x186: 0xc6, 0x187: 0x9b, - 0x188: 0xc7, 0x189: 0xc8, 0x18a: 0x9b, 0x18b: 0x9b, 0x18c: 0xc9, 0x18d: 0x9b, 0x18e: 0x9b, 0x18f: 0x9b, - 0x190: 0xca, 0x191: 0x32, 0x192: 0x33, 0x193: 0x34, 0x194: 0x9b, 0x195: 0x9b, 0x196: 0x9b, 0x197: 0x9b, - 0x198: 0x9b, 0x199: 0x9b, 0x19a: 0x9b, 0x19b: 0x9b, 0x19c: 0x9b, 0x19d: 0x9b, 0x19e: 0x9b, 0x19f: 0x9b, - 0x1a0: 0x9b, 0x1a1: 0x9b, 0x1a2: 0x9b, 0x1a3: 0x9b, 0x1a4: 0x9b, 0x1a5: 0x9b, 0x1a6: 0x9b, 0x1a7: 0x9b, - 0x1a8: 0xcb, 0x1a9: 0xcc, 0x1aa: 0x9b, 0x1ab: 0xcd, 0x1ac: 0x9b, 0x1ad: 0xce, 0x1ae: 0xcf, 0x1af: 0x9b, - 0x1b0: 0xd0, 0x1b1: 0x35, 0x1b2: 0x28, 0x1b3: 0x36, 0x1b4: 0xd1, 0x1b5: 0xd2, 0x1b6: 0xd3, 0x1b7: 0xd4, - 0x1b8: 0xd5, 0x1b9: 0xd6, 0x1ba: 0xd7, 0x1bb: 0xd8, 0x1bc: 0xd9, 0x1bd: 0xda, 0x1be: 0xdb, 0x1bf: 0x37, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x38, 0x1c1: 0xdc, 0x1c2: 0xdd, 0x1c3: 0xde, 0x1c4: 0xdf, 0x1c5: 0x39, 0x1c6: 0x3a, 0x1c7: 0xe0, - 0x1c8: 0xe1, 0x1c9: 0x3b, 0x1ca: 0x3c, 0x1cb: 0x3d, 0x1cc: 0x3e, 0x1cd: 0x3f, 0x1ce: 0x40, 0x1cf: 0x41, - 0x1d0: 0x9f, 0x1d1: 0x9f, 0x1d2: 0x9f, 0x1d3: 0x9f, 0x1d4: 0x9f, 0x1d5: 0x9f, 0x1d6: 0x9f, 0x1d7: 0x9f, - 0x1d8: 0x9f, 0x1d9: 0x9f, 0x1da: 0x9f, 0x1db: 0x9f, 0x1dc: 0x9f, 0x1dd: 0x9f, 0x1de: 0x9f, 0x1df: 0x9f, - 0x1e0: 0x9f, 0x1e1: 0x9f, 0x1e2: 0x9f, 0x1e3: 0x9f, 0x1e4: 0x9f, 0x1e5: 0x9f, 0x1e6: 0x9f, 0x1e7: 0x9f, - 0x1e8: 0x9f, 0x1e9: 0x9f, 0x1ea: 0x9f, 0x1eb: 0x9f, 0x1ec: 0x9f, 0x1ed: 0x9f, 0x1ee: 0x9f, 0x1ef: 0x9f, - 0x1f0: 0x9f, 0x1f1: 0x9f, 0x1f2: 0x9f, 0x1f3: 0x9f, 0x1f4: 0x9f, 0x1f5: 0x9f, 0x1f6: 0x9f, 0x1f7: 0x9f, - 0x1f8: 0x9f, 0x1f9: 0x9f, 0x1fa: 0x9f, 0x1fb: 0x9f, 0x1fc: 0x9f, 0x1fd: 0x9f, 0x1fe: 0x9f, 0x1ff: 0x9f, - // Block 0x8, offset 0x200 - 0x200: 0x9f, 0x201: 0x9f, 0x202: 0x9f, 0x203: 0x9f, 0x204: 0x9f, 0x205: 0x9f, 0x206: 0x9f, 0x207: 0x9f, - 0x208: 0x9f, 0x209: 0x9f, 0x20a: 0x9f, 0x20b: 0x9f, 0x20c: 0x9f, 0x20d: 0x9f, 0x20e: 0x9f, 0x20f: 0x9f, - 0x210: 0x9f, 0x211: 0x9f, 0x212: 0x9f, 0x213: 0x9f, 0x214: 0x9f, 0x215: 0x9f, 0x216: 0x9f, 0x217: 0x9f, - 0x218: 0x9f, 0x219: 0x9f, 0x21a: 0x9f, 0x21b: 0x9f, 0x21c: 0x9f, 0x21d: 0x9f, 0x21e: 0x9f, 0x21f: 0x9f, - 0x220: 0x9f, 0x221: 0x9f, 0x222: 0x9f, 0x223: 0x9f, 0x224: 0x9f, 0x225: 0x9f, 0x226: 0x9f, 0x227: 0x9f, - 0x228: 0x9f, 0x229: 0x9f, 0x22a: 0x9f, 0x22b: 0x9f, 0x22c: 0x9f, 0x22d: 0x9f, 0x22e: 0x9f, 0x22f: 0x9f, - 0x230: 0x9f, 0x231: 0x9f, 0x232: 0x9f, 0x233: 0x9f, 0x234: 0x9f, 0x235: 0x9f, 0x236: 0xb2, 0x237: 0x9b, - 0x238: 0x9f, 0x239: 0x9f, 0x23a: 0x9f, 0x23b: 0x9f, 0x23c: 0x9f, 0x23d: 0x9f, 0x23e: 0x9f, 0x23f: 0x9f, - // Block 0x9, offset 0x240 - 0x240: 0x9f, 0x241: 0x9f, 0x242: 0x9f, 0x243: 0x9f, 0x244: 0x9f, 0x245: 0x9f, 0x246: 0x9f, 0x247: 0x9f, - 0x248: 0x9f, 0x249: 0x9f, 0x24a: 0x9f, 0x24b: 0x9f, 0x24c: 0x9f, 0x24d: 0x9f, 0x24e: 0x9f, 0x24f: 0x9f, - 0x250: 0x9f, 0x251: 0x9f, 0x252: 0x9f, 0x253: 0x9f, 0x254: 0x9f, 0x255: 0x9f, 0x256: 0x9f, 0x257: 0x9f, - 0x258: 0x9f, 0x259: 0x9f, 0x25a: 0x9f, 0x25b: 0x9f, 0x25c: 0x9f, 0x25d: 0x9f, 0x25e: 0x9f, 0x25f: 0x9f, - 0x260: 0x9f, 0x261: 0x9f, 0x262: 0x9f, 0x263: 0x9f, 0x264: 0x9f, 0x265: 0x9f, 0x266: 0x9f, 0x267: 0x9f, - 0x268: 0x9f, 0x269: 0x9f, 0x26a: 0x9f, 0x26b: 0x9f, 0x26c: 0x9f, 0x26d: 0x9f, 0x26e: 0x9f, 0x26f: 0x9f, - 0x270: 0x9f, 0x271: 0x9f, 0x272: 0x9f, 0x273: 0x9f, 0x274: 0x9f, 0x275: 0x9f, 0x276: 0x9f, 0x277: 0x9f, - 0x278: 0x9f, 0x279: 0x9f, 0x27a: 0x9f, 0x27b: 0x9f, 0x27c: 0x9f, 0x27d: 0x9f, 0x27e: 0x9f, 0x27f: 0x9f, - // Block 0xa, offset 0x280 - 0x280: 0x9f, 0x281: 0x9f, 0x282: 0x9f, 0x283: 0x9f, 0x284: 0x9f, 0x285: 0x9f, 0x286: 0x9f, 0x287: 0x9f, - 0x288: 0x9f, 0x289: 0x9f, 0x28a: 0x9f, 0x28b: 0x9f, 0x28c: 0x9f, 0x28d: 0x9f, 0x28e: 0x9f, 0x28f: 0x9f, - 0x290: 0x9f, 0x291: 0x9f, 0x292: 0x9f, 0x293: 0x9f, 0x294: 0x9f, 0x295: 0x9f, 0x296: 0x9f, 0x297: 0x9f, - 0x298: 0x9f, 0x299: 0x9f, 0x29a: 0x9f, 0x29b: 0x9f, 0x29c: 0x9f, 0x29d: 0x9f, 0x29e: 0x9f, 0x29f: 0x9f, - 0x2a0: 0x9f, 0x2a1: 0x9f, 0x2a2: 0x9f, 0x2a3: 0x9f, 0x2a4: 0x9f, 0x2a5: 0x9f, 0x2a6: 0x9f, 0x2a7: 0x9f, - 0x2a8: 0x9f, 0x2a9: 0x9f, 0x2aa: 0x9f, 0x2ab: 0x9f, 0x2ac: 0x9f, 0x2ad: 0x9f, 0x2ae: 0x9f, 0x2af: 0x9f, - 0x2b0: 0x9f, 0x2b1: 0x9f, 0x2b2: 0x9f, 0x2b3: 0x9f, 0x2b4: 0x9f, 0x2b5: 0x9f, 0x2b6: 0x9f, 0x2b7: 0x9f, - 0x2b8: 0x9f, 0x2b9: 0x9f, 0x2ba: 0x9f, 0x2bb: 0x9f, 0x2bc: 0x9f, 0x2bd: 0x9f, 0x2be: 0x9f, 0x2bf: 0xe2, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x9f, 0x2c1: 0x9f, 0x2c2: 0x9f, 0x2c3: 0x9f, 0x2c4: 0x9f, 0x2c5: 0x9f, 0x2c6: 0x9f, 0x2c7: 0x9f, - 0x2c8: 0x9f, 0x2c9: 0x9f, 0x2ca: 0x9f, 0x2cb: 0x9f, 0x2cc: 0x9f, 0x2cd: 0x9f, 0x2ce: 0x9f, 0x2cf: 0x9f, - 0x2d0: 0x9f, 0x2d1: 0x9f, 0x2d2: 0xe3, 0x2d3: 0xe4, 0x2d4: 0x9f, 0x2d5: 0x9f, 0x2d6: 0x9f, 0x2d7: 0x9f, - 0x2d8: 0xe5, 0x2d9: 0x42, 0x2da: 0x43, 0x2db: 0xe6, 0x2dc: 0x44, 0x2dd: 0x45, 0x2de: 0x46, 0x2df: 0xe7, - 0x2e0: 0xe8, 0x2e1: 0xe9, 0x2e2: 0xea, 0x2e3: 0xeb, 0x2e4: 0xec, 0x2e5: 0xed, 0x2e6: 0xee, 0x2e7: 0xef, - 0x2e8: 0xf0, 0x2e9: 0xf1, 0x2ea: 0xf2, 0x2eb: 0xf3, 0x2ec: 0xf4, 0x2ed: 0xf5, 0x2ee: 0xf6, 0x2ef: 0xf7, - 0x2f0: 0x9f, 0x2f1: 0x9f, 0x2f2: 0x9f, 0x2f3: 0x9f, 0x2f4: 0x9f, 0x2f5: 0x9f, 0x2f6: 0x9f, 0x2f7: 0x9f, - 0x2f8: 0x9f, 0x2f9: 0x9f, 0x2fa: 0x9f, 0x2fb: 0x9f, 0x2fc: 0x9f, 0x2fd: 0x9f, 0x2fe: 0x9f, 0x2ff: 0x9f, - // Block 0xc, offset 0x300 - 0x300: 0x9f, 0x301: 0x9f, 0x302: 0x9f, 0x303: 0x9f, 0x304: 0x9f, 0x305: 0x9f, 0x306: 0x9f, 0x307: 0x9f, - 0x308: 0x9f, 0x309: 0x9f, 0x30a: 0x9f, 0x30b: 0x9f, 0x30c: 0x9f, 0x30d: 0x9f, 0x30e: 0x9f, 0x30f: 0x9f, - 0x310: 0x9f, 0x311: 0x9f, 0x312: 0x9f, 0x313: 0x9f, 0x314: 0x9f, 0x315: 0x9f, 0x316: 0x9f, 0x317: 0x9f, - 0x318: 0x9f, 0x319: 0x9f, 0x31a: 0x9f, 0x31b: 0x9f, 0x31c: 0x9f, 0x31d: 0x9f, 0x31e: 0xf8, 0x31f: 0xf9, - // Block 0xd, offset 0x340 - 0x340: 0xba, 0x341: 0xba, 0x342: 0xba, 0x343: 0xba, 0x344: 0xba, 0x345: 0xba, 0x346: 0xba, 0x347: 0xba, - 0x348: 0xba, 0x349: 0xba, 0x34a: 0xba, 0x34b: 0xba, 0x34c: 0xba, 0x34d: 0xba, 0x34e: 0xba, 0x34f: 0xba, - 0x350: 0xba, 0x351: 0xba, 0x352: 0xba, 0x353: 0xba, 0x354: 0xba, 0x355: 0xba, 0x356: 0xba, 0x357: 0xba, - 0x358: 0xba, 0x359: 0xba, 0x35a: 0xba, 0x35b: 0xba, 0x35c: 0xba, 0x35d: 0xba, 0x35e: 0xba, 0x35f: 0xba, - 0x360: 0xba, 0x361: 0xba, 0x362: 0xba, 0x363: 0xba, 0x364: 0xba, 0x365: 0xba, 0x366: 0xba, 0x367: 0xba, - 0x368: 0xba, 0x369: 0xba, 0x36a: 0xba, 0x36b: 0xba, 0x36c: 0xba, 0x36d: 0xba, 0x36e: 0xba, 0x36f: 0xba, - 0x370: 0xba, 0x371: 0xba, 0x372: 0xba, 0x373: 0xba, 0x374: 0xba, 0x375: 0xba, 0x376: 0xba, 0x377: 0xba, - 0x378: 0xba, 0x379: 0xba, 0x37a: 0xba, 0x37b: 0xba, 0x37c: 0xba, 0x37d: 0xba, 0x37e: 0xba, 0x37f: 0xba, - // Block 0xe, offset 0x380 - 0x380: 0xba, 0x381: 0xba, 0x382: 0xba, 0x383: 0xba, 0x384: 0xba, 0x385: 0xba, 0x386: 0xba, 0x387: 0xba, - 0x388: 0xba, 0x389: 0xba, 0x38a: 0xba, 0x38b: 0xba, 0x38c: 0xba, 0x38d: 0xba, 0x38e: 0xba, 0x38f: 0xba, - 0x390: 0xba, 0x391: 0xba, 0x392: 0xba, 0x393: 0xba, 0x394: 0xba, 0x395: 0xba, 0x396: 0xba, 0x397: 0xba, - 0x398: 0xba, 0x399: 0xba, 0x39a: 0xba, 0x39b: 0xba, 0x39c: 0xba, 0x39d: 0xba, 0x39e: 0xba, 0x39f: 0xba, - 0x3a0: 0xba, 0x3a1: 0xba, 0x3a2: 0xba, 0x3a3: 0xba, 0x3a4: 0xfa, 0x3a5: 0xfb, 0x3a6: 0xfc, 0x3a7: 0xfd, - 0x3a8: 0x47, 0x3a9: 0xfe, 0x3aa: 0xff, 0x3ab: 0x48, 0x3ac: 0x49, 0x3ad: 0x4a, 0x3ae: 0x4b, 0x3af: 0x4c, - 0x3b0: 0x100, 0x3b1: 0x4d, 0x3b2: 0x4e, 0x3b3: 0x4f, 0x3b4: 0x50, 0x3b5: 0x51, 0x3b6: 0x101, 0x3b7: 0x52, - 0x3b8: 0x53, 0x3b9: 0x54, 0x3ba: 0x55, 0x3bb: 0x56, 0x3bc: 0x57, 0x3bd: 0x58, 0x3be: 0x59, 0x3bf: 0x5a, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x102, 0x3c1: 0x103, 0x3c2: 0x9f, 0x3c3: 0x104, 0x3c4: 0x105, 0x3c5: 0x9b, 0x3c6: 0x106, 0x3c7: 0x107, - 0x3c8: 0xba, 0x3c9: 0xba, 0x3ca: 0x108, 0x3cb: 0x109, 0x3cc: 0x10a, 0x3cd: 0x10b, 0x3ce: 0x10c, 0x3cf: 0x10d, - 0x3d0: 0x10e, 0x3d1: 0x9f, 0x3d2: 0x10f, 0x3d3: 0x110, 0x3d4: 0x111, 0x3d5: 0x112, 0x3d6: 0xba, 0x3d7: 0xba, - 0x3d8: 0x9f, 0x3d9: 0x9f, 0x3da: 0x9f, 0x3db: 0x9f, 0x3dc: 0x113, 0x3dd: 0x114, 0x3de: 0xba, 0x3df: 0xba, - 0x3e0: 0x115, 0x3e1: 0x116, 0x3e2: 0x117, 0x3e3: 0x118, 0x3e4: 0x119, 0x3e5: 0xba, 0x3e6: 0x11a, 0x3e7: 0x11b, - 0x3e8: 0x11c, 0x3e9: 0x11d, 0x3ea: 0x11e, 0x3eb: 0x5b, 0x3ec: 0x11f, 0x3ed: 0x120, 0x3ee: 0x5c, 0x3ef: 0xba, - 0x3f0: 0x121, 0x3f1: 0x122, 0x3f2: 0x123, 0x3f3: 0x124, 0x3f4: 0x125, 0x3f5: 0xba, 0x3f6: 0xba, 0x3f7: 0xba, - 0x3f8: 0xba, 0x3f9: 0x126, 0x3fa: 0xba, 0x3fb: 0xba, 0x3fc: 0x127, 0x3fd: 0x128, 0x3fe: 0xba, 0x3ff: 0x129, - // Block 0x10, offset 0x400 - 0x400: 0x12a, 0x401: 0x12b, 0x402: 0x12c, 0x403: 0x12d, 0x404: 0x12e, 0x405: 0x12f, 0x406: 0x130, 0x407: 0x131, - 0x408: 0x132, 0x409: 0xba, 0x40a: 0x133, 0x40b: 0x134, 0x40c: 0x5d, 0x40d: 0x5e, 0x40e: 0xba, 0x40f: 0xba, - 0x410: 0x135, 0x411: 0x136, 0x412: 0x137, 0x413: 0x138, 0x414: 0xba, 0x415: 0xba, 0x416: 0x139, 0x417: 0x13a, - 0x418: 0x13b, 0x419: 0x13c, 0x41a: 0x13d, 0x41b: 0x13e, 0x41c: 0x13f, 0x41d: 0xba, 0x41e: 0xba, 0x41f: 0xba, - 0x420: 0x140, 0x421: 0xba, 0x422: 0x141, 0x423: 0x142, 0x424: 0xba, 0x425: 0xba, 0x426: 0x143, 0x427: 0x144, - 0x428: 0x145, 0x429: 0x146, 0x42a: 0x147, 0x42b: 0x148, 0x42c: 0xba, 0x42d: 0xba, 0x42e: 0xba, 0x42f: 0xba, - 0x430: 0x149, 0x431: 0x14a, 0x432: 0x14b, 0x433: 0xba, 0x434: 0x14c, 0x435: 0x14d, 0x436: 0x14e, 0x437: 0xba, - 0x438: 0xba, 0x439: 0xba, 0x43a: 0xba, 0x43b: 0x14f, 0x43c: 0xba, 0x43d: 0xba, 0x43e: 0xba, 0x43f: 0x150, - // Block 0x11, offset 0x440 - 0x440: 0x9f, 0x441: 0x9f, 0x442: 0x9f, 0x443: 0x9f, 0x444: 0x9f, 0x445: 0x9f, 0x446: 0x9f, 0x447: 0x9f, - 0x448: 0x9f, 0x449: 0x9f, 0x44a: 0x9f, 0x44b: 0x9f, 0x44c: 0x9f, 0x44d: 0x9f, 0x44e: 0x151, 0x44f: 0xba, - 0x450: 0x9b, 0x451: 0x152, 0x452: 0x9f, 0x453: 0x9f, 0x454: 0x9f, 0x455: 0x153, 0x456: 0xba, 0x457: 0xba, - 0x458: 0xba, 0x459: 0xba, 0x45a: 0xba, 0x45b: 0xba, 0x45c: 0xba, 0x45d: 0xba, 0x45e: 0xba, 0x45f: 0xba, - 0x460: 0xba, 0x461: 0xba, 0x462: 0xba, 0x463: 0xba, 0x464: 0xba, 0x465: 0xba, 0x466: 0xba, 0x467: 0xba, - 0x468: 0xba, 0x469: 0xba, 0x46a: 0xba, 0x46b: 0xba, 0x46c: 0xba, 0x46d: 0xba, 0x46e: 0xba, 0x46f: 0xba, - 0x470: 0xba, 0x471: 0xba, 0x472: 0xba, 0x473: 0xba, 0x474: 0xba, 0x475: 0xba, 0x476: 0xba, 0x477: 0xba, - 0x478: 0xba, 0x479: 0xba, 0x47a: 0xba, 0x47b: 0xba, 0x47c: 0xba, 0x47d: 0xba, 0x47e: 0xba, 0x47f: 0xba, - // Block 0x12, offset 0x480 - 0x480: 0x9f, 0x481: 0x9f, 0x482: 0x9f, 0x483: 0x9f, 0x484: 0x9f, 0x485: 0x9f, 0x486: 0x9f, 0x487: 0x9f, - 0x488: 0x9f, 0x489: 0x9f, 0x48a: 0x9f, 0x48b: 0x9f, 0x48c: 0x9f, 0x48d: 0x9f, 0x48e: 0x9f, 0x48f: 0x9f, - 0x490: 0x154, 0x491: 0xba, 0x492: 0xba, 0x493: 0xba, 0x494: 0xba, 0x495: 0xba, 0x496: 0xba, 0x497: 0xba, - 0x498: 0xba, 0x499: 0xba, 0x49a: 0xba, 0x49b: 0xba, 0x49c: 0xba, 0x49d: 0xba, 0x49e: 0xba, 0x49f: 0xba, - 0x4a0: 0xba, 0x4a1: 0xba, 0x4a2: 0xba, 0x4a3: 0xba, 0x4a4: 0xba, 0x4a5: 0xba, 0x4a6: 0xba, 0x4a7: 0xba, - 0x4a8: 0xba, 0x4a9: 0xba, 0x4aa: 0xba, 0x4ab: 0xba, 0x4ac: 0xba, 0x4ad: 0xba, 0x4ae: 0xba, 0x4af: 0xba, - 0x4b0: 0xba, 0x4b1: 0xba, 0x4b2: 0xba, 0x4b3: 0xba, 0x4b4: 0xba, 0x4b5: 0xba, 0x4b6: 0xba, 0x4b7: 0xba, - 0x4b8: 0xba, 0x4b9: 0xba, 0x4ba: 0xba, 0x4bb: 0xba, 0x4bc: 0xba, 0x4bd: 0xba, 0x4be: 0xba, 0x4bf: 0xba, - // Block 0x13, offset 0x4c0 - 0x4c0: 0xba, 0x4c1: 0xba, 0x4c2: 0xba, 0x4c3: 0xba, 0x4c4: 0xba, 0x4c5: 0xba, 0x4c6: 0xba, 0x4c7: 0xba, - 0x4c8: 0xba, 0x4c9: 0xba, 0x4ca: 0xba, 0x4cb: 0xba, 0x4cc: 0xba, 0x4cd: 0xba, 0x4ce: 0xba, 0x4cf: 0xba, - 0x4d0: 0x9f, 0x4d1: 0x9f, 0x4d2: 0x9f, 0x4d3: 0x9f, 0x4d4: 0x9f, 0x4d5: 0x9f, 0x4d6: 0x9f, 0x4d7: 0x9f, - 0x4d8: 0x9f, 0x4d9: 0x155, 0x4da: 0xba, 0x4db: 0xba, 0x4dc: 0xba, 0x4dd: 0xba, 0x4de: 0xba, 0x4df: 0xba, - 0x4e0: 0xba, 0x4e1: 0xba, 0x4e2: 0xba, 0x4e3: 0xba, 0x4e4: 0xba, 0x4e5: 0xba, 0x4e6: 0xba, 0x4e7: 0xba, - 0x4e8: 0xba, 0x4e9: 0xba, 0x4ea: 0xba, 0x4eb: 0xba, 0x4ec: 0xba, 0x4ed: 0xba, 0x4ee: 0xba, 0x4ef: 0xba, - 0x4f0: 0xba, 0x4f1: 0xba, 0x4f2: 0xba, 0x4f3: 0xba, 0x4f4: 0xba, 0x4f5: 0xba, 0x4f6: 0xba, 0x4f7: 0xba, - 0x4f8: 0xba, 0x4f9: 0xba, 0x4fa: 0xba, 0x4fb: 0xba, 0x4fc: 0xba, 0x4fd: 0xba, 0x4fe: 0xba, 0x4ff: 0xba, - // Block 0x14, offset 0x500 - 0x500: 0xba, 0x501: 0xba, 0x502: 0xba, 0x503: 0xba, 0x504: 0xba, 0x505: 0xba, 0x506: 0xba, 0x507: 0xba, - 0x508: 0xba, 0x509: 0xba, 0x50a: 0xba, 0x50b: 0xba, 0x50c: 0xba, 0x50d: 0xba, 0x50e: 0xba, 0x50f: 0xba, - 0x510: 0xba, 0x511: 0xba, 0x512: 0xba, 0x513: 0xba, 0x514: 0xba, 0x515: 0xba, 0x516: 0xba, 0x517: 0xba, - 0x518: 0xba, 0x519: 0xba, 0x51a: 0xba, 0x51b: 0xba, 0x51c: 0xba, 0x51d: 0xba, 0x51e: 0xba, 0x51f: 0xba, - 0x520: 0x9f, 0x521: 0x9f, 0x522: 0x9f, 0x523: 0x9f, 0x524: 0x9f, 0x525: 0x9f, 0x526: 0x9f, 0x527: 0x9f, - 0x528: 0x148, 0x529: 0x156, 0x52a: 0xba, 0x52b: 0x157, 0x52c: 0x158, 0x52d: 0x159, 0x52e: 0x15a, 0x52f: 0xba, - 0x530: 0xba, 0x531: 0xba, 0x532: 0xba, 0x533: 0xba, 0x534: 0xba, 0x535: 0xba, 0x536: 0xba, 0x537: 0xba, - 0x538: 0xba, 0x539: 0x15b, 0x53a: 0x15c, 0x53b: 0xba, 0x53c: 0x9f, 0x53d: 0x15d, 0x53e: 0x15e, 0x53f: 0x15f, - // Block 0x15, offset 0x540 - 0x540: 0x9f, 0x541: 0x9f, 0x542: 0x9f, 0x543: 0x9f, 0x544: 0x9f, 0x545: 0x9f, 0x546: 0x9f, 0x547: 0x9f, - 0x548: 0x9f, 0x549: 0x9f, 0x54a: 0x9f, 0x54b: 0x9f, 0x54c: 0x9f, 0x54d: 0x9f, 0x54e: 0x9f, 0x54f: 0x9f, - 0x550: 0x9f, 0x551: 0x9f, 0x552: 0x9f, 0x553: 0x9f, 0x554: 0x9f, 0x555: 0x9f, 0x556: 0x9f, 0x557: 0x9f, - 0x558: 0x9f, 0x559: 0x9f, 0x55a: 0x9f, 0x55b: 0x9f, 0x55c: 0x9f, 0x55d: 0x9f, 0x55e: 0x9f, 0x55f: 0x160, - 0x560: 0x9f, 0x561: 0x9f, 0x562: 0x9f, 0x563: 0x9f, 0x564: 0x9f, 0x565: 0x9f, 0x566: 0x9f, 0x567: 0x9f, - 0x568: 0x9f, 0x569: 0x9f, 0x56a: 0x9f, 0x56b: 0x161, 0x56c: 0xba, 0x56d: 0xba, 0x56e: 0xba, 0x56f: 0xba, - 0x570: 0xba, 0x571: 0xba, 0x572: 0xba, 0x573: 0xba, 0x574: 0xba, 0x575: 0xba, 0x576: 0xba, 0x577: 0xba, - 0x578: 0xba, 0x579: 0xba, 0x57a: 0xba, 0x57b: 0xba, 0x57c: 0xba, 0x57d: 0xba, 0x57e: 0xba, 0x57f: 0xba, - // Block 0x16, offset 0x580 - 0x580: 0x9f, 0x581: 0x9f, 0x582: 0x9f, 0x583: 0x9f, 0x584: 0x162, 0x585: 0x163, 0x586: 0x9f, 0x587: 0x9f, - 0x588: 0x9f, 0x589: 0x9f, 0x58a: 0x9f, 0x58b: 0x164, 0x58c: 0xba, 0x58d: 0xba, 0x58e: 0xba, 0x58f: 0xba, - 0x590: 0xba, 0x591: 0xba, 0x592: 0xba, 0x593: 0xba, 0x594: 0xba, 0x595: 0xba, 0x596: 0xba, 0x597: 0xba, - 0x598: 0xba, 0x599: 0xba, 0x59a: 0xba, 0x59b: 0xba, 0x59c: 0xba, 0x59d: 0xba, 0x59e: 0xba, 0x59f: 0xba, - 0x5a0: 0xba, 0x5a1: 0xba, 0x5a2: 0xba, 0x5a3: 0xba, 0x5a4: 0xba, 0x5a5: 0xba, 0x5a6: 0xba, 0x5a7: 0xba, - 0x5a8: 0xba, 0x5a9: 0xba, 0x5aa: 0xba, 0x5ab: 0xba, 0x5ac: 0xba, 0x5ad: 0xba, 0x5ae: 0xba, 0x5af: 0xba, - 0x5b0: 0x9f, 0x5b1: 0x165, 0x5b2: 0x166, 0x5b3: 0xba, 0x5b4: 0xba, 0x5b5: 0xba, 0x5b6: 0xba, 0x5b7: 0xba, - 0x5b8: 0xba, 0x5b9: 0xba, 0x5ba: 0xba, 0x5bb: 0xba, 0x5bc: 0xba, 0x5bd: 0xba, 0x5be: 0xba, 0x5bf: 0xba, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x9b, 0x5c1: 0x9b, 0x5c2: 0x9b, 0x5c3: 0x167, 0x5c4: 0x168, 0x5c5: 0x169, 0x5c6: 0x16a, 0x5c7: 0x16b, - 0x5c8: 0x9b, 0x5c9: 0x16c, 0x5ca: 0xba, 0x5cb: 0x16d, 0x5cc: 0x9b, 0x5cd: 0x16e, 0x5ce: 0xba, 0x5cf: 0xba, - 0x5d0: 0x5f, 0x5d1: 0x60, 0x5d2: 0x61, 0x5d3: 0x62, 0x5d4: 0x63, 0x5d5: 0x64, 0x5d6: 0x65, 0x5d7: 0x66, - 0x5d8: 0x67, 0x5d9: 0x68, 0x5da: 0x69, 0x5db: 0x6a, 0x5dc: 0x6b, 0x5dd: 0x6c, 0x5de: 0x6d, 0x5df: 0x6e, - 0x5e0: 0x9b, 0x5e1: 0x9b, 0x5e2: 0x9b, 0x5e3: 0x9b, 0x5e4: 0x9b, 0x5e5: 0x9b, 0x5e6: 0x9b, 0x5e7: 0x9b, - 0x5e8: 0x16f, 0x5e9: 0x170, 0x5ea: 0x171, 0x5eb: 0xba, 0x5ec: 0xba, 0x5ed: 0xba, 0x5ee: 0xba, 0x5ef: 0xba, - 0x5f0: 0xba, 0x5f1: 0xba, 0x5f2: 0xba, 0x5f3: 0xba, 0x5f4: 0xba, 0x5f5: 0xba, 0x5f6: 0xba, 0x5f7: 0xba, - 0x5f8: 0xba, 0x5f9: 0xba, 0x5fa: 0xba, 0x5fb: 0xba, 0x5fc: 0xba, 0x5fd: 0xba, 0x5fe: 0xba, 0x5ff: 0xba, - // Block 0x18, offset 0x600 - 0x600: 0x172, 0x601: 0xba, 0x602: 0xba, 0x603: 0xba, 0x604: 0x173, 0x605: 0x174, 0x606: 0xba, 0x607: 0xba, - 0x608: 0xba, 0x609: 0xba, 0x60a: 0xba, 0x60b: 0x175, 0x60c: 0xba, 0x60d: 0xba, 0x60e: 0xba, 0x60f: 0xba, - 0x610: 0xba, 0x611: 0xba, 0x612: 0xba, 0x613: 0xba, 0x614: 0xba, 0x615: 0xba, 0x616: 0xba, 0x617: 0xba, - 0x618: 0xba, 0x619: 0xba, 0x61a: 0xba, 0x61b: 0xba, 0x61c: 0xba, 0x61d: 0xba, 0x61e: 0xba, 0x61f: 0xba, - 0x620: 0x121, 0x621: 0x121, 0x622: 0x121, 0x623: 0x176, 0x624: 0x6f, 0x625: 0x177, 0x626: 0xba, 0x627: 0xba, - 0x628: 0xba, 0x629: 0xba, 0x62a: 0xba, 0x62b: 0xba, 0x62c: 0xba, 0x62d: 0xba, 0x62e: 0xba, 0x62f: 0xba, - 0x630: 0xba, 0x631: 0x178, 0x632: 0x179, 0x633: 0xba, 0x634: 0x17a, 0x635: 0xba, 0x636: 0xba, 0x637: 0xba, - 0x638: 0x70, 0x639: 0x71, 0x63a: 0x72, 0x63b: 0x17b, 0x63c: 0xba, 0x63d: 0xba, 0x63e: 0xba, 0x63f: 0xba, - // Block 0x19, offset 0x640 - 0x640: 0x17c, 0x641: 0x9b, 0x642: 0x17d, 0x643: 0x17e, 0x644: 0x73, 0x645: 0x74, 0x646: 0x17f, 0x647: 0x180, - 0x648: 0x75, 0x649: 0x181, 0x64a: 0xba, 0x64b: 0xba, 0x64c: 0x9b, 0x64d: 0x9b, 0x64e: 0x9b, 0x64f: 0x9b, - 0x650: 0x9b, 0x651: 0x9b, 0x652: 0x9b, 0x653: 0x9b, 0x654: 0x9b, 0x655: 0x9b, 0x656: 0x9b, 0x657: 0x9b, - 0x658: 0x9b, 0x659: 0x9b, 0x65a: 0x9b, 0x65b: 0x182, 0x65c: 0x9b, 0x65d: 0x183, 0x65e: 0x9b, 0x65f: 0x184, - 0x660: 0x185, 0x661: 0x186, 0x662: 0x187, 0x663: 0xba, 0x664: 0x188, 0x665: 0x189, 0x666: 0x18a, 0x667: 0x18b, - 0x668: 0x9b, 0x669: 0x18c, 0x66a: 0x18d, 0x66b: 0xba, 0x66c: 0xba, 0x66d: 0xba, 0x66e: 0xba, 0x66f: 0xba, - 0x670: 0xba, 0x671: 0xba, 0x672: 0xba, 0x673: 0xba, 0x674: 0xba, 0x675: 0xba, 0x676: 0xba, 0x677: 0xba, - 0x678: 0xba, 0x679: 0xba, 0x67a: 0xba, 0x67b: 0xba, 0x67c: 0xba, 0x67d: 0xba, 0x67e: 0xba, 0x67f: 0xba, - // Block 0x1a, offset 0x680 - 0x680: 0x9f, 0x681: 0x9f, 0x682: 0x9f, 0x683: 0x9f, 0x684: 0x9f, 0x685: 0x9f, 0x686: 0x9f, 0x687: 0x9f, - 0x688: 0x9f, 0x689: 0x9f, 0x68a: 0x9f, 0x68b: 0x9f, 0x68c: 0x9f, 0x68d: 0x9f, 0x68e: 0x9f, 0x68f: 0x9f, - 0x690: 0x9f, 0x691: 0x9f, 0x692: 0x9f, 0x693: 0x9f, 0x694: 0x9f, 0x695: 0x9f, 0x696: 0x9f, 0x697: 0x9f, - 0x698: 0x9f, 0x699: 0x9f, 0x69a: 0x9f, 0x69b: 0x18e, 0x69c: 0x9f, 0x69d: 0x9f, 0x69e: 0x9f, 0x69f: 0x9f, - 0x6a0: 0x9f, 0x6a1: 0x9f, 0x6a2: 0x9f, 0x6a3: 0x9f, 0x6a4: 0x9f, 0x6a5: 0x9f, 0x6a6: 0x9f, 0x6a7: 0x9f, - 0x6a8: 0x9f, 0x6a9: 0x9f, 0x6aa: 0x9f, 0x6ab: 0x9f, 0x6ac: 0x9f, 0x6ad: 0x9f, 0x6ae: 0x9f, 0x6af: 0x9f, - 0x6b0: 0x9f, 0x6b1: 0x9f, 0x6b2: 0x9f, 0x6b3: 0x9f, 0x6b4: 0x9f, 0x6b5: 0x9f, 0x6b6: 0x9f, 0x6b7: 0x9f, - 0x6b8: 0x9f, 0x6b9: 0x9f, 0x6ba: 0x9f, 0x6bb: 0x9f, 0x6bc: 0x9f, 0x6bd: 0x9f, 0x6be: 0x9f, 0x6bf: 0x9f, - // Block 0x1b, offset 0x6c0 - 0x6c0: 0x9f, 0x6c1: 0x9f, 0x6c2: 0x9f, 0x6c3: 0x9f, 0x6c4: 0x9f, 0x6c5: 0x9f, 0x6c6: 0x9f, 0x6c7: 0x9f, - 0x6c8: 0x9f, 0x6c9: 0x9f, 0x6ca: 0x9f, 0x6cb: 0x9f, 0x6cc: 0x9f, 0x6cd: 0x9f, 0x6ce: 0x9f, 0x6cf: 0x9f, - 0x6d0: 0x9f, 0x6d1: 0x9f, 0x6d2: 0x9f, 0x6d3: 0x9f, 0x6d4: 0x9f, 0x6d5: 0x9f, 0x6d6: 0x9f, 0x6d7: 0x9f, - 0x6d8: 0x9f, 0x6d9: 0x9f, 0x6da: 0x9f, 0x6db: 0x9f, 0x6dc: 0x18f, 0x6dd: 0x9f, 0x6de: 0x9f, 0x6df: 0x9f, - 0x6e0: 0x190, 0x6e1: 0x9f, 0x6e2: 0x9f, 0x6e3: 0x9f, 0x6e4: 0x9f, 0x6e5: 0x9f, 0x6e6: 0x9f, 0x6e7: 0x9f, - 0x6e8: 0x9f, 0x6e9: 0x9f, 0x6ea: 0x9f, 0x6eb: 0x9f, 0x6ec: 0x9f, 0x6ed: 0x9f, 0x6ee: 0x9f, 0x6ef: 0x9f, - 0x6f0: 0x9f, 0x6f1: 0x9f, 0x6f2: 0x9f, 0x6f3: 0x9f, 0x6f4: 0x9f, 0x6f5: 0x9f, 0x6f6: 0x9f, 0x6f7: 0x9f, - 0x6f8: 0x9f, 0x6f9: 0x9f, 0x6fa: 0x9f, 0x6fb: 0x9f, 0x6fc: 0x9f, 0x6fd: 0x9f, 0x6fe: 0x9f, 0x6ff: 0x9f, - // Block 0x1c, offset 0x700 - 0x700: 0x9f, 0x701: 0x9f, 0x702: 0x9f, 0x703: 0x9f, 0x704: 0x9f, 0x705: 0x9f, 0x706: 0x9f, 0x707: 0x9f, - 0x708: 0x9f, 0x709: 0x9f, 0x70a: 0x9f, 0x70b: 0x9f, 0x70c: 0x9f, 0x70d: 0x9f, 0x70e: 0x9f, 0x70f: 0x9f, - 0x710: 0x9f, 0x711: 0x9f, 0x712: 0x9f, 0x713: 0x9f, 0x714: 0x9f, 0x715: 0x9f, 0x716: 0x9f, 0x717: 0x9f, - 0x718: 0x9f, 0x719: 0x9f, 0x71a: 0x9f, 0x71b: 0x9f, 0x71c: 0x9f, 0x71d: 0x9f, 0x71e: 0x9f, 0x71f: 0x9f, - 0x720: 0x9f, 0x721: 0x9f, 0x722: 0x9f, 0x723: 0x9f, 0x724: 0x9f, 0x725: 0x9f, 0x726: 0x9f, 0x727: 0x9f, - 0x728: 0x9f, 0x729: 0x9f, 0x72a: 0x9f, 0x72b: 0x9f, 0x72c: 0x9f, 0x72d: 0x9f, 0x72e: 0x9f, 0x72f: 0x9f, - 0x730: 0x9f, 0x731: 0x9f, 0x732: 0x9f, 0x733: 0x9f, 0x734: 0x9f, 0x735: 0x9f, 0x736: 0x9f, 0x737: 0x9f, - 0x738: 0x9f, 0x739: 0x9f, 0x73a: 0x191, 0x73b: 0x9f, 0x73c: 0x9f, 0x73d: 0x9f, 0x73e: 0x9f, 0x73f: 0x9f, - // Block 0x1d, offset 0x740 - 0x740: 0x9f, 0x741: 0x9f, 0x742: 0x9f, 0x743: 0x9f, 0x744: 0x9f, 0x745: 0x9f, 0x746: 0x9f, 0x747: 0x9f, - 0x748: 0x9f, 0x749: 0x9f, 0x74a: 0x9f, 0x74b: 0x9f, 0x74c: 0x9f, 0x74d: 0x9f, 0x74e: 0x9f, 0x74f: 0x9f, - 0x750: 0x9f, 0x751: 0x9f, 0x752: 0x9f, 0x753: 0x9f, 0x754: 0x9f, 0x755: 0x9f, 0x756: 0x9f, 0x757: 0x9f, - 0x758: 0x9f, 0x759: 0x9f, 0x75a: 0x9f, 0x75b: 0x9f, 0x75c: 0x9f, 0x75d: 0x9f, 0x75e: 0x9f, 0x75f: 0x9f, - 0x760: 0x9f, 0x761: 0x9f, 0x762: 0x9f, 0x763: 0x9f, 0x764: 0x9f, 0x765: 0x9f, 0x766: 0x9f, 0x767: 0x9f, - 0x768: 0x9f, 0x769: 0x9f, 0x76a: 0x9f, 0x76b: 0x9f, 0x76c: 0x9f, 0x76d: 0x9f, 0x76e: 0x9f, 0x76f: 0x192, - 0x770: 0xba, 0x771: 0xba, 0x772: 0xba, 0x773: 0xba, 0x774: 0xba, 0x775: 0xba, 0x776: 0xba, 0x777: 0xba, - 0x778: 0xba, 0x779: 0xba, 0x77a: 0xba, 0x77b: 0xba, 0x77c: 0xba, 0x77d: 0xba, 0x77e: 0xba, 0x77f: 0xba, - // Block 0x1e, offset 0x780 - 0x780: 0xba, 0x781: 0xba, 0x782: 0xba, 0x783: 0xba, 0x784: 0xba, 0x785: 0xba, 0x786: 0xba, 0x787: 0xba, - 0x788: 0xba, 0x789: 0xba, 0x78a: 0xba, 0x78b: 0xba, 0x78c: 0xba, 0x78d: 0xba, 0x78e: 0xba, 0x78f: 0xba, - 0x790: 0xba, 0x791: 0xba, 0x792: 0xba, 0x793: 0xba, 0x794: 0xba, 0x795: 0xba, 0x796: 0xba, 0x797: 0xba, - 0x798: 0xba, 0x799: 0xba, 0x79a: 0xba, 0x79b: 0xba, 0x79c: 0xba, 0x79d: 0xba, 0x79e: 0xba, 0x79f: 0xba, - 0x7a0: 0x76, 0x7a1: 0x77, 0x7a2: 0x78, 0x7a3: 0x193, 0x7a4: 0x79, 0x7a5: 0x7a, 0x7a6: 0x194, 0x7a7: 0x7b, - 0x7a8: 0x7c, 0x7a9: 0xba, 0x7aa: 0xba, 0x7ab: 0xba, 0x7ac: 0xba, 0x7ad: 0xba, 0x7ae: 0xba, 0x7af: 0xba, - 0x7b0: 0xba, 0x7b1: 0xba, 0x7b2: 0xba, 0x7b3: 0xba, 0x7b4: 0xba, 0x7b5: 0xba, 0x7b6: 0xba, 0x7b7: 0xba, - 0x7b8: 0xba, 0x7b9: 0xba, 0x7ba: 0xba, 0x7bb: 0xba, 0x7bc: 0xba, 0x7bd: 0xba, 0x7be: 0xba, 0x7bf: 0xba, - // Block 0x1f, offset 0x7c0 - 0x7d0: 0x0d, 0x7d1: 0x0e, 0x7d2: 0x0f, 0x7d3: 0x10, 0x7d4: 0x11, 0x7d5: 0x0b, 0x7d6: 0x12, 0x7d7: 0x07, - 0x7d8: 0x13, 0x7d9: 0x0b, 0x7da: 0x0b, 0x7db: 0x14, 0x7dc: 0x0b, 0x7dd: 0x15, 0x7de: 0x16, 0x7df: 0x17, - 0x7e0: 0x07, 0x7e1: 0x07, 0x7e2: 0x07, 0x7e3: 0x07, 0x7e4: 0x07, 0x7e5: 0x07, 0x7e6: 0x07, 0x7e7: 0x07, - 0x7e8: 0x07, 0x7e9: 0x07, 0x7ea: 0x18, 0x7eb: 0x19, 0x7ec: 0x1a, 0x7ed: 0x07, 0x7ee: 0x1b, 0x7ef: 0x1c, - 0x7f0: 0x0b, 0x7f1: 0x0b, 0x7f2: 0x0b, 0x7f3: 0x0b, 0x7f4: 0x0b, 0x7f5: 0x0b, 0x7f6: 0x0b, 0x7f7: 0x0b, - 0x7f8: 0x0b, 0x7f9: 0x0b, 0x7fa: 0x0b, 0x7fb: 0x0b, 0x7fc: 0x0b, 0x7fd: 0x0b, 0x7fe: 0x0b, 0x7ff: 0x0b, - // Block 0x20, offset 0x800 - 0x800: 0x0b, 0x801: 0x0b, 0x802: 0x0b, 0x803: 0x0b, 0x804: 0x0b, 0x805: 0x0b, 0x806: 0x0b, 0x807: 0x0b, - 0x808: 0x0b, 0x809: 0x0b, 0x80a: 0x0b, 0x80b: 0x0b, 0x80c: 0x0b, 0x80d: 0x0b, 0x80e: 0x0b, 0x80f: 0x0b, - 0x810: 0x0b, 0x811: 0x0b, 0x812: 0x0b, 0x813: 0x0b, 0x814: 0x0b, 0x815: 0x0b, 0x816: 0x0b, 0x817: 0x0b, - 0x818: 0x0b, 0x819: 0x0b, 0x81a: 0x0b, 0x81b: 0x0b, 0x81c: 0x0b, 0x81d: 0x0b, 0x81e: 0x0b, 0x81f: 0x0b, - 0x820: 0x0b, 0x821: 0x0b, 0x822: 0x0b, 0x823: 0x0b, 0x824: 0x0b, 0x825: 0x0b, 0x826: 0x0b, 0x827: 0x0b, - 0x828: 0x0b, 0x829: 0x0b, 0x82a: 0x0b, 0x82b: 0x0b, 0x82c: 0x0b, 0x82d: 0x0b, 0x82e: 0x0b, 0x82f: 0x0b, - 0x830: 0x0b, 0x831: 0x0b, 0x832: 0x0b, 0x833: 0x0b, 0x834: 0x0b, 0x835: 0x0b, 0x836: 0x0b, 0x837: 0x0b, - 0x838: 0x0b, 0x839: 0x0b, 0x83a: 0x0b, 0x83b: 0x0b, 0x83c: 0x0b, 0x83d: 0x0b, 0x83e: 0x0b, 0x83f: 0x0b, - // Block 0x21, offset 0x840 - 0x840: 0x195, 0x841: 0x196, 0x842: 0xba, 0x843: 0xba, 0x844: 0x197, 0x845: 0x197, 0x846: 0x197, 0x847: 0x198, - 0x848: 0xba, 0x849: 0xba, 0x84a: 0xba, 0x84b: 0xba, 0x84c: 0xba, 0x84d: 0xba, 0x84e: 0xba, 0x84f: 0xba, - 0x850: 0xba, 0x851: 0xba, 0x852: 0xba, 0x853: 0xba, 0x854: 0xba, 0x855: 0xba, 0x856: 0xba, 0x857: 0xba, - 0x858: 0xba, 0x859: 0xba, 0x85a: 0xba, 0x85b: 0xba, 0x85c: 0xba, 0x85d: 0xba, 0x85e: 0xba, 0x85f: 0xba, - 0x860: 0xba, 0x861: 0xba, 0x862: 0xba, 0x863: 0xba, 0x864: 0xba, 0x865: 0xba, 0x866: 0xba, 0x867: 0xba, - 0x868: 0xba, 0x869: 0xba, 0x86a: 0xba, 0x86b: 0xba, 0x86c: 0xba, 0x86d: 0xba, 0x86e: 0xba, 0x86f: 0xba, - 0x870: 0xba, 0x871: 0xba, 0x872: 0xba, 0x873: 0xba, 0x874: 0xba, 0x875: 0xba, 0x876: 0xba, 0x877: 0xba, - 0x878: 0xba, 0x879: 0xba, 0x87a: 0xba, 0x87b: 0xba, 0x87c: 0xba, 0x87d: 0xba, 0x87e: 0xba, 0x87f: 0xba, - // Block 0x22, offset 0x880 - 0x880: 0x0b, 0x881: 0x0b, 0x882: 0x0b, 0x883: 0x0b, 0x884: 0x0b, 0x885: 0x0b, 0x886: 0x0b, 0x887: 0x0b, - 0x888: 0x0b, 0x889: 0x0b, 0x88a: 0x0b, 0x88b: 0x0b, 0x88c: 0x0b, 0x88d: 0x0b, 0x88e: 0x0b, 0x88f: 0x0b, - 0x890: 0x0b, 0x891: 0x0b, 0x892: 0x0b, 0x893: 0x0b, 0x894: 0x0b, 0x895: 0x0b, 0x896: 0x0b, 0x897: 0x0b, - 0x898: 0x0b, 0x899: 0x0b, 0x89a: 0x0b, 0x89b: 0x0b, 0x89c: 0x0b, 0x89d: 0x0b, 0x89e: 0x0b, 0x89f: 0x0b, - 0x8a0: 0x1f, 0x8a1: 0x0b, 0x8a2: 0x0b, 0x8a3: 0x0b, 0x8a4: 0x0b, 0x8a5: 0x0b, 0x8a6: 0x0b, 0x8a7: 0x0b, - 0x8a8: 0x0b, 0x8a9: 0x0b, 0x8aa: 0x0b, 0x8ab: 0x0b, 0x8ac: 0x0b, 0x8ad: 0x0b, 0x8ae: 0x0b, 0x8af: 0x0b, - 0x8b0: 0x0b, 0x8b1: 0x0b, 0x8b2: 0x0b, 0x8b3: 0x0b, 0x8b4: 0x0b, 0x8b5: 0x0b, 0x8b6: 0x0b, 0x8b7: 0x0b, - 0x8b8: 0x0b, 0x8b9: 0x0b, 0x8ba: 0x0b, 0x8bb: 0x0b, 0x8bc: 0x0b, 0x8bd: 0x0b, 0x8be: 0x0b, 0x8bf: 0x0b, - // Block 0x23, offset 0x8c0 - 0x8c0: 0x0b, 0x8c1: 0x0b, 0x8c2: 0x0b, 0x8c3: 0x0b, 0x8c4: 0x0b, 0x8c5: 0x0b, 0x8c6: 0x0b, 0x8c7: 0x0b, - 0x8c8: 0x0b, 0x8c9: 0x0b, 0x8ca: 0x0b, 0x8cb: 0x0b, 0x8cc: 0x0b, 0x8cd: 0x0b, 0x8ce: 0x0b, 0x8cf: 0x0b, -} - -// idnaSparseOffset: 284 entries, 568 bytes -var idnaSparseOffset = []uint16{0x0, 0x8, 0x19, 0x25, 0x27, 0x2c, 0x33, 0x3e, 0x4a, 0x4e, 0x5d, 0x62, 0x6c, 0x78, 0x86, 0x8b, 0x94, 0xa4, 0xb2, 0xbe, 0xca, 0xdb, 0xe5, 0xec, 0xf9, 0x10a, 0x111, 0x11c, 0x12b, 0x139, 0x143, 0x145, 0x14a, 0x14d, 0x150, 0x152, 0x15e, 0x169, 0x171, 0x177, 0x17d, 0x182, 0x187, 0x18a, 0x18e, 0x194, 0x199, 0x1a5, 0x1af, 0x1b5, 0x1c6, 0x1d0, 0x1d3, 0x1db, 0x1de, 0x1eb, 0x1f3, 0x1f7, 0x1fe, 0x206, 0x216, 0x222, 0x224, 0x22e, 0x23a, 0x246, 0x252, 0x25a, 0x25f, 0x26c, 0x27d, 0x281, 0x28c, 0x290, 0x299, 0x2a1, 0x2a7, 0x2ac, 0x2af, 0x2b3, 0x2b9, 0x2bd, 0x2c1, 0x2c5, 0x2cb, 0x2d3, 0x2da, 0x2e5, 0x2ef, 0x2f3, 0x2f6, 0x2fc, 0x300, 0x302, 0x305, 0x307, 0x30a, 0x314, 0x317, 0x326, 0x32a, 0x32f, 0x332, 0x336, 0x33b, 0x340, 0x346, 0x352, 0x361, 0x367, 0x36b, 0x37a, 0x37f, 0x387, 0x391, 0x39c, 0x3a4, 0x3b5, 0x3be, 0x3ce, 0x3db, 0x3e5, 0x3ea, 0x3f7, 0x3fb, 0x400, 0x402, 0x406, 0x408, 0x40c, 0x415, 0x41b, 0x41f, 0x42f, 0x439, 0x43e, 0x441, 0x447, 0x44e, 0x453, 0x457, 0x45d, 0x462, 0x46b, 0x470, 0x476, 0x47d, 0x484, 0x48b, 0x48f, 0x494, 0x497, 0x49c, 0x4a8, 0x4ae, 0x4b3, 0x4ba, 0x4c2, 0x4c7, 0x4cb, 0x4db, 0x4e2, 0x4e6, 0x4ea, 0x4f1, 0x4f3, 0x4f6, 0x4f9, 0x4fd, 0x506, 0x50a, 0x512, 0x51a, 0x51e, 0x524, 0x52d, 0x539, 0x540, 0x549, 0x553, 0x55a, 0x568, 0x575, 0x582, 0x58b, 0x58f, 0x59f, 0x5a7, 0x5b2, 0x5bb, 0x5c1, 0x5c9, 0x5d2, 0x5dd, 0x5e0, 0x5ec, 0x5f5, 0x5f8, 0x5fd, 0x602, 0x60f, 0x61a, 0x623, 0x62d, 0x630, 0x63a, 0x643, 0x64f, 0x65c, 0x669, 0x677, 0x67e, 0x682, 0x685, 0x68a, 0x68d, 0x692, 0x695, 0x69c, 0x6a3, 0x6a7, 0x6b2, 0x6b5, 0x6b8, 0x6bb, 0x6c1, 0x6c7, 0x6cd, 0x6d0, 0x6d3, 0x6d6, 0x6dd, 0x6e0, 0x6e5, 0x6ef, 0x6f2, 0x6f6, 0x705, 0x711, 0x715, 0x71a, 0x71e, 0x723, 0x727, 0x72c, 0x735, 0x740, 0x746, 0x74c, 0x752, 0x758, 0x761, 0x764, 0x767, 0x76b, 0x76f, 0x773, 0x779, 0x77f, 0x784, 0x787, 0x797, 0x79e, 0x7a1, 0x7a6, 0x7aa, 0x7b0, 0x7b5, 0x7b9, 0x7bf, 0x7c5, 0x7c9, 0x7d2, 0x7d7, 0x7da, 0x7dd, 0x7e1, 0x7e5, 0x7e8, 0x7f8, 0x809, 0x80e, 0x810, 0x812} - -// idnaSparseValues: 2069 entries, 8276 bytes -var idnaSparseValues = [2069]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0000, lo: 0x07}, - {value: 0xe105, lo: 0x80, hi: 0x96}, - {value: 0x0018, lo: 0x97, hi: 0x97}, - {value: 0xe105, lo: 0x98, hi: 0x9e}, - {value: 0x001f, lo: 0x9f, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xb7}, - {value: 0x0008, lo: 0xb8, hi: 0xbf}, - // Block 0x1, offset 0x8 - {value: 0x0000, lo: 0x10}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0xe01d, lo: 0x81, hi: 0x81}, - {value: 0x0008, lo: 0x82, hi: 0x82}, - {value: 0x0335, lo: 0x83, hi: 0x83}, - {value: 0x034d, lo: 0x84, hi: 0x84}, - {value: 0x0365, lo: 0x85, hi: 0x85}, - {value: 0xe00d, lo: 0x86, hi: 0x86}, - {value: 0x0008, lo: 0x87, hi: 0x87}, - {value: 0xe00d, lo: 0x88, hi: 0x88}, - {value: 0x0008, lo: 0x89, hi: 0x89}, - {value: 0xe00d, lo: 0x8a, hi: 0x8a}, - {value: 0x0008, lo: 0x8b, hi: 0x8b}, - {value: 0xe00d, lo: 0x8c, hi: 0x8c}, - {value: 0x0008, lo: 0x8d, hi: 0x8d}, - {value: 0xe00d, lo: 0x8e, hi: 0x8e}, - {value: 0x0008, lo: 0x8f, hi: 0xbf}, - // Block 0x2, offset 0x19 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x0249, lo: 0xb0, hi: 0xb0}, - {value: 0x037d, lo: 0xb1, hi: 0xb1}, - {value: 0x0259, lo: 0xb2, hi: 0xb2}, - {value: 0x0269, lo: 0xb3, hi: 0xb3}, - {value: 0x034d, lo: 0xb4, hi: 0xb4}, - {value: 0x0395, lo: 0xb5, hi: 0xb5}, - {value: 0xe1bd, lo: 0xb6, hi: 0xb6}, - {value: 0x0279, lo: 0xb7, hi: 0xb7}, - {value: 0x0289, lo: 0xb8, hi: 0xb8}, - {value: 0x0008, lo: 0xb9, hi: 0xbf}, - // Block 0x3, offset 0x25 - {value: 0x0000, lo: 0x01}, - {value: 0x3308, lo: 0x80, hi: 0xbf}, - // Block 0x4, offset 0x27 - {value: 0x0000, lo: 0x04}, - {value: 0x03f5, lo: 0x80, hi: 0x8f}, - {value: 0xe105, lo: 0x90, hi: 0x9f}, - {value: 0x049d, lo: 0xa0, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x5, offset 0x2c - {value: 0x0000, lo: 0x06}, - {value: 0xe185, lo: 0x80, hi: 0x8f}, - {value: 0x0545, lo: 0x90, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x98}, - {value: 0x0008, lo: 0x99, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x6, offset 0x33 - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0401, lo: 0x87, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x88}, - {value: 0x0018, lo: 0x89, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0x90}, - {value: 0x3308, lo: 0x91, hi: 0xbd}, - {value: 0x0818, lo: 0xbe, hi: 0xbe}, - {value: 0x3308, lo: 0xbf, hi: 0xbf}, - // Block 0x7, offset 0x3e - {value: 0x0000, lo: 0x0b}, - {value: 0x0818, lo: 0x80, hi: 0x80}, - {value: 0x3308, lo: 0x81, hi: 0x82}, - {value: 0x0818, lo: 0x83, hi: 0x83}, - {value: 0x3308, lo: 0x84, hi: 0x85}, - {value: 0x0818, lo: 0x86, hi: 0x86}, - {value: 0x3308, lo: 0x87, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0808, lo: 0x90, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xae}, - {value: 0x0808, lo: 0xaf, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0x8, offset 0x4a - {value: 0x0000, lo: 0x03}, - {value: 0x0a08, lo: 0x80, hi: 0x87}, - {value: 0x0c08, lo: 0x88, hi: 0x99}, - {value: 0x0a08, lo: 0x9a, hi: 0xbf}, - // Block 0x9, offset 0x4e - {value: 0x0000, lo: 0x0e}, - {value: 0x3308, lo: 0x80, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8c}, - {value: 0x0c08, lo: 0x8d, hi: 0x8d}, - {value: 0x0a08, lo: 0x8e, hi: 0x98}, - {value: 0x0c08, lo: 0x99, hi: 0x9b}, - {value: 0x0a08, lo: 0x9c, hi: 0xaa}, - {value: 0x0c08, lo: 0xab, hi: 0xac}, - {value: 0x0a08, lo: 0xad, hi: 0xb0}, - {value: 0x0c08, lo: 0xb1, hi: 0xb1}, - {value: 0x0a08, lo: 0xb2, hi: 0xb2}, - {value: 0x0c08, lo: 0xb3, hi: 0xb4}, - {value: 0x0a08, lo: 0xb5, hi: 0xb7}, - {value: 0x0c08, lo: 0xb8, hi: 0xb9}, - {value: 0x0a08, lo: 0xba, hi: 0xbf}, - // Block 0xa, offset 0x5d - {value: 0x0000, lo: 0x04}, - {value: 0x0808, lo: 0x80, hi: 0xa5}, - {value: 0x3308, lo: 0xa6, hi: 0xb0}, - {value: 0x0808, lo: 0xb1, hi: 0xb1}, - {value: 0x0040, lo: 0xb2, hi: 0xbf}, - // Block 0xb, offset 0x62 - {value: 0x0000, lo: 0x09}, - {value: 0x0808, lo: 0x80, hi: 0x89}, - {value: 0x0a08, lo: 0x8a, hi: 0xaa}, - {value: 0x3308, lo: 0xab, hi: 0xb3}, - {value: 0x0808, lo: 0xb4, hi: 0xb5}, - {value: 0x0018, lo: 0xb6, hi: 0xb9}, - {value: 0x0818, lo: 0xba, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbc}, - {value: 0x3308, lo: 0xbd, hi: 0xbd}, - {value: 0x0818, lo: 0xbe, hi: 0xbf}, - // Block 0xc, offset 0x6c - {value: 0x0000, lo: 0x0b}, - {value: 0x0808, lo: 0x80, hi: 0x95}, - {value: 0x3308, lo: 0x96, hi: 0x99}, - {value: 0x0808, lo: 0x9a, hi: 0x9a}, - {value: 0x3308, lo: 0x9b, hi: 0xa3}, - {value: 0x0808, lo: 0xa4, hi: 0xa4}, - {value: 0x3308, lo: 0xa5, hi: 0xa7}, - {value: 0x0808, lo: 0xa8, hi: 0xa8}, - {value: 0x3308, lo: 0xa9, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x0818, lo: 0xb0, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0xd, offset 0x78 - {value: 0x0000, lo: 0x0d}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0a08, lo: 0xa0, hi: 0xa9}, - {value: 0x0c08, lo: 0xaa, hi: 0xac}, - {value: 0x0808, lo: 0xad, hi: 0xad}, - {value: 0x0c08, lo: 0xae, hi: 0xae}, - {value: 0x0a08, lo: 0xaf, hi: 0xb0}, - {value: 0x0c08, lo: 0xb1, hi: 0xb2}, - {value: 0x0a08, lo: 0xb3, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xb5}, - {value: 0x0a08, lo: 0xb6, hi: 0xb8}, - {value: 0x0c08, lo: 0xb9, hi: 0xb9}, - {value: 0x0a08, lo: 0xba, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0xe, offset 0x86 - {value: 0x0000, lo: 0x04}, - {value: 0x0040, lo: 0x80, hi: 0x92}, - {value: 0x3308, lo: 0x93, hi: 0xa1}, - {value: 0x0840, lo: 0xa2, hi: 0xa2}, - {value: 0x3308, lo: 0xa3, hi: 0xbf}, - // Block 0xf, offset 0x8b - {value: 0x0000, lo: 0x08}, - {value: 0x3308, lo: 0x80, hi: 0x82}, - {value: 0x3008, lo: 0x83, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0xb9}, - {value: 0x3308, lo: 0xba, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbf}, - // Block 0x10, offset 0x94 - {value: 0x0000, lo: 0x0f}, - {value: 0x3308, lo: 0x80, hi: 0x80}, - {value: 0x3008, lo: 0x81, hi: 0x82}, - {value: 0x0040, lo: 0x83, hi: 0x85}, - {value: 0x3008, lo: 0x86, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x3008, lo: 0x8a, hi: 0x8c}, - {value: 0x3b08, lo: 0x8d, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x96}, - {value: 0x3008, lo: 0x97, hi: 0x97}, - {value: 0x0040, lo: 0x98, hi: 0xa5}, - {value: 0x0008, lo: 0xa6, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x11, offset 0xa4 - {value: 0x0000, lo: 0x0d}, - {value: 0x3308, lo: 0x80, hi: 0x80}, - {value: 0x3008, lo: 0x81, hi: 0x83}, - {value: 0x3308, lo: 0x84, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0x8c}, - {value: 0x0040, lo: 0x8d, hi: 0x8d}, - {value: 0x0008, lo: 0x8e, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x91}, - {value: 0x0008, lo: 0x92, hi: 0xa8}, - {value: 0x0040, lo: 0xa9, hi: 0xa9}, - {value: 0x0008, lo: 0xaa, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbd}, - {value: 0x3308, lo: 0xbe, hi: 0xbf}, - // Block 0x12, offset 0xb2 - {value: 0x0000, lo: 0x0b}, - {value: 0x3308, lo: 0x80, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x83}, - {value: 0x0040, lo: 0x84, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0x8c}, - {value: 0x0040, lo: 0x8d, hi: 0x8d}, - {value: 0x0008, lo: 0x8e, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x91}, - {value: 0x0008, lo: 0x92, hi: 0xba}, - {value: 0x3b08, lo: 0xbb, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbf}, - // Block 0x13, offset 0xbe - {value: 0x0000, lo: 0x0b}, - {value: 0x0040, lo: 0x80, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x83}, - {value: 0x0040, lo: 0x84, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x99}, - {value: 0x0008, lo: 0x9a, hi: 0xb1}, - {value: 0x0040, lo: 0xb2, hi: 0xb2}, - {value: 0x0008, lo: 0xb3, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0x14, offset 0xca - {value: 0x0000, lo: 0x10}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x89}, - {value: 0x3b08, lo: 0x8a, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8e}, - {value: 0x3008, lo: 0x8f, hi: 0x91}, - {value: 0x3308, lo: 0x92, hi: 0x94}, - {value: 0x0040, lo: 0x95, hi: 0x95}, - {value: 0x3308, lo: 0x96, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x97}, - {value: 0x3008, lo: 0x98, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xa5}, - {value: 0x0008, lo: 0xa6, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xb1}, - {value: 0x3008, lo: 0xb2, hi: 0xb3}, - {value: 0x0018, lo: 0xb4, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0x15, offset 0xdb - {value: 0x0000, lo: 0x09}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0xb0}, - {value: 0x3308, lo: 0xb1, hi: 0xb1}, - {value: 0x0008, lo: 0xb2, hi: 0xb2}, - {value: 0x08f1, lo: 0xb3, hi: 0xb3}, - {value: 0x3308, lo: 0xb4, hi: 0xb9}, - {value: 0x3b08, lo: 0xba, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbe}, - {value: 0x0018, lo: 0xbf, hi: 0xbf}, - // Block 0x16, offset 0xe5 - {value: 0x0000, lo: 0x06}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x3308, lo: 0x87, hi: 0x8e}, - {value: 0x0018, lo: 0x8f, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0x9b}, - {value: 0x0040, lo: 0x9c, hi: 0xbf}, - // Block 0x17, offset 0xec - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x84}, - {value: 0x0040, lo: 0x85, hi: 0x85}, - {value: 0x0008, lo: 0x86, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x87}, - {value: 0x3308, lo: 0x88, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9b}, - {value: 0x0961, lo: 0x9c, hi: 0x9c}, - {value: 0x0999, lo: 0x9d, hi: 0x9d}, - {value: 0x0008, lo: 0x9e, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0x18, offset 0xf9 - {value: 0x0000, lo: 0x10}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x8a}, - {value: 0x0008, lo: 0x8b, hi: 0x8b}, - {value: 0xe03d, lo: 0x8c, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0x97}, - {value: 0x3308, lo: 0x98, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa9}, - {value: 0x0018, lo: 0xaa, hi: 0xb4}, - {value: 0x3308, lo: 0xb5, hi: 0xb5}, - {value: 0x0018, lo: 0xb6, hi: 0xb6}, - {value: 0x3308, lo: 0xb7, hi: 0xb7}, - {value: 0x0018, lo: 0xb8, hi: 0xb8}, - {value: 0x3308, lo: 0xb9, hi: 0xb9}, - {value: 0x0018, lo: 0xba, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbf}, - // Block 0x19, offset 0x10a - {value: 0x0000, lo: 0x06}, - {value: 0x0018, lo: 0x80, hi: 0x85}, - {value: 0x3308, lo: 0x86, hi: 0x86}, - {value: 0x0018, lo: 0x87, hi: 0x8c}, - {value: 0x0040, lo: 0x8d, hi: 0x8d}, - {value: 0x0018, lo: 0x8e, hi: 0x9a}, - {value: 0x0040, lo: 0x9b, hi: 0xbf}, - // Block 0x1a, offset 0x111 - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0xaa}, - {value: 0x3008, lo: 0xab, hi: 0xac}, - {value: 0x3308, lo: 0xad, hi: 0xb0}, - {value: 0x3008, lo: 0xb1, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb7}, - {value: 0x3008, lo: 0xb8, hi: 0xb8}, - {value: 0x3b08, lo: 0xb9, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbc}, - {value: 0x3308, lo: 0xbd, hi: 0xbe}, - {value: 0x0008, lo: 0xbf, hi: 0xbf}, - // Block 0x1b, offset 0x11c - {value: 0x0000, lo: 0x0e}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0018, lo: 0x8a, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x95}, - {value: 0x3008, lo: 0x96, hi: 0x97}, - {value: 0x3308, lo: 0x98, hi: 0x99}, - {value: 0x0008, lo: 0x9a, hi: 0x9d}, - {value: 0x3308, lo: 0x9e, hi: 0xa0}, - {value: 0x0008, lo: 0xa1, hi: 0xa1}, - {value: 0x3008, lo: 0xa2, hi: 0xa4}, - {value: 0x0008, lo: 0xa5, hi: 0xa6}, - {value: 0x3008, lo: 0xa7, hi: 0xad}, - {value: 0x0008, lo: 0xae, hi: 0xb0}, - {value: 0x3308, lo: 0xb1, hi: 0xb4}, - {value: 0x0008, lo: 0xb5, hi: 0xbf}, - // Block 0x1c, offset 0x12b - {value: 0x0000, lo: 0x0d}, - {value: 0x0008, lo: 0x80, hi: 0x81}, - {value: 0x3308, lo: 0x82, hi: 0x82}, - {value: 0x3008, lo: 0x83, hi: 0x84}, - {value: 0x3308, lo: 0x85, hi: 0x86}, - {value: 0x3008, lo: 0x87, hi: 0x8c}, - {value: 0x3308, lo: 0x8d, hi: 0x8d}, - {value: 0x0008, lo: 0x8e, hi: 0x8e}, - {value: 0x3008, lo: 0x8f, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x3008, lo: 0x9a, hi: 0x9c}, - {value: 0x3308, lo: 0x9d, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0x1d, offset 0x139 - {value: 0x0000, lo: 0x09}, - {value: 0x0040, lo: 0x80, hi: 0x86}, - {value: 0x055d, lo: 0x87, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8c}, - {value: 0x055d, lo: 0x8d, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xba}, - {value: 0x0018, lo: 0xbb, hi: 0xbb}, - {value: 0xe105, lo: 0xbc, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbf}, - // Block 0x1e, offset 0x143 - {value: 0x0000, lo: 0x01}, - {value: 0x0018, lo: 0x80, hi: 0xbf}, - // Block 0x1f, offset 0x145 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0xa0}, - {value: 0x2018, lo: 0xa1, hi: 0xb5}, - {value: 0x0018, lo: 0xb6, hi: 0xbf}, - // Block 0x20, offset 0x14a - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0xa7}, - {value: 0x2018, lo: 0xa8, hi: 0xbf}, - // Block 0x21, offset 0x14d - {value: 0x0000, lo: 0x02}, - {value: 0x2018, lo: 0x80, hi: 0x82}, - {value: 0x0018, lo: 0x83, hi: 0xbf}, - // Block 0x22, offset 0x150 - {value: 0x0000, lo: 0x01}, - {value: 0x0008, lo: 0x80, hi: 0xbf}, - // Block 0x23, offset 0x152 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x0008, lo: 0x8a, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0x98}, - {value: 0x0040, lo: 0x99, hi: 0x99}, - {value: 0x0008, lo: 0x9a, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x24, offset 0x15e - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x0008, lo: 0x8a, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xb0}, - {value: 0x0040, lo: 0xb1, hi: 0xb1}, - {value: 0x0008, lo: 0xb2, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb7}, - {value: 0x0008, lo: 0xb8, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0x25, offset 0x169 - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x0040, lo: 0x81, hi: 0x81}, - {value: 0x0008, lo: 0x82, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0xbf}, - // Block 0x26, offset 0x171 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x91}, - {value: 0x0008, lo: 0x92, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0xbf}, - // Block 0x27, offset 0x177 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x9a}, - {value: 0x0040, lo: 0x9b, hi: 0x9c}, - {value: 0x3308, lo: 0x9d, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbf}, - // Block 0x28, offset 0x17d - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x29, offset 0x182 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb7}, - {value: 0xe045, lo: 0xb8, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0x2a, offset 0x187 - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0xbf}, - // Block 0x2b, offset 0x18a - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xac}, - {value: 0x0018, lo: 0xad, hi: 0xae}, - {value: 0x0008, lo: 0xaf, hi: 0xbf}, - // Block 0x2c, offset 0x18e - {value: 0x0000, lo: 0x05}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0x9c}, - {value: 0x0040, lo: 0x9d, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x2d, offset 0x194 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xaa}, - {value: 0x0018, lo: 0xab, hi: 0xb0}, - {value: 0x0008, lo: 0xb1, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0x2e, offset 0x199 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0x8c}, - {value: 0x0040, lo: 0x8d, hi: 0x8d}, - {value: 0x0008, lo: 0x8e, hi: 0x91}, - {value: 0x3308, lo: 0x92, hi: 0x93}, - {value: 0x3b08, lo: 0x94, hi: 0x94}, - {value: 0x0040, lo: 0x95, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb3}, - {value: 0x3b08, lo: 0xb4, hi: 0xb4}, - {value: 0x0018, lo: 0xb5, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0x2f, offset 0x1a5 - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x91}, - {value: 0x3308, lo: 0x92, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xad}, - {value: 0x0008, lo: 0xae, hi: 0xb0}, - {value: 0x0040, lo: 0xb1, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xbf}, - // Block 0x30, offset 0x1af - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0xb3}, - {value: 0x3340, lo: 0xb4, hi: 0xb5}, - {value: 0x3008, lo: 0xb6, hi: 0xb6}, - {value: 0x3308, lo: 0xb7, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbf}, - // Block 0x31, offset 0x1b5 - {value: 0x0000, lo: 0x10}, - {value: 0x3008, lo: 0x80, hi: 0x85}, - {value: 0x3308, lo: 0x86, hi: 0x86}, - {value: 0x3008, lo: 0x87, hi: 0x88}, - {value: 0x3308, lo: 0x89, hi: 0x91}, - {value: 0x3b08, lo: 0x92, hi: 0x92}, - {value: 0x3308, lo: 0x93, hi: 0x93}, - {value: 0x0018, lo: 0x94, hi: 0x96}, - {value: 0x0008, lo: 0x97, hi: 0x97}, - {value: 0x0018, lo: 0x98, hi: 0x9b}, - {value: 0x0008, lo: 0x9c, hi: 0x9c}, - {value: 0x3308, lo: 0x9d, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa9}, - {value: 0x0040, lo: 0xaa, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0x32, offset 0x1c6 - {value: 0x0000, lo: 0x09}, - {value: 0x0018, lo: 0x80, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x86}, - {value: 0x0218, lo: 0x87, hi: 0x87}, - {value: 0x0018, lo: 0x88, hi: 0x8a}, - {value: 0x33c0, lo: 0x8b, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0208, lo: 0xa0, hi: 0xbf}, - // Block 0x33, offset 0x1d0 - {value: 0x0000, lo: 0x02}, - {value: 0x0208, lo: 0x80, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0x34, offset 0x1d3 - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0x84}, - {value: 0x3308, lo: 0x85, hi: 0x86}, - {value: 0x0208, lo: 0x87, hi: 0xa8}, - {value: 0x3308, lo: 0xa9, hi: 0xa9}, - {value: 0x0208, lo: 0xaa, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x35, offset 0x1db - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xbf}, - // Block 0x36, offset 0x1de - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0x9f}, - {value: 0x3308, lo: 0xa0, hi: 0xa2}, - {value: 0x3008, lo: 0xa3, hi: 0xa6}, - {value: 0x3308, lo: 0xa7, hi: 0xa8}, - {value: 0x3008, lo: 0xa9, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xaf}, - {value: 0x3008, lo: 0xb0, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb2}, - {value: 0x3008, lo: 0xb3, hi: 0xb8}, - {value: 0x3308, lo: 0xb9, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0x37, offset 0x1eb - {value: 0x0000, lo: 0x07}, - {value: 0x0018, lo: 0x80, hi: 0x80}, - {value: 0x0040, lo: 0x81, hi: 0x83}, - {value: 0x0018, lo: 0x84, hi: 0x85}, - {value: 0x0008, lo: 0x86, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0x38, offset 0x1f3 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x39, offset 0x1f7 - {value: 0x0000, lo: 0x06}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0028, lo: 0x9a, hi: 0x9a}, - {value: 0x0040, lo: 0x9b, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0xbf}, - // Block 0x3a, offset 0x1fe - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0x96}, - {value: 0x3308, lo: 0x97, hi: 0x98}, - {value: 0x3008, lo: 0x99, hi: 0x9a}, - {value: 0x3308, lo: 0x9b, hi: 0x9b}, - {value: 0x0040, lo: 0x9c, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x3b, offset 0x206 - {value: 0x0000, lo: 0x0f}, - {value: 0x0008, lo: 0x80, hi: 0x94}, - {value: 0x3008, lo: 0x95, hi: 0x95}, - {value: 0x3308, lo: 0x96, hi: 0x96}, - {value: 0x3008, lo: 0x97, hi: 0x97}, - {value: 0x3308, lo: 0x98, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0x9f}, - {value: 0x3b08, lo: 0xa0, hi: 0xa0}, - {value: 0x3008, lo: 0xa1, hi: 0xa1}, - {value: 0x3308, lo: 0xa2, hi: 0xa2}, - {value: 0x3008, lo: 0xa3, hi: 0xa4}, - {value: 0x3308, lo: 0xa5, hi: 0xac}, - {value: 0x3008, lo: 0xad, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbe}, - {value: 0x3308, lo: 0xbf, hi: 0xbf}, - // Block 0x3c, offset 0x216 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xa6}, - {value: 0x0008, lo: 0xa7, hi: 0xa7}, - {value: 0x0018, lo: 0xa8, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xbd}, - {value: 0x3318, lo: 0xbe, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0x3d, offset 0x222 - {value: 0x0000, lo: 0x01}, - {value: 0x0040, lo: 0x80, hi: 0xbf}, - // Block 0x3e, offset 0x224 - {value: 0x0000, lo: 0x09}, - {value: 0x3308, lo: 0x80, hi: 0x83}, - {value: 0x3008, lo: 0x84, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0xb3}, - {value: 0x3308, lo: 0xb4, hi: 0xb4}, - {value: 0x3008, lo: 0xb5, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbc}, - {value: 0x3008, lo: 0xbd, hi: 0xbf}, - // Block 0x3f, offset 0x22e - {value: 0x0000, lo: 0x0b}, - {value: 0x3008, lo: 0x80, hi: 0x81}, - {value: 0x3308, lo: 0x82, hi: 0x82}, - {value: 0x3008, lo: 0x83, hi: 0x83}, - {value: 0x3808, lo: 0x84, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0xaa}, - {value: 0x3308, lo: 0xab, hi: 0xb3}, - {value: 0x0018, lo: 0xb4, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbf}, - // Block 0x40, offset 0x23a - {value: 0x0000, lo: 0x0b}, - {value: 0x3308, lo: 0x80, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0xa0}, - {value: 0x3008, lo: 0xa1, hi: 0xa1}, - {value: 0x3308, lo: 0xa2, hi: 0xa5}, - {value: 0x3008, lo: 0xa6, hi: 0xa7}, - {value: 0x3308, lo: 0xa8, hi: 0xa9}, - {value: 0x3808, lo: 0xaa, hi: 0xaa}, - {value: 0x3b08, lo: 0xab, hi: 0xab}, - {value: 0x3308, lo: 0xac, hi: 0xad}, - {value: 0x0008, lo: 0xae, hi: 0xbf}, - // Block 0x41, offset 0x246 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0xa5}, - {value: 0x3308, lo: 0xa6, hi: 0xa6}, - {value: 0x3008, lo: 0xa7, hi: 0xa7}, - {value: 0x3308, lo: 0xa8, hi: 0xa9}, - {value: 0x3008, lo: 0xaa, hi: 0xac}, - {value: 0x3308, lo: 0xad, hi: 0xad}, - {value: 0x3008, lo: 0xae, hi: 0xae}, - {value: 0x3308, lo: 0xaf, hi: 0xb1}, - {value: 0x3808, lo: 0xb2, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xbb}, - {value: 0x0018, lo: 0xbc, hi: 0xbf}, - // Block 0x42, offset 0x252 - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0xa3}, - {value: 0x3008, lo: 0xa4, hi: 0xab}, - {value: 0x3308, lo: 0xac, hi: 0xb3}, - {value: 0x3008, lo: 0xb4, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xba}, - {value: 0x0018, lo: 0xbb, hi: 0xbf}, - // Block 0x43, offset 0x25a - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0x8c}, - {value: 0x0008, lo: 0x8d, hi: 0xbd}, - {value: 0x0018, lo: 0xbe, hi: 0xbf}, - // Block 0x44, offset 0x25f - {value: 0x0000, lo: 0x0c}, - {value: 0x0e29, lo: 0x80, hi: 0x80}, - {value: 0x0e41, lo: 0x81, hi: 0x81}, - {value: 0x0e59, lo: 0x82, hi: 0x82}, - {value: 0x0e71, lo: 0x83, hi: 0x83}, - {value: 0x0e89, lo: 0x84, hi: 0x85}, - {value: 0x0ea1, lo: 0x86, hi: 0x86}, - {value: 0x0eb9, lo: 0x87, hi: 0x87}, - {value: 0x057d, lo: 0x88, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x8f}, - {value: 0x059d, lo: 0x90, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbc}, - {value: 0x059d, lo: 0xbd, hi: 0xbf}, - // Block 0x45, offset 0x26c - {value: 0x0000, lo: 0x10}, - {value: 0x0018, lo: 0x80, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x3308, lo: 0x90, hi: 0x92}, - {value: 0x0018, lo: 0x93, hi: 0x93}, - {value: 0x3308, lo: 0x94, hi: 0xa0}, - {value: 0x3008, lo: 0xa1, hi: 0xa1}, - {value: 0x3308, lo: 0xa2, hi: 0xa8}, - {value: 0x0008, lo: 0xa9, hi: 0xac}, - {value: 0x3308, lo: 0xad, hi: 0xad}, - {value: 0x0008, lo: 0xae, hi: 0xb3}, - {value: 0x3308, lo: 0xb4, hi: 0xb4}, - {value: 0x0008, lo: 0xb5, hi: 0xb6}, - {value: 0x3008, lo: 0xb7, hi: 0xb7}, - {value: 0x3308, lo: 0xb8, hi: 0xb9}, - {value: 0x0008, lo: 0xba, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x46, offset 0x27d - {value: 0x0000, lo: 0x03}, - {value: 0x3308, lo: 0x80, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xba}, - {value: 0x3308, lo: 0xbb, hi: 0xbf}, - // Block 0x47, offset 0x281 - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x87}, - {value: 0xe045, lo: 0x88, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x97}, - {value: 0xe045, lo: 0x98, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa7}, - {value: 0xe045, lo: 0xa8, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb7}, - {value: 0xe045, lo: 0xb8, hi: 0xbf}, - // Block 0x48, offset 0x28c - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0x8f}, - {value: 0x3318, lo: 0x90, hi: 0xb0}, - {value: 0x0040, lo: 0xb1, hi: 0xbf}, - // Block 0x49, offset 0x290 - {value: 0x0000, lo: 0x08}, - {value: 0x0018, lo: 0x80, hi: 0x82}, - {value: 0x0040, lo: 0x83, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0x84}, - {value: 0x0018, lo: 0x85, hi: 0x88}, - {value: 0x24c1, lo: 0x89, hi: 0x89}, - {value: 0x0018, lo: 0x8a, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0xbf}, - // Block 0x4a, offset 0x299 - {value: 0x0000, lo: 0x07}, - {value: 0x0018, lo: 0x80, hi: 0xab}, - {value: 0x24f1, lo: 0xac, hi: 0xac}, - {value: 0x2529, lo: 0xad, hi: 0xad}, - {value: 0x0018, lo: 0xae, hi: 0xae}, - {value: 0x2579, lo: 0xaf, hi: 0xaf}, - {value: 0x25b1, lo: 0xb0, hi: 0xb0}, - {value: 0x0018, lo: 0xb1, hi: 0xbf}, - // Block 0x4b, offset 0x2a1 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0x9f}, - {value: 0x0080, lo: 0xa0, hi: 0xa0}, - {value: 0x0018, lo: 0xa1, hi: 0xad}, - {value: 0x0080, lo: 0xae, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xbf}, - // Block 0x4c, offset 0x2a7 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0xa8}, - {value: 0x09dd, lo: 0xa9, hi: 0xa9}, - {value: 0x09fd, lo: 0xaa, hi: 0xaa}, - {value: 0x0018, lo: 0xab, hi: 0xbf}, - // Block 0x4d, offset 0x2ac - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0xa6}, - {value: 0x0040, lo: 0xa7, hi: 0xbf}, - // Block 0x4e, offset 0x2af - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x8b}, - {value: 0x28c1, lo: 0x8c, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0xbf}, - // Block 0x4f, offset 0x2b3 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0xb3}, - {value: 0x0e7e, lo: 0xb4, hi: 0xb4}, - {value: 0x292a, lo: 0xb5, hi: 0xb5}, - {value: 0x0e9e, lo: 0xb6, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xbf}, - // Block 0x50, offset 0x2b9 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x9b}, - {value: 0x2941, lo: 0x9c, hi: 0x9c}, - {value: 0x0018, lo: 0x9d, hi: 0xbf}, - // Block 0x51, offset 0x2bd - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xb5}, - {value: 0x0018, lo: 0xb6, hi: 0xbf}, - // Block 0x52, offset 0x2c1 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x97}, - {value: 0x0018, lo: 0x98, hi: 0xbf}, - // Block 0x53, offset 0x2c5 - {value: 0x0000, lo: 0x05}, - {value: 0xe185, lo: 0x80, hi: 0x8f}, - {value: 0x03f5, lo: 0x90, hi: 0x9f}, - {value: 0x0ebd, lo: 0xa0, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x54, offset 0x2cb - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0xa5}, - {value: 0x0040, lo: 0xa6, hi: 0xa6}, - {value: 0x0008, lo: 0xa7, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xac}, - {value: 0x0008, lo: 0xad, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x55, offset 0x2d3 - {value: 0x0000, lo: 0x06}, - {value: 0x0008, lo: 0x80, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xae}, - {value: 0xe075, lo: 0xaf, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb0}, - {value: 0x0040, lo: 0xb1, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0x56, offset 0x2da - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa6}, - {value: 0x0040, lo: 0xa7, hi: 0xa7}, - {value: 0x0008, lo: 0xa8, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xb7}, - {value: 0x0008, lo: 0xb8, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0x57, offset 0x2e5 - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x8e}, - {value: 0x0040, lo: 0x8f, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0x9f}, - {value: 0x3308, lo: 0xa0, hi: 0xbf}, - // Block 0x58, offset 0x2ef - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xae}, - {value: 0x0008, lo: 0xaf, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xbf}, - // Block 0x59, offset 0x2f3 - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0xbf}, - // Block 0x5a, offset 0x2f6 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0x9e}, - {value: 0x0ef5, lo: 0x9f, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xbf}, - // Block 0x5b, offset 0x2fc - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xb2}, - {value: 0x0f15, lo: 0xb3, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xbf}, - // Block 0x5c, offset 0x300 - {value: 0x0020, lo: 0x01}, - {value: 0x0f35, lo: 0x80, hi: 0xbf}, - // Block 0x5d, offset 0x302 - {value: 0x0020, lo: 0x02}, - {value: 0x1735, lo: 0x80, hi: 0x8f}, - {value: 0x1915, lo: 0x90, hi: 0xbf}, - // Block 0x5e, offset 0x305 - {value: 0x0020, lo: 0x01}, - {value: 0x1f15, lo: 0x80, hi: 0xbf}, - // Block 0x5f, offset 0x307 - {value: 0x0000, lo: 0x02}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0xbf}, - // Block 0x60, offset 0x30a - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x98}, - {value: 0x3308, lo: 0x99, hi: 0x9a}, - {value: 0x29e2, lo: 0x9b, hi: 0x9b}, - {value: 0x2a0a, lo: 0x9c, hi: 0x9c}, - {value: 0x0008, lo: 0x9d, hi: 0x9e}, - {value: 0x2a31, lo: 0x9f, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xa0}, - {value: 0x0008, lo: 0xa1, hi: 0xbf}, - // Block 0x61, offset 0x314 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xbe}, - {value: 0x2a69, lo: 0xbf, hi: 0xbf}, - // Block 0x62, offset 0x317 - {value: 0x0000, lo: 0x0e}, - {value: 0x0040, lo: 0x80, hi: 0x84}, - {value: 0x0008, lo: 0x85, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xb0}, - {value: 0x2a35, lo: 0xb1, hi: 0xb1}, - {value: 0x2a55, lo: 0xb2, hi: 0xb2}, - {value: 0x2a75, lo: 0xb3, hi: 0xb3}, - {value: 0x2a95, lo: 0xb4, hi: 0xb4}, - {value: 0x2a75, lo: 0xb5, hi: 0xb5}, - {value: 0x2ab5, lo: 0xb6, hi: 0xb6}, - {value: 0x2ad5, lo: 0xb7, hi: 0xb7}, - {value: 0x2af5, lo: 0xb8, hi: 0xb9}, - {value: 0x2b15, lo: 0xba, hi: 0xbb}, - {value: 0x2b35, lo: 0xbc, hi: 0xbd}, - {value: 0x2b15, lo: 0xbe, hi: 0xbf}, - // Block 0x63, offset 0x326 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x64, offset 0x32a - {value: 0x0030, lo: 0x04}, - {value: 0x2aa2, lo: 0x80, hi: 0x9d}, - {value: 0x305a, lo: 0x9e, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0x9f}, - {value: 0x30a2, lo: 0xa0, hi: 0xbf}, - // Block 0x65, offset 0x32f - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, - // Block 0x66, offset 0x332 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0x8c}, - {value: 0x0040, lo: 0x8d, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0xbf}, - // Block 0x67, offset 0x336 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xbd}, - {value: 0x0018, lo: 0xbe, hi: 0xbf}, - // Block 0x68, offset 0x33b - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xbf}, - // Block 0x69, offset 0x340 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0xa5}, - {value: 0x0018, lo: 0xa6, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb1}, - {value: 0x0018, lo: 0xb2, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xbf}, - // Block 0x6a, offset 0x346 - {value: 0x0000, lo: 0x0b}, - {value: 0x0040, lo: 0x80, hi: 0x81}, - {value: 0xe00d, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0x83}, - {value: 0x03f5, lo: 0x84, hi: 0x84}, - {value: 0x1329, lo: 0x85, hi: 0x85}, - {value: 0x447d, lo: 0x86, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0xb6}, - {value: 0x0008, lo: 0xb7, hi: 0xb7}, - {value: 0x2009, lo: 0xb8, hi: 0xb8}, - {value: 0x6e89, lo: 0xb9, hi: 0xb9}, - {value: 0x0008, lo: 0xba, hi: 0xbf}, - // Block 0x6b, offset 0x352 - {value: 0x0000, lo: 0x0e}, - {value: 0x0008, lo: 0x80, hi: 0x81}, - {value: 0x3308, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0x85}, - {value: 0x3b08, lo: 0x86, hi: 0x86}, - {value: 0x0008, lo: 0x87, hi: 0x8a}, - {value: 0x3308, lo: 0x8b, hi: 0x8b}, - {value: 0x0008, lo: 0x8c, hi: 0xa2}, - {value: 0x3008, lo: 0xa3, hi: 0xa4}, - {value: 0x3308, lo: 0xa5, hi: 0xa6}, - {value: 0x3008, lo: 0xa7, hi: 0xa7}, - {value: 0x0018, lo: 0xa8, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0x6c, offset 0x361 - {value: 0x0000, lo: 0x05}, - {value: 0x0208, lo: 0x80, hi: 0xb1}, - {value: 0x0108, lo: 0xb2, hi: 0xb2}, - {value: 0x0008, lo: 0xb3, hi: 0xb3}, - {value: 0x0018, lo: 0xb4, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xbf}, - // Block 0x6d, offset 0x367 - {value: 0x0000, lo: 0x03}, - {value: 0x3008, lo: 0x80, hi: 0x81}, - {value: 0x0008, lo: 0x82, hi: 0xb3}, - {value: 0x3008, lo: 0xb4, hi: 0xbf}, - // Block 0x6e, offset 0x36b - {value: 0x0000, lo: 0x0e}, - {value: 0x3008, lo: 0x80, hi: 0x83}, - {value: 0x3b08, lo: 0x84, hi: 0x84}, - {value: 0x3308, lo: 0x85, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x8d}, - {value: 0x0018, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x3308, lo: 0xa0, hi: 0xb1}, - {value: 0x0008, lo: 0xb2, hi: 0xb7}, - {value: 0x0018, lo: 0xb8, hi: 0xba}, - {value: 0x0008, lo: 0xbb, hi: 0xbb}, - {value: 0x0018, lo: 0xbc, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbe}, - {value: 0x3308, lo: 0xbf, hi: 0xbf}, - // Block 0x6f, offset 0x37a - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xa5}, - {value: 0x3308, lo: 0xa6, hi: 0xad}, - {value: 0x0018, lo: 0xae, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x70, offset 0x37f - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x3308, lo: 0x87, hi: 0x91}, - {value: 0x3008, lo: 0x92, hi: 0x92}, - {value: 0x3808, lo: 0x93, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x9e}, - {value: 0x0018, lo: 0x9f, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbf}, - // Block 0x71, offset 0x387 - {value: 0x0000, lo: 0x09}, - {value: 0x3308, lo: 0x80, hi: 0x82}, - {value: 0x3008, lo: 0x83, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb3}, - {value: 0x3008, lo: 0xb4, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xb9}, - {value: 0x3008, lo: 0xba, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbf}, - // Block 0x72, offset 0x391 - {value: 0x0000, lo: 0x0a}, - {value: 0x3808, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8e}, - {value: 0x0008, lo: 0x8f, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa4}, - {value: 0x3308, lo: 0xa5, hi: 0xa5}, - {value: 0x0008, lo: 0xa6, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0x73, offset 0x39c - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0xa8}, - {value: 0x3308, lo: 0xa9, hi: 0xae}, - {value: 0x3008, lo: 0xaf, hi: 0xb0}, - {value: 0x3308, lo: 0xb1, hi: 0xb2}, - {value: 0x3008, lo: 0xb3, hi: 0xb4}, - {value: 0x3308, lo: 0xb5, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0x74, offset 0x3a4 - {value: 0x0000, lo: 0x10}, - {value: 0x0008, lo: 0x80, hi: 0x82}, - {value: 0x3308, lo: 0x83, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0x8b}, - {value: 0x3308, lo: 0x8c, hi: 0x8c}, - {value: 0x3008, lo: 0x8d, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9b}, - {value: 0x0018, lo: 0x9c, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xb9}, - {value: 0x0008, lo: 0xba, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbc}, - {value: 0x3008, lo: 0xbd, hi: 0xbd}, - {value: 0x0008, lo: 0xbe, hi: 0xbf}, - // Block 0x75, offset 0x3b5 - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb0}, - {value: 0x0008, lo: 0xb1, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb4}, - {value: 0x0008, lo: 0xb5, hi: 0xb6}, - {value: 0x3308, lo: 0xb7, hi: 0xb8}, - {value: 0x0008, lo: 0xb9, hi: 0xbd}, - {value: 0x3308, lo: 0xbe, hi: 0xbf}, - // Block 0x76, offset 0x3be - {value: 0x0000, lo: 0x0f}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x3308, lo: 0x81, hi: 0x81}, - {value: 0x0008, lo: 0x82, hi: 0x82}, - {value: 0x0040, lo: 0x83, hi: 0x9a}, - {value: 0x0008, lo: 0x9b, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xaa}, - {value: 0x3008, lo: 0xab, hi: 0xab}, - {value: 0x3308, lo: 0xac, hi: 0xad}, - {value: 0x3008, lo: 0xae, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb1}, - {value: 0x0008, lo: 0xb2, hi: 0xb4}, - {value: 0x3008, lo: 0xb5, hi: 0xb5}, - {value: 0x3b08, lo: 0xb6, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0x77, offset 0x3ce - {value: 0x0000, lo: 0x0c}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x88}, - {value: 0x0008, lo: 0x89, hi: 0x8e}, - {value: 0x0040, lo: 0x8f, hi: 0x90}, - {value: 0x0008, lo: 0x91, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa6}, - {value: 0x0040, lo: 0xa7, hi: 0xa7}, - {value: 0x0008, lo: 0xa8, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x78, offset 0x3db - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0x9b}, - {value: 0x449d, lo: 0x9c, hi: 0x9c}, - {value: 0x44b5, lo: 0x9d, hi: 0x9d}, - {value: 0x2971, lo: 0x9e, hi: 0x9e}, - {value: 0xe06d, lo: 0x9f, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xaf}, - {value: 0x44cd, lo: 0xb0, hi: 0xbf}, - // Block 0x79, offset 0x3e5 - {value: 0x0000, lo: 0x04}, - {value: 0x44ed, lo: 0x80, hi: 0x8f}, - {value: 0x450d, lo: 0x90, hi: 0x9f}, - {value: 0x452d, lo: 0xa0, hi: 0xaf}, - {value: 0x450d, lo: 0xb0, hi: 0xbf}, - // Block 0x7a, offset 0x3ea - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0xa2}, - {value: 0x3008, lo: 0xa3, hi: 0xa4}, - {value: 0x3308, lo: 0xa5, hi: 0xa5}, - {value: 0x3008, lo: 0xa6, hi: 0xa7}, - {value: 0x3308, lo: 0xa8, hi: 0xa8}, - {value: 0x3008, lo: 0xa9, hi: 0xaa}, - {value: 0x0018, lo: 0xab, hi: 0xab}, - {value: 0x3008, lo: 0xac, hi: 0xac}, - {value: 0x3b08, lo: 0xad, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0x7b, offset 0x3f7 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xbf}, - // Block 0x7c, offset 0x3fb - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x8a}, - {value: 0x0018, lo: 0x8b, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0x7d, offset 0x400 - {value: 0x0020, lo: 0x01}, - {value: 0x454d, lo: 0x80, hi: 0xbf}, - // Block 0x7e, offset 0x402 - {value: 0x0020, lo: 0x03}, - {value: 0x4d4d, lo: 0x80, hi: 0x94}, - {value: 0x4b0d, lo: 0x95, hi: 0x95}, - {value: 0x4fed, lo: 0x96, hi: 0xbf}, - // Block 0x7f, offset 0x406 - {value: 0x0020, lo: 0x01}, - {value: 0x552d, lo: 0x80, hi: 0xbf}, - // Block 0x80, offset 0x408 - {value: 0x0020, lo: 0x03}, - {value: 0x5d2d, lo: 0x80, hi: 0x84}, - {value: 0x568d, lo: 0x85, hi: 0x85}, - {value: 0x5dcd, lo: 0x86, hi: 0xbf}, - // Block 0x81, offset 0x40c - {value: 0x0020, lo: 0x08}, - {value: 0x6b8d, lo: 0x80, hi: 0x8f}, - {value: 0x6d4d, lo: 0x90, hi: 0x90}, - {value: 0x6d8d, lo: 0x91, hi: 0xab}, - {value: 0x6ea1, lo: 0xac, hi: 0xac}, - {value: 0x70ed, lo: 0xad, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x710d, lo: 0xb0, hi: 0xbf}, - // Block 0x82, offset 0x415 - {value: 0x0020, lo: 0x05}, - {value: 0x730d, lo: 0x80, hi: 0xad}, - {value: 0x656d, lo: 0xae, hi: 0xae}, - {value: 0x78cd, lo: 0xaf, hi: 0xb5}, - {value: 0x6f8d, lo: 0xb6, hi: 0xb6}, - {value: 0x79ad, lo: 0xb7, hi: 0xbf}, - // Block 0x83, offset 0x41b - {value: 0x0028, lo: 0x03}, - {value: 0x7c21, lo: 0x80, hi: 0x82}, - {value: 0x7be1, lo: 0x83, hi: 0x83}, - {value: 0x7c99, lo: 0x84, hi: 0xbf}, - // Block 0x84, offset 0x41f - {value: 0x0038, lo: 0x0f}, - {value: 0x9db1, lo: 0x80, hi: 0x83}, - {value: 0x9e59, lo: 0x84, hi: 0x85}, - {value: 0x9e91, lo: 0x86, hi: 0x87}, - {value: 0x9ec9, lo: 0x88, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x91}, - {value: 0xa089, lo: 0x92, hi: 0x97}, - {value: 0xa1a1, lo: 0x98, hi: 0x9c}, - {value: 0xa281, lo: 0x9d, hi: 0xb3}, - {value: 0x9d41, lo: 0xb4, hi: 0xb4}, - {value: 0x9db1, lo: 0xb5, hi: 0xb5}, - {value: 0xa789, lo: 0xb6, hi: 0xbb}, - {value: 0xa869, lo: 0xbc, hi: 0xbc}, - {value: 0xa7f9, lo: 0xbd, hi: 0xbd}, - {value: 0xa8d9, lo: 0xbe, hi: 0xbf}, - // Block 0x85, offset 0x42f - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8c}, - {value: 0x0008, lo: 0x8d, hi: 0xa6}, - {value: 0x0040, lo: 0xa7, hi: 0xa7}, - {value: 0x0008, lo: 0xa8, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbb}, - {value: 0x0008, lo: 0xbc, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbe}, - {value: 0x0008, lo: 0xbf, hi: 0xbf}, - // Block 0x86, offset 0x439 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0xbf}, - // Block 0x87, offset 0x43e - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x88, offset 0x441 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0x82}, - {value: 0x0040, lo: 0x83, hi: 0x86}, - {value: 0x0018, lo: 0x87, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xbf}, - // Block 0x89, offset 0x447 - {value: 0x0000, lo: 0x06}, - {value: 0x0018, lo: 0x80, hi: 0x8e}, - {value: 0x0040, lo: 0x8f, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0x9b}, - {value: 0x0040, lo: 0x9c, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xa0}, - {value: 0x0040, lo: 0xa1, hi: 0xbf}, - // Block 0x8a, offset 0x44e - {value: 0x0000, lo: 0x04}, - {value: 0x0040, lo: 0x80, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0xbc}, - {value: 0x3308, lo: 0xbd, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0x8b, offset 0x453 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0x9c}, - {value: 0x0040, lo: 0x9d, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x8c, offset 0x457 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x90}, - {value: 0x0040, lo: 0x91, hi: 0x9f}, - {value: 0x3308, lo: 0xa0, hi: 0xa0}, - {value: 0x0018, lo: 0xa1, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0x8d, offset 0x45d - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xac}, - {value: 0x0008, lo: 0xad, hi: 0xbf}, - // Block 0x8e, offset 0x462 - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x81}, - {value: 0x0008, lo: 0x82, hi: 0x89}, - {value: 0x0018, lo: 0x8a, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x8f, offset 0x46b - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9e}, - {value: 0x0018, lo: 0x9f, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x90, offset 0x470 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x83}, - {value: 0x0040, lo: 0x84, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0xbf}, - // Block 0x91, offset 0x476 - {value: 0x0000, lo: 0x06}, - {value: 0xe145, lo: 0x80, hi: 0x87}, - {value: 0xe1c5, lo: 0x88, hi: 0x8f}, - {value: 0xe145, lo: 0x90, hi: 0x97}, - {value: 0x8b0d, lo: 0x98, hi: 0x9f}, - {value: 0x8b25, lo: 0xa0, hi: 0xa7}, - {value: 0x0008, lo: 0xa8, hi: 0xbf}, - // Block 0x92, offset 0x47d - {value: 0x0000, lo: 0x06}, - {value: 0x0008, lo: 0x80, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa9}, - {value: 0x0040, lo: 0xaa, hi: 0xaf}, - {value: 0x8b25, lo: 0xb0, hi: 0xb7}, - {value: 0x8b0d, lo: 0xb8, hi: 0xbf}, - // Block 0x93, offset 0x484 - {value: 0x0000, lo: 0x06}, - {value: 0xe145, lo: 0x80, hi: 0x87}, - {value: 0xe1c5, lo: 0x88, hi: 0x8f}, - {value: 0xe145, lo: 0x90, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0x94, offset 0x48b - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x95, offset 0x48f - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xae}, - {value: 0x0018, lo: 0xaf, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, - // Block 0x96, offset 0x494 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0x97, offset 0x497 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xbf}, - // Block 0x98, offset 0x49c - {value: 0x0000, lo: 0x0b}, - {value: 0x0808, lo: 0x80, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x87}, - {value: 0x0808, lo: 0x88, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x0808, lo: 0x8a, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb6}, - {value: 0x0808, lo: 0xb7, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbb}, - {value: 0x0808, lo: 0xbc, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbe}, - {value: 0x0808, lo: 0xbf, hi: 0xbf}, - // Block 0x99, offset 0x4a8 - {value: 0x0000, lo: 0x05}, - {value: 0x0808, lo: 0x80, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x96}, - {value: 0x0818, lo: 0x97, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xb6}, - {value: 0x0818, lo: 0xb7, hi: 0xbf}, - // Block 0x9a, offset 0x4ae - {value: 0x0000, lo: 0x04}, - {value: 0x0808, lo: 0x80, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0xa6}, - {value: 0x0818, lo: 0xa7, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, - // Block 0x9b, offset 0x4b3 - {value: 0x0000, lo: 0x06}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xb3}, - {value: 0x0808, lo: 0xb4, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xba}, - {value: 0x0818, lo: 0xbb, hi: 0xbf}, - // Block 0x9c, offset 0x4ba - {value: 0x0000, lo: 0x07}, - {value: 0x0808, lo: 0x80, hi: 0x95}, - {value: 0x0818, lo: 0x96, hi: 0x9b}, - {value: 0x0040, lo: 0x9c, hi: 0x9e}, - {value: 0x0018, lo: 0x9f, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbe}, - {value: 0x0818, lo: 0xbf, hi: 0xbf}, - // Block 0x9d, offset 0x4c2 - {value: 0x0000, lo: 0x04}, - {value: 0x0808, lo: 0x80, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xbb}, - {value: 0x0818, lo: 0xbc, hi: 0xbd}, - {value: 0x0808, lo: 0xbe, hi: 0xbf}, - // Block 0x9e, offset 0x4c7 - {value: 0x0000, lo: 0x03}, - {value: 0x0818, lo: 0x80, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0x91}, - {value: 0x0818, lo: 0x92, hi: 0xbf}, - // Block 0x9f, offset 0x4cb - {value: 0x0000, lo: 0x0f}, - {value: 0x0808, lo: 0x80, hi: 0x80}, - {value: 0x3308, lo: 0x81, hi: 0x83}, - {value: 0x0040, lo: 0x84, hi: 0x84}, - {value: 0x3308, lo: 0x85, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x8b}, - {value: 0x3308, lo: 0x8c, hi: 0x8f}, - {value: 0x0808, lo: 0x90, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x94}, - {value: 0x0808, lo: 0x95, hi: 0x97}, - {value: 0x0040, lo: 0x98, hi: 0x98}, - {value: 0x0808, lo: 0x99, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb7}, - {value: 0x3308, lo: 0xb8, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0xa0, offset 0x4db - {value: 0x0000, lo: 0x06}, - {value: 0x0818, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x8f}, - {value: 0x0818, lo: 0x90, hi: 0x98}, - {value: 0x0040, lo: 0x99, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xbc}, - {value: 0x0818, lo: 0xbd, hi: 0xbf}, - // Block 0xa1, offset 0x4e2 - {value: 0x0000, lo: 0x03}, - {value: 0x0808, lo: 0x80, hi: 0x9c}, - {value: 0x0818, lo: 0x9d, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0xa2, offset 0x4e6 - {value: 0x0000, lo: 0x03}, - {value: 0x0808, lo: 0x80, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb8}, - {value: 0x0018, lo: 0xb9, hi: 0xbf}, - // Block 0xa3, offset 0x4ea - {value: 0x0000, lo: 0x06}, - {value: 0x0808, lo: 0x80, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x97}, - {value: 0x0818, lo: 0x98, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xb7}, - {value: 0x0818, lo: 0xb8, hi: 0xbf}, - // Block 0xa4, offset 0x4f1 - {value: 0x0000, lo: 0x01}, - {value: 0x0808, lo: 0x80, hi: 0xbf}, - // Block 0xa5, offset 0x4f3 - {value: 0x0000, lo: 0x02}, - {value: 0x0808, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0xbf}, - // Block 0xa6, offset 0x4f6 - {value: 0x0000, lo: 0x02}, - {value: 0x03dd, lo: 0x80, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xbf}, - // Block 0xa7, offset 0x4f9 - {value: 0x0000, lo: 0x03}, - {value: 0x0808, lo: 0x80, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xb9}, - {value: 0x0818, lo: 0xba, hi: 0xbf}, - // Block 0xa8, offset 0x4fd - {value: 0x0000, lo: 0x08}, - {value: 0x0908, lo: 0x80, hi: 0x80}, - {value: 0x0a08, lo: 0x81, hi: 0xa1}, - {value: 0x0c08, lo: 0xa2, hi: 0xa2}, - {value: 0x0a08, lo: 0xa3, hi: 0xa3}, - {value: 0x3308, lo: 0xa4, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xaf}, - {value: 0x0808, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0xa9, offset 0x506 - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0818, lo: 0xa0, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0xaa, offset 0x50a - {value: 0x0000, lo: 0x07}, - {value: 0x0808, lo: 0x80, hi: 0x9c}, - {value: 0x0818, lo: 0x9d, hi: 0xa6}, - {value: 0x0808, lo: 0xa7, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xaf}, - {value: 0x0a08, lo: 0xb0, hi: 0xb2}, - {value: 0x0c08, lo: 0xb3, hi: 0xb3}, - {value: 0x0a08, lo: 0xb4, hi: 0xbf}, - // Block 0xab, offset 0x512 - {value: 0x0000, lo: 0x07}, - {value: 0x0a08, lo: 0x80, hi: 0x84}, - {value: 0x0808, lo: 0x85, hi: 0x85}, - {value: 0x3308, lo: 0x86, hi: 0x90}, - {value: 0x0a18, lo: 0x91, hi: 0x93}, - {value: 0x0c18, lo: 0x94, hi: 0x94}, - {value: 0x0818, lo: 0x95, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0xbf}, - // Block 0xac, offset 0x51a - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0808, lo: 0xa0, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0xad, offset 0x51e - {value: 0x0000, lo: 0x05}, - {value: 0x3008, lo: 0x80, hi: 0x80}, - {value: 0x3308, lo: 0x81, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0xb7}, - {value: 0x3308, lo: 0xb8, hi: 0xbf}, - // Block 0xae, offset 0x524 - {value: 0x0000, lo: 0x08}, - {value: 0x3308, lo: 0x80, hi: 0x85}, - {value: 0x3b08, lo: 0x86, hi: 0x86}, - {value: 0x0018, lo: 0x87, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x91}, - {value: 0x0018, lo: 0x92, hi: 0xa5}, - {value: 0x0008, lo: 0xa6, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0xaf, offset 0x52d - {value: 0x0000, lo: 0x0b}, - {value: 0x3308, lo: 0x80, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0xaf}, - {value: 0x3008, lo: 0xb0, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb6}, - {value: 0x3008, lo: 0xb7, hi: 0xb8}, - {value: 0x3b08, lo: 0xb9, hi: 0xb9}, - {value: 0x3308, lo: 0xba, hi: 0xba}, - {value: 0x0018, lo: 0xbb, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbd}, - {value: 0x0018, lo: 0xbe, hi: 0xbf}, - // Block 0xb0, offset 0x539 - {value: 0x0000, lo: 0x06}, - {value: 0x0018, lo: 0x80, hi: 0x81}, - {value: 0x0040, lo: 0x82, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xa8}, - {value: 0x0040, lo: 0xa9, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0xb1, offset 0x540 - {value: 0x0000, lo: 0x08}, - {value: 0x3308, lo: 0x80, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0xa6}, - {value: 0x3308, lo: 0xa7, hi: 0xab}, - {value: 0x3008, lo: 0xac, hi: 0xac}, - {value: 0x3308, lo: 0xad, hi: 0xb2}, - {value: 0x3b08, lo: 0xb3, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xb5}, - {value: 0x0008, lo: 0xb6, hi: 0xbf}, - // Block 0xb2, offset 0x549 - {value: 0x0000, lo: 0x09}, - {value: 0x0018, lo: 0x80, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0x84}, - {value: 0x3008, lo: 0x85, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb3}, - {value: 0x0018, lo: 0xb4, hi: 0xb5}, - {value: 0x0008, lo: 0xb6, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0xb3, offset 0x553 - {value: 0x0000, lo: 0x06}, - {value: 0x3308, lo: 0x80, hi: 0x81}, - {value: 0x3008, lo: 0x82, hi: 0x82}, - {value: 0x0008, lo: 0x83, hi: 0xb2}, - {value: 0x3008, lo: 0xb3, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xbe}, - {value: 0x3008, lo: 0xbf, hi: 0xbf}, - // Block 0xb4, offset 0x55a - {value: 0x0000, lo: 0x0d}, - {value: 0x3808, lo: 0x80, hi: 0x80}, - {value: 0x0008, lo: 0x81, hi: 0x84}, - {value: 0x0018, lo: 0x85, hi: 0x88}, - {value: 0x3308, lo: 0x89, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0x9b}, - {value: 0x0008, lo: 0x9c, hi: 0x9c}, - {value: 0x0018, lo: 0x9d, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xa0}, - {value: 0x0018, lo: 0xa1, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0xb5, offset 0x568 - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x91}, - {value: 0x0040, lo: 0x92, hi: 0x92}, - {value: 0x0008, lo: 0x93, hi: 0xab}, - {value: 0x3008, lo: 0xac, hi: 0xae}, - {value: 0x3308, lo: 0xaf, hi: 0xb1}, - {value: 0x3008, lo: 0xb2, hi: 0xb3}, - {value: 0x3308, lo: 0xb4, hi: 0xb4}, - {value: 0x3808, lo: 0xb5, hi: 0xb5}, - {value: 0x3308, lo: 0xb6, hi: 0xb7}, - {value: 0x0018, lo: 0xb8, hi: 0xbd}, - {value: 0x3308, lo: 0xbe, hi: 0xbe}, - {value: 0x0040, lo: 0xbf, hi: 0xbf}, - // Block 0xb6, offset 0x575 - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x0008, lo: 0x8a, hi: 0x8d}, - {value: 0x0040, lo: 0x8e, hi: 0x8e}, - {value: 0x0008, lo: 0x8f, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9e}, - {value: 0x0008, lo: 0x9f, hi: 0xa8}, - {value: 0x0018, lo: 0xa9, hi: 0xa9}, - {value: 0x0040, lo: 0xaa, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0xb7, offset 0x582 - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0x9e}, - {value: 0x3308, lo: 0x9f, hi: 0x9f}, - {value: 0x3008, lo: 0xa0, hi: 0xa2}, - {value: 0x3308, lo: 0xa3, hi: 0xa9}, - {value: 0x3b08, lo: 0xaa, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbf}, - // Block 0xb8, offset 0x58b - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xb4}, - {value: 0x3008, lo: 0xb5, hi: 0xb7}, - {value: 0x3308, lo: 0xb8, hi: 0xbf}, - // Block 0xb9, offset 0x58f - {value: 0x0000, lo: 0x0f}, - {value: 0x3008, lo: 0x80, hi: 0x81}, - {value: 0x3b08, lo: 0x82, hi: 0x82}, - {value: 0x3308, lo: 0x83, hi: 0x84}, - {value: 0x3008, lo: 0x85, hi: 0x85}, - {value: 0x3308, lo: 0x86, hi: 0x86}, - {value: 0x0008, lo: 0x87, hi: 0x8a}, - {value: 0x0018, lo: 0x8b, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0x9b}, - {value: 0x0040, lo: 0x9c, hi: 0x9c}, - {value: 0x0018, lo: 0x9d, hi: 0x9d}, - {value: 0x3308, lo: 0x9e, hi: 0x9e}, - {value: 0x0008, lo: 0x9f, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0xba, offset 0x59f - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x3008, lo: 0xb0, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb8}, - {value: 0x3008, lo: 0xb9, hi: 0xb9}, - {value: 0x3308, lo: 0xba, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbe}, - {value: 0x3308, lo: 0xbf, hi: 0xbf}, - // Block 0xbb, offset 0x5a7 - {value: 0x0000, lo: 0x0a}, - {value: 0x3308, lo: 0x80, hi: 0x80}, - {value: 0x3008, lo: 0x81, hi: 0x81}, - {value: 0x3b08, lo: 0x82, hi: 0x82}, - {value: 0x3308, lo: 0x83, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0x85}, - {value: 0x0018, lo: 0x86, hi: 0x86}, - {value: 0x0008, lo: 0x87, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0xbf}, - // Block 0xbc, offset 0x5b2 - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0xae}, - {value: 0x3008, lo: 0xaf, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xb7}, - {value: 0x3008, lo: 0xb8, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0xbd, offset 0x5bb - {value: 0x0000, lo: 0x05}, - {value: 0x3308, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0x9b}, - {value: 0x3308, lo: 0x9c, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0xbf}, - // Block 0xbe, offset 0x5c1 - {value: 0x0000, lo: 0x07}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x3008, lo: 0xb0, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xba}, - {value: 0x3008, lo: 0xbb, hi: 0xbc}, - {value: 0x3308, lo: 0xbd, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0xbf, offset 0x5c9 - {value: 0x0000, lo: 0x08}, - {value: 0x3308, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x83}, - {value: 0x0008, lo: 0x84, hi: 0x84}, - {value: 0x0040, lo: 0x85, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xbf}, - // Block 0xc0, offset 0x5d2 - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0xaa}, - {value: 0x3308, lo: 0xab, hi: 0xab}, - {value: 0x3008, lo: 0xac, hi: 0xac}, - {value: 0x3308, lo: 0xad, hi: 0xad}, - {value: 0x3008, lo: 0xae, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb5}, - {value: 0x3808, lo: 0xb6, hi: 0xb6}, - {value: 0x3308, lo: 0xb7, hi: 0xb7}, - {value: 0x0008, lo: 0xb8, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0xc1, offset 0x5dd - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0xbf}, - // Block 0xc2, offset 0x5e0 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0x9a}, - {value: 0x0040, lo: 0x9b, hi: 0x9c}, - {value: 0x3308, lo: 0x9d, hi: 0x9f}, - {value: 0x3008, lo: 0xa0, hi: 0xa1}, - {value: 0x3308, lo: 0xa2, hi: 0xa5}, - {value: 0x3008, lo: 0xa6, hi: 0xa6}, - {value: 0x3308, lo: 0xa7, hi: 0xaa}, - {value: 0x3b08, lo: 0xab, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb9}, - {value: 0x0018, lo: 0xba, hi: 0xbf}, - // Block 0xc3, offset 0x5ec - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0xab}, - {value: 0x3008, lo: 0xac, hi: 0xae}, - {value: 0x3308, lo: 0xaf, hi: 0xb7}, - {value: 0x3008, lo: 0xb8, hi: 0xb8}, - {value: 0x3b08, lo: 0xb9, hi: 0xb9}, - {value: 0x3308, lo: 0xba, hi: 0xba}, - {value: 0x0018, lo: 0xbb, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0xc4, offset 0x5f5 - {value: 0x0000, lo: 0x02}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x049d, lo: 0xa0, hi: 0xbf}, - // Block 0xc5, offset 0x5f8 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xa9}, - {value: 0x0018, lo: 0xaa, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xbe}, - {value: 0x0008, lo: 0xbf, hi: 0xbf}, - // Block 0xc6, offset 0x5fd - {value: 0x0000, lo: 0x04}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xa9}, - {value: 0x0008, lo: 0xaa, hi: 0xbf}, - // Block 0xc7, offset 0x602 - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x90}, - {value: 0x3008, lo: 0x91, hi: 0x93}, - {value: 0x3308, lo: 0x94, hi: 0x97}, - {value: 0x0040, lo: 0x98, hi: 0x99}, - {value: 0x3308, lo: 0x9a, hi: 0x9b}, - {value: 0x3008, lo: 0x9c, hi: 0x9f}, - {value: 0x3b08, lo: 0xa0, hi: 0xa0}, - {value: 0x0008, lo: 0xa1, hi: 0xa1}, - {value: 0x0018, lo: 0xa2, hi: 0xa2}, - {value: 0x0008, lo: 0xa3, hi: 0xa3}, - {value: 0x3008, lo: 0xa4, hi: 0xa4}, - {value: 0x0040, lo: 0xa5, hi: 0xbf}, - // Block 0xc8, offset 0x60f - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x3308, lo: 0x81, hi: 0x8a}, - {value: 0x0008, lo: 0x8b, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb3}, - {value: 0x3b08, lo: 0xb4, hi: 0xb4}, - {value: 0x3308, lo: 0xb5, hi: 0xb8}, - {value: 0x3008, lo: 0xb9, hi: 0xb9}, - {value: 0x0008, lo: 0xba, hi: 0xba}, - {value: 0x3308, lo: 0xbb, hi: 0xbe}, - {value: 0x0018, lo: 0xbf, hi: 0xbf}, - // Block 0xc9, offset 0x61a - {value: 0x0000, lo: 0x08}, - {value: 0x0018, lo: 0x80, hi: 0x86}, - {value: 0x3b08, lo: 0x87, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x90}, - {value: 0x3308, lo: 0x91, hi: 0x96}, - {value: 0x3008, lo: 0x97, hi: 0x98}, - {value: 0x3308, lo: 0x99, hi: 0x9b}, - {value: 0x0008, lo: 0x9c, hi: 0xbf}, - // Block 0xca, offset 0x623 - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x3308, lo: 0x8a, hi: 0x96}, - {value: 0x3008, lo: 0x97, hi: 0x97}, - {value: 0x3308, lo: 0x98, hi: 0x98}, - {value: 0x3b08, lo: 0x99, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0x9c}, - {value: 0x0008, lo: 0x9d, hi: 0x9d}, - {value: 0x0018, lo: 0x9e, hi: 0xa2}, - {value: 0x0040, lo: 0xa3, hi: 0xbf}, - // Block 0xcb, offset 0x62d - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0xcc, offset 0x630 - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x89}, - {value: 0x0008, lo: 0x8a, hi: 0xae}, - {value: 0x3008, lo: 0xaf, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xb7}, - {value: 0x3308, lo: 0xb8, hi: 0xbd}, - {value: 0x3008, lo: 0xbe, hi: 0xbe}, - {value: 0x3b08, lo: 0xbf, hi: 0xbf}, - // Block 0xcd, offset 0x63a - {value: 0x0000, lo: 0x08}, - {value: 0x0008, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0018, lo: 0x9a, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb1}, - {value: 0x0008, lo: 0xb2, hi: 0xbf}, - // Block 0xce, offset 0x643 - {value: 0x0000, lo: 0x0b}, - {value: 0x0008, lo: 0x80, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0x91}, - {value: 0x3308, lo: 0x92, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xa8}, - {value: 0x3008, lo: 0xa9, hi: 0xa9}, - {value: 0x3308, lo: 0xaa, hi: 0xb0}, - {value: 0x3008, lo: 0xb1, hi: 0xb1}, - {value: 0x3308, lo: 0xb2, hi: 0xb3}, - {value: 0x3008, lo: 0xb4, hi: 0xb4}, - {value: 0x3308, lo: 0xb5, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xbf}, - // Block 0xcf, offset 0x64f - {value: 0x0000, lo: 0x0c}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x87}, - {value: 0x0008, lo: 0x88, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0x8a}, - {value: 0x0008, lo: 0x8b, hi: 0xb0}, - {value: 0x3308, lo: 0xb1, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xb9}, - {value: 0x3308, lo: 0xba, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbb}, - {value: 0x3308, lo: 0xbc, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbe}, - {value: 0x3308, lo: 0xbf, hi: 0xbf}, - // Block 0xd0, offset 0x65c - {value: 0x0000, lo: 0x0c}, - {value: 0x3308, lo: 0x80, hi: 0x83}, - {value: 0x3b08, lo: 0x84, hi: 0x85}, - {value: 0x0008, lo: 0x86, hi: 0x86}, - {value: 0x3308, lo: 0x87, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa5}, - {value: 0x0040, lo: 0xa6, hi: 0xa6}, - {value: 0x0008, lo: 0xa7, hi: 0xa8}, - {value: 0x0040, lo: 0xa9, hi: 0xa9}, - {value: 0x0008, lo: 0xaa, hi: 0xbf}, - // Block 0xd1, offset 0x669 - {value: 0x0000, lo: 0x0d}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x3008, lo: 0x8a, hi: 0x8e}, - {value: 0x0040, lo: 0x8f, hi: 0x8f}, - {value: 0x3308, lo: 0x90, hi: 0x91}, - {value: 0x0040, lo: 0x92, hi: 0x92}, - {value: 0x3008, lo: 0x93, hi: 0x94}, - {value: 0x3308, lo: 0x95, hi: 0x95}, - {value: 0x3008, lo: 0x96, hi: 0x96}, - {value: 0x3b08, lo: 0x97, hi: 0x97}, - {value: 0x0008, lo: 0x98, hi: 0x98}, - {value: 0x0040, lo: 0x99, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa9}, - {value: 0x0040, lo: 0xaa, hi: 0xbf}, - // Block 0xd2, offset 0x677 - {value: 0x0000, lo: 0x06}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xb2}, - {value: 0x3308, lo: 0xb3, hi: 0xb4}, - {value: 0x3008, lo: 0xb5, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0xd3, offset 0x67e - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xb1}, - {value: 0x0040, lo: 0xb2, hi: 0xbe}, - {value: 0x0018, lo: 0xbf, hi: 0xbf}, - // Block 0xd4, offset 0x682 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0xbf}, - // Block 0xd5, offset 0x685 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0xd6, offset 0x68a - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x83}, - {value: 0x0040, lo: 0x84, hi: 0xbf}, - // Block 0xd7, offset 0x68d - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xaf}, - {value: 0x0340, lo: 0xb0, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0xd8, offset 0x692 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0xbf}, - // Block 0xd9, offset 0x695 - {value: 0x0000, lo: 0x06}, - {value: 0x0008, lo: 0x80, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa9}, - {value: 0x0040, lo: 0xaa, hi: 0xad}, - {value: 0x0018, lo: 0xae, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, - // Block 0xda, offset 0x69c - {value: 0x0000, lo: 0x06}, - {value: 0x0040, lo: 0x80, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb4}, - {value: 0x0018, lo: 0xb5, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xbf}, - // Block 0xdb, offset 0x6a3 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xbf}, - // Block 0xdc, offset 0x6a7 - {value: 0x0000, lo: 0x0a}, - {value: 0x0008, lo: 0x80, hi: 0x83}, - {value: 0x0018, lo: 0x84, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9a}, - {value: 0x0018, lo: 0x9b, hi: 0xa1}, - {value: 0x0040, lo: 0xa2, hi: 0xa2}, - {value: 0x0008, lo: 0xa3, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xbc}, - {value: 0x0008, lo: 0xbd, hi: 0xbf}, - // Block 0xdd, offset 0x6b2 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0xbf}, - // Block 0xde, offset 0x6b5 - {value: 0x0000, lo: 0x02}, - {value: 0xe105, lo: 0x80, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0xdf, offset 0x6b8 - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0x9a}, - {value: 0x0040, lo: 0x9b, hi: 0xbf}, - // Block 0xe0, offset 0x6bb - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8e}, - {value: 0x3308, lo: 0x8f, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x90}, - {value: 0x3008, lo: 0x91, hi: 0xbf}, - // Block 0xe1, offset 0x6c1 - {value: 0x0000, lo: 0x05}, - {value: 0x3008, lo: 0x80, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8e}, - {value: 0x3308, lo: 0x8f, hi: 0x92}, - {value: 0x0008, lo: 0x93, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0xe2, offset 0x6c7 - {value: 0x0000, lo: 0x05}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xa1}, - {value: 0x0018, lo: 0xa2, hi: 0xa2}, - {value: 0x0008, lo: 0xa3, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xbf}, - // Block 0xe3, offset 0x6cd - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb7}, - {value: 0x0040, lo: 0xb8, hi: 0xbf}, - // Block 0xe4, offset 0x6d0 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb2}, - {value: 0x0040, lo: 0xb3, hi: 0xbf}, - // Block 0xe5, offset 0x6d3 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x9e}, - {value: 0x0040, lo: 0x9f, hi: 0xbf}, - // Block 0xe6, offset 0x6d6 - {value: 0x0000, lo: 0x06}, - {value: 0x0040, lo: 0x80, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x92}, - {value: 0x0040, lo: 0x93, hi: 0xa3}, - {value: 0x0008, lo: 0xa4, hi: 0xa7}, - {value: 0x0040, lo: 0xa8, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0xe7, offset 0x6dd - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xbb}, - {value: 0x0040, lo: 0xbc, hi: 0xbf}, - // Block 0xe8, offset 0x6e0 - {value: 0x0000, lo: 0x04}, - {value: 0x0008, lo: 0x80, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbc}, - {value: 0x0040, lo: 0xbd, hi: 0xbf}, - // Block 0xe9, offset 0x6e5 - {value: 0x0000, lo: 0x09}, - {value: 0x0008, lo: 0x80, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x8f}, - {value: 0x0008, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9b}, - {value: 0x0018, lo: 0x9c, hi: 0x9c}, - {value: 0x3308, lo: 0x9d, hi: 0x9e}, - {value: 0x0018, lo: 0x9f, hi: 0x9f}, - {value: 0x03c0, lo: 0xa0, hi: 0xa3}, - {value: 0x0040, lo: 0xa4, hi: 0xbf}, - // Block 0xea, offset 0x6ef - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xbf}, - // Block 0xeb, offset 0x6f2 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xa6}, - {value: 0x0040, lo: 0xa7, hi: 0xa8}, - {value: 0x0018, lo: 0xa9, hi: 0xbf}, - // Block 0xec, offset 0x6f6 - {value: 0x0000, lo: 0x0e}, - {value: 0x0018, lo: 0x80, hi: 0x9d}, - {value: 0xb5b9, lo: 0x9e, hi: 0x9e}, - {value: 0xb601, lo: 0x9f, hi: 0x9f}, - {value: 0xb649, lo: 0xa0, hi: 0xa0}, - {value: 0xb6b1, lo: 0xa1, hi: 0xa1}, - {value: 0xb719, lo: 0xa2, hi: 0xa2}, - {value: 0xb781, lo: 0xa3, hi: 0xa3}, - {value: 0xb7e9, lo: 0xa4, hi: 0xa4}, - {value: 0x3018, lo: 0xa5, hi: 0xa6}, - {value: 0x3318, lo: 0xa7, hi: 0xa9}, - {value: 0x0018, lo: 0xaa, hi: 0xac}, - {value: 0x3018, lo: 0xad, hi: 0xb2}, - {value: 0x0340, lo: 0xb3, hi: 0xba}, - {value: 0x3318, lo: 0xbb, hi: 0xbf}, - // Block 0xed, offset 0x705 - {value: 0x0000, lo: 0x0b}, - {value: 0x3318, lo: 0x80, hi: 0x82}, - {value: 0x0018, lo: 0x83, hi: 0x84}, - {value: 0x3318, lo: 0x85, hi: 0x8b}, - {value: 0x0018, lo: 0x8c, hi: 0xa9}, - {value: 0x3318, lo: 0xaa, hi: 0xad}, - {value: 0x0018, lo: 0xae, hi: 0xba}, - {value: 0xb851, lo: 0xbb, hi: 0xbb}, - {value: 0xb899, lo: 0xbc, hi: 0xbc}, - {value: 0xb8e1, lo: 0xbd, hi: 0xbd}, - {value: 0xb949, lo: 0xbe, hi: 0xbe}, - {value: 0xb9b1, lo: 0xbf, hi: 0xbf}, - // Block 0xee, offset 0x711 - {value: 0x0000, lo: 0x03}, - {value: 0xba19, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0xa8}, - {value: 0x0040, lo: 0xa9, hi: 0xbf}, - // Block 0xef, offset 0x715 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x81}, - {value: 0x3318, lo: 0x82, hi: 0x84}, - {value: 0x0018, lo: 0x85, hi: 0x85}, - {value: 0x0040, lo: 0x86, hi: 0xbf}, - // Block 0xf0, offset 0x71a - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xbf}, - // Block 0xf1, offset 0x71e - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xb8}, - {value: 0x0040, lo: 0xb9, hi: 0xbf}, - // Block 0xf2, offset 0x723 - {value: 0x0000, lo: 0x03}, - {value: 0x3308, lo: 0x80, hi: 0xb6}, - {value: 0x0018, lo: 0xb7, hi: 0xba}, - {value: 0x3308, lo: 0xbb, hi: 0xbf}, - // Block 0xf3, offset 0x727 - {value: 0x0000, lo: 0x04}, - {value: 0x3308, lo: 0x80, hi: 0xac}, - {value: 0x0018, lo: 0xad, hi: 0xb4}, - {value: 0x3308, lo: 0xb5, hi: 0xb5}, - {value: 0x0018, lo: 0xb6, hi: 0xbf}, - // Block 0xf4, offset 0x72c - {value: 0x0000, lo: 0x08}, - {value: 0x0018, lo: 0x80, hi: 0x83}, - {value: 0x3308, lo: 0x84, hi: 0x84}, - {value: 0x0018, lo: 0x85, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x9a}, - {value: 0x3308, lo: 0x9b, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xa0}, - {value: 0x3308, lo: 0xa1, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, - // Block 0xf5, offset 0x735 - {value: 0x0000, lo: 0x0a}, - {value: 0x3308, lo: 0x80, hi: 0x86}, - {value: 0x0040, lo: 0x87, hi: 0x87}, - {value: 0x3308, lo: 0x88, hi: 0x98}, - {value: 0x0040, lo: 0x99, hi: 0x9a}, - {value: 0x3308, lo: 0x9b, hi: 0xa1}, - {value: 0x0040, lo: 0xa2, hi: 0xa2}, - {value: 0x3308, lo: 0xa3, hi: 0xa4}, - {value: 0x0040, lo: 0xa5, hi: 0xa5}, - {value: 0x3308, lo: 0xa6, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xbf}, - // Block 0xf6, offset 0x740 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xaf}, - {value: 0x3308, lo: 0xb0, hi: 0xb6}, - {value: 0x0008, lo: 0xb7, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0xf7, offset 0x746 - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0x89}, - {value: 0x0040, lo: 0x8a, hi: 0x8d}, - {value: 0x0008, lo: 0x8e, hi: 0x8e}, - {value: 0x0018, lo: 0x8f, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0xbf}, - // Block 0xf8, offset 0x74c - {value: 0x0000, lo: 0x05}, - {value: 0x0008, lo: 0x80, hi: 0xab}, - {value: 0x3308, lo: 0xac, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xb9}, - {value: 0x0040, lo: 0xba, hi: 0xbe}, - {value: 0x0018, lo: 0xbf, hi: 0xbf}, - // Block 0xf9, offset 0x752 - {value: 0x0000, lo: 0x05}, - {value: 0x0808, lo: 0x80, hi: 0x84}, - {value: 0x0040, lo: 0x85, hi: 0x86}, - {value: 0x0818, lo: 0x87, hi: 0x8f}, - {value: 0x3308, lo: 0x90, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0xbf}, - // Block 0xfa, offset 0x758 - {value: 0x0000, lo: 0x08}, - {value: 0x0a08, lo: 0x80, hi: 0x83}, - {value: 0x3308, lo: 0x84, hi: 0x8a}, - {value: 0x0b08, lo: 0x8b, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8f}, - {value: 0x0808, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9d}, - {value: 0x0818, lo: 0x9e, hi: 0x9f}, - {value: 0x0040, lo: 0xa0, hi: 0xbf}, - // Block 0xfb, offset 0x761 - {value: 0x0000, lo: 0x02}, - {value: 0x0040, lo: 0x80, hi: 0xb0}, - {value: 0x0818, lo: 0xb1, hi: 0xbf}, - // Block 0xfc, offset 0x764 - {value: 0x0000, lo: 0x02}, - {value: 0x0818, lo: 0x80, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0xfd, offset 0x767 - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0818, lo: 0x81, hi: 0xbd}, - {value: 0x0040, lo: 0xbe, hi: 0xbf}, - // Block 0xfe, offset 0x76b - {value: 0x0000, lo: 0x03}, - {value: 0x0040, lo: 0x80, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb1}, - {value: 0x0040, lo: 0xb2, hi: 0xbf}, - // Block 0xff, offset 0x76f - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xbf}, - // Block 0x100, offset 0x773 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xae}, - {value: 0x0040, lo: 0xaf, hi: 0xb0}, - {value: 0x0018, lo: 0xb1, hi: 0xbf}, - // Block 0x101, offset 0x779 - {value: 0x0000, lo: 0x05}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0018, lo: 0x81, hi: 0x8f}, - {value: 0x0040, lo: 0x90, hi: 0x90}, - {value: 0x0018, lo: 0x91, hi: 0xb5}, - {value: 0x0040, lo: 0xb6, hi: 0xbf}, - // Block 0x102, offset 0x77f - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x8f}, - {value: 0xc1d9, lo: 0x90, hi: 0x90}, - {value: 0x0018, lo: 0x91, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xbf}, - // Block 0x103, offset 0x784 - {value: 0x0000, lo: 0x02}, - {value: 0x0040, lo: 0x80, hi: 0xa5}, - {value: 0x0018, lo: 0xa6, hi: 0xbf}, - // Block 0x104, offset 0x787 - {value: 0x0000, lo: 0x0f}, - {value: 0xc801, lo: 0x80, hi: 0x80}, - {value: 0xc851, lo: 0x81, hi: 0x81}, - {value: 0xc8a1, lo: 0x82, hi: 0x82}, - {value: 0xc8f1, lo: 0x83, hi: 0x83}, - {value: 0xc941, lo: 0x84, hi: 0x84}, - {value: 0xc991, lo: 0x85, hi: 0x85}, - {value: 0xc9e1, lo: 0x86, hi: 0x86}, - {value: 0xca31, lo: 0x87, hi: 0x87}, - {value: 0xca81, lo: 0x88, hi: 0x88}, - {value: 0x0040, lo: 0x89, hi: 0x8f}, - {value: 0xcad1, lo: 0x90, hi: 0x90}, - {value: 0xcaf1, lo: 0x91, hi: 0x91}, - {value: 0x0040, lo: 0x92, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xa5}, - {value: 0x0040, lo: 0xa6, hi: 0xbf}, - // Block 0x105, offset 0x797 - {value: 0x0000, lo: 0x06}, - {value: 0x0018, lo: 0x80, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xac}, - {value: 0x0040, lo: 0xad, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x106, offset 0x79e - {value: 0x0000, lo: 0x02}, - {value: 0x0018, lo: 0x80, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xbf}, - // Block 0x107, offset 0x7a1 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x98}, - {value: 0x0040, lo: 0x99, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xab}, - {value: 0x0040, lo: 0xac, hi: 0xbf}, - // Block 0x108, offset 0x7a6 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0xbf}, - // Block 0x109, offset 0x7aa - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0x99}, - {value: 0x0040, lo: 0x9a, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xbf}, - // Block 0x10a, offset 0x7b0 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x87}, - {value: 0x0040, lo: 0x88, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xbf}, - // Block 0x10b, offset 0x7b5 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x8b}, - {value: 0x0040, lo: 0x8c, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0xbf}, - // Block 0x10c, offset 0x7b9 - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0xb1}, - {value: 0x0040, lo: 0xb2, hi: 0xb2}, - {value: 0x0018, lo: 0xb3, hi: 0xb6}, - {value: 0x0040, lo: 0xb7, hi: 0xb9}, - {value: 0x0018, lo: 0xba, hi: 0xbf}, - // Block 0x10d, offset 0x7bf - {value: 0x0000, lo: 0x05}, - {value: 0x0018, lo: 0x80, hi: 0xa2}, - {value: 0x0040, lo: 0xa3, hi: 0xa4}, - {value: 0x0018, lo: 0xa5, hi: 0xaa}, - {value: 0x0040, lo: 0xab, hi: 0xad}, - {value: 0x0018, lo: 0xae, hi: 0xbf}, - // Block 0x10e, offset 0x7c5 - {value: 0x0000, lo: 0x03}, - {value: 0x0018, lo: 0x80, hi: 0x8a}, - {value: 0x0040, lo: 0x8b, hi: 0x8c}, - {value: 0x0018, lo: 0x8d, hi: 0xbf}, - // Block 0x10f, offset 0x7c9 - {value: 0x0000, lo: 0x08}, - {value: 0x0018, lo: 0x80, hi: 0x93}, - {value: 0x0040, lo: 0x94, hi: 0x9f}, - {value: 0x0018, lo: 0xa0, hi: 0xad}, - {value: 0x0040, lo: 0xae, hi: 0xaf}, - {value: 0x0018, lo: 0xb0, hi: 0xb3}, - {value: 0x0040, lo: 0xb4, hi: 0xb7}, - {value: 0x0018, lo: 0xb8, hi: 0xba}, - {value: 0x0040, lo: 0xbb, hi: 0xbf}, - // Block 0x110, offset 0x7d2 - {value: 0x0000, lo: 0x04}, - {value: 0x0018, lo: 0x80, hi: 0x82}, - {value: 0x0040, lo: 0x83, hi: 0x8f}, - {value: 0x0018, lo: 0x90, hi: 0x95}, - {value: 0x0040, lo: 0x96, hi: 0xbf}, - // Block 0x111, offset 0x7d7 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0x96}, - {value: 0x0040, lo: 0x97, hi: 0xbf}, - // Block 0x112, offset 0x7da - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xb4}, - {value: 0x0040, lo: 0xb5, hi: 0xbf}, - // Block 0x113, offset 0x7dd - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0x9d}, - {value: 0x0040, lo: 0x9e, hi: 0x9f}, - {value: 0x0008, lo: 0xa0, hi: 0xbf}, - // Block 0x114, offset 0x7e1 - {value: 0x0000, lo: 0x03}, - {value: 0x0008, lo: 0x80, hi: 0xa1}, - {value: 0x0040, lo: 0xa2, hi: 0xaf}, - {value: 0x0008, lo: 0xb0, hi: 0xbf}, - // Block 0x115, offset 0x7e5 - {value: 0x0000, lo: 0x02}, - {value: 0x0008, lo: 0x80, hi: 0xa0}, - {value: 0x0040, lo: 0xa1, hi: 0xbf}, - // Block 0x116, offset 0x7e8 - {value: 0x0020, lo: 0x0f}, - {value: 0xded1, lo: 0x80, hi: 0x89}, - {value: 0x8e35, lo: 0x8a, hi: 0x8a}, - {value: 0xe011, lo: 0x8b, hi: 0x9c}, - {value: 0x8e55, lo: 0x9d, hi: 0x9d}, - {value: 0xe251, lo: 0x9e, hi: 0xa2}, - {value: 0x8e75, lo: 0xa3, hi: 0xa3}, - {value: 0xe2f1, lo: 0xa4, hi: 0xab}, - {value: 0x7f0d, lo: 0xac, hi: 0xac}, - {value: 0xe3f1, lo: 0xad, hi: 0xaf}, - {value: 0x8e95, lo: 0xb0, hi: 0xb0}, - {value: 0xe451, lo: 0xb1, hi: 0xb6}, - {value: 0x8eb5, lo: 0xb7, hi: 0xb9}, - {value: 0xe511, lo: 0xba, hi: 0xba}, - {value: 0x8f15, lo: 0xbb, hi: 0xbb}, - {value: 0xe531, lo: 0xbc, hi: 0xbf}, - // Block 0x117, offset 0x7f8 - {value: 0x0020, lo: 0x10}, - {value: 0x93b5, lo: 0x80, hi: 0x80}, - {value: 0xf0b1, lo: 0x81, hi: 0x86}, - {value: 0x93d5, lo: 0x87, hi: 0x8a}, - {value: 0xda11, lo: 0x8b, hi: 0x8b}, - {value: 0xf171, lo: 0x8c, hi: 0x96}, - {value: 0x9455, lo: 0x97, hi: 0x97}, - {value: 0xf2d1, lo: 0x98, hi: 0xa3}, - {value: 0x9475, lo: 0xa4, hi: 0xa6}, - {value: 0xf451, lo: 0xa7, hi: 0xaa}, - {value: 0x94d5, lo: 0xab, hi: 0xab}, - {value: 0xf4d1, lo: 0xac, hi: 0xac}, - {value: 0x94f5, lo: 0xad, hi: 0xad}, - {value: 0xf4f1, lo: 0xae, hi: 0xaf}, - {value: 0x9515, lo: 0xb0, hi: 0xb1}, - {value: 0xf531, lo: 0xb2, hi: 0xbe}, - {value: 0x2040, lo: 0xbf, hi: 0xbf}, - // Block 0x118, offset 0x809 - {value: 0x0000, lo: 0x04}, - {value: 0x0040, lo: 0x80, hi: 0x80}, - {value: 0x0340, lo: 0x81, hi: 0x81}, - {value: 0x0040, lo: 0x82, hi: 0x9f}, - {value: 0x0340, lo: 0xa0, hi: 0xbf}, - // Block 0x119, offset 0x80e - {value: 0x0000, lo: 0x01}, - {value: 0x0340, lo: 0x80, hi: 0xbf}, - // Block 0x11a, offset 0x810 - {value: 0x0000, lo: 0x01}, - {value: 0x33c0, lo: 0x80, hi: 0xbf}, - // Block 0x11b, offset 0x812 - {value: 0x0000, lo: 0x02}, - {value: 0x33c0, lo: 0x80, hi: 0xaf}, - {value: 0x0040, lo: 0xb0, hi: 0xbf}, -} - -// Total table size 42780 bytes (41KiB); checksum: 29936AB9 diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go index 97db2340ec..6929a9fd5c 100644 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ b/vendor/golang.org/x/net/internal/socks/socks.go @@ -127,7 +127,7 @@ type Dialer struct { // establishing the transport connection. ProxyDial func(context.Context, string, string) (net.Conn, error) - // AuthMethods specifies the list of request authentication + // AuthMethods specifies the list of request authention // methods. // If empty, SOCKS client requests only AuthMethodNotRequired. AuthMethods []AuthMethod diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go deleted file mode 100644 index 200617ea86..0000000000 --- a/vendor/golang.org/x/net/publicsuffix/list.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go - -// Package publicsuffix provides a public suffix list based on data from -// https://publicsuffix.org/ -// -// A public suffix is one under which Internet users can directly register -// names. It is related to, but different from, a TLD (top level domain). -// -// "com" is a TLD (top level domain). Top level means it has no dots. -// -// "com" is also a public suffix. Amazon and Google have registered different -// siblings under that domain: "amazon.com" and "google.com". -// -// "au" is another TLD, again because it has no dots. But it's not "amazon.au". -// Instead, it's "amazon.com.au". -// -// "com.au" isn't an actual TLD, because it's not at the top level (it has -// dots). But it is an eTLD (effective TLD), because that's the branching point -// for domain name registrars. -// -// Another name for "an eTLD" is "a public suffix". Often, what's more of -// interest is the eTLD+1, or one more label than the public suffix. For -// example, browsers partition read/write access to HTTP cookies according to -// the eTLD+1. Web pages served from "amazon.com.au" can't read cookies from -// "google.com.au", but web pages served from "maps.google.com" can share -// cookies from "www.google.com", so you don't have to sign into Google Maps -// separately from signing into Google Web Search. Note that all four of those -// domains have 3 labels and 2 dots. The first two domains are each an eTLD+1, -// the last two are not (but share the same eTLD+1: "google.com"). -// -// All of these domains have the same eTLD+1: -// - "www.books.amazon.co.uk" -// - "books.amazon.co.uk" -// - "amazon.co.uk" -// Specifically, the eTLD+1 is "amazon.co.uk", because the eTLD is "co.uk". -// -// There is no closed form algorithm to calculate the eTLD of a domain. -// Instead, the calculation is data driven. This package provides a -// pre-compiled snapshot of Mozilla's PSL (Public Suffix List) data at -// https://publicsuffix.org/ -package publicsuffix // import "golang.org/x/net/publicsuffix" - -// TODO: specify case sensitivity and leading/trailing dot behavior for -// func PublicSuffix and func EffectiveTLDPlusOne. - -import ( - "fmt" - "net/http/cookiejar" - "strings" -) - -// List implements the cookiejar.PublicSuffixList interface by calling the -// PublicSuffix function. -var List cookiejar.PublicSuffixList = list{} - -type list struct{} - -func (list) PublicSuffix(domain string) string { - ps, _ := PublicSuffix(domain) - return ps -} - -func (list) String() string { - return version -} - -// PublicSuffix returns the public suffix of the domain using a copy of the -// publicsuffix.org database compiled into the library. -// -// icann is whether the public suffix is managed by the Internet Corporation -// for Assigned Names and Numbers. If not, the public suffix is either a -// privately managed domain (and in practice, not a top level domain) or an -// unmanaged top level domain (and not explicitly mentioned in the -// publicsuffix.org list). For example, "foo.org" and "foo.co.uk" are ICANN -// domains, "foo.dyndns.org" and "foo.blogspot.co.uk" are private domains and -// "cromulent" is an unmanaged top level domain. -// -// Use cases for distinguishing ICANN domains like "foo.com" from private -// domains like "foo.appspot.com" can be found at -// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases -func PublicSuffix(domain string) (publicSuffix string, icann bool) { - lo, hi := uint32(0), uint32(numTLD) - s, suffix, icannNode, wildcard := domain, len(domain), false, false -loop: - for { - dot := strings.LastIndex(s, ".") - if wildcard { - icann = icannNode - suffix = 1 + dot - } - if lo == hi { - break - } - f := find(s[1+dot:], lo, hi) - if f == notFound { - break - } - - u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) - icannNode = u&(1<>= nodesBitsICANN - u = children[u&(1<>= childrenBitsLo - hi = u & (1<>= childrenBitsHi - switch u & (1<>= childrenBitsNodeType - wildcard = u&(1<>= nodesBitsTextLength - offset := x & (1< 0 { + outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", ")) + } + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl) + + // Check if err return available + errvar := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + break + } + } + + // Prepare arguments to Syscall. + var args []string + n := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\tvar _p%d *byte\n", n) + text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name) + text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\tvar _p%d *byte\n", n) + text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass dummy pointer in that case. + // Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). + text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name) + text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n) + args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) + n++ + } else if p.Type == "int64" && (*openbsd || *netbsd) { + args = append(args, "0") + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else if endianness == "little-endian" { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } else if p.Type == "int64" && *dragonfly { + if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil { + args = append(args, "0") + } + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else if endianness == "little-endian" { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" { + if len(args)%2 == 1 && *arm { + // arm abi specifies 64-bit argument uses + // (even, odd) pair + args = append(args, "0") + } + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } + + // Determine which form to use; pad args with zeros. + asm := "Syscall" + if nonblock != nil { + if errvar == "" && goos == "linux" { + asm = "RawSyscallNoError" + } else { + asm = "RawSyscall" + } + } else { + if errvar == "" && goos == "linux" { + asm = "SyscallNoError" + } + } + if len(args) <= 3 { + for len(args) < 3 { + args = append(args, "0") + } + } else if len(args) <= 6 { + asm += "6" + for len(args) < 6 { + args = append(args, "0") + } + } else if len(args) <= 9 { + asm += "9" + for len(args) < 9 { + args = append(args, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct) + } + + // System call number. + if sysname == "" { + sysname = "SYS_" + funct + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToUpper(sysname) + } + + var libcFn string + if libc { + asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call + sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_ + sysname = strings.ToLower(sysname) // lowercase + if sysname == "getdirentries64" { + // Special case - libSystem name and + // raw syscall name don't match. + sysname = "__getdirentries64" + } + libcFn = sysname + sysname = "funcPC(libc_" + sysname + "_trampoline)" + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist) + + // Assign return values. + body := "" + ret := []string{"_", "_", "_"} + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" && !*plan9 { + reg = "e1" + ret[2] = reg + doErrno = true + } else if p.Name == "err" && *plan9 { + ret[0] = "r0" + ret[2] = "e1" + break + } else { + reg = fmt.Sprintf("r%d", i) + ret[i] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%s != 0", reg) + } + if p.Type == "int64" && endianness != "" { + // 64-bit number in r1:r0 or r0:r1. + if i+2 > len(out) { + fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct) + } + if endianness == "big-endian" { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) + } else { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) + } + ret[i] = fmt.Sprintf("r%d", i) + ret[i+1] = fmt.Sprintf("r%d", i+1) + } + if reg != "e1" || *plan9 { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { + text += fmt.Sprintf("\t%s\n", call) + } else { + if errvar == "" && goos == "linux" { + // raw syscall without error on Linux, see golang.org/issue/22924 + text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call) + } else { + text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) + } + } + text += body + + if *plan9 && ret[2] == "e1" { + text += "\tif int32(r0) == -1 {\n" + text += "\t\terr = e1\n" + text += "\t}\n" + } else if doErrno { + text += "\tif e1 != 0 {\n" + text += "\t\terr = errnoErr(e1)\n" + text += "\t}\n" + } + text += "\treturn\n" + text += "}\n\n" + + if libc && !trampolines[libcFn] { + // some system calls share a trampoline, like read and readlen. + trampolines[libcFn] = true + // Declare assembly trampoline. + text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn) + // Assembly trampoline calls the libc_* function, which this magic + // redirects to use the function from libSystem. + text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn) + text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn) + text += "\n" + } + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go new file mode 100644 index 0000000000..3be3cdfc3b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go @@ -0,0 +1,415 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_aix.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt +*/ +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + aix = flag.Bool("aix", false, "aix") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + text := "" + cExtern := "/*\n#include \n#include \n" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // Check if value return, err return available + errvar := "" + retvar := "" + rettype := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + } else { + retvar = p.Name + rettype = p.Type + } + } + + // System call name. + if sysname == "" { + sysname = funct + } + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + cRettype := "" + if rettype == "unsafe.Pointer" { + cRettype = "uintptr_t" + } else if rettype == "uintptr" { + cRettype = "uintptr_t" + } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { + cRettype = "uintptr_t" + } else if rettype == "int" { + cRettype = "int" + } else if rettype == "int32" { + cRettype = "int" + } else if rettype == "int64" { + cRettype = "long long" + } else if rettype == "uint32" { + cRettype = "unsigned int" + } else if rettype == "uint64" { + cRettype = "unsigned long long" + } else { + cRettype = "int" + } + if sysname == "exit" { + cRettype = "void" + } + + // Change p.Types to c + var cIn []string + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "string" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t", "size_t") + } else if p.Type == "unsafe.Pointer" { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "uintptr" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "int" { + cIn = append(cIn, "int") + } else if p.Type == "int32" { + cIn = append(cIn, "int") + } else if p.Type == "int64" { + cIn = append(cIn, "long long") + } else if p.Type == "uint32" { + cIn = append(cIn, "unsigned int") + } else if p.Type == "uint64" { + cIn = append(cIn, "unsigned long long") + } else { + cIn = append(cIn, "int") + } + } + + if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + cExtern += "#define c_select select\n" + } + // Imports of system calls from libc + cExtern += fmt.Sprintf("%s %s", cRettype, sysname) + cIn := strings.Join(cIn, ", ") + cExtern += fmt.Sprintf("(%s);\n", cIn) + } + + // So file name. + if *aix { + if modname == "" { + modname = "libc.a/shr_64.o" + } else { + fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) + os.Exit(1) + } + } + + strconvfunc := "C.CString" + + // Go function header. + if outps != "" { + outps = fmt.Sprintf(" (%s)", outps) + } + if text != "" { + text += "\n" + } + + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) + + // Prepare arguments to Syscall. + var args []string + n := 0 + argN := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) + n++ + text += fmt.Sprintf("\tvar _p%d int\n", n) + text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) + args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + n++ + } else if p.Type == "bool" { + text += fmt.Sprintf("\tvar _p%d uint32\n", n) + text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) + args = append(args, fmt.Sprintf("_p%d", n)) + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "unsafe.Pointer" { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "int" { + if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { + args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) + } else if argN == 0 && funct == "fcntl" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := "" + if sysname == "exit" { + if errvar != "" { + call += "er :=" + } else { + call += "" + } + } else if errvar != "" { + call += "r0,er :=" + } else if retvar != "" { + call += "r0,_ :=" + } else { + call += "" + } + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist) + } else { + call += fmt.Sprintf("C.%s(%s)", sysname, arglist) + } + + // Assign return values. + body := "" + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + } else { + reg = "r0" + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + + // verify return + if sysname != "exit" && errvar != "" { + if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { + body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } else { + body += "\tif (r0 ==-1 && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + } else if errvar != "" { + body += "\tif (er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + + text += fmt.Sprintf("\t%s\n", call) + text += body + + text += "\treturn\n" + text += "}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + + +%s +*/ +import "C" +import ( + "unsafe" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go new file mode 100644 index 0000000000..c960099517 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go @@ -0,0 +1,614 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_aix.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt + + +This program will generate three files and handle both gc and gccgo implementation: + - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) + - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 + - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. + + The generated code looks like this + +zsyscall_aix_ppc64.go +func asyscall(...) (n int, err error) { + // Pointer Creation + r1, e1 := callasyscall(...) + // Type Conversion + // Error Handler + return +} + +zsyscall_aix_ppc64_gc.go +//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" +//go:linkname libc_asyscall libc_asyscall +var asyscall syscallFunc + +func callasyscall(...) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) + return +} + +zsyscall_aix_ppc64_ggcgo.go + +// int asyscall(...) + +import "C" + +func callasyscall(...) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.asyscall(...)) + e1 = syscall.GetErrno() + return +} +*/ + +package main + +import ( + "bufio" + "flag" + "fmt" + "io/ioutil" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + aix = flag.Bool("aix", false, "aix") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + // GCCGO + textgccgo := "" + cExtern := "/*\n#include \n" + // GC + textgc := "" + dynimports := "" + linknames := "" + var vars []string + // COMMON + textcommon := "" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + if sysname == "" { + sysname = funct + } + + onlyCommon := false + if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" { + // This function call another syscall which is already implemented. + // Therefore, the gc and gccgo part must not be generated. + onlyCommon = true + } + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + + textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + if !onlyCommon { + textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + } + + // Check if value return, err return available + errvar := "" + rettype := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + } else { + rettype = p.Type + } + } + + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + // GCCGO Prototype return type + cRettype := "" + if rettype == "unsafe.Pointer" { + cRettype = "uintptr_t" + } else if rettype == "uintptr" { + cRettype = "uintptr_t" + } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { + cRettype = "uintptr_t" + } else if rettype == "int" { + cRettype = "int" + } else if rettype == "int32" { + cRettype = "int" + } else if rettype == "int64" { + cRettype = "long long" + } else if rettype == "uint32" { + cRettype = "unsigned int" + } else if rettype == "uint64" { + cRettype = "unsigned long long" + } else { + cRettype = "int" + } + if sysname == "exit" { + cRettype = "void" + } + + // GCCGO Prototype arguments type + var cIn []string + for i, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "string" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t", "size_t") + } else if p.Type == "unsafe.Pointer" { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "uintptr" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "int" { + if (i == 0 || i == 2) && funct == "fcntl" { + // These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock + cIn = append(cIn, "uintptr_t") + } else { + cIn = append(cIn, "int") + } + + } else if p.Type == "int32" { + cIn = append(cIn, "int") + } else if p.Type == "int64" { + cIn = append(cIn, "long long") + } else if p.Type == "uint32" { + cIn = append(cIn, "unsigned int") + } else if p.Type == "uint64" { + cIn = append(cIn, "unsigned long long") + } else { + cIn = append(cIn, "int") + } + } + + if !onlyCommon { + // GCCGO Prototype Generation + // Imports of system calls from libc + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + cExtern += "#define c_select select\n" + } + cExtern += fmt.Sprintf("%s %s", cRettype, sysname) + cIn := strings.Join(cIn, ", ") + cExtern += fmt.Sprintf("(%s);\n", cIn) + } + // GC Library name + if modname == "" { + modname = "libc.a/shr_64.o" + } else { + fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) + os.Exit(1) + } + sysvarname := fmt.Sprintf("libc_%s", sysname) + + if !onlyCommon { + // GC Runtime import of function to allow cross-platform builds. + dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname) + // GC Link symbol to proc address variable. + linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname) + // GC Library proc address variable. + vars = append(vars, sysvarname) + } + + strconvfunc := "BytePtrFromString" + strconvtype := "*byte" + + // Go function header. + if outps != "" { + outps = fmt.Sprintf(" (%s)", outps) + } + if textcommon != "" { + textcommon += "\n" + } + + textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) + + // Prepare arguments tocall. + var argscommon []string // Arguments in the common part + var argscall []string // Arguments for call prototype + var argsgc []string // Arguments for gc call (with syscall6) + var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall) + n := 0 + argN := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if p.Type == "string" && errvar != "" { + textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) + textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") + } else if p.Type == "bool" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if p.Type == "int" { + if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { + // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + + } else { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + nargs := len(argsgc) + + // COMMON function generation + argscommonlist := strings.Join(argscommon, ", ") + callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) + ret := []string{"_", "_"} + body := "" + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + ret[1] = reg + doErrno = true + } else { + reg = "r0" + ret[0] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%s != 0", reg) + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" { + textcommon += fmt.Sprintf("\t%s\n", callcommon) + } else { + textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) + } + textcommon += body + + if doErrno { + textcommon += "\tif e1 != 0 {\n" + textcommon += "\t\terr = errnoErr(e1)\n" + textcommon += "\t}\n" + } + textcommon += "\treturn\n" + textcommon += "}\n" + + if onlyCommon { + continue + } + + // CALL Prototype + callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) + + // GC function generation + asm := "syscall6" + if nonblock != nil { + asm = "rawSyscall6" + } + + if len(argsgc) <= 6 { + for len(argsgc) < 6 { + argsgc = append(argsgc, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) + os.Exit(1) + } + argsgclist := strings.Join(argsgc, ", ") + callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) + + textgc += callProto + textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) + textgc += "\treturn\n}\n" + + // GCCGO function generation + argsgccgolist := strings.Join(argsgccgo, ", ") + var callgccgo string + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist) + } else { + callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) + } + textgccgo += callProto + textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) + textgccgo += "\te1 = syscall.GetErrno()\n" + textgccgo += "\treturn\n}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + + // Print zsyscall_aix_ppc64.go + err := ioutil.WriteFile("zsyscall_aix_ppc64.go", + []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gc.go + vardecls := "\t" + strings.Join(vars, ",\n\t") + vardecls += " syscallFunc" + err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", + []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gccgo.go + err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", + []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } +} + +const srcTemplate1 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + +import ( + "unsafe" +) + + +%s + +%s +` +const srcTemplate2 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build !gccgo + +package %s + +import ( + "unsafe" +) +%s +%s +%s +type syscallFunc uintptr + +var ( +%s +) + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +%s +` +const srcTemplate3 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build gccgo + +package %s + +%s +*/ +import "C" +import ( + "syscall" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go new file mode 100644 index 0000000000..3d864738b6 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go @@ -0,0 +1,335 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* + This program reads a file containing function prototypes + (like syscall_solaris.go) and generates system call bodies. + The prototypes are marked by lines beginning with "//sys" + and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt +*/ + +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + text := "" + dynimports := "" + linknames := "" + var vars []string + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // So file name. + if modname == "" { + modname = "libc" + } + + // System call name. + if sysname == "" { + sysname = funct + } + + // System call pointer variable name. + sysvarname := fmt.Sprintf("proc%s", sysname) + + strconvfunc := "BytePtrFromString" + strconvtype := "*byte" + + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + // Runtime import of function to allow cross-platform builds. + dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname) + // Link symbol to proc address variable. + linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname) + // Library proc address variable. + vars = append(vars, sysvarname) + + // Go function header. + outlist := strings.Join(out, ", ") + if outlist != "" { + outlist = fmt.Sprintf(" (%s)", outlist) + } + if text != "" { + text += "\n" + } + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist) + + // Check if err return available + errvar := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + continue + } + } + + // Prepare arguments to Syscall. + var args []string + n := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1]) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) + n++ + } else if p.Type == "int64" && endianness != "" { + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + } else if p.Type == "bool" { + text += fmt.Sprintf("\tvar _p%d uint32\n", n) + text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) + args = append(args, fmt.Sprintf("uintptr(_p%d)", n)) + n++ + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } + nargs := len(args) + + // Determine which form to use; pad args with zeros. + asm := "sysvicall6" + if nonblock != nil { + asm = "rawSysvicall6" + } + if len(args) <= 6 { + for len(args) < 6 { + args = append(args, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path) + os.Exit(1) + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist) + + // Assign return values. + body := "" + ret := []string{"_", "_", "_"} + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + ret[2] = reg + doErrno = true + } else { + reg = fmt.Sprintf("r%d", i) + ret[i] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%d != 0", reg) + } + if p.Type == "int64" && endianness != "" { + // 64-bit number in r1:r0 or r0:r1. + if i+2 > len(out) { + fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path) + os.Exit(1) + } + if endianness == "big-endian" { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) + } else { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) + } + ret[i] = fmt.Sprintf("r%d", i) + ret[i+1] = fmt.Sprintf("r%d", i+1) + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { + text += fmt.Sprintf("\t%s\n", call) + } else { + text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) + } + text += body + + if doErrno { + text += "\tif e1 != 0 {\n" + text += "\t\terr = e1\n" + text += "\t}\n" + } + text += "\treturn\n" + text += "}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + vardecls := "\t" + strings.Join(vars, ",\n\t") + vardecls += " syscallFunc" + fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + +import ( + "syscall" + "unsafe" +) +%s +%s +%s +var ( +%s +) + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go new file mode 100644 index 0000000000..b6b409909c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go @@ -0,0 +1,355 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Parse the header files for OpenBSD and generate a Go usable sysctl MIB. +// +// Build a MIB with each entry being an array containing the level, type and +// a hash that will contain additional entries if the current entry is a node. +// We then walk this MIB and create a flattened sysctl name to OID hash. + +package main + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "regexp" + "sort" + "strings" +) + +var ( + goos, goarch string +) + +// cmdLine returns this programs's commandline arguments. +func cmdLine() string { + return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags. +func buildTags() string { + return fmt.Sprintf("%s,%s", goarch, goos) +} + +// reMatch performs regular expression match and stores the substring slice to value pointed by m. +func reMatch(re *regexp.Regexp, str string, m *[]string) bool { + *m = re.FindStringSubmatch(str) + if *m != nil { + return true + } + return false +} + +type nodeElement struct { + n int + t string + pE *map[string]nodeElement +} + +var ( + debugEnabled bool + mib map[string]nodeElement + node *map[string]nodeElement + nodeMap map[string]string + sysCtl []string +) + +var ( + ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`) + ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`) + ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`) + netInetRE = regexp.MustCompile(`^netinet/`) + netInet6RE = regexp.MustCompile(`^netinet6/`) + netRE = regexp.MustCompile(`^net/`) + bracesRE = regexp.MustCompile(`{.*}`) + ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`) + fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`) +) + +func debug(s string) { + if debugEnabled { + fmt.Fprintln(os.Stderr, s) + } +} + +// Walk the MIB and build a sysctl name to OID mapping. +func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) { + lNode := pNode // local copy of pointer to node + var keys []string + for k := range *lNode { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, key := range keys { + nodename := name + if name != "" { + nodename += "." + } + nodename += key + + nodeoid := append(oid, (*pNode)[key].n) + + if (*pNode)[key].t == `CTLTYPE_NODE` { + if _, ok := nodeMap[nodename]; ok { + lNode = &mib + ctlName := nodeMap[nodename] + for _, part := range strings.Split(ctlName, ".") { + lNode = ((*lNode)[part]).pE + } + } else { + lNode = (*pNode)[key].pE + } + buildSysctl(lNode, nodename, nodeoid) + } else if (*pNode)[key].t != "" { + oidStr := []string{} + for j := range nodeoid { + oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j])) + } + text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n" + sysCtl = append(sysCtl, text) + } + } +} + +func main() { + // Get the OS (using GOOS_TARGET if it exist) + goos = os.Getenv("GOOS_TARGET") + if goos == "" { + goos = os.Getenv("GOOS") + } + // Get the architecture (using GOARCH_TARGET if it exists) + goarch = os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + // Check if GOOS and GOARCH environment variables are defined + if goarch == "" || goos == "" { + fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") + os.Exit(1) + } + + mib = make(map[string]nodeElement) + headers := [...]string{ + `sys/sysctl.h`, + `sys/socket.h`, + `sys/tty.h`, + `sys/malloc.h`, + `sys/mount.h`, + `sys/namei.h`, + `sys/sem.h`, + `sys/shm.h`, + `sys/vmmeter.h`, + `uvm/uvmexp.h`, + `uvm/uvm_param.h`, + `uvm/uvm_swap_encrypt.h`, + `ddb/db_var.h`, + `net/if.h`, + `net/if_pfsync.h`, + `net/pipex.h`, + `netinet/in.h`, + `netinet/icmp_var.h`, + `netinet/igmp_var.h`, + `netinet/ip_ah.h`, + `netinet/ip_carp.h`, + `netinet/ip_divert.h`, + `netinet/ip_esp.h`, + `netinet/ip_ether.h`, + `netinet/ip_gre.h`, + `netinet/ip_ipcomp.h`, + `netinet/ip_ipip.h`, + `netinet/pim_var.h`, + `netinet/tcp_var.h`, + `netinet/udp_var.h`, + `netinet6/in6.h`, + `netinet6/ip6_divert.h`, + `netinet6/pim6_var.h`, + `netinet/icmp6.h`, + `netmpls/mpls.h`, + } + + ctls := [...]string{ + `kern`, + `vm`, + `fs`, + `net`, + //debug /* Special handling required */ + `hw`, + //machdep /* Arch specific */ + `user`, + `ddb`, + //vfs /* Special handling required */ + `fs.posix`, + `kern.forkstat`, + `kern.intrcnt`, + `kern.malloc`, + `kern.nchstats`, + `kern.seminfo`, + `kern.shminfo`, + `kern.timecounter`, + `kern.tty`, + `kern.watchdog`, + `net.bpf`, + `net.ifq`, + `net.inet`, + `net.inet.ah`, + `net.inet.carp`, + `net.inet.divert`, + `net.inet.esp`, + `net.inet.etherip`, + `net.inet.gre`, + `net.inet.icmp`, + `net.inet.igmp`, + `net.inet.ip`, + `net.inet.ip.ifq`, + `net.inet.ipcomp`, + `net.inet.ipip`, + `net.inet.mobileip`, + `net.inet.pfsync`, + `net.inet.pim`, + `net.inet.tcp`, + `net.inet.udp`, + `net.inet6`, + `net.inet6.divert`, + `net.inet6.ip6`, + `net.inet6.icmp6`, + `net.inet6.pim6`, + `net.inet6.tcp6`, + `net.inet6.udp6`, + `net.mpls`, + `net.mpls.ifq`, + `net.key`, + `net.pflow`, + `net.pfsync`, + `net.pipex`, + `net.rt`, + `vm.swapencrypt`, + //vfsgenctl /* Special handling required */ + } + + // Node name "fixups" + ctlMap := map[string]string{ + "ipproto": "net.inet", + "net.inet.ipproto": "net.inet", + "net.inet6.ipv6proto": "net.inet6", + "net.inet6.ipv6": "net.inet6.ip6", + "net.inet.icmpv6": "net.inet6.icmp6", + "net.inet6.divert6": "net.inet6.divert", + "net.inet6.tcp6": "net.inet.tcp", + "net.inet6.udp6": "net.inet.udp", + "mpls": "net.mpls", + "swpenc": "vm.swapencrypt", + } + + // Node mappings + nodeMap = map[string]string{ + "net.inet.ip.ifq": "net.ifq", + "net.inet.pfsync": "net.pfsync", + "net.mpls.ifq": "net.ifq", + } + + mCtls := make(map[string]bool) + for _, ctl := range ctls { + mCtls[ctl] = true + } + + for _, header := range headers { + debug("Processing " + header) + file, err := os.Open(filepath.Join("/usr/include", header)) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + var sub []string + if reMatch(ctlNames1RE, s.Text(), &sub) || + reMatch(ctlNames2RE, s.Text(), &sub) || + reMatch(ctlNames3RE, s.Text(), &sub) { + if sub[1] == `CTL_NAMES` { + // Top level. + node = &mib + } else { + // Node. + nodename := strings.ToLower(sub[2]) + ctlName := "" + if reMatch(netInetRE, header, &sub) { + ctlName = "net.inet." + nodename + } else if reMatch(netInet6RE, header, &sub) { + ctlName = "net.inet6." + nodename + } else if reMatch(netRE, header, &sub) { + ctlName = "net." + nodename + } else { + ctlName = nodename + ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) + } + + if val, ok := ctlMap[ctlName]; ok { + ctlName = val + } + if _, ok := mCtls[ctlName]; !ok { + debug("Ignoring " + ctlName + "...") + continue + } + + // Walk down from the top of the MIB. + node = &mib + for _, part := range strings.Split(ctlName, ".") { + if _, ok := (*node)[part]; !ok { + debug("Missing node " + part) + (*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} + } + node = (*node)[part].pE + } + } + + // Populate current node with entries. + i := -1 + for !strings.HasPrefix(s.Text(), "}") { + s.Scan() + if reMatch(bracesRE, s.Text(), &sub) { + i++ + } + if !reMatch(ctlTypeRE, s.Text(), &sub) { + continue + } + (*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} + } + } + } + err = s.Err() + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + file.Close() + } + buildSysctl(&mib, "", []int{}) + + sort.Strings(sysCtl) + text := strings.Join(sysCtl, "") + + fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) +} + +const srcTemplate = `// %s +// Code generated by the command above; DO NOT EDIT. + +// +build %s + +package unix + +type mibentry struct { + ctlname string + ctloid []_C_int +} + +var sysctlMib = []mibentry { +%s +} +` diff --git a/vendor/golang.org/x/sys/unix/mksysnum.go b/vendor/golang.org/x/sys/unix/mksysnum.go new file mode 100644 index 0000000000..baa6ecd850 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksysnum.go @@ -0,0 +1,190 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Generate system call table for DragonFly, NetBSD, +// FreeBSD, OpenBSD or Darwin from master list +// (for example, /usr/src/sys/kern/syscalls.master or +// sys/syscall.h). +package main + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "regexp" + "strings" +) + +var ( + goos, goarch string +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return fmt.Sprintf("%s,%s", goarch, goos) +} + +func checkErr(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} + +// source string and substring slice for regexp +type re struct { + str string // source string + sub []string // matched sub-string +} + +// Match performs regular expression match +func (r *re) Match(exp string) bool { + r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) + if r.sub != nil { + return true + } + return false +} + +// fetchFile fetches a text file from URL +func fetchFile(URL string) io.Reader { + resp, err := http.Get(URL) + checkErr(err) + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + checkErr(err) + return strings.NewReader(string(body)) +} + +// readFile reads a text file from path +func readFile(path string) io.Reader { + file, err := os.Open(os.Args[1]) + checkErr(err) + return file +} + +func format(name, num, proto string) string { + name = strings.ToUpper(name) + // There are multiple entries for enosys and nosys, so comment them out. + nm := re{str: name} + if nm.Match(`^SYS_E?NOSYS$`) { + name = fmt.Sprintf("// %s", name) + } + if name == `SYS_SYS_EXIT` { + name = `SYS_EXIT` + } + return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) +} + +func main() { + // Get the OS (using GOOS_TARGET if it exist) + goos = os.Getenv("GOOS_TARGET") + if goos == "" { + goos = os.Getenv("GOOS") + } + // Get the architecture (using GOARCH_TARGET if it exists) + goarch = os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + // Check if GOOS and GOARCH environment variables are defined + if goarch == "" || goos == "" { + fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") + os.Exit(1) + } + + file := strings.TrimSpace(os.Args[1]) + var syscalls io.Reader + if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { + // Download syscalls.master file + syscalls = fetchFile(file) + } else { + syscalls = readFile(file) + } + + var text, line string + s := bufio.NewScanner(syscalls) + for s.Scan() { + t := re{str: line} + if t.Match(`^(.*)\\$`) { + // Handle continuation + line = t.sub[1] + line += strings.TrimLeft(s.Text(), " \t") + } else { + // New line + line = s.Text() + } + t = re{str: line} + if t.Match(`\\$`) { + continue + } + t = re{str: line} + + switch goos { + case "dragonfly": + if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { + num, proto := t.sub[1], t.sub[2] + name := fmt.Sprintf("SYS_%s", t.sub[3]) + text += format(name, num, proto) + } + case "freebsd": + if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { + num, proto := t.sub[1], t.sub[2] + name := fmt.Sprintf("SYS_%s", t.sub[3]) + text += format(name, num, proto) + } + case "openbsd": + if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { + num, proto, name := t.sub[1], t.sub[3], t.sub[4] + text += format(name, num, proto) + } + case "netbsd": + if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { + num, proto, compat := t.sub[1], t.sub[6], t.sub[8] + name := t.sub[7] + "_" + t.sub[9] + if t.sub[11] != "" { + name = t.sub[7] + "_" + t.sub[11] + } + name = strings.ToUpper(name) + if compat == "" || compat == "13" || compat == "30" || compat == "50" { + text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) + } + } + case "darwin": + if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) { + name, num := t.sub[1], t.sub[2] + name = strings.ToUpper(name) + text += fmt.Sprintf(" SYS_%s = %s;\n", name, num) + } + default: + fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) + os.Exit(1) + + } + } + err := s.Err() + checkErr(err) + + fmt.Printf(template, cmdLine(), buildTags(), text) +} + +const template = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package unix + +const( +%s)` diff --git a/vendor/golang.org/x/sys/unix/types_aix.go b/vendor/golang.org/x/sys/unix/types_aix.go new file mode 100644 index 0000000000..40d2beede5 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_aix.go @@ -0,0 +1,237 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore +// +build aix + +/* +Input to cgo -godefs. See also mkerrors.sh and mkall.sh +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong + PathMax = C.PATH_MAX +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +type off64 C.off64_t +type off C.off_t +type Mode_t C.mode_t + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +type Timex C.struct_timex + +type Time_t C.time_t + +type Tms C.struct_tms + +type Utimbuf C.struct_utimbuf + +type Timezone C.struct_timezone + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit64 + +type Pid_t C.pid_t + +type _Gid_t C.gid_t + +type dev_t C.dev_t + +// Files + +type Stat_t C.struct_stat + +type StatxTimestamp C.struct_statx_timestamp + +type Statx_t C.struct_statx + +type Dirent C.struct_dirent + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Cmsghdr C.struct_cmsghdr + +type ICMPv6Filter C.struct_icmp6_filter + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type Linger C.struct_linger + +type Msghdr C.struct_msghdr + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr +) + +type IfMsgHdr C.struct_if_msghdr + +// Misc + +type FdSet C.fd_set + +type Utsname C.struct_utsname + +type Ustat_t C.struct_ustat + +type Sigset_t C.sigset_t + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// Terminal handling + +type Termios C.struct_termios + +type Termio C.struct_termio + +type Winsize C.struct_winsize + +//poll + +type PollFd struct { + Fd int32 + Events uint16 + Revents uint16 +} + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +//flock_t + +type Flock_t C.struct_flock64 + +// Statfs + +type Fsid_t C.struct_fsid_t +type Fsid64_t C.struct_fsid64_t + +type Statfs_t C.struct_statfs + +const RNDGETENTCNT = 0x80045200 diff --git a/vendor/golang.org/x/sys/unix/types_darwin.go b/vendor/golang.org/x/sys/unix/types_darwin.go new file mode 100644 index 0000000000..155c2e692b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_darwin.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define __DARWIN_UNIX03 0 +#define KERNEL +#define _DARWIN_USE_64_BIT_INODE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat64 + +type Statfs_t C.struct_statfs64 + +type Flock_t C.struct_flock + +type Fstore_t C.struct_fstore + +type Radvisory_t C.struct_radvisory + +type Fbootstraptransfer_t C.struct_fbootstraptransfer + +type Log2phys_t C.struct_log2phys + +type Fsid C.struct_fsid + +type Dirent C.struct_dirent + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet4Pktinfo C.struct_in_pktinfo + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfmaMsghdr2 C.struct_ifma_msghdr2 + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// uname + +type Utsname C.struct_utsname + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_dragonfly.go b/vendor/golang.org/x/sys/unix/types_dragonfly.go new file mode 100644 index 0000000000..3365dd79d0 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_dragonfly.go @@ -0,0 +1,263 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.struct_fsid + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Uname + +type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go new file mode 100644 index 0000000000..a121dc3368 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_freebsd.go @@ -0,0 +1,400 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define _WANT_FREEBSD11_STAT 1 +#define _WANT_FREEBSD11_STATFS 1 +#define _WANT_FREEBSD11_DIRENT 1 +#define _WANT_FREEBSD11_KEVENT 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +// This structure is a duplicate of if_data on FreeBSD 8-STABLE. +// See /usr/include/net/if.h. +struct if_data8 { + u_char ifi_type; + u_char ifi_physical; + u_char ifi_addrlen; + u_char ifi_hdrlen; + u_char ifi_link_state; + u_char ifi_spare_char1; + u_char ifi_spare_char2; + u_char ifi_datalen; + u_long ifi_mtu; + u_long ifi_metric; + u_long ifi_baudrate; + u_long ifi_ipackets; + u_long ifi_ierrors; + u_long ifi_opackets; + u_long ifi_oerrors; + u_long ifi_collisions; + u_long ifi_ibytes; + u_long ifi_obytes; + u_long ifi_imcasts; + u_long ifi_omcasts; + u_long ifi_iqdrops; + u_long ifi_noproto; + u_long ifi_hwassist; +// FIXME: these are now unions, so maybe need to change definitions? +#undef ifi_epoch + time_t ifi_epoch; +#undef ifi_lastchange + struct timeval ifi_lastchange; +}; + +// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE. +// See /usr/include/net/if.h. +struct if_msghdr8 { + u_short ifm_msglen; + u_char ifm_version; + u_char ifm_type; + int ifm_addrs; + int ifm_flags; + u_short ifm_index; + struct if_data8 ifm_data; +}; +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +const ( + _statfsVersion = C.STATFS_VERSION + _dirblksiz = C.DIRBLKSIZ +) + +type Stat_t C.struct_stat + +type stat_freebsd11_t C.struct_freebsd11_stat + +type Statfs_t C.struct_statfs + +type statfs_freebsd11_t C.struct_freebsd11_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type dirent_freebsd11 C.struct_freebsd11_dirent + +type Fsid C.struct_fsid + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Advice to Fadvise + +const ( + FADV_NORMAL = C.POSIX_FADV_NORMAL + FADV_RANDOM = C.POSIX_FADV_RANDOM + FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL + FADV_WILLNEED = C.POSIX_FADV_WILLNEED + FADV_DONTNEED = C.POSIX_FADV_DONTNEED + FADV_NOREUSE = C.POSIX_FADV_NOREUSE +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPMreqn C.struct_ip_mreqn + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPMreqn = C.sizeof_struct_ip_mreqn + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_ATTACH = C.PT_ATTACH + PTRACE_CONT = C.PT_CONTINUE + PTRACE_DETACH = C.PT_DETACH + PTRACE_GETFPREGS = C.PT_GETFPREGS + PTRACE_GETFSBASE = C.PT_GETFSBASE + PTRACE_GETLWPLIST = C.PT_GETLWPLIST + PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS + PTRACE_GETREGS = C.PT_GETREGS + PTRACE_GETXSTATE = C.PT_GETXSTATE + PTRACE_IO = C.PT_IO + PTRACE_KILL = C.PT_KILL + PTRACE_LWPEVENTS = C.PT_LWP_EVENTS + PTRACE_LWPINFO = C.PT_LWPINFO + PTRACE_SETFPREGS = C.PT_SETFPREGS + PTRACE_SETREGS = C.PT_SETREGS + PTRACE_SINGLESTEP = C.PT_STEP + PTRACE_TRACEME = C.PT_TRACE_ME +) + +const ( + PIOD_READ_D = C.PIOD_READ_D + PIOD_WRITE_D = C.PIOD_WRITE_D + PIOD_READ_I = C.PIOD_READ_I + PIOD_WRITE_I = C.PIOD_WRITE_I +) + +const ( + PL_FLAG_BORN = C.PL_FLAG_BORN + PL_FLAG_EXITED = C.PL_FLAG_EXITED + PL_FLAG_SI = C.PL_FLAG_SI +) + +const ( + TRAP_BRKPT = C.TRAP_BRKPT + TRAP_TRACE = C.TRAP_TRACE +) + +type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo + +type __Siginfo C.struct___siginfo + +type Sigset_t C.sigset_t + +type Reg C.struct_reg + +type FpReg C.struct_fpreg + +type PtraceIoDesc C.struct_ptrace_io_desc + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent_freebsd11 + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + sizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 + sizeofIfData = C.sizeof_struct_if_data + SizeofIfData = C.sizeof_struct_if_data8 + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type ifMsghdr C.struct_if_msghdr + +type IfMsghdr C.struct_if_msghdr8 + +type ifData C.struct_if_data + +type IfData C.struct_if_data8 + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr + SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfZbuf C.struct_bpf_zbuf + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfZbufHeader C.struct_bpf_zbuf_header + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLINIGNEOF = C.POLLINIGNEOF + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Capabilities + +type CapRights C.struct_cap_rights + +// Uname + +type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_netbsd.go b/vendor/golang.org/x/sys/unix/types_netbsd.go new file mode 100644 index 0000000000..4a96d72c37 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_netbsd.go @@ -0,0 +1,290 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.fsid_t + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Advice to Fadvise + +const ( + FADV_NORMAL = C.POSIX_FADV_NORMAL + FADV_RANDOM = C.POSIX_FADV_RANDOM + FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL + FADV_WILLNEED = C.POSIX_FADV_WILLNEED + FADV_DONTNEED = C.POSIX_FADV_DONTNEED + FADV_NOREUSE = C.POSIX_FADV_NOREUSE +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +type Mclpool C.struct_mclpool + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfTimeval C.struct_bpf_timeval + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +type Ptmget C.struct_ptmget + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Sysctl + +type Sysctlnode C.struct_sysctlnode + +// Uname + +type Utsname C.struct_utsname + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go new file mode 100644 index 0000000000..775cb57dc8 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_openbsd.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.fsid_t + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +type Mclpool C.struct_mclpool + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfTimeval C.struct_bpf_timeval + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Signal Sets + +type Sigset_t C.sigset_t + +// Uname + +type Utsname C.struct_utsname + +// Uvmexp + +const SizeofUvmexp = C.sizeof_struct_uvmexp + +type Uvmexp C.struct_uvmexp + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go new file mode 100644 index 0000000000..2b716f9348 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_solaris.go @@ -0,0 +1,266 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +// These defines ensure that builds done on newer versions of Solaris are +// backwards-compatible with older versions of Solaris and +// OpenSolaris-based derivatives. +#define __USE_SUNOS_SOCKETS__ // msghdr +#define __USE_LEGACY_PROTOTYPES__ // iovec +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong + PathMax = C.PATH_MAX + MaxHostNameLen = C.MAXHOSTNAMELEN +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +type Tms C.struct_tms + +type Utimbuf C.struct_utimbuf + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +// Filesystems + +type _Fsblkcnt_t C.fsblkcnt_t + +type Statvfs_t C.struct_statvfs + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Select + +type FdSet C.fd_set + +// Misc + +type Utsname C.struct_utsname + +type Ustat_t C.struct_ustat + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_EACCESS = C.AT_EACCESS +) + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfTimeval C.struct_bpf_timeval + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Termio C.struct_termio + +type Winsize C.struct_winsize + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) diff --git a/vendor/golang.org/x/text/encoding/charmap/maketables.go b/vendor/golang.org/x/text/encoding/charmap/maketables.go new file mode 100644 index 0000000000..f7941701e8 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/charmap/maketables.go @@ -0,0 +1,556 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" + "unicode/utf8" + + "golang.org/x/text/encoding" + "golang.org/x/text/internal/gen" +) + +const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + + ` !"#$%&'()*+,-./0123456789:;<=>?` + + `@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` + + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f" + +var encodings = []struct { + name string + mib string + comment string + varName string + replacement byte + mapping string +}{ + { + "IBM Code Page 037", + "IBM037", + "", + "CodePage037", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm", + }, + { + "IBM Code Page 437", + "PC8CodePage437", + "", + "CodePage437", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm", + }, + { + "IBM Code Page 850", + "PC850Multilingual", + "", + "CodePage850", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm", + }, + { + "IBM Code Page 852", + "PCp852", + "", + "CodePage852", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm", + }, + { + "IBM Code Page 855", + "IBM855", + "", + "CodePage855", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm", + }, + { + "Windows Code Page 858", // PC latin1 with Euro + "IBM00858", + "", + "CodePage858", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm", + }, + { + "IBM Code Page 860", + "IBM860", + "", + "CodePage860", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm", + }, + { + "IBM Code Page 862", + "PC862LatinHebrew", + "", + "CodePage862", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm", + }, + { + "IBM Code Page 863", + "IBM863", + "", + "CodePage863", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm", + }, + { + "IBM Code Page 865", + "IBM865", + "", + "CodePage865", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm", + }, + { + "IBM Code Page 866", + "IBM866", + "", + "CodePage866", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-ibm866.txt", + }, + { + "IBM Code Page 1047", + "IBM1047", + "", + "CodePage1047", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm", + }, + { + "IBM Code Page 1140", + "IBM01140", + "", + "CodePage1140", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm", + }, + { + "ISO 8859-1", + "ISOLatin1", + "", + "ISO8859_1", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm", + }, + { + "ISO 8859-2", + "ISOLatin2", + "", + "ISO8859_2", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-2.txt", + }, + { + "ISO 8859-3", + "ISOLatin3", + "", + "ISO8859_3", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-3.txt", + }, + { + "ISO 8859-4", + "ISOLatin4", + "", + "ISO8859_4", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-4.txt", + }, + { + "ISO 8859-5", + "ISOLatinCyrillic", + "", + "ISO8859_5", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-5.txt", + }, + { + "ISO 8859-6", + "ISOLatinArabic", + "", + "ISO8859_6,ISO8859_6E,ISO8859_6I", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-6.txt", + }, + { + "ISO 8859-7", + "ISOLatinGreek", + "", + "ISO8859_7", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-7.txt", + }, + { + "ISO 8859-8", + "ISOLatinHebrew", + "", + "ISO8859_8,ISO8859_8E,ISO8859_8I", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-8.txt", + }, + { + "ISO 8859-9", + "ISOLatin5", + "", + "ISO8859_9", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm", + }, + { + "ISO 8859-10", + "ISOLatin6", + "", + "ISO8859_10", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-10.txt", + }, + { + "ISO 8859-13", + "ISO885913", + "", + "ISO8859_13", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-13.txt", + }, + { + "ISO 8859-14", + "ISO885914", + "", + "ISO8859_14", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-14.txt", + }, + { + "ISO 8859-15", + "ISO885915", + "", + "ISO8859_15", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-15.txt", + }, + { + "ISO 8859-16", + "ISO885916", + "", + "ISO8859_16", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-16.txt", + }, + { + "KOI8-R", + "KOI8R", + "", + "KOI8R", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-koi8-r.txt", + }, + { + "KOI8-U", + "KOI8U", + "", + "KOI8U", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-koi8-u.txt", + }, + { + "Macintosh", + "Macintosh", + "", + "Macintosh", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-macintosh.txt", + }, + { + "Macintosh Cyrillic", + "MacintoshCyrillic", + "", + "MacintoshCyrillic", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt", + }, + { + "Windows 874", + "Windows874", + "", + "Windows874", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-874.txt", + }, + { + "Windows 1250", + "Windows1250", + "", + "Windows1250", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1250.txt", + }, + { + "Windows 1251", + "Windows1251", + "", + "Windows1251", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1251.txt", + }, + { + "Windows 1252", + "Windows1252", + "", + "Windows1252", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1252.txt", + }, + { + "Windows 1253", + "Windows1253", + "", + "Windows1253", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1253.txt", + }, + { + "Windows 1254", + "Windows1254", + "", + "Windows1254", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1254.txt", + }, + { + "Windows 1255", + "Windows1255", + "", + "Windows1255", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1255.txt", + }, + { + "Windows 1256", + "Windows1256", + "", + "Windows1256", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1256.txt", + }, + { + "Windows 1257", + "Windows1257", + "", + "Windows1257", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1257.txt", + }, + { + "Windows 1258", + "Windows1258", + "", + "Windows1258", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1258.txt", + }, + { + "X-User-Defined", + "XUserDefined", + "It is defined at http://encoding.spec.whatwg.org/#x-user-defined", + "XUserDefined", + encoding.ASCIISub, + ascii + + "\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" + + "\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" + + "\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" + + "\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" + + "\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" + + "\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" + + "\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" + + "\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" + + "\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" + + "\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" + + "\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" + + "\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" + + "\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" + + "\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" + + "\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" + + "\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff", + }, +} + +func getWHATWG(url string) string { + res, err := http.Get(url) + if err != nil { + log.Fatalf("%q: Get: %v", url, err) + } + defer res.Body.Close() + + mapping := make([]rune, 128) + for i := range mapping { + mapping[i] = '\ufffd' + } + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := 0, 0 + if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 128 <= x { + log.Fatalf("code %d is out of range", x) + } + if 0x80 <= y && y < 0xa0 { + // We diverge from the WHATWG spec by mapping control characters + // in the range [0x80, 0xa0) to U+FFFD. + continue + } + mapping[x] = rune(y) + } + return ascii + string(mapping) +} + +func getUCM(url string) string { + res, err := http.Get(url) + if err != nil { + log.Fatalf("%q: Get: %v", url, err) + } + defer res.Body.Close() + + mapping := make([]rune, 256) + for i := range mapping { + mapping[i] = '\ufffd' + } + + charsFound := 0 + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + var c byte + var r rune + if _, err := fmt.Sscanf(s, ` \x%x |0`, &r, &c); err != nil { + continue + } + mapping[c] = r + charsFound++ + } + + if charsFound < 200 { + log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound) + } + + return string(mapping) +} + +func main() { + mibs := map[string]bool{} + all := []string{} + + w := gen.NewCodeWriter() + defer w.WriteGoFile("tables.go", "charmap") + + printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) } + + printf("import (\n") + printf("\t\"golang.org/x/text/encoding\"\n") + printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n") + printf(")\n\n") + for _, e := range encodings { + varNames := strings.Split(e.varName, ",") + all = append(all, varNames...) + varName := varNames[0] + switch { + case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"): + e.mapping = getWHATWG(e.mapping) + case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"): + e.mapping = getUCM(e.mapping) + } + + asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00 + if asciiSuperset { + low = 0x80 + } + lvn := 1 + if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") { + lvn = 3 + } + lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:] + printf("// %s is the %s encoding.\n", varName, e.name) + if e.comment != "" { + printf("//\n// %s\n", e.comment) + } + printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n", + varName, lowerVarName, lowerVarName, e.name) + if mibs[e.mib] { + log.Fatalf("MIB type %q declared multiple times.", e.mib) + } + printf("mib: identifier.%s,\n", e.mib) + printf("asciiSuperset: %t,\n", asciiSuperset) + printf("low: 0x%02x,\n", low) + printf("replacement: 0x%02x,\n", e.replacement) + + printf("decode: [256]utf8Enc{\n") + i, backMapping := 0, map[rune]byte{} + for _, c := range e.mapping { + if _, ok := backMapping[c]; !ok && c != utf8.RuneError { + backMapping[c] = byte(i) + } + var buf [8]byte + n := utf8.EncodeRune(buf[:], c) + if n > 3 { + panic(fmt.Sprintf("rune %q (%U) is too long", c, c)) + } + printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2]) + if i%2 == 1 { + printf("\n") + } + i++ + } + printf("},\n") + + printf("encode: [256]uint32{\n") + encode := make([]uint32, 0, 256) + for c, i := range backMapping { + encode = append(encode, uint32(i)<<24|uint32(c)) + } + sort.Sort(byRune(encode)) + for len(encode) < cap(encode) { + encode = append(encode, encode[len(encode)-1]) + } + for i, enc := range encode { + printf("0x%08x,", enc) + if i%8 == 7 { + printf("\n") + } + } + printf("},\n}\n") + + // Add an estimate of the size of a single Charmap{} struct value, which + // includes two 256 elem arrays of 4 bytes and some extra fields, which + // align to 3 uint64s on 64-bit architectures. + w.Size += 2*4*256 + 3*8 + } + // TODO: add proper line breaking. + printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n")) +} + +type byRune []uint32 + +func (b byRune) Len() int { return len(b) } +func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff } +func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/htmlindex/gen.go b/vendor/golang.org/x/text/encoding/htmlindex/gen.go new file mode 100644 index 0000000000..ac6b4a77fd --- /dev/null +++ b/vendor/golang.org/x/text/encoding/htmlindex/gen.go @@ -0,0 +1,173 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "strings" + + "golang.org/x/text/internal/gen" +) + +type group struct { + Encodings []struct { + Labels []string + Name string + } +} + +func main() { + gen.Init() + + r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") + var groups []group + if err := json.NewDecoder(r).Decode(&groups); err != nil { + log.Fatalf("Error reading encodings.json: %v", err) + } + + w := &bytes.Buffer{} + fmt.Fprintln(w, "type htmlEncoding byte") + fmt.Fprintln(w, "const (") + for i, g := range groups { + for _, e := range g.Encodings { + key := strings.ToLower(e.Name) + name := consts[key] + if name == "" { + log.Fatalf("No const defined for %s.", key) + } + if i == 0 { + fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) + } else { + fmt.Fprintf(w, "%s\n", name) + } + } + } + fmt.Fprintln(w, "numEncodings") + fmt.Fprint(w, ")\n\n") + + fmt.Fprintln(w, "var canonical = [numEncodings]string{") + for _, g := range groups { + for _, e := range g.Encodings { + fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) + } + } + fmt.Fprint(w, "}\n\n") + + fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") + for _, g := range groups { + for _, e := range g.Encodings { + for _, l := range e.Labels { + key := strings.ToLower(e.Name) + name := consts[key] + fmt.Fprintf(w, "%q: %s,\n", l, name) + } + } + } + fmt.Fprint(w, "}\n\n") + + var tags []string + fmt.Fprintln(w, "var localeMap = []htmlEncoding{") + for _, loc := range locales { + tags = append(tags, loc.tag) + fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) + } + fmt.Fprint(w, "}\n\n") + + fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) + + gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) +} + +// consts maps canonical encoding name to internal constant. +var consts = map[string]string{ + "utf-8": "utf8", + "ibm866": "ibm866", + "iso-8859-2": "iso8859_2", + "iso-8859-3": "iso8859_3", + "iso-8859-4": "iso8859_4", + "iso-8859-5": "iso8859_5", + "iso-8859-6": "iso8859_6", + "iso-8859-7": "iso8859_7", + "iso-8859-8": "iso8859_8", + "iso-8859-8-i": "iso8859_8I", + "iso-8859-10": "iso8859_10", + "iso-8859-13": "iso8859_13", + "iso-8859-14": "iso8859_14", + "iso-8859-15": "iso8859_15", + "iso-8859-16": "iso8859_16", + "koi8-r": "koi8r", + "koi8-u": "koi8u", + "macintosh": "macintosh", + "windows-874": "windows874", + "windows-1250": "windows1250", + "windows-1251": "windows1251", + "windows-1252": "windows1252", + "windows-1253": "windows1253", + "windows-1254": "windows1254", + "windows-1255": "windows1255", + "windows-1256": "windows1256", + "windows-1257": "windows1257", + "windows-1258": "windows1258", + "x-mac-cyrillic": "macintoshCyrillic", + "gbk": "gbk", + "gb18030": "gb18030", + // "hz-gb-2312": "hzgb2312", // Was removed from WhatWG + "big5": "big5", + "euc-jp": "eucjp", + "iso-2022-jp": "iso2022jp", + "shift_jis": "shiftJIS", + "euc-kr": "euckr", + "replacement": "replacement", + "utf-16be": "utf16be", + "utf-16le": "utf16le", + "x-user-defined": "xUserDefined", +} + +// locales is taken from +// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm. +var locales = []struct{ tag, name string }{ + // The default value. Explicitly state latin to benefit from the exact + // script option, while still making 1252 the default encoding for languages + // written in Latin script. + {"und_Latn", "windows-1252"}, + {"ar", "windows-1256"}, + {"ba", "windows-1251"}, + {"be", "windows-1251"}, + {"bg", "windows-1251"}, + {"cs", "windows-1250"}, + {"el", "iso-8859-7"}, + {"et", "windows-1257"}, + {"fa", "windows-1256"}, + {"he", "windows-1255"}, + {"hr", "windows-1250"}, + {"hu", "iso-8859-2"}, + {"ja", "shift_jis"}, + {"kk", "windows-1251"}, + {"ko", "euc-kr"}, + {"ku", "windows-1254"}, + {"ky", "windows-1251"}, + {"lt", "windows-1257"}, + {"lv", "windows-1257"}, + {"mk", "windows-1251"}, + {"pl", "iso-8859-2"}, + {"ru", "windows-1251"}, + {"sah", "windows-1251"}, + {"sk", "windows-1250"}, + {"sl", "iso-8859-2"}, + {"sr", "windows-1251"}, + {"tg", "windows-1251"}, + {"th", "windows-874"}, + {"tr", "windows-1254"}, + {"tt", "windows-1251"}, + {"uk", "windows-1251"}, + {"vi", "windows-1258"}, + {"zh-hans", "gb18030"}, + {"zh-hant", "big5"}, +} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go new file mode 100644 index 0000000000..26cfef9c6b --- /dev/null +++ b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go @@ -0,0 +1,142 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "encoding/xml" + "fmt" + "io" + "log" + "strings" + + "golang.org/x/text/internal/gen" +) + +type registry struct { + XMLName xml.Name `xml:"registry"` + Updated string `xml:"updated"` + Registry []struct { + ID string `xml:"id,attr"` + Record []struct { + Name string `xml:"name"` + Xref []struct { + Type string `xml:"type,attr"` + Data string `xml:"data,attr"` + } `xml:"xref"` + Desc struct { + Data string `xml:",innerxml"` + // Any []struct { + // Data string `xml:",chardata"` + // } `xml:",any"` + // Data string `xml:",chardata"` + } `xml:"description,"` + MIB string `xml:"value"` + Alias []string `xml:"alias"` + MIME string `xml:"preferred_alias"` + } `xml:"record"` + } `xml:"registry"` +} + +func main() { + r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") + reg := ®istry{} + if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { + log.Fatalf("Error decoding charset registry: %v", err) + } + if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { + log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) + } + + w := &bytes.Buffer{} + fmt.Fprintf(w, "const (\n") + for _, rec := range reg.Registry[0].Record { + constName := "" + for _, a := range rec.Alias { + if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { + // Some of the constant definitions have comments in them. Strip those. + constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) + } + } + if constName == "" { + switch rec.MIB { + case "2085": + constName = "HZGB2312" // Not listed as alias for some reason. + default: + log.Fatalf("No cs alias defined for %s.", rec.MIB) + } + } + if rec.MIME != "" { + rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) + } + fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) + if len(rec.Desc.Data) > 0 { + fmt.Fprint(w, "// ") + d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) + inElem := true + attr := "" + for { + t, err := d.Token() + if err != nil { + if err != io.EOF { + log.Fatal(err) + } + break + } + switch x := t.(type) { + case xml.CharData: + attr = "" // Don't need attribute info. + a := bytes.Split([]byte(x), []byte("\n")) + for i, b := range a { + if b = bytes.TrimSpace(b); len(b) != 0 { + if !inElem && i > 0 { + fmt.Fprint(w, "\n// ") + } + inElem = false + fmt.Fprintf(w, "%s ", string(b)) + } + } + case xml.StartElement: + if x.Name.Local == "xref" { + inElem = true + use := false + for _, a := range x.Attr { + if a.Name.Local == "type" { + use = use || a.Value != "person" + } + if a.Name.Local == "data" && use { + // Patch up URLs to use https. From some links, the + // https version is different from the http one. + s := a.Value + s = strings.Replace(s, "http://", "https://", -1) + s = strings.Replace(s, "/unicode/", "/", -1) + attr = s + " " + } + } + } + case xml.EndElement: + inElem = false + fmt.Fprint(w, attr) + } + } + fmt.Fprint(w, "\n") + } + for _, x := range rec.Xref { + switch x.Type { + case "rfc": + fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) + case "uri": + fmt.Fprintf(w, "// Reference: %s\n", x.Data) + } + } + fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) + fmt.Fprintln(w) + } + fmt.Fprintln(w, ")") + + gen.WriteGoFile("mib.go", "identifier", w.Bytes()) +} diff --git a/vendor/golang.org/x/text/encoding/japanese/maketables.go b/vendor/golang.org/x/text/encoding/japanese/maketables.go new file mode 100644 index 0000000000..023957a672 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/japanese/maketables.go @@ -0,0 +1,161 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +// TODO: Emoji extensions? +// https://www.unicode.org/faq/emoji_dingbats.html +// https://www.unicode.org/Public/UNIDATA/EmojiSources.txt + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +type entry struct { + jisCode, table int +} + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n") + fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n") + + reverse := [65536]entry{} + for i := range reverse { + reverse[i].table = -1 + } + + tables := []struct { + url string + name string + }{ + {"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"}, + {"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"}, + } + for i, table := range tables { + res, err := http.Get(table.url) + if err != nil { + log.Fatalf("%q: Get: %v", table.url, err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := 0, uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("%q: could not parse %q", table.url, s) + } + if x < 0 || 120*94 <= x { + log.Fatalf("%q: JIS code %d is out of range", table.url, x) + } + mapping[x] = y + if reverse[y].table == -1 { + reverse[y] = entry{jisCode: x, table: i} + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("%q: scanner error: %v", table.url, err) + } + + fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n", + table.name, table.name, table.url) + fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name) + for i, m := range mapping { + if m != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, m) + } + } + fmt.Printf("}\n\n") + } + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v.table == -1 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const (\n") + fmt.Printf("\tjis0208 = 1\n") + fmt.Printf("\tjis0212 = 2\n") + fmt.Printf("\tcodeMask = 0x7f\n") + fmt.Printf("\tcodeShift = 7\n") + fmt.Printf("\ttableShift = 14\n") + fmt.Printf(")\n\n") + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("//\n") + fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n") + fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n") + fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n") + fmt.Printf("// JIS code (94*j1 + j2) within that table.\n") + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x.table == -1 { + continue + } + fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n", + j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/korean/maketables.go b/vendor/golang.org/x/text/encoding/korean/maketables.go new file mode 100644 index 0000000000..c84034fb67 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/korean/maketables.go @@ -0,0 +1,143 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") + fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") + + res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + reverse := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { + log.Fatalf("EUC-KR code %d is out of range", x) + } + mapping[x] = y + if reverse[y] == 0 { + c0, c1 := uint16(0), uint16(0) + if x < 178*(0xc7-0x81) { + c0 = uint16(x/178) + 0x81 + c1 = uint16(x % 178) + switch { + case c1 < 1*26: + c1 += 0x41 + case c1 < 2*26: + c1 += 0x47 + default: + c1 += 0x4d + } + } else { + x -= 178 * (0xc7 - 0x81) + c0 = uint16(x/94) + 0xc7 + c1 = uint16(x%94) + 0xa1 + } + reverse[y] = c0<<8 | c1 + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") + fmt.Printf("var decode = [...]uint16{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go new file mode 100644 index 0000000000..55016c7862 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go @@ -0,0 +1,161 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") + fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") + + printGB18030() + printGBK() +} + +func printGB18030() { + res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") + fmt.Printf("var gb18030 = [...][2]uint16{\n") + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint32(0), uint32(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0x10000 && y < 0x10000 { + fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) + } + } + fmt.Printf("}\n\n") +} + +func printGBK() { + res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + reverse := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 126*190 <= x { + log.Fatalf("GBK code %d is out of range", x) + } + mapping[x] = y + if reverse[y] == 0 { + c0, c1 := x/190, x%190 + if c1 >= 0x3f { + c1++ + } + reverse[y] = (0x81+c0)<<8 | (0x40 + c1) + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") + fmt.Printf("var decode = [...]uint16{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go new file mode 100644 index 0000000000..cf7fdb31a5 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go @@ -0,0 +1,140 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") + fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") + + res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint32{} + reverse := [65536 * 4]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint32(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 126*157 <= x { + log.Fatalf("Big5 code %d is out of range", x) + } + mapping[x] = y + + // The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that + // "The index pointer for code point in index is the first pointer + // corresponding to code point in index", which would normally mean + // that the code below should be guarded by "if reverse[y] == 0", but + // last instead of first seems to match the behavior of + // "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in + // http://encoding.spec.whatwg.org/index-big5.txt, as index 2148 + // (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc") + // and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc". + c0, c1 := x/157, x%157 + if c1 < 0x3f { + c1 += 0x40 + } else { + c1 += 0x62 + } + reverse[y] = (0x81+c0)<<8 | c1 + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") + fmt.Printf("var decode = [...]uint32{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%08X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/internal/language/compact/gen.go b/vendor/golang.org/x/text/internal/language/compact/gen.go new file mode 100644 index 0000000000..0c36a052f6 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen.go @@ -0,0 +1,64 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Language tag table generator. +// Data read from the web. + +package main + +import ( + "flag" + "fmt" + "log" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/unicode/cldr" +) + +var ( + test = flag.Bool("test", + false, + "test existing tables; can be used to compare web data with package data.") + outputFile = flag.String("output", + "tables.go", + "output file for generated tables") +) + +func main() { + gen.Init() + + w := gen.NewCodeWriter() + defer w.WriteGoFile("tables.go", "compact") + + fmt.Fprintln(w, `import "golang.org/x/text/internal/language"`) + + b := newBuilder(w) + gen.WriteCLDRVersion(w) + + b.writeCompactIndex() +} + +type builder struct { + w *gen.CodeWriter + data *cldr.CLDR + supp *cldr.SupplementalData +} + +func newBuilder(w *gen.CodeWriter) *builder { + r := gen.OpenCLDRCoreZip() + defer r.Close() + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + if err != nil { + log.Fatal(err) + } + b := builder{ + w: w, + data: data, + supp: data.Supplemental(), + } + return &b +} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_index.go b/vendor/golang.org/x/text/internal/language/compact/gen_index.go new file mode 100644 index 0000000000..136cefaf08 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen_index.go @@ -0,0 +1,113 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This file generates derivative tables based on the language package itself. + +import ( + "fmt" + "log" + "sort" + "strings" + + "golang.org/x/text/internal/language" +) + +// Compact indices: +// Note -va-X variants only apply to localization variants. +// BCP variants only ever apply to language. +// The only ambiguity between tags is with regions. + +func (b *builder) writeCompactIndex() { + // Collect all language tags for which we have any data in CLDR. + m := map[language.Tag]bool{} + for _, lang := range b.data.Locales() { + // We include all locales unconditionally to be consistent with en_US. + // We want en_US, even though it has no data associated with it. + + // TODO: put any of the languages for which no data exists at the end + // of the index. This allows all components based on ICU to use that + // as the cutoff point. + // if x := data.RawLDML(lang); false || + // x.LocaleDisplayNames != nil || + // x.Characters != nil || + // x.Delimiters != nil || + // x.Measurement != nil || + // x.Dates != nil || + // x.Numbers != nil || + // x.Units != nil || + // x.ListPatterns != nil || + // x.Collations != nil || + // x.Segmentations != nil || + // x.Rbnf != nil || + // x.Annotations != nil || + // x.Metadata != nil { + + // TODO: support POSIX natively, albeit non-standard. + tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1)) + m[tag] = true + // } + } + + // TODO: plural rules are also defined for the deprecated tags: + // iw mo sh tl + // Consider removing these as compact tags. + + // Include locales for plural rules, which uses a different structure. + for _, plurals := range b.supp.Plurals { + for _, rules := range plurals.PluralRules { + for _, lang := range strings.Split(rules.Locales, " ") { + m[language.Make(lang)] = true + } + } + } + + var coreTags []language.CompactCoreInfo + var special []string + + for t := range m { + if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { + log.Fatalf("Unexpected extension %v in %v", x, t) + } + if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { + cci, ok := language.GetCompactCore(t) + if !ok { + log.Fatalf("Locale for non-basic language %q", t) + } + coreTags = append(coreTags, cci) + } else { + special = append(special, t.String()) + } + } + + w := b.w + + sort.Slice(coreTags, func(i, j int) bool { return coreTags[i] < coreTags[j] }) + sort.Strings(special) + + w.WriteComment(` + NumCompactTags is the number of common tags. The maximum tag is + NumCompactTags-1.`) + w.WriteConst("NumCompactTags", len(m)) + + fmt.Fprintln(w, "const (") + for i, t := range coreTags { + fmt.Fprintf(w, "%s ID = %d\n", ident(t.Tag().String()), i) + } + for i, t := range special { + fmt.Fprintf(w, "%s ID = %d\n", ident(t), i+len(coreTags)) + } + fmt.Fprintln(w, ")") + + w.WriteVar("coreTags", coreTags) + + w.WriteConst("specialTagsStr", strings.Join(special, " ")) +} + +func ident(s string) string { + return strings.Replace(s, "-", "", -1) + "Index" +} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go new file mode 100644 index 0000000000..9543d58323 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go @@ -0,0 +1,54 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "log" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/language" + "golang.org/x/text/internal/language/compact" + "golang.org/x/text/unicode/cldr" +) + +func main() { + r := gen.OpenCLDRCoreZip() + defer r.Close() + + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + if err != nil { + log.Fatalf("DecodeZip: %v", err) + } + + w := gen.NewCodeWriter() + defer w.WriteGoFile("parents.go", "compact") + + // Create parents table. + type ID uint16 + parents := make([]ID, compact.NumCompactTags) + for _, loc := range data.Locales() { + tag := language.MustParse(loc) + index, ok := compact.FromTag(tag) + if !ok { + continue + } + parentIndex := compact.ID(0) // und + for p := tag.Parent(); p != language.Und; p = p.Parent() { + if x, ok := compact.FromTag(p); ok { + parentIndex = x + break + } + } + parents[index] = ID(parentIndex) + } + + w.WriteComment(` + parents maps a compact index of a tag to the compact index of the parent of + this tag.`) + w.WriteVar("parents", parents) +} diff --git a/vendor/golang.org/x/text/internal/language/gen.go b/vendor/golang.org/x/text/internal/language/gen.go new file mode 100644 index 0000000000..cdcc7febcb --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/gen.go @@ -0,0 +1,1520 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Language tag table generator. +// Data read from the web. + +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/tag" + "golang.org/x/text/unicode/cldr" +) + +var ( + test = flag.Bool("test", + false, + "test existing tables; can be used to compare web data with package data.") + outputFile = flag.String("output", + "tables.go", + "output file for generated tables") +) + +var comment = []string{ + ` +lang holds an alphabetically sorted list of ISO-639 language identifiers. +All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag. +For 2-byte language identifiers, the two successive bytes have the following meaning: + - if the first letter of the 2- and 3-letter ISO codes are the same: + the second and third letter of the 3-letter ISO code. + - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3. +For 3-byte language identifiers the 4th byte is 0.`, + ` +langNoIndex is a bit vector of all 3-letter language codes that are not used as an index +in lookup tables. The language ids for these language codes are derived directly +from the letters and are not consecutive.`, + ` +altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives +to 2-letter language codes that cannot be derived using the method described above. +Each 3-letter code is followed by its 1-byte langID.`, + ` +altLangIndex is used to convert indexes in altLangISO3 to langIDs.`, + ` +AliasMap maps langIDs to their suggested replacements.`, + ` +script is an alphabetically sorted list of ISO 15924 codes. The index +of the script in the string, divided by 4, is the internal scriptID.`, + ` +isoRegionOffset needs to be added to the index of regionISO to obtain the regionID +for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for +the UN.M49 codes used for groups.)`, + ` +regionISO holds a list of alphabetically sorted 2-letter ISO region codes. +Each 2-letter codes is followed by two bytes with the following meaning: + - [A-Z}{2}: the first letter of the 2-letter code plus these two + letters form the 3-letter ISO code. + - 0, n: index into altRegionISO3.`, + ` +regionTypes defines the status of a region for various standards.`, + ` +m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are +codes indicating collections of regions.`, + ` +m49Index gives indexes into fromM49 based on the three most significant bits +of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in + fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]] +for an entry where the first 7 bits match the 7 lsb of the UN.M49 code. +The region code is stored in the 9 lsb of the indexed value.`, + ` +fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.`, + ` +altRegionISO3 holds a list of 3-letter region codes that cannot be +mapped to 2-letter codes using the default algorithm. This is a short list.`, + ` +altRegionIDs holds a list of regionIDs the positions of which match those +of the 3-letter ISO codes in altRegionISO3.`, + ` +variantNumSpecialized is the number of specialized variants in variants.`, + ` +suppressScript is an index from langID to the dominant script for that language, +if it exists. If a script is given, it should be suppressed from the language tag.`, + ` +likelyLang is a lookup table, indexed by langID, for the most likely +scripts and regions given incomplete information. If more entries exist for a +given language, region and script are the index and size respectively +of the list in likelyLangList.`, + ` +likelyLangList holds lists info associated with likelyLang.`, + ` +likelyRegion is a lookup table, indexed by regionID, for the most likely +languages and scripts given incomplete information. If more entries exist +for a given regionID, lang and script are the index and size respectively +of the list in likelyRegionList. +TODO: exclude containers and user-definable regions from the list.`, + ` +likelyRegionList holds lists info associated with likelyRegion.`, + ` +likelyScript is a lookup table, indexed by scriptID, for the most likely +languages and regions given a script.`, + ` +nRegionGroups is the number of region groups.`, + ` +regionInclusion maps region identifiers to sets of regions in regionInclusionBits, +where each set holds all groupings that are directly connected in a region +containment graph.`, + ` +regionInclusionBits is an array of bit vectors where every vector represents +a set of region groupings. These sets are used to compute the distance +between two regions for the purpose of language matching.`, + ` +regionInclusionNext marks, for each entry in regionInclusionBits, the set of +all groups that are reachable from the groups set in the respective entry.`, +} + +// TODO: consider changing some of these structures to tries. This can reduce +// memory, but may increase the need for memory allocations. This could be +// mitigated if we can piggyback on language tags for common cases. + +func failOnError(e error) { + if e != nil { + log.Panic(e) + } +} + +type setType int + +const ( + Indexed setType = 1 + iota // all elements must be of same size + Linear +) + +type stringSet struct { + s []string + sorted, frozen bool + + // We often need to update values after the creation of an index is completed. + // We include a convenience map for keeping track of this. + update map[string]string + typ setType // used for checking. +} + +func (ss *stringSet) clone() stringSet { + c := *ss + c.s = append([]string(nil), c.s...) + return c +} + +func (ss *stringSet) setType(t setType) { + if ss.typ != t && ss.typ != 0 { + log.Panicf("type %d cannot be assigned as it was already %d", t, ss.typ) + } +} + +// parse parses a whitespace-separated string and initializes ss with its +// components. +func (ss *stringSet) parse(s string) { + scan := bufio.NewScanner(strings.NewReader(s)) + scan.Split(bufio.ScanWords) + for scan.Scan() { + ss.add(scan.Text()) + } +} + +func (ss *stringSet) assertChangeable() { + if ss.frozen { + log.Panic("attempt to modify a frozen stringSet") + } +} + +func (ss *stringSet) add(s string) { + ss.assertChangeable() + ss.s = append(ss.s, s) + ss.sorted = ss.frozen +} + +func (ss *stringSet) freeze() { + ss.compact() + ss.frozen = true +} + +func (ss *stringSet) compact() { + if ss.sorted { + return + } + a := ss.s + sort.Strings(a) + k := 0 + for i := 1; i < len(a); i++ { + if a[k] != a[i] { + a[k+1] = a[i] + k++ + } + } + ss.s = a[:k+1] + ss.sorted = ss.frozen +} + +type funcSorter struct { + fn func(a, b string) bool + sort.StringSlice +} + +func (s funcSorter) Less(i, j int) bool { + return s.fn(s.StringSlice[i], s.StringSlice[j]) +} + +func (ss *stringSet) sortFunc(f func(a, b string) bool) { + ss.compact() + sort.Sort(funcSorter{f, sort.StringSlice(ss.s)}) +} + +func (ss *stringSet) remove(s string) { + ss.assertChangeable() + if i, ok := ss.find(s); ok { + copy(ss.s[i:], ss.s[i+1:]) + ss.s = ss.s[:len(ss.s)-1] + } +} + +func (ss *stringSet) replace(ol, nu string) { + ss.s[ss.index(ol)] = nu + ss.sorted = ss.frozen +} + +func (ss *stringSet) index(s string) int { + ss.setType(Indexed) + i, ok := ss.find(s) + if !ok { + if i < len(ss.s) { + log.Panicf("find: item %q is not in list. Closest match is %q.", s, ss.s[i]) + } + log.Panicf("find: item %q is not in list", s) + + } + return i +} + +func (ss *stringSet) find(s string) (int, bool) { + ss.compact() + i := sort.SearchStrings(ss.s, s) + return i, i != len(ss.s) && ss.s[i] == s +} + +func (ss *stringSet) slice() []string { + ss.compact() + return ss.s +} + +func (ss *stringSet) updateLater(v, key string) { + if ss.update == nil { + ss.update = map[string]string{} + } + ss.update[v] = key +} + +// join joins the string and ensures that all entries are of the same length. +func (ss *stringSet) join() string { + ss.setType(Indexed) + n := len(ss.s[0]) + for _, s := range ss.s { + if len(s) != n { + log.Panicf("join: not all entries are of the same length: %q", s) + } + } + ss.s = append(ss.s, strings.Repeat("\xff", n)) + return strings.Join(ss.s, "") +} + +// ianaEntry holds information for an entry in the IANA Language Subtag Repository. +// All types use the same entry. +// See http://tools.ietf.org/html/bcp47#section-5.1 for a description of the various +// fields. +type ianaEntry struct { + typ string + description []string + scope string + added string + preferred string + deprecated string + suppressScript string + macro string + prefix []string +} + +type builder struct { + w *gen.CodeWriter + hw io.Writer // MultiWriter for w and w.Hash + data *cldr.CLDR + supp *cldr.SupplementalData + + // indices + locale stringSet // common locales + lang stringSet // canonical language ids (2 or 3 letter ISO codes) with data + langNoIndex stringSet // 3-letter ISO codes with no associated data + script stringSet // 4-letter ISO codes + region stringSet // 2-letter ISO or 3-digit UN M49 codes + variant stringSet // 4-8-alphanumeric variant code. + + // Region codes that are groups with their corresponding group IDs. + groups map[int]index + + // langInfo + registry map[string]*ianaEntry +} + +type index uint + +func newBuilder(w *gen.CodeWriter) *builder { + r := gen.OpenCLDRCoreZip() + defer r.Close() + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + failOnError(err) + b := builder{ + w: w, + hw: io.MultiWriter(w, w.Hash), + data: data, + supp: data.Supplemental(), + } + b.parseRegistry() + return &b +} + +func (b *builder) parseRegistry() { + r := gen.OpenIANAFile("assignments/language-subtag-registry") + defer r.Close() + b.registry = make(map[string]*ianaEntry) + + scan := bufio.NewScanner(r) + scan.Split(bufio.ScanWords) + var record *ianaEntry + for more := scan.Scan(); more; { + key := scan.Text() + more = scan.Scan() + value := scan.Text() + switch key { + case "Type:": + record = &ianaEntry{typ: value} + case "Subtag:", "Tag:": + if s := strings.SplitN(value, "..", 2); len(s) > 1 { + for a := s[0]; a <= s[1]; a = inc(a) { + b.addToRegistry(a, record) + } + } else { + b.addToRegistry(value, record) + } + case "Suppress-Script:": + record.suppressScript = value + case "Added:": + record.added = value + case "Deprecated:": + record.deprecated = value + case "Macrolanguage:": + record.macro = value + case "Preferred-Value:": + record.preferred = value + case "Prefix:": + record.prefix = append(record.prefix, value) + case "Scope:": + record.scope = value + case "Description:": + buf := []byte(value) + for more = scan.Scan(); more; more = scan.Scan() { + b := scan.Bytes() + if b[0] == '%' || b[len(b)-1] == ':' { + break + } + buf = append(buf, ' ') + buf = append(buf, b...) + } + record.description = append(record.description, string(buf)) + continue + default: + continue + } + more = scan.Scan() + } + if scan.Err() != nil { + log.Panic(scan.Err()) + } +} + +func (b *builder) addToRegistry(key string, entry *ianaEntry) { + if info, ok := b.registry[key]; ok { + if info.typ != "language" || entry.typ != "extlang" { + log.Fatalf("parseRegistry: tag %q already exists", key) + } + } else { + b.registry[key] = entry + } +} + +var commentIndex = make(map[string]string) + +func init() { + for _, s := range comment { + key := strings.TrimSpace(strings.SplitN(s, " ", 2)[0]) + commentIndex[key] = s + } +} + +func (b *builder) comment(name string) { + if s := commentIndex[name]; len(s) > 0 { + b.w.WriteComment(s) + } else { + fmt.Fprintln(b.w) + } +} + +func (b *builder) pf(f string, x ...interface{}) { + fmt.Fprintf(b.hw, f, x...) + fmt.Fprint(b.hw, "\n") +} + +func (b *builder) p(x ...interface{}) { + fmt.Fprintln(b.hw, x...) +} + +func (b *builder) addSize(s int) { + b.w.Size += s + b.pf("// Size: %d bytes", s) +} + +func (b *builder) writeConst(name string, x interface{}) { + b.comment(name) + b.w.WriteConst(name, x) +} + +// writeConsts computes f(v) for all v in values and writes the results +// as constants named _v to a single constant block. +func (b *builder) writeConsts(f func(string) int, values ...string) { + b.pf("const (") + for _, v := range values { + b.pf("\t_%s = %v", v, f(v)) + } + b.pf(")") +} + +// writeType writes the type of the given value, which must be a struct. +func (b *builder) writeType(value interface{}) { + b.comment(reflect.TypeOf(value).Name()) + b.w.WriteType(value) +} + +func (b *builder) writeSlice(name string, ss interface{}) { + b.writeSliceAddSize(name, 0, ss) +} + +func (b *builder) writeSliceAddSize(name string, extraSize int, ss interface{}) { + b.comment(name) + b.w.Size += extraSize + v := reflect.ValueOf(ss) + t := v.Type().Elem() + b.pf("// Size: %d bytes, %d elements", v.Len()*int(t.Size())+extraSize, v.Len()) + + fmt.Fprintf(b.w, "var %s = ", name) + b.w.WriteArray(ss) + b.p() +} + +type FromTo struct { + From, To uint16 +} + +func (b *builder) writeSortedMap(name string, ss *stringSet, index func(s string) uint16) { + ss.sortFunc(func(a, b string) bool { + return index(a) < index(b) + }) + m := []FromTo{} + for _, s := range ss.s { + m = append(m, FromTo{index(s), index(ss.update[s])}) + } + b.writeSlice(name, m) +} + +const base = 'z' - 'a' + 1 + +func strToInt(s string) uint { + v := uint(0) + for i := 0; i < len(s); i++ { + v *= base + v += uint(s[i] - 'a') + } + return v +} + +// converts the given integer to the original ASCII string passed to strToInt. +// len(s) must match the number of characters obtained. +func intToStr(v uint, s []byte) { + for i := len(s) - 1; i >= 0; i-- { + s[i] = byte(v%base) + 'a' + v /= base + } +} + +func (b *builder) writeBitVector(name string, ss []string) { + vec := make([]uint8, int(math.Ceil(math.Pow(base, float64(len(ss[0])))/8))) + for _, s := range ss { + v := strToInt(s) + vec[v/8] |= 1 << (v % 8) + } + b.writeSlice(name, vec) +} + +// TODO: convert this type into a list or two-stage trie. +func (b *builder) writeMapFunc(name string, m map[string]string, f func(string) uint16) { + b.comment(name) + v := reflect.ValueOf(m) + sz := v.Len() * (2 + int(v.Type().Key().Size())) + for _, k := range m { + sz += len(k) + } + b.addSize(sz) + keys := []string{} + b.pf(`var %s = map[string]uint16{`, name) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + b.pf("\t%q: %v,", k, f(m[k])) + } + b.p("}") +} + +func (b *builder) writeMap(name string, m interface{}) { + b.comment(name) + v := reflect.ValueOf(m) + sz := v.Len() * (2 + int(v.Type().Key().Size()) + int(v.Type().Elem().Size())) + b.addSize(sz) + f := strings.FieldsFunc(fmt.Sprintf("%#v", m), func(r rune) bool { + return strings.IndexRune("{}, ", r) != -1 + }) + sort.Strings(f[1:]) + b.pf(`var %s = %s{`, name, f[0]) + for _, kv := range f[1:] { + b.pf("\t%s,", kv) + } + b.p("}") +} + +func (b *builder) langIndex(s string) uint16 { + if s == "und" { + return 0 + } + if i, ok := b.lang.find(s); ok { + return uint16(i) + } + return uint16(strToInt(s)) + uint16(len(b.lang.s)) +} + +// inc advances the string to its lexicographical successor. +func inc(s string) string { + const maxTagLength = 4 + var buf [maxTagLength]byte + intToStr(strToInt(strings.ToLower(s))+1, buf[:len(s)]) + for i := 0; i < len(s); i++ { + if s[i] <= 'Z' { + buf[i] -= 'a' - 'A' + } + } + return string(buf[:len(s)]) +} + +func (b *builder) parseIndices() { + meta := b.supp.Metadata + + for k, v := range b.registry { + var ss *stringSet + switch v.typ { + case "language": + if len(k) == 2 || v.suppressScript != "" || v.scope == "special" { + b.lang.add(k) + continue + } else { + ss = &b.langNoIndex + } + case "region": + ss = &b.region + case "script": + ss = &b.script + case "variant": + ss = &b.variant + default: + continue + } + ss.add(k) + } + // Include any language for which there is data. + for _, lang := range b.data.Locales() { + if x := b.data.RawLDML(lang); false || + x.LocaleDisplayNames != nil || + x.Characters != nil || + x.Delimiters != nil || + x.Measurement != nil || + x.Dates != nil || + x.Numbers != nil || + x.Units != nil || + x.ListPatterns != nil || + x.Collations != nil || + x.Segmentations != nil || + x.Rbnf != nil || + x.Annotations != nil || + x.Metadata != nil { + + from := strings.Split(lang, "_") + if lang := from[0]; lang != "root" { + b.lang.add(lang) + } + } + } + // Include locales for plural rules, which uses a different structure. + for _, plurals := range b.data.Supplemental().Plurals { + for _, rules := range plurals.PluralRules { + for _, lang := range strings.Split(rules.Locales, " ") { + if lang = strings.Split(lang, "_")[0]; lang != "root" { + b.lang.add(lang) + } + } + } + } + // Include languages in likely subtags. + for _, m := range b.supp.LikelySubtags.LikelySubtag { + from := strings.Split(m.From, "_") + b.lang.add(from[0]) + } + // Include ISO-639 alpha-3 bibliographic entries. + for _, a := range meta.Alias.LanguageAlias { + if a.Reason == "bibliographic" { + b.langNoIndex.add(a.Type) + } + } + // Include regions in territoryAlias (not all are in the IANA registry!) + for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { + if len(reg.Type) == 2 { + b.region.add(reg.Type) + } + } + + for _, s := range b.lang.s { + if len(s) == 3 { + b.langNoIndex.remove(s) + } + } + b.writeConst("NumLanguages", len(b.lang.slice())+len(b.langNoIndex.slice())) + b.writeConst("NumScripts", len(b.script.slice())) + b.writeConst("NumRegions", len(b.region.slice())) + + // Add dummy codes at the start of each list to represent "unspecified". + b.lang.add("---") + b.script.add("----") + b.region.add("---") + + // common locales + b.locale.parse(meta.DefaultContent.Locales) +} + +// TODO: region inclusion data will probably not be use used in future matchers. + +func (b *builder) computeRegionGroups() { + b.groups = make(map[int]index) + + // Create group indices. + for i := 1; b.region.s[i][0] < 'A'; i++ { // Base M49 indices on regionID. + b.groups[i] = index(len(b.groups)) + } + for _, g := range b.supp.TerritoryContainment.Group { + // Skip UN and EURO zone as they are flattening the containment + // relationship. + if g.Type == "EZ" || g.Type == "UN" { + continue + } + group := b.region.index(g.Type) + if _, ok := b.groups[group]; !ok { + b.groups[group] = index(len(b.groups)) + } + } + if len(b.groups) > 64 { + log.Fatalf("only 64 groups supported, found %d", len(b.groups)) + } + b.writeConst("nRegionGroups", len(b.groups)) +} + +var langConsts = []string{ + "af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", + "et", "fa", "fi", "fil", "fr", "gu", "he", "hi", "hr", "hu", "hy", "id", "is", + "it", "ja", "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", + "mn", "mo", "mr", "ms", "mul", "my", "nb", "ne", "nl", "no", "pa", "pl", "pt", + "ro", "ru", "sh", "si", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", + "tl", "tn", "tr", "uk", "ur", "uz", "vi", "zh", "zu", + + // constants for grandfathered tags (if not already defined) + "jbo", "ami", "bnn", "hak", "tlh", "lb", "nv", "pwn", "tao", "tay", "tsu", + "nn", "sfb", "vgt", "sgg", "cmn", "nan", "hsn", +} + +// writeLanguage generates all tables needed for language canonicalization. +func (b *builder) writeLanguage() { + meta := b.supp.Metadata + + b.writeConst("nonCanonicalUnd", b.lang.index("und")) + b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...) + b.writeConst("langPrivateStart", b.langIndex("qaa")) + b.writeConst("langPrivateEnd", b.langIndex("qtz")) + + // Get language codes that need to be mapped (overlong 3-letter codes, + // deprecated 2-letter codes, legacy and grandfathered tags.) + langAliasMap := stringSet{} + aliasTypeMap := map[string]AliasType{} + + // altLangISO3 get the alternative ISO3 names that need to be mapped. + altLangISO3 := stringSet{} + // Add dummy start to avoid the use of index 0. + altLangISO3.add("---") + altLangISO3.updateLater("---", "aa") + + lang := b.lang.clone() + for _, a := range meta.Alias.LanguageAlias { + if a.Replacement == "" { + a.Replacement = "und" + } + // TODO: support mapping to tags + repl := strings.SplitN(a.Replacement, "_", 2)[0] + if a.Reason == "overlong" { + if len(a.Replacement) == 2 && len(a.Type) == 3 { + lang.updateLater(a.Replacement, a.Type) + } + } else if len(a.Type) <= 3 { + switch a.Reason { + case "macrolanguage": + aliasTypeMap[a.Type] = Macro + case "deprecated": + // handled elsewhere + continue + case "bibliographic", "legacy": + if a.Type == "no" { + continue + } + aliasTypeMap[a.Type] = Legacy + default: + log.Fatalf("new %s alias: %s", a.Reason, a.Type) + } + langAliasMap.add(a.Type) + langAliasMap.updateLater(a.Type, repl) + } + } + // Manually add the mapping of "nb" (Norwegian) to its macro language. + // This can be removed if CLDR adopts this change. + langAliasMap.add("nb") + langAliasMap.updateLater("nb", "no") + aliasTypeMap["nb"] = Macro + + for k, v := range b.registry { + // Also add deprecated values for 3-letter ISO codes, which CLDR omits. + if v.typ == "language" && v.deprecated != "" && v.preferred != "" { + langAliasMap.add(k) + langAliasMap.updateLater(k, v.preferred) + aliasTypeMap[k] = Deprecated + } + } + // Fix CLDR mappings. + lang.updateLater("tl", "tgl") + lang.updateLater("sh", "hbs") + lang.updateLater("mo", "mol") + lang.updateLater("no", "nor") + lang.updateLater("tw", "twi") + lang.updateLater("nb", "nob") + lang.updateLater("ak", "aka") + lang.updateLater("bh", "bih") + + // Ensure that each 2-letter code is matched with a 3-letter code. + for _, v := range lang.s[1:] { + s, ok := lang.update[v] + if !ok { + if s, ok = lang.update[langAliasMap.update[v]]; !ok { + continue + } + lang.update[v] = s + } + if v[0] != s[0] { + altLangISO3.add(s) + altLangISO3.updateLater(s, v) + } + } + + // Complete canonicalized language tags. + lang.freeze() + for i, v := range lang.s { + // We can avoid these manual entries by using the IANA registry directly. + // Seems easier to update the list manually, as changes are rare. + // The panic in this loop will trigger if we miss an entry. + add := "" + if s, ok := lang.update[v]; ok { + if s[0] == v[0] { + add = s[1:] + } else { + add = string([]byte{0, byte(altLangISO3.index(s))}) + } + } else if len(v) == 3 { + add = "\x00" + } else { + log.Panicf("no data for long form of %q", v) + } + lang.s[i] += add + } + b.writeConst("lang", tag.Index(lang.join())) + + b.writeConst("langNoIndexOffset", len(b.lang.s)) + + // space of all valid 3-letter language identifiers. + b.writeBitVector("langNoIndex", b.langNoIndex.slice()) + + altLangIndex := []uint16{} + for i, s := range altLangISO3.slice() { + altLangISO3.s[i] += string([]byte{byte(len(altLangIndex))}) + if i > 0 { + idx := b.lang.index(altLangISO3.update[s]) + altLangIndex = append(altLangIndex, uint16(idx)) + } + } + b.writeConst("altLangISO3", tag.Index(altLangISO3.join())) + b.writeSlice("altLangIndex", altLangIndex) + + b.writeSortedMap("AliasMap", &langAliasMap, b.langIndex) + types := make([]AliasType, len(langAliasMap.s)) + for i, s := range langAliasMap.s { + types[i] = aliasTypeMap[s] + } + b.writeSlice("AliasTypes", types) +} + +var scriptConsts = []string{ + "Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy", + "Zzzz", +} + +func (b *builder) writeScript() { + b.writeConsts(b.script.index, scriptConsts...) + b.writeConst("script", tag.Index(b.script.join())) + + supp := make([]uint8, len(b.lang.slice())) + for i, v := range b.lang.slice()[1:] { + if sc := b.registry[v].suppressScript; sc != "" { + supp[i+1] = uint8(b.script.index(sc)) + } + } + b.writeSlice("suppressScript", supp) + + // There is only one deprecated script in CLDR. This value is hard-coded. + // We check here if the code must be updated. + for _, a := range b.supp.Metadata.Alias.ScriptAlias { + if a.Type != "Qaai" { + log.Panicf("unexpected deprecated stript %q", a.Type) + } + } +} + +func parseM49(s string) int16 { + if len(s) == 0 { + return 0 + } + v, err := strconv.ParseUint(s, 10, 10) + failOnError(err) + return int16(v) +} + +var regionConsts = []string{ + "001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US", + "ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo. +} + +func (b *builder) writeRegion() { + b.writeConsts(b.region.index, regionConsts...) + + isoOffset := b.region.index("AA") + m49map := make([]int16, len(b.region.slice())) + fromM49map := make(map[int16]int) + altRegionISO3 := "" + altRegionIDs := []uint16{} + + b.writeConst("isoRegionOffset", isoOffset) + + // 2-letter region lookup and mapping to numeric codes. + regionISO := b.region.clone() + regionISO.s = regionISO.s[isoOffset:] + regionISO.sorted = false + + regionTypes := make([]byte, len(b.region.s)) + + // Is the region valid BCP 47? + for s, e := range b.registry { + if len(s) == 2 && s == strings.ToUpper(s) { + i := b.region.index(s) + for _, d := range e.description { + if strings.Contains(d, "Private use") { + regionTypes[i] = iso3166UserAssigned + } + } + regionTypes[i] |= bcp47Region + } + } + + // Is the region a valid ccTLD? + r := gen.OpenIANAFile("domains/root/db") + defer r.Close() + + buf, err := ioutil.ReadAll(r) + failOnError(err) + re := regexp.MustCompile(`"/domains/root/db/([a-z]{2}).html"`) + for _, m := range re.FindAllSubmatch(buf, -1) { + i := b.region.index(strings.ToUpper(string(m[1]))) + regionTypes[i] |= ccTLD + } + + b.writeSlice("regionTypes", regionTypes) + + iso3Set := make(map[string]int) + update := func(iso2, iso3 string) { + i := regionISO.index(iso2) + if j, ok := iso3Set[iso3]; !ok && iso3[0] == iso2[0] { + regionISO.s[i] += iso3[1:] + iso3Set[iso3] = -1 + } else { + if ok && j >= 0 { + regionISO.s[i] += string([]byte{0, byte(j)}) + } else { + iso3Set[iso3] = len(altRegionISO3) + regionISO.s[i] += string([]byte{0, byte(len(altRegionISO3))}) + altRegionISO3 += iso3 + altRegionIDs = append(altRegionIDs, uint16(isoOffset+i)) + } + } + } + for _, tc := range b.supp.CodeMappings.TerritoryCodes { + i := regionISO.index(tc.Type) + isoOffset + if d := m49map[i]; d != 0 { + log.Panicf("%s found as a duplicate UN.M49 code of %03d", tc.Numeric, d) + } + m49 := parseM49(tc.Numeric) + m49map[i] = m49 + if r := fromM49map[m49]; r == 0 { + fromM49map[m49] = i + } else if r != i { + dep := b.registry[regionISO.s[r-isoOffset]].deprecated + if t := b.registry[tc.Type]; t != nil && dep != "" && (t.deprecated == "" || t.deprecated > dep) { + fromM49map[m49] = i + } + } + } + for _, ta := range b.supp.Metadata.Alias.TerritoryAlias { + if len(ta.Type) == 3 && ta.Type[0] <= '9' && len(ta.Replacement) == 2 { + from := parseM49(ta.Type) + if r := fromM49map[from]; r == 0 { + fromM49map[from] = regionISO.index(ta.Replacement) + isoOffset + } + } + } + for _, tc := range b.supp.CodeMappings.TerritoryCodes { + if len(tc.Alpha3) == 3 { + update(tc.Type, tc.Alpha3) + } + } + // This entries are not included in territoryCodes. Mostly 3-letter variants + // of deleted codes and an entry for QU. + for _, m := range []struct{ iso2, iso3 string }{ + {"CT", "CTE"}, + {"DY", "DHY"}, + {"HV", "HVO"}, + {"JT", "JTN"}, + {"MI", "MID"}, + {"NH", "NHB"}, + {"NQ", "ATN"}, + {"PC", "PCI"}, + {"PU", "PUS"}, + {"PZ", "PCZ"}, + {"RH", "RHO"}, + {"VD", "VDR"}, + {"WK", "WAK"}, + // These three-letter codes are used for others as well. + {"FQ", "ATF"}, + } { + update(m.iso2, m.iso3) + } + for i, s := range regionISO.s { + if len(s) != 4 { + regionISO.s[i] = s + " " + } + } + b.writeConst("regionISO", tag.Index(regionISO.join())) + b.writeConst("altRegionISO3", altRegionISO3) + b.writeSlice("altRegionIDs", altRegionIDs) + + // Create list of deprecated regions. + // TODO: consider inserting SF -> FI. Not included by CLDR, but is the only + // Transitionally-reserved mapping not included. + regionOldMap := stringSet{} + // Include regions in territoryAlias (not all are in the IANA registry!) + for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { + if len(reg.Type) == 2 && reg.Reason == "deprecated" && len(reg.Replacement) == 2 { + regionOldMap.add(reg.Type) + regionOldMap.updateLater(reg.Type, reg.Replacement) + i, _ := regionISO.find(reg.Type) + j, _ := regionISO.find(reg.Replacement) + if k := m49map[i+isoOffset]; k == 0 { + m49map[i+isoOffset] = m49map[j+isoOffset] + } + } + } + b.writeSortedMap("regionOldMap", ®ionOldMap, func(s string) uint16 { + return uint16(b.region.index(s)) + }) + // 3-digit region lookup, groupings. + for i := 1; i < isoOffset; i++ { + m := parseM49(b.region.s[i]) + m49map[i] = m + fromM49map[m] = i + } + b.writeSlice("m49", m49map) + + const ( + searchBits = 7 + regionBits = 9 + ) + if len(m49map) >= 1< %d", len(m49map), 1<>searchBits] = int16(len(fromM49)) + } + b.writeSlice("m49Index", m49Index) + b.writeSlice("fromM49", fromM49) +} + +const ( + // TODO: put these lists in regionTypes as user data? Could be used for + // various optimizations and refinements and could be exposed in the API. + iso3166Except = "AC CP DG EA EU FX IC SU TA UK" + iso3166Trans = "AN BU CS NT TP YU ZR" // SF is not in our set of Regions. + // DY and RH are actually not deleted, but indeterminately reserved. + iso3166DelCLDR = "CT DD DY FQ HV JT MI NH NQ PC PU PZ RH VD WK YD" +) + +const ( + iso3166UserAssigned = 1 << iota + ccTLD + bcp47Region +) + +func find(list []string, s string) int { + for i, t := range list { + if t == s { + return i + } + } + return -1 +} + +// writeVariants generates per-variant information and creates a map from variant +// name to index value. We assign index values such that sorting multiple +// variants by index value will result in the correct order. +// There are two types of variants: specialized and general. Specialized variants +// are only applicable to certain language or language-script pairs. Generalized +// variants apply to any language. Generalized variants always sort after +// specialized variants. We will therefore always assign a higher index value +// to a generalized variant than any other variant. Generalized variants are +// sorted alphabetically among themselves. +// Specialized variants may also sort after other specialized variants. Such +// variants will be ordered after any of the variants they may follow. +// We assume that if a variant x is followed by a variant y, then for any prefix +// p of x, p-x is a prefix of y. This allows us to order tags based on the +// maximum of the length of any of its prefixes. +// TODO: it is possible to define a set of Prefix values on variants such that +// a total order cannot be defined to the point that this algorithm breaks. +// In other words, we cannot guarantee the same order of variants for the +// future using the same algorithm or for non-compliant combinations of +// variants. For this reason, consider using simple alphabetic sorting +// of variants and ignore Prefix restrictions altogether. +func (b *builder) writeVariant() { + generalized := stringSet{} + specialized := stringSet{} + specializedExtend := stringSet{} + // Collate the variants by type and check assumptions. + for _, v := range b.variant.slice() { + e := b.registry[v] + if len(e.prefix) == 0 { + generalized.add(v) + continue + } + c := strings.Split(e.prefix[0], "-") + hasScriptOrRegion := false + if len(c) > 1 { + _, hasScriptOrRegion = b.script.find(c[1]) + if !hasScriptOrRegion { + _, hasScriptOrRegion = b.region.find(c[1]) + + } + } + if len(c) == 1 || len(c) == 2 && hasScriptOrRegion { + // Variant is preceded by a language. + specialized.add(v) + continue + } + // Variant is preceded by another variant. + specializedExtend.add(v) + prefix := c[0] + "-" + if hasScriptOrRegion { + prefix += c[1] + } + for _, p := range e.prefix { + // Verify that the prefix minus the last element is a prefix of the + // predecessor element. + i := strings.LastIndex(p, "-") + pred := b.registry[p[i+1:]] + if find(pred.prefix, p[:i]) < 0 { + log.Fatalf("prefix %q for variant %q not consistent with predecessor spec", p, v) + } + // The sorting used below does not work in the general case. It works + // if we assume that variants that may be followed by others only have + // prefixes of the same length. Verify this. + count := strings.Count(p[:i], "-") + for _, q := range pred.prefix { + if c := strings.Count(q, "-"); c != count { + log.Fatalf("variant %q preceding %q has a prefix %q of size %d; want %d", p[i+1:], v, q, c, count) + } + } + if !strings.HasPrefix(p, prefix) { + log.Fatalf("prefix %q of variant %q should start with %q", p, v, prefix) + } + } + } + + // Sort extended variants. + a := specializedExtend.s + less := func(v, w string) bool { + // Sort by the maximum number of elements. + maxCount := func(s string) (max int) { + for _, p := range b.registry[s].prefix { + if c := strings.Count(p, "-"); c > max { + max = c + } + } + return + } + if cv, cw := maxCount(v), maxCount(w); cv != cw { + return cv < cw + } + // Sort by name as tie breaker. + return v < w + } + sort.Sort(funcSorter{less, sort.StringSlice(a)}) + specializedExtend.frozen = true + + // Create index from variant name to index. + variantIndex := make(map[string]uint8) + add := func(s []string) { + for _, v := range s { + variantIndex[v] = uint8(len(variantIndex)) + } + } + add(specialized.slice()) + add(specializedExtend.s) + numSpecialized := len(variantIndex) + add(generalized.slice()) + if n := len(variantIndex); n > 255 { + log.Fatalf("maximum number of variants exceeded: was %d; want <= 255", n) + } + b.writeMap("variantIndex", variantIndex) + b.writeConst("variantNumSpecialized", numSpecialized) +} + +func (b *builder) writeLanguageInfo() { +} + +// writeLikelyData writes tables that are used both for finding parent relations and for +// language matching. Each entry contains additional bits to indicate the status of the +// data to know when it cannot be used for parent relations. +func (b *builder) writeLikelyData() { + const ( + isList = 1 << iota + scriptInFrom + regionInFrom + ) + type ( // generated types + likelyScriptRegion struct { + region uint16 + script uint8 + flags uint8 + } + likelyLangScript struct { + lang uint16 + script uint8 + flags uint8 + } + likelyLangRegion struct { + lang uint16 + region uint16 + } + // likelyTag is used for getting likely tags for group regions, where + // the likely region might be a region contained in the group. + likelyTag struct { + lang uint16 + region uint16 + script uint8 + } + ) + var ( // generated variables + likelyRegionGroup = make([]likelyTag, len(b.groups)) + likelyLang = make([]likelyScriptRegion, len(b.lang.s)) + likelyRegion = make([]likelyLangScript, len(b.region.s)) + likelyScript = make([]likelyLangRegion, len(b.script.s)) + likelyLangList = []likelyScriptRegion{} + likelyRegionList = []likelyLangScript{} + ) + type fromTo struct { + from, to []string + } + langToOther := map[int][]fromTo{} + regionToOther := map[int][]fromTo{} + for _, m := range b.supp.LikelySubtags.LikelySubtag { + from := strings.Split(m.From, "_") + to := strings.Split(m.To, "_") + if len(to) != 3 { + log.Fatalf("invalid number of subtags in %q: found %d, want 3", m.To, len(to)) + } + if len(from) > 3 { + log.Fatalf("invalid number of subtags: found %d, want 1-3", len(from)) + } + if from[0] != to[0] && from[0] != "und" { + log.Fatalf("unexpected language change in expansion: %s -> %s", from, to) + } + if len(from) == 3 { + if from[2] != to[2] { + log.Fatalf("unexpected region change in expansion: %s -> %s", from, to) + } + if from[0] != "und" { + log.Fatalf("unexpected fully specified from tag: %s -> %s", from, to) + } + } + if len(from) == 1 || from[0] != "und" { + id := 0 + if from[0] != "und" { + id = b.lang.index(from[0]) + } + langToOther[id] = append(langToOther[id], fromTo{from, to}) + } else if len(from) == 2 && len(from[1]) == 4 { + sid := b.script.index(from[1]) + likelyScript[sid].lang = uint16(b.langIndex(to[0])) + likelyScript[sid].region = uint16(b.region.index(to[2])) + } else { + r := b.region.index(from[len(from)-1]) + if id, ok := b.groups[r]; ok { + if from[0] != "und" { + log.Fatalf("region changed unexpectedly: %s -> %s", from, to) + } + likelyRegionGroup[id].lang = uint16(b.langIndex(to[0])) + likelyRegionGroup[id].script = uint8(b.script.index(to[1])) + likelyRegionGroup[id].region = uint16(b.region.index(to[2])) + } else { + regionToOther[r] = append(regionToOther[r], fromTo{from, to}) + } + } + } + b.writeType(likelyLangRegion{}) + b.writeSlice("likelyScript", likelyScript) + + for id := range b.lang.s { + list := langToOther[id] + if len(list) == 1 { + likelyLang[id].region = uint16(b.region.index(list[0].to[2])) + likelyLang[id].script = uint8(b.script.index(list[0].to[1])) + } else if len(list) > 1 { + likelyLang[id].flags = isList + likelyLang[id].region = uint16(len(likelyLangList)) + likelyLang[id].script = uint8(len(list)) + for _, x := range list { + flags := uint8(0) + if len(x.from) > 1 { + if x.from[1] == x.to[2] { + flags = regionInFrom + } else { + flags = scriptInFrom + } + } + likelyLangList = append(likelyLangList, likelyScriptRegion{ + region: uint16(b.region.index(x.to[2])), + script: uint8(b.script.index(x.to[1])), + flags: flags, + }) + } + } + } + // TODO: merge suppressScript data with this table. + b.writeType(likelyScriptRegion{}) + b.writeSlice("likelyLang", likelyLang) + b.writeSlice("likelyLangList", likelyLangList) + + for id := range b.region.s { + list := regionToOther[id] + if len(list) == 1 { + likelyRegion[id].lang = uint16(b.langIndex(list[0].to[0])) + likelyRegion[id].script = uint8(b.script.index(list[0].to[1])) + if len(list[0].from) > 2 { + likelyRegion[id].flags = scriptInFrom + } + } else if len(list) > 1 { + likelyRegion[id].flags = isList + likelyRegion[id].lang = uint16(len(likelyRegionList)) + likelyRegion[id].script = uint8(len(list)) + for i, x := range list { + if len(x.from) == 2 && i != 0 || i > 0 && len(x.from) != 3 { + log.Fatalf("unspecified script must be first in list: %v at %d", x.from, i) + } + x := likelyLangScript{ + lang: uint16(b.langIndex(x.to[0])), + script: uint8(b.script.index(x.to[1])), + } + if len(list[0].from) > 2 { + x.flags = scriptInFrom + } + likelyRegionList = append(likelyRegionList, x) + } + } + } + b.writeType(likelyLangScript{}) + b.writeSlice("likelyRegion", likelyRegion) + b.writeSlice("likelyRegionList", likelyRegionList) + + b.writeType(likelyTag{}) + b.writeSlice("likelyRegionGroup", likelyRegionGroup) +} + +func (b *builder) writeRegionInclusionData() { + var ( + // mm holds for each group the set of groups with a distance of 1. + mm = make(map[int][]index) + + // containment holds for each group the transitive closure of + // containment of other groups. + containment = make(map[index][]index) + ) + for _, g := range b.supp.TerritoryContainment.Group { + // Skip UN and EURO zone as they are flattening the containment + // relationship. + if g.Type == "EZ" || g.Type == "UN" { + continue + } + group := b.region.index(g.Type) + groupIdx := b.groups[group] + for _, mem := range strings.Split(g.Contains, " ") { + r := b.region.index(mem) + mm[r] = append(mm[r], groupIdx) + if g, ok := b.groups[r]; ok { + mm[group] = append(mm[group], g) + containment[groupIdx] = append(containment[groupIdx], g) + } + } + } + + regionContainment := make([]uint64, len(b.groups)) + for _, g := range b.groups { + l := containment[g] + + // Compute the transitive closure of containment. + for i := 0; i < len(l); i++ { + l = append(l, containment[l[i]]...) + } + + // Compute the bitmask. + regionContainment[g] = 1 << g + for _, v := range l { + regionContainment[g] |= 1 << v + } + } + b.writeSlice("regionContainment", regionContainment) + + regionInclusion := make([]uint8, len(b.region.s)) + bvs := make(map[uint64]index) + // Make the first bitvector positions correspond with the groups. + for r, i := range b.groups { + bv := uint64(1 << i) + for _, g := range mm[r] { + bv |= 1 << g + } + bvs[bv] = i + regionInclusion[r] = uint8(bvs[bv]) + } + for r := 1; r < len(b.region.s); r++ { + if _, ok := b.groups[r]; !ok { + bv := uint64(0) + for _, g := range mm[r] { + bv |= 1 << g + } + if bv == 0 { + // Pick the world for unspecified regions. + bv = 1 << b.groups[b.region.index("001")] + } + if _, ok := bvs[bv]; !ok { + bvs[bv] = index(len(bvs)) + } + regionInclusion[r] = uint8(bvs[bv]) + } + } + b.writeSlice("regionInclusion", regionInclusion) + regionInclusionBits := make([]uint64, len(bvs)) + for k, v := range bvs { + regionInclusionBits[v] = uint64(k) + } + // Add bit vectors for increasingly large distances until a fixed point is reached. + regionInclusionNext := []uint8{} + for i := 0; i < len(regionInclusionBits); i++ { + bits := regionInclusionBits[i] + next := bits + for i := uint(0); i < uint(len(b.groups)); i++ { + if bits&(1< 6 { + log.Fatalf("Too many groups: %d", i) + } + idToIndex[mv.Id] = uint8(i + 1) + // TODO: also handle '-' + for _, r := range strings.Split(mv.Value, "+") { + todo := []string{r} + for k := 0; k < len(todo); k++ { + r := todo[k] + regionToGroups[b.regionIndex(r)] |= 1 << uint8(i) + todo = append(todo, regionHierarchy[r]...) + } + } + } + b.w.WriteVar("regionToGroups", regionToGroups) + + // maps language id to in- and out-of-group region. + paradigmLocales := [][3]uint16{} + locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ") + for i := 0; i < len(locales); i += 2 { + x := [3]uint16{} + for j := 0; j < 2; j++ { + pc := strings.SplitN(locales[i+j], "-", 2) + x[0] = b.langIndex(pc[0]) + if len(pc) == 2 { + x[1+j] = uint16(b.regionIndex(pc[1])) + } + } + paradigmLocales = append(paradigmLocales, x) + } + b.w.WriteVar("paradigmLocales", paradigmLocales) + + b.w.WriteType(mutualIntelligibility{}) + b.w.WriteType(scriptIntelligibility{}) + b.w.WriteType(regionIntelligibility{}) + + matchLang := []mutualIntelligibility{} + matchScript := []scriptIntelligibility{} + matchRegion := []regionIntelligibility{} + // Convert the languageMatch entries in lists keyed by desired language. + for _, m := range lm[0].LanguageMatch { + // Different versions of CLDR use different separators. + desired := strings.Replace(m.Desired, "-", "_", -1) + supported := strings.Replace(m.Supported, "-", "_", -1) + d := strings.Split(desired, "_") + s := strings.Split(supported, "_") + if len(d) != len(s) { + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + continue + } + distance, _ := strconv.ParseInt(m.Distance, 10, 8) + switch len(d) { + case 2: + if desired == supported && desired == "*_*" { + continue + } + // language-script pair. + matchScript = append(matchScript, scriptIntelligibility{ + wantLang: uint16(b.langIndex(d[0])), + haveLang: uint16(b.langIndex(s[0])), + wantScript: uint8(b.scriptIndex(d[1])), + haveScript: uint8(b.scriptIndex(s[1])), + distance: uint8(distance), + }) + if m.Oneway != "true" { + matchScript = append(matchScript, scriptIntelligibility{ + wantLang: uint16(b.langIndex(s[0])), + haveLang: uint16(b.langIndex(d[0])), + wantScript: uint8(b.scriptIndex(s[1])), + haveScript: uint8(b.scriptIndex(d[1])), + distance: uint8(distance), + }) + } + case 1: + if desired == supported && desired == "*" { + continue + } + if distance == 1 { + // nb == no is already handled by macro mapping. Check there + // really is only this case. + if d[0] != "no" || s[0] != "nb" { + log.Fatalf("unhandled equivalence %s == %s", s[0], d[0]) + } + continue + } + // TODO: consider dropping oneway field and just doubling the entry. + matchLang = append(matchLang, mutualIntelligibility{ + want: uint16(b.langIndex(d[0])), + have: uint16(b.langIndex(s[0])), + distance: uint8(distance), + oneway: m.Oneway == "true", + }) + case 3: + if desired == supported && desired == "*_*_*" { + continue + } + if desired != supported { + // This is now supported by CLDR, but only one case, which + // should already be covered by paradigm locales. For instance, + // test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in + // testdata/CLDRLocaleMatcherTest.txt tests this. + if supported != "en_*_GB" { + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + } + continue + } + ri := regionIntelligibility{ + lang: b.langIndex(d[0]), + distance: uint8(distance), + } + if d[1] != "*" { + ri.script = uint8(b.scriptIndex(d[1])) + } + switch { + case d[2] == "*": + ri.group = 0x80 // not contained in anything + case strings.HasPrefix(d[2], "$!"): + ri.group = 0x80 + d[2] = "$" + d[2][len("$!"):] + fallthrough + case strings.HasPrefix(d[2], "$"): + ri.group |= idToIndex[d[2]] + } + matchRegion = append(matchRegion, ri) + default: + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + } + } + sort.SliceStable(matchLang, func(i, j int) bool { + return matchLang[i].distance < matchLang[j].distance + }) + b.w.WriteComment(` + matchLang holds pairs of langIDs of base languages that are typically + mutually intelligible. Each pair is associated with a confidence and + whether the intelligibility goes one or both ways.`) + b.w.WriteVar("matchLang", matchLang) + + b.w.WriteComment(` + matchScript holds pairs of scriptIDs where readers of one script + can typically also read the other. Each is associated with a confidence.`) + sort.SliceStable(matchScript, func(i, j int) bool { + return matchScript[i].distance < matchScript[j].distance + }) + b.w.WriteVar("matchScript", matchScript) + + sort.SliceStable(matchRegion, func(i, j int) bool { + return matchRegion[i].distance < matchRegion[j].distance + }) + b.w.WriteVar("matchRegion", matchRegion) +} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen.go b/vendor/golang.org/x/text/unicode/bidi/gen.go new file mode 100644 index 0000000000..987fc169cc --- /dev/null +++ b/vendor/golang.org/x/text/unicode/bidi/gen.go @@ -0,0 +1,133 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "flag" + "log" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/triegen" + "golang.org/x/text/internal/ucd" +) + +var outputFile = flag.String("out", "tables.go", "output file") + +func main() { + gen.Init() + gen.Repackage("gen_trieval.go", "trieval.go", "bidi") + gen.Repackage("gen_ranges.go", "ranges_test.go", "bidi") + + genTables() +} + +// bidiClass names and codes taken from class "bc" in +// https://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt +var bidiClass = map[string]Class{ + "AL": AL, // ArabicLetter + "AN": AN, // ArabicNumber + "B": B, // ParagraphSeparator + "BN": BN, // BoundaryNeutral + "CS": CS, // CommonSeparator + "EN": EN, // EuropeanNumber + "ES": ES, // EuropeanSeparator + "ET": ET, // EuropeanTerminator + "L": L, // LeftToRight + "NSM": NSM, // NonspacingMark + "ON": ON, // OtherNeutral + "R": R, // RightToLeft + "S": S, // SegmentSeparator + "WS": WS, // WhiteSpace + + "FSI": Control, + "PDF": Control, + "PDI": Control, + "LRE": Control, + "LRI": Control, + "LRO": Control, + "RLE": Control, + "RLI": Control, + "RLO": Control, +} + +func genTables() { + if numClass > 0x0F { + log.Fatalf("Too many Class constants (%#x > 0x0F).", numClass) + } + w := gen.NewCodeWriter() + defer w.WriteVersionedGoFile(*outputFile, "bidi") + + gen.WriteUnicodeVersion(w) + + t := triegen.NewTrie("bidi") + + // Build data about bracket mapping. These bits need to be or-ed with + // any other bits. + orMask := map[rune]uint64{} + + xorMap := map[rune]int{} + xorMasks := []rune{0} // First value is no-op. + + ucd.Parse(gen.OpenUCDFile("BidiBrackets.txt"), func(p *ucd.Parser) { + r1 := p.Rune(0) + r2 := p.Rune(1) + xor := r1 ^ r2 + if _, ok := xorMap[xor]; !ok { + xorMap[xor] = len(xorMasks) + xorMasks = append(xorMasks, xor) + } + entry := uint64(xorMap[xor]) << xorMaskShift + switch p.String(2) { + case "o": + entry |= openMask + case "c", "n": + default: + log.Fatalf("Unknown bracket class %q.", p.String(2)) + } + orMask[r1] = entry + }) + + w.WriteComment(` + xorMasks contains masks to be xor-ed with brackets to get the reverse + version.`) + w.WriteVar("xorMasks", xorMasks) + + done := map[rune]bool{} + + insert := func(r rune, c Class) { + if !done[r] { + t.Insert(r, orMask[r]|uint64(c)) + done[r] = true + } + } + + // Insert the derived BiDi properties. + ucd.Parse(gen.OpenUCDFile("extracted/DerivedBidiClass.txt"), func(p *ucd.Parser) { + r := p.Rune(0) + class, ok := bidiClass[p.String(1)] + if !ok { + log.Fatalf("%U: Unknown BiDi class %q", r, p.String(1)) + } + insert(r, class) + }) + visitDefaults(insert) + + // TODO: use sparse blocks. This would reduce table size considerably + // from the looks of it. + + sz, err := t.Gen(w) + if err != nil { + log.Fatal(err) + } + w.Size += sz +} + +// dummy values to make methods in gen_common compile. The real versions +// will be generated by this file to tables.go. +var ( + xorMasks []rune +) diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go new file mode 100644 index 0000000000..02c3b505d6 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go @@ -0,0 +1,57 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "unicode" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/ucd" + "golang.org/x/text/unicode/rangetable" +) + +// These tables are hand-extracted from: +// https://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedBidiClass.txt +func visitDefaults(fn func(r rune, c Class)) { + // first write default values for ranges listed above. + visitRunes(fn, AL, []rune{ + 0x0600, 0x07BF, // Arabic + 0x08A0, 0x08FF, // Arabic Extended-A + 0xFB50, 0xFDCF, // Arabic Presentation Forms + 0xFDF0, 0xFDFF, + 0xFE70, 0xFEFF, + 0x0001EE00, 0x0001EEFF, // Arabic Mathematical Alpha Symbols + }) + visitRunes(fn, R, []rune{ + 0x0590, 0x05FF, // Hebrew + 0x07C0, 0x089F, // Nko et al. + 0xFB1D, 0xFB4F, + 0x00010800, 0x00010FFF, // Cypriot Syllabary et. al. + 0x0001E800, 0x0001EDFF, + 0x0001EF00, 0x0001EFFF, + }) + visitRunes(fn, ET, []rune{ // European Terminator + 0x20A0, 0x20Cf, // Currency symbols + }) + rangetable.Visit(unicode.Noncharacter_Code_Point, func(r rune) { + fn(r, BN) // Boundary Neutral + }) + ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) { + if p.String(1) == "Default_Ignorable_Code_Point" { + fn(p.Rune(0), BN) // Boundary Neutral + } + }) +} + +func visitRunes(fn func(r rune, c Class), c Class, runes []rune) { + for i := 0; i < len(runes); i += 2 { + lo, hi := runes[i], runes[i+1] + for j := lo; j <= hi; j++ { + fn(j, c) + } + } +} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go new file mode 100644 index 0000000000..9cb9942894 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go @@ -0,0 +1,64 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// Class is the Unicode BiDi class. Each rune has a single class. +type Class uint + +const ( + L Class = iota // LeftToRight + R // RightToLeft + EN // EuropeanNumber + ES // EuropeanSeparator + ET // EuropeanTerminator + AN // ArabicNumber + CS // CommonSeparator + B // ParagraphSeparator + S // SegmentSeparator + WS // WhiteSpace + ON // OtherNeutral + BN // BoundaryNeutral + NSM // NonspacingMark + AL // ArabicLetter + Control // Control LRO - PDI + + numClass + + LRO // LeftToRightOverride + RLO // RightToLeftOverride + LRE // LeftToRightEmbedding + RLE // RightToLeftEmbedding + PDF // PopDirectionalFormat + LRI // LeftToRightIsolate + RLI // RightToLeftIsolate + FSI // FirstStrongIsolate + PDI // PopDirectionalIsolate + + unknownClass = ^Class(0) +) + +var controlToClass = map[rune]Class{ + 0x202D: LRO, // LeftToRightOverride, + 0x202E: RLO, // RightToLeftOverride, + 0x202A: LRE, // LeftToRightEmbedding, + 0x202B: RLE, // RightToLeftEmbedding, + 0x202C: PDF, // PopDirectionalFormat, + 0x2066: LRI, // LeftToRightIsolate, + 0x2067: RLI, // RightToLeftIsolate, + 0x2068: FSI, // FirstStrongIsolate, + 0x2069: PDI, // PopDirectionalIsolate, +} + +// A trie entry has the following bits: +// 7..5 XOR mask for brackets +// 4 1: Bracket open, 0: Bracket close +// 3..0 Class type + +const ( + openMask = 0x10 + xorMaskShift = 5 +) diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go new file mode 100644 index 0000000000..30a3aa9334 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/norm/maketables.go @@ -0,0 +1,986 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Normalization table generator. +// Data read from the web. +// See forminfo.go for a description of the trie values associated with each rune. + +package main + +import ( + "bytes" + "encoding/binary" + "flag" + "fmt" + "io" + "log" + "sort" + "strconv" + "strings" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/triegen" + "golang.org/x/text/internal/ucd" +) + +func main() { + gen.Init() + loadUnicodeData() + compactCCC() + loadCompositionExclusions() + completeCharFields(FCanonical) + completeCharFields(FCompatibility) + computeNonStarterCounts() + verifyComputed() + printChars() + testDerived() + printTestdata() + makeTables() +} + +var ( + tablelist = flag.String("tables", + "all", + "comma-separated list of which tables to generate; "+ + "can be 'decomp', 'recomp', 'info' and 'all'") + test = flag.Bool("test", + false, + "test existing tables against DerivedNormalizationProps and generate test data for regression testing") + verbose = flag.Bool("verbose", + false, + "write data to stdout as it is parsed") +) + +const MaxChar = 0x10FFFF // anything above this shouldn't exist + +// Quick Check properties of runes allow us to quickly +// determine whether a rune may occur in a normal form. +// For a given normal form, a rune may be guaranteed to occur +// verbatim (QC=Yes), may or may not combine with another +// rune (QC=Maybe), or may not occur (QC=No). +type QCResult int + +const ( + QCUnknown QCResult = iota + QCYes + QCNo + QCMaybe +) + +func (r QCResult) String() string { + switch r { + case QCYes: + return "Yes" + case QCNo: + return "No" + case QCMaybe: + return "Maybe" + } + return "***UNKNOWN***" +} + +const ( + FCanonical = iota // NFC or NFD + FCompatibility // NFKC or NFKD + FNumberOfFormTypes +) + +const ( + MComposed = iota // NFC or NFKC + MDecomposed // NFD or NFKD + MNumberOfModes +) + +// This contains only the properties we're interested in. +type Char struct { + name string + codePoint rune // if zero, this index is not a valid code point. + ccc uint8 // canonical combining class + origCCC uint8 + excludeInComp bool // from CompositionExclusions.txt + compatDecomp bool // it has a compatibility expansion + + nTrailingNonStarters uint8 + nLeadingNonStarters uint8 // must be equal to trailing if non-zero + + forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility + + state State +} + +var chars = make([]Char, MaxChar+1) +var cccMap = make(map[uint8]uint8) + +func (c Char) String() string { + buf := new(bytes.Buffer) + + fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name) + fmt.Fprintf(buf, " ccc: %v\n", c.ccc) + fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp) + fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp) + fmt.Fprintf(buf, " state: %v\n", c.state) + fmt.Fprintf(buf, " NFC:\n") + fmt.Fprint(buf, c.forms[FCanonical]) + fmt.Fprintf(buf, " NFKC:\n") + fmt.Fprint(buf, c.forms[FCompatibility]) + + return buf.String() +} + +// In UnicodeData.txt, some ranges are marked like this: +// 3400;;Lo;0;L;;;;;N;;;;; +// 4DB5;;Lo;0;L;;;;;N;;;;; +// parseCharacter keeps a state variable indicating the weirdness. +type State int + +const ( + SNormal State = iota // known to be zero for the type + SFirst + SLast + SMissing +) + +var lastChar = rune('\u0000') + +func (c Char) isValid() bool { + return c.codePoint != 0 && c.state != SMissing +} + +type FormInfo struct { + quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed + verified [MNumberOfModes]bool // index: MComposed or MDecomposed + + combinesForward bool // May combine with rune on the right + combinesBackward bool // May combine with rune on the left + isOneWay bool // Never appears in result + inDecomp bool // Some decompositions result in this char. + decomp Decomposition + expandedDecomp Decomposition +} + +func (f FormInfo) String() string { + buf := bytes.NewBuffer(make([]byte, 0)) + + fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed]) + fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed]) + fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward) + fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward) + fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay) + fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp) + fmt.Fprintf(buf, " decomposition: %X\n", f.decomp) + fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp) + + return buf.String() +} + +type Decomposition []rune + +func parseDecomposition(s string, skipfirst bool) (a []rune, err error) { + decomp := strings.Split(s, " ") + if len(decomp) > 0 && skipfirst { + decomp = decomp[1:] + } + for _, d := range decomp { + point, err := strconv.ParseUint(d, 16, 64) + if err != nil { + return a, err + } + a = append(a, rune(point)) + } + return a, nil +} + +func loadUnicodeData() { + f := gen.OpenUCDFile("UnicodeData.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + r := p.Rune(ucd.CodePoint) + char := &chars[r] + + char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass)) + decmap := p.String(ucd.DecompMapping) + + exp, err := parseDecomposition(decmap, false) + isCompat := false + if err != nil { + if len(decmap) > 0 { + exp, err = parseDecomposition(decmap, true) + if err != nil { + log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err) + } + isCompat = true + } + } + + char.name = p.String(ucd.Name) + char.codePoint = r + char.forms[FCompatibility].decomp = exp + if !isCompat { + char.forms[FCanonical].decomp = exp + } else { + char.compatDecomp = true + } + if len(decmap) > 0 { + char.forms[FCompatibility].decomp = exp + } + } + if err := p.Err(); err != nil { + log.Fatal(err) + } +} + +// compactCCC converts the sparse set of CCC values to a continguous one, +// reducing the number of bits needed from 8 to 6. +func compactCCC() { + m := make(map[uint8]uint8) + for i := range chars { + c := &chars[i] + m[c.ccc] = 0 + } + cccs := []int{} + for v, _ := range m { + cccs = append(cccs, int(v)) + } + sort.Ints(cccs) + for i, c := range cccs { + cccMap[uint8(i)] = uint8(c) + m[uint8(c)] = uint8(i) + } + for i := range chars { + c := &chars[i] + c.origCCC = c.ccc + c.ccc = m[c.ccc] + } + if len(m) >= 1<<6 { + log.Fatalf("too many difference CCC values: %d >= 64", len(m)) + } +} + +// CompositionExclusions.txt has form: +// 0958 # ... +// See https://unicode.org/reports/tr44/ for full explanation +func loadCompositionExclusions() { + f := gen.OpenUCDFile("CompositionExclusions.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + c := &chars[p.Rune(0)] + if c.excludeInComp { + log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint) + } + c.excludeInComp = true + } + if e := p.Err(); e != nil { + log.Fatal(e) + } +} + +// hasCompatDecomp returns true if any of the recursive +// decompositions contains a compatibility expansion. +// In this case, the character may not occur in NFK*. +func hasCompatDecomp(r rune) bool { + c := &chars[r] + if c.compatDecomp { + return true + } + for _, d := range c.forms[FCompatibility].decomp { + if hasCompatDecomp(d) { + return true + } + } + return false +} + +// Hangul related constants. +const ( + HangulBase = 0xAC00 + HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28) + + JamoLBase = 0x1100 + JamoLEnd = 0x1113 + JamoVBase = 0x1161 + JamoVEnd = 0x1176 + JamoTBase = 0x11A8 + JamoTEnd = 0x11C3 + + JamoLVTCount = 19 * 21 * 28 + JamoTCount = 28 +) + +func isHangul(r rune) bool { + return HangulBase <= r && r < HangulEnd +} + +func isHangulWithoutJamoT(r rune) bool { + if !isHangul(r) { + return false + } + r -= HangulBase + return r < JamoLVTCount && r%JamoTCount == 0 +} + +func ccc(r rune) uint8 { + return chars[r].ccc +} + +// Insert a rune in a buffer, ordered by Canonical Combining Class. +func insertOrdered(b Decomposition, r rune) Decomposition { + n := len(b) + b = append(b, 0) + cc := ccc(r) + if cc > 0 { + // Use bubble sort. + for ; n > 0; n-- { + if ccc(b[n-1]) <= cc { + break + } + b[n] = b[n-1] + } + } + b[n] = r + return b +} + +// Recursively decompose. +func decomposeRecursive(form int, r rune, d Decomposition) Decomposition { + dcomp := chars[r].forms[form].decomp + if len(dcomp) == 0 { + return insertOrdered(d, r) + } + for _, c := range dcomp { + d = decomposeRecursive(form, c, d) + } + return d +} + +func completeCharFields(form int) { + // Phase 0: pre-expand decomposition. + for i := range chars { + f := &chars[i].forms[form] + if len(f.decomp) == 0 { + continue + } + exp := make(Decomposition, 0) + for _, c := range f.decomp { + exp = decomposeRecursive(form, c, exp) + } + f.expandedDecomp = exp + } + + // Phase 1: composition exclusion, mark decomposition. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + // Marks script-specific exclusions and version restricted. + f.isOneWay = c.excludeInComp + + // Singletons + f.isOneWay = f.isOneWay || len(f.decomp) == 1 + + // Non-starter decompositions + if len(f.decomp) > 1 { + chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0 + f.isOneWay = f.isOneWay || chk + } + + // Runes that decompose into more than two runes. + f.isOneWay = f.isOneWay || len(f.decomp) > 2 + + if form == FCompatibility { + f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint) + } + + for _, r := range f.decomp { + chars[r].forms[form].inDecomp = true + } + } + + // Phase 2: forward and backward combining. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + if !f.isOneWay && len(f.decomp) == 2 { + f0 := &chars[f.decomp[0]].forms[form] + f1 := &chars[f.decomp[1]].forms[form] + if !f0.isOneWay { + f0.combinesForward = true + } + if !f1.isOneWay { + f1.combinesBackward = true + } + } + if isHangulWithoutJamoT(rune(i)) { + f.combinesForward = true + } + } + + // Phase 3: quick check values. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + switch { + case len(f.decomp) > 0: + f.quickCheck[MDecomposed] = QCNo + case isHangul(rune(i)): + f.quickCheck[MDecomposed] = QCNo + default: + f.quickCheck[MDecomposed] = QCYes + } + switch { + case f.isOneWay: + f.quickCheck[MComposed] = QCNo + case (i & 0xffff00) == JamoLBase: + f.quickCheck[MComposed] = QCYes + if JamoLBase <= i && i < JamoLEnd { + f.combinesForward = true + } + if JamoVBase <= i && i < JamoVEnd { + f.quickCheck[MComposed] = QCMaybe + f.combinesBackward = true + f.combinesForward = true + } + if JamoTBase <= i && i < JamoTEnd { + f.quickCheck[MComposed] = QCMaybe + f.combinesBackward = true + } + case !f.combinesBackward: + f.quickCheck[MComposed] = QCYes + default: + f.quickCheck[MComposed] = QCMaybe + } + } +} + +func computeNonStarterCounts() { + // Phase 4: leading and trailing non-starter count + for i := range chars { + c := &chars[i] + + runes := []rune{rune(i)} + // We always use FCompatibility so that the CGJ insertion points do not + // change for repeated normalizations with different forms. + if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 { + runes = exp + } + // We consider runes that combine backwards to be non-starters for the + // purpose of Stream-Safe Text Processing. + for _, r := range runes { + if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { + break + } + c.nLeadingNonStarters++ + } + for i := len(runes) - 1; i >= 0; i-- { + if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { + break + } + c.nTrailingNonStarters++ + } + if c.nTrailingNonStarters > 3 { + log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes) + } + + if isHangul(rune(i)) { + c.nTrailingNonStarters = 2 + if isHangulWithoutJamoT(rune(i)) { + c.nTrailingNonStarters = 1 + } + } + + if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t { + log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t) + } + if t := c.nTrailingNonStarters; t > 3 { + log.Fatalf("%U: number of trailing non-starters is %d > 3", t) + } + } +} + +func printBytes(w io.Writer, b []byte, name string) { + fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b)) + fmt.Fprintf(w, "var %s = [...]byte {", name) + for i, c := range b { + switch { + case i%64 == 0: + fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63) + case i%8 == 0: + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "0x%.2X, ", c) + } + fmt.Fprint(w, "\n}\n\n") +} + +// See forminfo.go for format. +func makeEntry(f *FormInfo, c *Char) uint16 { + e := uint16(0) + if r := c.codePoint; HangulBase <= r && r < HangulEnd { + e |= 0x40 + } + if f.combinesForward { + e |= 0x20 + } + if f.quickCheck[MDecomposed] == QCNo { + e |= 0x4 + } + switch f.quickCheck[MComposed] { + case QCYes: + case QCNo: + e |= 0x10 + case QCMaybe: + e |= 0x18 + default: + log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed]) + } + e |= uint16(c.nTrailingNonStarters) + return e +} + +// decompSet keeps track of unique decompositions, grouped by whether +// the decomposition is followed by a trailing and/or leading CCC. +type decompSet [7]map[string]bool + +const ( + normalDecomp = iota + firstMulti + firstCCC + endMulti + firstLeadingCCC + firstCCCZeroExcept + firstStarterWithNLead + lastDecomp +) + +var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"} + +func makeDecompSet() decompSet { + m := decompSet{} + for i := range m { + m[i] = make(map[string]bool) + } + return m +} +func (m *decompSet) insert(key int, s string) { + m[key][s] = true +} + +func printCharInfoTables(w io.Writer) int { + mkstr := func(r rune, f *FormInfo) (int, string) { + d := f.expandedDecomp + s := string([]rune(d)) + if max := 1 << 6; len(s) >= max { + const msg = "%U: too many bytes in decomposition: %d >= %d" + log.Fatalf(msg, r, len(s), max) + } + head := uint8(len(s)) + if f.quickCheck[MComposed] != QCYes { + head |= 0x40 + } + if f.combinesForward { + head |= 0x80 + } + s = string([]byte{head}) + s + + lccc := ccc(d[0]) + tccc := ccc(d[len(d)-1]) + cc := ccc(r) + if cc != 0 && lccc == 0 && tccc == 0 { + log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc) + } + if tccc < lccc && lccc != 0 { + const msg = "%U: lccc (%d) must be <= tcc (%d)" + log.Fatalf(msg, r, lccc, tccc) + } + index := normalDecomp + nTrail := chars[r].nTrailingNonStarters + nLead := chars[r].nLeadingNonStarters + if tccc > 0 || lccc > 0 || nTrail > 0 { + tccc <<= 2 + tccc |= nTrail + s += string([]byte{tccc}) + index = endMulti + for _, r := range d[1:] { + if ccc(r) == 0 { + index = firstCCC + } + } + if lccc > 0 || nLead > 0 { + s += string([]byte{lccc}) + if index == firstCCC { + log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r) + } + index = firstLeadingCCC + } + if cc != lccc { + if cc != 0 { + log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc) + } + index = firstCCCZeroExcept + } + } else if len(d) > 1 { + index = firstMulti + } + return index, s + } + + decompSet := makeDecompSet() + const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail. + decompSet.insert(firstStarterWithNLead, nLeadStr) + + // Store the uniqued decompositions in a byte buffer, + // preceded by their byte length. + for _, c := range chars { + for _, f := range c.forms { + if len(f.expandedDecomp) == 0 { + continue + } + if f.combinesBackward { + log.Fatalf("%U: combinesBackward and decompose", c.codePoint) + } + index, s := mkstr(c.codePoint, &f) + decompSet.insert(index, s) + } + } + + decompositions := bytes.NewBuffer(make([]byte, 0, 10000)) + size := 0 + positionMap := make(map[string]uint16) + decompositions.WriteString("\000") + fmt.Fprintln(w, "const (") + for i, m := range decompSet { + sa := []string{} + for s := range m { + sa = append(sa, s) + } + sort.Strings(sa) + for _, s := range sa { + p := decompositions.Len() + decompositions.WriteString(s) + positionMap[s] = uint16(p) + } + if cname[i] != "" { + fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len()) + } + } + fmt.Fprintln(w, "maxDecomp = 0x8000") + fmt.Fprintln(w, ")") + b := decompositions.Bytes() + printBytes(w, b, "decomps") + size += len(b) + + varnames := []string{"nfc", "nfkc"} + for i := 0; i < FNumberOfFormTypes; i++ { + trie := triegen.NewTrie(varnames[i]) + + for r, c := range chars { + f := c.forms[i] + d := f.expandedDecomp + if len(d) != 0 { + _, key := mkstr(c.codePoint, &f) + trie.Insert(rune(r), uint64(positionMap[key])) + if c.ccc != ccc(d[0]) { + // We assume the lead ccc of a decomposition !=0 in this case. + if ccc(d[0]) == 0 { + log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc) + } + } + } else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward { + // Handle cases where it can't be detected that the nLead should be equal + // to nTrail. + trie.Insert(c.codePoint, uint64(positionMap[nLeadStr])) + } else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 { + trie.Insert(c.codePoint, uint64(0x8000|v)) + } + } + sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]})) + if err != nil { + log.Fatal(err) + } + size += sz + } + return size +} + +func contains(sa []string, s string) bool { + for _, a := range sa { + if a == s { + return true + } + } + return false +} + +func makeTables() { + w := &bytes.Buffer{} + + size := 0 + if *tablelist == "" { + return + } + list := strings.Split(*tablelist, ",") + if *tablelist == "all" { + list = []string{"recomp", "info"} + } + + // Compute maximum decomposition size. + max := 0 + for _, c := range chars { + if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max { + max = n + } + } + fmt.Fprintln(w, `import "sync"`) + fmt.Fprintln(w) + + fmt.Fprintln(w, "const (") + fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.") + fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion()) + fmt.Fprintln(w) + fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform") + fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at") + fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that") + fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.") + fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max) + fmt.Fprintln(w, ")\n") + + // Print the CCC remap table. + size += len(cccMap) + fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap)) + for i := 0; i < len(cccMap); i++ { + if i%8 == 0 { + fmt.Fprintln(w) + } + fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)]) + } + fmt.Fprintln(w, "\n}\n") + + if contains(list, "info") { + size += printCharInfoTables(w) + } + + if contains(list, "recomp") { + // Note that we use 32 bit keys, instead of 64 bit. + // This clips the bits of three entries, but we know + // this won't cause a collision. The compiler will catch + // any changes made to UnicodeData.txt that introduces + // a collision. + // Note that the recomposition map for NFC and NFKC + // are identical. + + // Recomposition map + nrentries := 0 + for _, c := range chars { + f := c.forms[FCanonical] + if !f.isOneWay && len(f.decomp) > 0 { + nrentries++ + } + } + sz := nrentries * 8 + size += sz + fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz) + fmt.Fprintln(w, "var recompMap map[uint32]rune") + fmt.Fprintln(w, "var recompMapOnce sync.Once\n") + fmt.Fprintln(w, `const recompMapPacked = "" +`) + var buf [8]byte + for i, c := range chars { + f := c.forms[FCanonical] + d := f.decomp + if !f.isOneWay && len(d) > 0 { + key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1])) + binary.BigEndian.PutUint32(buf[:4], key) + binary.BigEndian.PutUint32(buf[4:], uint32(i)) + fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i)) + } + } + // hack so we don't have to special case the trailing plus sign + fmt.Fprintf(w, ` ""`) + fmt.Fprintln(w) + } + + fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size) + gen.WriteVersionedGoFile("tables.go", "norm", w.Bytes()) +} + +func printChars() { + if *verbose { + for _, c := range chars { + if !c.isValid() || c.state == SMissing { + continue + } + fmt.Println(c) + } + } +} + +// verifyComputed does various consistency tests. +func verifyComputed() { + for i, c := range chars { + for _, f := range c.forms { + isNo := (f.quickCheck[MDecomposed] == QCNo) + if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) { + log.Fatalf("%U: NF*D QC must be No if rune decomposes", i) + } + + isMaybe := f.quickCheck[MComposed] == QCMaybe + if f.combinesBackward != isMaybe { + log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i) + } + if len(f.decomp) > 0 && f.combinesForward && isMaybe { + log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i) + } + + if len(f.expandedDecomp) != 0 { + continue + } + if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b { + // We accept these runes to be treated differently (it only affects + // segment breaking in iteration, most likely on improper use), but + // reconsider if more characters are added. + // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; + // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; + // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; + // U+318E HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; + // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; + // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; + if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) { + log.Fatalf("%U: nLead was %v; want %v", i, a, b) + } + } + } + nfc := c.forms[FCanonical] + nfkc := c.forms[FCompatibility] + if nfc.combinesBackward != nfkc.combinesBackward { + log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint) + } + } +} + +// Use values in DerivedNormalizationProps.txt to compare against the +// values we computed. +// DerivedNormalizationProps.txt has form: +// 00C0..00C5 ; NFD_QC; N # ... +// 0374 ; NFD_QC; N # ... +// See https://unicode.org/reports/tr44/ for full explanation +func testDerived() { + f := gen.OpenUCDFile("DerivedNormalizationProps.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + r := p.Rune(0) + c := &chars[r] + + var ftype, mode int + qt := p.String(1) + switch qt { + case "NFC_QC": + ftype, mode = FCanonical, MComposed + case "NFD_QC": + ftype, mode = FCanonical, MDecomposed + case "NFKC_QC": + ftype, mode = FCompatibility, MComposed + case "NFKD_QC": + ftype, mode = FCompatibility, MDecomposed + default: + continue + } + var qr QCResult + switch p.String(2) { + case "Y": + qr = QCYes + case "N": + qr = QCNo + case "M": + qr = QCMaybe + default: + log.Fatalf(`Unexpected quick check value "%s"`, p.String(2)) + } + if got := c.forms[ftype].quickCheck[mode]; got != qr { + log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr) + } + c.forms[ftype].verified[mode] = true + } + if err := p.Err(); err != nil { + log.Fatal(err) + } + // Any unspecified value must be QCYes. Verify this. + for i, c := range chars { + for j, fd := range c.forms { + for k, qr := range fd.quickCheck { + if !fd.verified[k] && qr != QCYes { + m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n" + log.Printf(m, i, j, k, qr, c.name) + } + } + } + } +} + +var testHeader = `const ( + Yes = iota + No + Maybe +) + +type formData struct { + qc uint8 + combinesForward bool + decomposition string +} + +type runeData struct { + r rune + ccc uint8 + nLead uint8 + nTrail uint8 + f [2]formData // 0: canonical; 1: compatibility +} + +func f(qc uint8, cf bool, dec string) [2]formData { + return [2]formData{{qc, cf, dec}, {qc, cf, dec}} +} + +func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { + return [2]formData{{qc, cf, d}, {qck, cfk, dk}} +} + +var testData = []runeData{ +` + +func printTestdata() { + type lastInfo struct { + ccc uint8 + nLead uint8 + nTrail uint8 + f string + } + + last := lastInfo{} + w := &bytes.Buffer{} + fmt.Fprintf(w, testHeader) + for r, c := range chars { + f := c.forms[FCanonical] + qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) + f = c.forms[FCompatibility] + qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) + s := "" + if d == dk && qc == qck && cf == cfk { + s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d) + } else { + s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk) + } + current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s} + if last != current { + fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s) + last = current + } + } + fmt.Fprintln(w, "}") + gen.WriteVersionedGoFile("data_test.go", "norm", w.Bytes()) +} diff --git a/vendor/golang.org/x/text/unicode/norm/triegen.go b/vendor/golang.org/x/text/unicode/norm/triegen.go new file mode 100644 index 0000000000..45d711900d --- /dev/null +++ b/vendor/golang.org/x/text/unicode/norm/triegen.go @@ -0,0 +1,117 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Trie table generator. +// Used by make*tables tools to generate a go file with trie data structures +// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte +// sequence are used to lookup offsets in the index table to be used for the +// next byte. The last byte is used to index into a table with 16-bit values. + +package main + +import ( + "fmt" + "io" +) + +const maxSparseEntries = 16 + +type normCompacter struct { + sparseBlocks [][]uint64 + sparseOffset []uint16 + sparseCount int + name string +} + +func mostFrequentStride(a []uint64) int { + counts := make(map[int]int) + var v int + for _, x := range a { + if stride := int(x) - v; v != 0 && stride >= 0 { + counts[stride]++ + } + v = int(x) + } + var maxs, maxc int + for stride, cnt := range counts { + if cnt > maxc || (cnt == maxc && stride < maxs) { + maxs, maxc = stride, cnt + } + } + return maxs +} + +func countSparseEntries(a []uint64) int { + stride := mostFrequentStride(a) + var v, count int + for _, tv := range a { + if int(tv)-v != stride { + if tv != 0 { + count++ + } + } + v = int(tv) + } + return count +} + +func (c *normCompacter) Size(v []uint64) (sz int, ok bool) { + if n := countSparseEntries(v); n <= maxSparseEntries { + return (n+1)*4 + 2, true + } + return 0, false +} + +func (c *normCompacter) Store(v []uint64) uint32 { + h := uint32(len(c.sparseOffset)) + c.sparseBlocks = append(c.sparseBlocks, v) + c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount)) + c.sparseCount += countSparseEntries(v) + 1 + return h +} + +func (c *normCompacter) Handler() string { + return c.name + "Sparse.lookup" +} + +func (c *normCompacter) Print(w io.Writer) (retErr error) { + p := func(f string, x ...interface{}) { + if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil { + retErr = err + } + } + + ls := len(c.sparseBlocks) + p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2) + p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset) + + ns := c.sparseCount + p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4) + p("var %sSparseValues = [%d]valueRange {", c.name, ns) + for i, b := range c.sparseBlocks { + p("\n// Block %#x, offset %#x", i, c.sparseOffset[i]) + var v int + stride := mostFrequentStride(b) + n := countSparseEntries(b) + p("\n{value:%#04x,lo:%#02x},", stride, uint8(n)) + for i, nv := range b { + if int(nv)-v != stride { + if v != 0 { + p(",hi:%#02x},", 0x80+i-1) + } + if nv != 0 { + p("\n{value:%#04x,lo:%#02x", nv, 0x80+i) + } + } + v = int(nv) + } + if v != 0 { + p(",hi:%#02x},", 0x80+len(b)-1) + } + } + p("\n}\n\n") + return +} diff --git a/vendor/k8s.io/client-go/pkg/version/base.go b/vendor/k8s.io/client-go/pkg/version/base.go index 9b4c79f895..cc2c6906a1 100644 --- a/vendor/k8s.io/client-go/pkg/version/base.go +++ b/vendor/k8s.io/client-go/pkg/version/base.go @@ -55,8 +55,8 @@ var ( // NOTE: The $Format strings are replaced during 'git archive' thanks to the // companion .gitattributes file containing 'export-subst' in this same // directory. See also https://git-scm.com/docs/gitattributes - gitVersion string = "v0.0.0-master+$Format:%h$" - gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) + gitVersion string = "v0.0.0-master+d830efd3f" + gitCommit string = "d830efd3f73e85c6c205b6648d8fb4465b98fbd1" // sha1 from git, output of $(git rev-parse HEAD) gitTreeState string = "" // state of git tree, either "clean" or "dirty" buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') diff --git a/vendor/modules.txt b/vendor/modules.txt index ee2b5dd3e5..296dfef6bc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,8 +7,8 @@ github.com/Azure/azure-pipeline-go/pipeline # github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e github.com/Azure/azure-storage-blob-go/2018-03-28/azblob # github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 -github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm +github.com/Azure/go-ansiterm # github.com/Microsoft/go-winio v0.4.13 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid @@ -27,55 +27,53 @@ github.com/apilayer/freegeoip github.com/aristanetworks/goarista/monotime # github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 github.com/btcsuite/btcd/btcec -# github.com/caarlos0/env v3.5.0+incompatible -github.com/caarlos0/env # github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd github.com/codahale/hdrhistogram # github.com/containerd/containerd v1.2.7 github.com/containerd/containerd/errdefs # github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc github.com/containerd/continuity/fs +github.com/containerd/continuity/sysx github.com/containerd/continuity/pathdriver github.com/containerd/continuity/syscallx -github.com/containerd/continuity/sysx # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea github.com/deckarep/golang-set # github.com/docker/distribution v2.7.1+incompatible -github.com/docker/distribution/digestset github.com/docker/distribution/reference +github.com/docker/distribution/digestset github.com/docker/distribution/registry/api/errcode # github.com/docker/docker v0.7.3-0.20190806133308-ecdb0b22393b -github.com/docker/docker/api +github.com/docker/docker/pkg/reexec github.com/docker/docker/api/types -github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/container -github.com/docker/docker/api/types/events +github.com/docker/docker/client +github.com/docker/docker/pkg/archive +github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/api/types/filters -github.com/docker/docker/api/types/image github.com/docker/docker/api/types/mount github.com/docker/docker/api/types/network github.com/docker/docker/api/types/registry -github.com/docker/docker/api/types/strslice github.com/docker/docker/api/types/swarm -github.com/docker/docker/api/types/swarm/runtime +github.com/docker/docker/api/types/blkiodev +github.com/docker/docker/api/types/strslice +github.com/docker/docker/api +github.com/docker/docker/api/types/events +github.com/docker/docker/api/types/image github.com/docker/docker/api/types/time github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume -github.com/docker/docker/client github.com/docker/docker/errdefs -github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/fileutils github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils -github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/longpath -github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/pools -github.com/docker/docker/pkg/reexec github.com/docker/docker/pkg/system github.com/docker/docker/pkg/term +github.com/docker/docker/api/types/swarm/runtime +github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/term/windows # github.com/docker/go-connections v0.4.0 github.com/docker/go-connections/nat @@ -89,99 +87,100 @@ github.com/edsrzf/mmap-go github.com/elastic/gosigar github.com/elastic/gosigar/sys/windows # github.com/ethereum/go-ethereum v1.9.2 -github.com/ethereum/go-ethereum +github.com/ethereum/go-ethereum/accounts/abi/bind +github.com/ethereum/go-ethereum/common +github.com/ethereum/go-ethereum/ethclient +github.com/ethereum/go-ethereum/metrics +github.com/ethereum/go-ethereum/p2p +github.com/ethereum/go-ethereum/params +github.com/ethereum/go-ethereum/rpc +github.com/ethereum/go-ethereum/common/hexutil +github.com/ethereum/go-ethereum/core/types +github.com/ethereum/go-ethereum/crypto +github.com/ethereum/go-ethereum/crypto/ecies +github.com/ethereum/go-ethereum/node +github.com/ethereum/go-ethereum/p2p/enode +github.com/ethereum/go-ethereum/log github.com/ethereum/go-ethereum/accounts +github.com/ethereum/go-ethereum/accounts/keystore +github.com/ethereum/go-ethereum/cmd/utils +github.com/ethereum/go-ethereum/console +github.com/ethereum/go-ethereum/p2p/nat +github.com/ethereum/go-ethereum/rlp +github.com/ethereum/go-ethereum/metrics/influxdb +github.com/ethereum/go-ethereum/p2p/simulations +github.com/ethereum/go-ethereum/p2p/simulations/adapters +github.com/ethereum/go-ethereum github.com/ethereum/go-ethereum/accounts/abi -github.com/ethereum/go-ethereum/accounts/abi/bind -github.com/ethereum/go-ethereum/accounts/abi/bind/backends +github.com/ethereum/go-ethereum/event +github.com/ethereum/go-ethereum/metrics/exp +github.com/ethereum/go-ethereum/p2p/enr +github.com/ethereum/go-ethereum/common/bitutil github.com/ethereum/go-ethereum/accounts/external -github.com/ethereum/go-ethereum/accounts/keystore +github.com/ethereum/go-ethereum/common/mclock +github.com/ethereum/go-ethereum/p2p/discover +github.com/ethereum/go-ethereum/p2p/discv5 +github.com/ethereum/go-ethereum/p2p/netutil +github.com/ethereum/go-ethereum/trie +github.com/ethereum/go-ethereum/common/math +github.com/ethereum/go-ethereum/crypto/secp256k1 github.com/ethereum/go-ethereum/accounts/scwallet github.com/ethereum/go-ethereum/accounts/usbwallet -github.com/ethereum/go-ethereum/accounts/usbwallet/trezor -github.com/ethereum/go-ethereum/cmd/utils -github.com/ethereum/go-ethereum/common -github.com/ethereum/go-ethereum/common/bitutil +github.com/ethereum/go-ethereum/core/rawdb +github.com/ethereum/go-ethereum/ethdb +github.com/ethereum/go-ethereum/internal/debug github.com/ethereum/go-ethereum/common/fdlimit -github.com/ethereum/go-ethereum/common/hexutil -github.com/ethereum/go-ethereum/common/math -github.com/ethereum/go-ethereum/common/mclock -github.com/ethereum/go-ethereum/common/prque github.com/ethereum/go-ethereum/consensus github.com/ethereum/go-ethereum/consensus/clique github.com/ethereum/go-ethereum/consensus/ethash -github.com/ethereum/go-ethereum/consensus/misc -github.com/ethereum/go-ethereum/console -github.com/ethereum/go-ethereum/contracts/checkpointoracle -github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract github.com/ethereum/go-ethereum/core -github.com/ethereum/go-ethereum/core/bloombits -github.com/ethereum/go-ethereum/core/forkid -github.com/ethereum/go-ethereum/core/rawdb -github.com/ethereum/go-ethereum/core/state -github.com/ethereum/go-ethereum/core/types github.com/ethereum/go-ethereum/core/vm -github.com/ethereum/go-ethereum/crypto -github.com/ethereum/go-ethereum/crypto/bn256 -github.com/ethereum/go-ethereum/crypto/bn256/cloudflare -github.com/ethereum/go-ethereum/crypto/bn256/google -github.com/ethereum/go-ethereum/crypto/ecies -github.com/ethereum/go-ethereum/crypto/secp256k1 github.com/ethereum/go-ethereum/dashboard github.com/ethereum/go-ethereum/eth github.com/ethereum/go-ethereum/eth/downloader -github.com/ethereum/go-ethereum/eth/fetcher -github.com/ethereum/go-ethereum/eth/filters github.com/ethereum/go-ethereum/eth/gasprice -github.com/ethereum/go-ethereum/eth/tracers -github.com/ethereum/go-ethereum/eth/tracers/internal/tracers -github.com/ethereum/go-ethereum/ethclient -github.com/ethereum/go-ethereum/ethdb -github.com/ethereum/go-ethereum/ethdb/leveldb -github.com/ethereum/go-ethereum/ethdb/memorydb github.com/ethereum/go-ethereum/ethstats -github.com/ethereum/go-ethereum/event github.com/ethereum/go-ethereum/graphql -github.com/ethereum/go-ethereum/internal/debug -github.com/ethereum/go-ethereum/internal/ethapi -github.com/ethereum/go-ethereum/internal/jsre -github.com/ethereum/go-ethereum/internal/jsre/deps -github.com/ethereum/go-ethereum/internal/web3ext github.com/ethereum/go-ethereum/les -github.com/ethereum/go-ethereum/les/flowcontrol -github.com/ethereum/go-ethereum/light -github.com/ethereum/go-ethereum/log -github.com/ethereum/go-ethereum/metrics -github.com/ethereum/go-ethereum/metrics/exp -github.com/ethereum/go-ethereum/metrics/influxdb -github.com/ethereum/go-ethereum/metrics/prometheus github.com/ethereum/go-ethereum/miner -github.com/ethereum/go-ethereum/node -github.com/ethereum/go-ethereum/p2p -github.com/ethereum/go-ethereum/p2p/discover -github.com/ethereum/go-ethereum/p2p/discv5 -github.com/ethereum/go-ethereum/p2p/enode -github.com/ethereum/go-ethereum/p2p/enr -github.com/ethereum/go-ethereum/p2p/nat -github.com/ethereum/go-ethereum/p2p/netutil -github.com/ethereum/go-ethereum/p2p/simulations -github.com/ethereum/go-ethereum/p2p/simulations/adapters +github.com/ethereum/go-ethereum/whisper/whisperv6 +github.com/ethereum/go-ethereum/internal/jsre +github.com/ethereum/go-ethereum/internal/web3ext github.com/ethereum/go-ethereum/p2p/simulations/pipes -github.com/ethereum/go-ethereum/params -github.com/ethereum/go-ethereum/rlp -github.com/ethereum/go-ethereum/rpc +github.com/ethereum/go-ethereum/accounts/abi/bind/backends +github.com/ethereum/go-ethereum/metrics/prometheus +github.com/ethereum/go-ethereum/internal/ethapi github.com/ethereum/go-ethereum/signer/core +github.com/ethereum/go-ethereum/common/prque +github.com/ethereum/go-ethereum/accounts/usbwallet/trezor +github.com/ethereum/go-ethereum/ethdb/leveldb +github.com/ethereum/go-ethereum/ethdb/memorydb +github.com/ethereum/go-ethereum/core/state +github.com/ethereum/go-ethereum/consensus/misc +github.com/ethereum/go-ethereum/crypto/bn256 +github.com/ethereum/go-ethereum/core/bloombits +github.com/ethereum/go-ethereum/core/forkid +github.com/ethereum/go-ethereum/eth/fetcher +github.com/ethereum/go-ethereum/eth/filters +github.com/ethereum/go-ethereum/eth/tracers +github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/les/flowcontrol +github.com/ethereum/go-ethereum/light +github.com/ethereum/go-ethereum/internal/jsre/deps github.com/ethereum/go-ethereum/signer/storage -github.com/ethereum/go-ethereum/trie -github.com/ethereum/go-ethereum/whisper/whisperv6 +github.com/ethereum/go-ethereum/crypto/bn256/cloudflare +github.com/ethereum/go-ethereum/crypto/bn256/google +github.com/ethereum/go-ethereum/eth/tracers/internal/tracers +github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract # github.com/ethersphere/go-sw3 v0.1.1 github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswap github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswapfactory +github.com/ethersphere/go-sw3/contracts-v0-1-0/simpleswap # github.com/fatih/color v1.7.0 github.com/fatih/color # github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc -github.com/fjl/memsize github.com/fjl/memsize/memsizeui +github.com/fjl/memsize # github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c github.com/gballet/go-libpcsclite # github.com/go-ole/go-ole v1.2.4 @@ -211,10 +210,10 @@ github.com/googleapis/gnostic/extensions github.com/gorilla/websocket # github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 github.com/graph-gophers/graphql-go +github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/errors github.com/graph-gophers/graphql-go/internal/common github.com/graph-gophers/graphql-go/internal/exec -github.com/graph-gophers/graphql-go/internal/exec/packer github.com/graph-gophers/graphql-go/internal/exec/resolvable github.com/graph-gophers/graphql-go/internal/exec/selected github.com/graph-gophers/graphql-go/internal/query @@ -222,8 +221,8 @@ github.com/graph-gophers/graphql-go/internal/schema github.com/graph-gophers/graphql-go/internal/validation github.com/graph-gophers/graphql-go/introspection github.com/graph-gophers/graphql-go/log -github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/trace +github.com/graph-gophers/graphql-go/internal/exec/packer # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru @@ -277,15 +276,15 @@ github.com/olekukonko/tablewriter # github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go/v1 +github.com/opencontainers/image-spec/specs-go # github.com/opencontainers/runc v0.1.1 github.com/opencontainers/runc/libcontainer/system github.com/opencontainers/runc/libcontainer/user # github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go -github.com/opentracing/opentracing-go/ext github.com/opentracing/opentracing-go/log +github.com/opentracing/opentracing-go/ext # github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e github.com/oschwald/maxminddb-golang # github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 @@ -310,12 +309,6 @@ github.com/robertkrimen/otto/token github.com/rs/cors # github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 github.com/rs/xhandler -# github.com/rsksmart/rds-swarm v0.0.0-20191108144433-2691bb410e40 -github.com/rsksmart/rds-swarm/config -github.com/rsksmart/rds-swarm/resolver -github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver -github.com/rsksmart/rds-swarm/resolver/rsk_resolver -github.com/rsksmart/rds-swarm/utils # github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus # github.com/spf13/pflag v1.0.3 @@ -328,17 +321,17 @@ github.com/steakknife/bloomfilter github.com/steakknife/hamming # github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 github.com/syndtr/goleveldb/leveldb +github.com/syndtr/goleveldb/leveldb/opt +github.com/syndtr/goleveldb/leveldb/iterator +github.com/syndtr/goleveldb/leveldb/storage +github.com/syndtr/goleveldb/leveldb/util +github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/cache github.com/syndtr/goleveldb/leveldb/comparer -github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/filter -github.com/syndtr/goleveldb/leveldb/iterator github.com/syndtr/goleveldb/leveldb/journal github.com/syndtr/goleveldb/leveldb/memdb -github.com/syndtr/goleveldb/leveldb/opt -github.com/syndtr/goleveldb/leveldb/storage github.com/syndtr/goleveldb/leveldb/table -github.com/syndtr/goleveldb/leveldb/util # github.com/tilinna/clock v1.0.2 github.com/tilinna/clock # github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef @@ -348,56 +341,55 @@ github.com/tyler-smith/go-bip39/wordlists github.com/uber/jaeger-client-go github.com/uber/jaeger-client-go/config github.com/uber/jaeger-client-go/internal/baggage -github.com/uber/jaeger-client-go/internal/baggage/remote github.com/uber/jaeger-client-go/internal/spanlog github.com/uber/jaeger-client-go/internal/throttler -github.com/uber/jaeger-client-go/internal/throttler/remote github.com/uber/jaeger-client-go/log -github.com/uber/jaeger-client-go/rpcmetrics github.com/uber/jaeger-client-go/thrift -github.com/uber/jaeger-client-go/thrift-gen/agent -github.com/uber/jaeger-client-go/thrift-gen/baggage github.com/uber/jaeger-client-go/thrift-gen/jaeger github.com/uber/jaeger-client-go/thrift-gen/sampling github.com/uber/jaeger-client-go/thrift-gen/zipkincore github.com/uber/jaeger-client-go/utils +github.com/uber/jaeger-client-go/internal/baggage/remote +github.com/uber/jaeger-client-go/internal/throttler/remote +github.com/uber/jaeger-client-go/rpcmetrics +github.com/uber/jaeger-client-go/thrift-gen/agent +github.com/uber/jaeger-client-go/thrift-gen/baggage # github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7 github.com/uber/jaeger-lib/metrics # github.com/vbauerster/mpb v3.4.0+incompatible github.com/vbauerster/mpb -github.com/vbauerster/mpb/cwriter github.com/vbauerster/mpb/decor +github.com/vbauerster/mpb/cwriter github.com/vbauerster/mpb/internal # github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 github.com/wsddn/go-ecdh # golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 -golang.org/x/crypto/cast5 -golang.org/x/crypto/curve25519 +golang.org/x/crypto/scrypt +golang.org/x/crypto/sha3 golang.org/x/crypto/openpgp +golang.org/x/crypto/pbkdf2 golang.org/x/crypto/openpgp/armor -golang.org/x/crypto/openpgp/elgamal golang.org/x/crypto/openpgp/errors golang.org/x/crypto/openpgp/packet golang.org/x/crypto/openpgp/s2k -golang.org/x/crypto/pbkdf2 -golang.org/x/crypto/ripemd160 -golang.org/x/crypto/scrypt -golang.org/x/crypto/sha3 golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.0.0-20191105084925-a882066a44e0 +golang.org/x/crypto/ripemd160 +golang.org/x/crypto/cast5 +golang.org/x/crypto/openpgp/elgamal +golang.org/x/crypto/curve25519 +# golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 golang.org/x/net/context -golang.org/x/net/context/ctxhttp golang.org/x/net/html +golang.org/x/net/websocket +golang.org/x/net/http2 golang.org/x/net/html/atom golang.org/x/net/html/charset +golang.org/x/net/proxy golang.org/x/net/http/httpguts -golang.org/x/net/http2 golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/internal/socks -golang.org/x/net/proxy -golang.org/x/net/publicsuffix -golang.org/x/net/websocket +golang.org/x/net/context/ctxhttp # golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 golang.org/x/oauth2/internal @@ -410,44 +402,44 @@ golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 +golang.org/x/text/unicode/norm +golang.org/x/text/transform golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex -golang.org/x/text/encoding/internal +golang.org/x/text/secure/bidirule +golang.org/x/text/unicode/bidi golang.org/x/text/encoding/internal/identifier +golang.org/x/text/encoding/internal golang.org/x/text/encoding/japanese golang.org/x/text/encoding/korean golang.org/x/text/encoding/simplifiedchinese golang.org/x/text/encoding/traditionalchinese golang.org/x/text/encoding/unicode +golang.org/x/text/language +golang.org/x/text/internal/utf8internal +golang.org/x/text/runes golang.org/x/text/internal/language golang.org/x/text/internal/language/compact golang.org/x/text/internal/tag -golang.org/x/text/internal/utf8internal -golang.org/x/text/language -golang.org/x/text/runes -golang.org/x/text/secure/bidirule -golang.org/x/text/transform -golang.org/x/text/unicode/bidi -golang.org/x/text/unicode/norm # golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/time/rate # google.golang.org/appengine v1.6.1 +google.golang.org/appengine/urlfetch google.golang.org/appengine/internal +google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/base google.golang.org/appengine/internal/datastore google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api -google.golang.org/appengine/internal/urlfetch -google.golang.org/appengine/urlfetch # google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 google.golang.org/genproto/googleapis/rpc/status # google.golang.org/grpc v1.22.1 google.golang.org/grpc/codes +google.golang.org/grpc/status +google.golang.org/grpc/internal google.golang.org/grpc/connectivity google.golang.org/grpc/grpclog -google.golang.org/grpc/internal -google.golang.org/grpc/status # gopkg.in/inf.v0 v0.9.1 gopkg.in/inf.v0 # gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce @@ -462,8 +454,10 @@ gopkg.in/urfave/cli.v1 # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190703205437-39734b2a72fe +k8s.io/api/core/v1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1 +k8s.io/api/autoscaling/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/auditregistration/v1alpha1 @@ -471,7 +465,6 @@ k8s.io/api/authentication/v1 k8s.io/api/authentication/v1beta1 k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 -k8s.io/api/autoscaling/v1 k8s.io/api/autoscaling/v2beta1 k8s.io/api/autoscaling/v2beta2 k8s.io/api/batch/v1 @@ -480,14 +473,13 @@ k8s.io/api/batch/v2alpha1 k8s.io/api/certificates/v1beta1 k8s.io/api/coordination/v1 k8s.io/api/coordination/v1beta1 -k8s.io/api/core/v1 +k8s.io/api/policy/v1beta1 k8s.io/api/events/v1beta1 k8s.io/api/extensions/v1beta1 k8s.io/api/networking/v1 k8s.io/api/networking/v1beta1 k8s.io/api/node/v1alpha1 k8s.io/api/node/v1beta1 -k8s.io/api/policy/v1beta1 k8s.io/api/rbac/v1 k8s.io/api/rbac/v1alpha1 k8s.io/api/rbac/v1beta1 @@ -499,44 +491,45 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 # k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76 -k8s.io/apimachinery/pkg/api/errors -k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 -k8s.io/apimachinery/pkg/apis/meta/v1/unstructured -k8s.io/apimachinery/pkg/conversion -k8s.io/apimachinery/pkg/conversion/queryparams -k8s.io/apimachinery/pkg/fields -k8s.io/apimachinery/pkg/labels k8s.io/apimachinery/pkg/runtime k8s.io/apimachinery/pkg/runtime/schema -k8s.io/apimachinery/pkg/runtime/serializer -k8s.io/apimachinery/pkg/runtime/serializer/json -k8s.io/apimachinery/pkg/runtime/serializer/protobuf -k8s.io/apimachinery/pkg/runtime/serializer/recognizer -k8s.io/apimachinery/pkg/runtime/serializer/streaming -k8s.io/apimachinery/pkg/runtime/serializer/versioning -k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/types -k8s.io/apimachinery/pkg/util/clock -k8s.io/apimachinery/pkg/util/errors -k8s.io/apimachinery/pkg/util/framer k8s.io/apimachinery/pkg/util/intstr -k8s.io/apimachinery/pkg/util/json -k8s.io/apimachinery/pkg/util/naming -k8s.io/apimachinery/pkg/util/net +k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/fields +k8s.io/apimachinery/pkg/labels +k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/util/runtime +k8s.io/apimachinery/pkg/watch +k8s.io/apimachinery/pkg/api/errors +k8s.io/apimachinery/pkg/runtime/serializer/streaming +k8s.io/apimachinery/pkg/util/net k8s.io/apimachinery/pkg/util/sets +k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/validation +k8s.io/apimachinery/pkg/conversion/queryparams +k8s.io/apimachinery/pkg/util/json +k8s.io/apimachinery/pkg/util/naming +k8s.io/apimachinery/third_party/forked/golang/reflect +k8s.io/apimachinery/pkg/runtime/serializer +k8s.io/apimachinery/pkg/version +k8s.io/apimachinery/pkg/util/clock k8s.io/apimachinery/pkg/util/validation/field +k8s.io/apimachinery/pkg/runtime/serializer/json +k8s.io/apimachinery/pkg/runtime/serializer/versioning +k8s.io/apimachinery/pkg/runtime/serializer/protobuf +k8s.io/apimachinery/pkg/runtime/serializer/recognizer +k8s.io/apimachinery/pkg/api/meta +k8s.io/apimachinery/pkg/util/framer k8s.io/apimachinery/pkg/util/yaml -k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/watch -k8s.io/apimachinery/third_party/forked/golang/reflect +k8s.io/apimachinery/pkg/apis/meta/v1/unstructured # k8s.io/client-go v0.0.0-20190706005506-4ed54556a14a -k8s.io/client-go/discovery k8s.io/client-go/kubernetes -k8s.io/client-go/kubernetes/scheme +k8s.io/client-go/rest +k8s.io/client-go/tools/clientcmd +k8s.io/client-go/discovery k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1 k8s.io/client-go/kubernetes/typed/apps/v1beta1 @@ -573,26 +566,25 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1 k8s.io/client-go/kubernetes/typed/storage/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1beta1 -k8s.io/client-go/pkg/apis/clientauthentication -k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 -k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 +k8s.io/client-go/util/flowcontrol k8s.io/client-go/pkg/version k8s.io/client-go/plugin/pkg/client/auth/exec -k8s.io/client-go/rest k8s.io/client-go/rest/watch -k8s.io/client-go/tools/auth -k8s.io/client-go/tools/clientcmd k8s.io/client-go/tools/clientcmd/api -k8s.io/client-go/tools/clientcmd/api/latest -k8s.io/client-go/tools/clientcmd/api/v1 k8s.io/client-go/tools/metrics -k8s.io/client-go/tools/reference k8s.io/client-go/transport k8s.io/client-go/util/cert -k8s.io/client-go/util/connrotation -k8s.io/client-go/util/flowcontrol +k8s.io/client-go/tools/auth +k8s.io/client-go/tools/clientcmd/api/latest k8s.io/client-go/util/homedir +k8s.io/client-go/kubernetes/scheme +k8s.io/client-go/tools/reference +k8s.io/client-go/pkg/apis/clientauthentication +k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 +k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 +k8s.io/client-go/util/connrotation k8s.io/client-go/util/keyutil +k8s.io/client-go/tools/clientcmd/api/v1 # k8s.io/klog v0.3.1 k8s.io/klog # k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a From badce67bdf2c223bd864490a39f92049a001edb9 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 11 Nov 2019 15:10:33 -0300 Subject: [PATCH 19/49] vendor: fix vendor --- vendor/github.com/caarlos0/env | 1 - vendor/github.com/rsksmart/rds-swarm | 1 - 2 files changed, 2 deletions(-) delete mode 160000 vendor/github.com/caarlos0/env delete mode 160000 vendor/github.com/rsksmart/rds-swarm diff --git a/vendor/github.com/caarlos0/env b/vendor/github.com/caarlos0/env deleted file mode 160000 index c67acb9fd5..0000000000 --- a/vendor/github.com/caarlos0/env +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c67acb9fd501532e9a396a2f185f617f849727dd diff --git a/vendor/github.com/rsksmart/rds-swarm b/vendor/github.com/rsksmart/rds-swarm deleted file mode 160000 index 85b02e96e2..0000000000 --- a/vendor/github.com/rsksmart/rds-swarm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 85b02e96e2adf3f771b3be2994b72d982adb24ea From de3ecbb5f5c2a33a0a2d3d821eb08f48c0e56180 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 11 Nov 2019 15:11:41 -0300 Subject: [PATCH 20/49] vendor: fix vendor --- .../github.com/caarlos0/env/config/config.go | 38 + .../MultiChainResolverABI.json | 336 ++++++ .../multi_chain_resolver.go | 996 ++++++++++++++++++ .../caarlos0/env/resolver/resolver.go | 153 +++ .../resolver/rsk_resolver/RSKResolverABI.json | 134 +++ .../env/resolver/rsk_resolver/rsk_resolver.go | 319 ++++++ vendor/github.com/caarlos0/env/utils/utils.go | 35 + vendor/github.com/rds-swarm/config/config.go | 38 + .../MultiChainResolverABI.json | 336 ++++++ .../multi_chain_resolver.go | 996 ++++++++++++++++++ .../github.com/rds-swarm/resolver/resolver.go | 153 +++ .../resolver/rsk_resolver/RSKResolverABI.json | 134 +++ .../resolver/rsk_resolver/rsk_resolver.go | 319 ++++++ vendor/github.com/rds-swarm/utils/utils.go | 35 + 14 files changed, 4022 insertions(+) create mode 100644 vendor/github.com/caarlos0/env/config/config.go create mode 100644 vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json create mode 100644 vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go create mode 100644 vendor/github.com/caarlos0/env/resolver/resolver.go create mode 100644 vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json create mode 100644 vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go create mode 100644 vendor/github.com/caarlos0/env/utils/utils.go create mode 100644 vendor/github.com/rds-swarm/config/config.go create mode 100644 vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json create mode 100644 vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go create mode 100644 vendor/github.com/rds-swarm/resolver/resolver.go create mode 100644 vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json create mode 100644 vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go create mode 100644 vendor/github.com/rds-swarm/utils/utils.go diff --git a/vendor/github.com/caarlos0/env/config/config.go b/vendor/github.com/caarlos0/env/config/config.go new file mode 100644 index 0000000000..1884f140ea --- /dev/null +++ b/vendor/github.com/caarlos0/env/config/config.go @@ -0,0 +1,38 @@ +package config + +import ( + "github.com/caarlos0/env" +) + +func init() { + env.Parse(&cfg) + env.Parse(&cfg.ResolverAddresses) +} + +// Configuration is the struct that holds the values of the network configuration +// env and envDefault are required by env library +// it corresponds with the os environment variable name and also its default value if omitted +type Configuration struct { + NetworkNodeAddress string `env:"RNS_NETWORK_NODE_ADDRESS" envDefault:"https://public-node.rsk.co"` + ResolverAddresses struct { + RSK string `env:"RNS_RESOLVER_ADDRESS_RSK" envDefault:"0x4efd25e3d348f8f25a14fb7655fba6f72edfe93a"` + MultiChain string `env:"RNS_RESOLVER_ADDRESS_MULTICHAIN" envDefault:"0x99a12be4C89CbF6CFD11d1F2c029904a7B644368"` + } +} + +var cfg Configuration = Configuration{} + +// GetConfiguration loads the environment variables into a Configuration struct and returns it. +func GetConfiguration() Configuration { + return cfg +} + +// SetRSKConfiguration overrides endpoint and contract to rns node +func SetRSKConfiguration(endpoint string, contract string) { + if endpoint != "" { + cfg.NetworkNodeAddress = endpoint + } + if contract != "" { + cfg.ResolverAddresses.RSK = contract + } +} diff --git a/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json b/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json new file mode 100644 index 0000000000..962eb5dd95 --- /dev/null +++ b/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json @@ -0,0 +1,336 @@ +[ + { + "inputs": [ + { + "name": "_rns", + "type": "address" + }, + { + "name": "_publicResolver", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": false, + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "content", + "type": "bytes32" + } + ], + "name": "ContentChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "chain", + "type": "bytes4" + }, + { + "indexed": false, + "name": "metadata", + "type": "bytes32" + } + ], + "name": "ChainMetadataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "chain", + "type": "bytes4" + }, + { + "indexed": false, + "name": "addr", + "type": "string" + } + ], + "name": "ChainAddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "addr", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addrValue", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "content", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "contentValue", + "type": "bytes32" + } + ], + "name": "setContent", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainAddr", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "addrValue", + "type": "string" + } + ], + "name": "setChainAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainMetadata", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "metadataValue", + "type": "bytes32" + } + ], + "name": "setChainMetadata", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainAddrAndMetadata", + "outputs": [ + { + "name": "", + "type": "string" + }, + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "addrValue", + "type": "string" + }, + { + "name": "metadataValue", + "type": "bytes32" + } + ], + "name": "setChainAddrWithMetadata", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go b/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go new file mode 100644 index 0000000000..0e4b1a3a21 --- /dev/null +++ b/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go @@ -0,0 +1,996 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package multichainresolver + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// MultichainresolverABI is the input ABI used to generate the binding from. +const MultichainresolverABI = "[{\"inputs\":[{\"name\":\"_rns\",\"type\":\"address\"},{\"name\":\"_publicResolver\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"content\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"metadata\",\"type\":\"bytes32\"}],\"name\":\"ChainMetadataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"string\"}],\"name\":\"ChainAddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentValue\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddr\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"}],\"name\":\"setChainAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddrAndMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainAddrWithMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" + +// Multichainresolver is an auto generated Go binding around an Ethereum contract. +type Multichainresolver struct { + MultichainresolverCaller // Read-only binding to the contract + MultichainresolverTransactor // Write-only binding to the contract + MultichainresolverFilterer // Log filterer for contract events +} + +// MultichainresolverCaller is an auto generated read-only Go binding around an Ethereum contract. +type MultichainresolverCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. +type MultichainresolverTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type MultichainresolverFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type MultichainresolverSession struct { + Contract *Multichainresolver // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MultichainresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type MultichainresolverCallerSession struct { + Contract *MultichainresolverCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// MultichainresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type MultichainresolverTransactorSession struct { + Contract *MultichainresolverTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MultichainresolverRaw is an auto generated low-level Go binding around an Ethereum contract. +type MultichainresolverRaw struct { + Contract *Multichainresolver // Generic contract binding to access the raw methods on +} + +// MultichainresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type MultichainresolverCallerRaw struct { + Contract *MultichainresolverCaller // Generic read-only contract binding to access the raw methods on +} + +// MultichainresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type MultichainresolverTransactorRaw struct { + Contract *MultichainresolverTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewMultichainresolver creates a new instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolver(address common.Address, backend bind.ContractBackend) (*Multichainresolver, error) { + contract, err := bindMultichainresolver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Multichainresolver{MultichainresolverCaller: MultichainresolverCaller{contract: contract}, MultichainresolverTransactor: MultichainresolverTransactor{contract: contract}, MultichainresolverFilterer: MultichainresolverFilterer{contract: contract}}, nil +} + +// NewMultichainresolverCaller creates a new read-only instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverCaller(address common.Address, caller bind.ContractCaller) (*MultichainresolverCaller, error) { + contract, err := bindMultichainresolver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MultichainresolverCaller{contract: contract}, nil +} + +// NewMultichainresolverTransactor creates a new write-only instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*MultichainresolverTransactor, error) { + contract, err := bindMultichainresolver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MultichainresolverTransactor{contract: contract}, nil +} + +// NewMultichainresolverFilterer creates a new log filterer instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*MultichainresolverFilterer, error) { + contract, err := bindMultichainresolver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MultichainresolverFilterer{contract: contract}, nil +} + +// bindMultichainresolver binds a generic wrapper to an already deployed contract. +func bindMultichainresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(MultichainresolverABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Multichainresolver *MultichainresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Multichainresolver.Contract.MultichainresolverCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Multichainresolver *MultichainresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Multichainresolver *MultichainresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Multichainresolver *MultichainresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Multichainresolver.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Multichainresolver *MultichainresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Multichainresolver.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Multichainresolver *MultichainresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Multichainresolver.Contract.contract.Transact(opts, method, params...) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "addr", node) + return *ret0, err +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverSession) Addr(node [32]byte) (common.Address, error) { + return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverCallerSession) Addr(node [32]byte) (common.Address, error) { + return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverCaller) ChainAddr(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, error) { + var ( + ret0 = new(string) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "chainAddr", node, chain) + return *ret0, err +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { + return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverCallerSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { + return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverCaller) ChainAddrAndMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, [32]byte, error) { + var ( + ret0 = new(string) + ret1 = new([32]byte) + ) + out := &[]interface{}{ + ret0, + ret1, + } + err := _Multichainresolver.contract.Call(opts, out, "chainAddrAndMetadata", node, chain) + return *ret0, *ret1, err +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { + return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { + return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCaller) ChainMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "chainMetadata", node, chain) + return *ret0, err +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { + return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { + return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "content", node) + return *ret0, err +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverSession) Content(node [32]byte) ([32]byte, error) { + return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) Content(node [32]byte) ([32]byte, error) { + return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "supportsInterface", interfaceId) + return *ret0, err +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setAddr", node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainAddr(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainAddr", node, chain, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainAddrWithMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainAddrWithMetadata", node, chain, addrValue, metadataValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainMetadata", node, chain, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setContent", node, contentValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) +} + +// MultichainresolverAddrChangedIterator is returned from FilterAddrChanged and is used to iterate over the raw logs and unpacked data for AddrChanged events raised by the Multichainresolver contract. +type MultichainresolverAddrChangedIterator struct { + Event *MultichainresolverAddrChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverAddrChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverAddrChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverAddrChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverAddrChanged represents a AddrChanged event raised by the Multichainresolver contract. +type MultichainresolverAddrChanged struct { + Node [32]byte + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddrChanged is a free log retrieval operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) FilterAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverAddrChangedIterator, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "AddrChanged", nodeRule) + if err != nil { + return nil, err + } + return &MultichainresolverAddrChangedIterator{contract: _Multichainresolver.contract, event: "AddrChanged", logs: logs, sub: sub}, nil +} + +// WatchAddrChanged is a free log subscription operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) WatchAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverAddrChanged, node [][32]byte) (event.Subscription, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "AddrChanged", nodeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddrChanged is a log parse operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) ParseAddrChanged(log types.Log) (*MultichainresolverAddrChanged, error) { + event := new(MultichainresolverAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverChainAddrChangedIterator is returned from FilterChainAddrChanged and is used to iterate over the raw logs and unpacked data for ChainAddrChanged events raised by the Multichainresolver contract. +type MultichainresolverChainAddrChangedIterator struct { + Event *MultichainresolverChainAddrChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverChainAddrChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverChainAddrChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverChainAddrChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverChainAddrChanged represents a ChainAddrChanged event raised by the Multichainresolver contract. +type MultichainresolverChainAddrChanged struct { + Node [32]byte + Chain [4]byte + Addr string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChainAddrChanged is a free log retrieval operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) FilterChainAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverChainAddrChangedIterator, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainAddrChanged", nodeRule) + if err != nil { + return nil, err + } + return &MultichainresolverChainAddrChangedIterator{contract: _Multichainresolver.contract, event: "ChainAddrChanged", logs: logs, sub: sub}, nil +} + +// WatchChainAddrChanged is a free log subscription operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) WatchChainAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainAddrChanged, node [][32]byte) (event.Subscription, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainAddrChanged", nodeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverChainAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChainAddrChanged is a log parse operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) ParseChainAddrChanged(log types.Log) (*MultichainresolverChainAddrChanged, error) { + event := new(MultichainresolverChainAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverChainMetadataChangedIterator is returned from FilterChainMetadataChanged and is used to iterate over the raw logs and unpacked data for ChainMetadataChanged events raised by the Multichainresolver contract. +type MultichainresolverChainMetadataChangedIterator struct { + Event *MultichainresolverChainMetadataChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverChainMetadataChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainMetadataChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainMetadataChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverChainMetadataChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverChainMetadataChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverChainMetadataChanged represents a ChainMetadataChanged event raised by the Multichainresolver contract. +type MultichainresolverChainMetadataChanged struct { + Node [32]byte + Chain [4]byte + Metadata [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChainMetadataChanged is a free log retrieval operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) FilterChainMetadataChanged(opts *bind.FilterOpts) (*MultichainresolverChainMetadataChangedIterator, error) { + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainMetadataChanged") + if err != nil { + return nil, err + } + return &MultichainresolverChainMetadataChangedIterator{contract: _Multichainresolver.contract, event: "ChainMetadataChanged", logs: logs, sub: sub}, nil +} + +// WatchChainMetadataChanged is a free log subscription operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) WatchChainMetadataChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainMetadataChanged) (event.Subscription, error) { + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainMetadataChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverChainMetadataChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChainMetadataChanged is a log parse operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) ParseChainMetadataChanged(log types.Log) (*MultichainresolverChainMetadataChanged, error) { + event := new(MultichainresolverChainMetadataChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverContentChangedIterator is returned from FilterContentChanged and is used to iterate over the raw logs and unpacked data for ContentChanged events raised by the Multichainresolver contract. +type MultichainresolverContentChangedIterator struct { + Event *MultichainresolverContentChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverContentChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverContentChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverContentChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverContentChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverContentChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverContentChanged represents a ContentChanged event raised by the Multichainresolver contract. +type MultichainresolverContentChanged struct { + Node [32]byte + Content [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterContentChanged is a free log retrieval operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) FilterContentChanged(opts *bind.FilterOpts) (*MultichainresolverContentChangedIterator, error) { + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ContentChanged") + if err != nil { + return nil, err + } + return &MultichainresolverContentChangedIterator{contract: _Multichainresolver.contract, event: "ContentChanged", logs: logs, sub: sub}, nil +} + +// WatchContentChanged is a free log subscription operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) WatchContentChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverContentChanged) (event.Subscription, error) { + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ContentChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverContentChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseContentChanged is a log parse operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) ParseContentChanged(log types.Log) (*MultichainresolverContentChanged, error) { + event := new(MultichainresolverContentChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { + return nil, err + } + return event, nil +} diff --git a/vendor/github.com/caarlos0/env/resolver/resolver.go b/vendor/github.com/caarlos0/env/resolver/resolver.go new file mode 100644 index 0000000000..0699762308 --- /dev/null +++ b/vendor/github.com/caarlos0/env/resolver/resolver.go @@ -0,0 +1,153 @@ +package resolver + +import ( + "errors" + + config "github.com/rsksmart/rds-swarm/config" + multichainresolver "github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver" + rskresolver "github.com/rsksmart/rds-swarm/resolver/rsk_resolver" + "github.com/rsksmart/rds-swarm/utils" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// ErrNoAddress is returned when there is no registered address through RNS +var ErrNoAddress = errors.New("domain without registered address in RNS") + +// ErrNoContent is returned when there is no registered content through RNS +var ErrNoContent = errors.New("domain without registered content in RNS") + +// Resolver interface is implemented by all types which can resolve both the address of a domain as well as its content. +type Resolver interface { + Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) + Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) +} + +func getPublicResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { + resolverAddress := common.HexToAddress(configuration.ResolverAddresses.RSK) + resolver, resolverError := rskresolver.NewRskresolver(resolverAddress, client) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func getMultiChainResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { + resolverAddress := common.HexToAddress(configuration.ResolverAddresses.MultiChain) + resolver, resolverError := multichainresolver.NewMultichainresolver(resolverAddress, client) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func setUpResolver(resolverConstructor func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (Resolver, error) { + configuration := config.GetConfiguration() + + client, clientError := ethclient.Dial(configuration.NetworkNodeAddress) + if clientError != nil { + return nil, clientError + } + defer client.Close() + + resolver, resolverError := resolverConstructor(client, configuration) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func resolveAddressFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (common.Address, error) { + var emptyAddress common.Address + + resolver, resolverError := setUpResolver(getResolverFunction) + if resolverError != nil { + return emptyAddress, resolverError + } + + resolvedAddress, resolutionError := resolveAddress(domainAddress, resolver) + if resolutionError != nil { + return emptyAddress, resolutionError + } + + return resolvedAddress, nil +} + +func resolveAddress(byteArrayAddress [32]byte, resolver Resolver) (common.Address, error) { + return resolver.Addr(&bind.CallOpts{}, byteArrayAddress) +} + +func resolveContentFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) ([32]byte, error) { + var emptyContent [32]byte + + resolver, resolverError := setUpResolver(getResolverFunction) + if resolverError != nil { + return emptyContent, resolverError + } + + resolvedContent, resolutionError := resolveContent(domainAddress, resolver) + if resolutionError != nil { + return emptyContent, resolutionError + } + + return resolvedContent, nil +} + +func resolveContent(byteArrayAddress [32]byte, resolver Resolver) ([32]byte, error) { + return resolver.Content(&bind.CallOpts{}, byteArrayAddress) +} + +// ResolveDomainAddress receives a domain string and returns its RNS-resolved hex address. +// It will attempt to solve the address through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty address. +func ResolveDomainAddress(domain string) (common.Address, error) { + domainAddress := utils.DomainToHashedByteArray(domain) + var emptyAddress, resolvedAddress common.Address + var resolvedError error + + resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getMultiChainResolver) + if resolvedError != nil { + return emptyAddress, resolvedError + } + + if resolvedAddress == emptyAddress { + resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getPublicResolver) + if resolvedError != nil { + return emptyAddress, resolvedError + } + } + + if resolvedAddress == emptyAddress { + resolvedError = ErrNoAddress + } + return resolvedAddress, resolvedError +} + +// ResolveDomainContent receives a domain string and returns its RNS-resolved associated content hash. +// It will attempt to solve the content through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty content. +func ResolveDomainContent(domain string) (common.Hash, error) { + domainAddress := utils.DomainToHashedByteArray(domain) + var emptyContent, resolvedContent [32]byte + var resolvedError error + + resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getMultiChainResolver) + if resolvedError != nil { + return emptyContent, resolvedError + } + + if resolvedContent == emptyContent { + resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getPublicResolver) + if resolvedError != nil { + return emptyContent, resolvedError + } + } + + if resolvedContent == emptyContent { + resolvedError = ErrNoContent + } + return resolvedContent, resolvedError +} diff --git a/vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json b/vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json new file mode 100644 index 0000000000..513179bdcb --- /dev/null +++ b/vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json @@ -0,0 +1,134 @@ +[ + { + "inputs": [ + { + "name": "rnsAddr", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": false, + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "kind", + "type": "bytes32" + } + ], + "name": "has", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addrValue", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "content", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "hash", + "type": "bytes32" + } + ], + "name": "setContent", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go b/vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go new file mode 100644 index 0000000000..3915ef1747 --- /dev/null +++ b/vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go @@ -0,0 +1,319 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package rskresolver + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// RskresolverABI is the input ABI used to generate the binding from. +const RskresolverABI = "[{\"inputs\":[{\"name\":\"rnsAddr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"kind\",\"type\":\"bytes32\"}],\"name\":\"has\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" + +// Rskresolver is an auto generated Go binding around an Ethereum contract. +type Rskresolver struct { + RskresolverCaller // Read-only binding to the contract + RskresolverTransactor // Write-only binding to the contract + RskresolverFilterer // Log filterer for contract events +} + +// RskresolverCaller is an auto generated read-only Go binding around an Ethereum contract. +type RskresolverCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. +type RskresolverTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type RskresolverFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type RskresolverSession struct { + Contract *Rskresolver // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RskresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type RskresolverCallerSession struct { + Contract *RskresolverCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// RskresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type RskresolverTransactorSession struct { + Contract *RskresolverTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RskresolverRaw is an auto generated low-level Go binding around an Ethereum contract. +type RskresolverRaw struct { + Contract *Rskresolver // Generic contract binding to access the raw methods on +} + +// RskresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type RskresolverCallerRaw struct { + Contract *RskresolverCaller // Generic read-only contract binding to access the raw methods on +} + +// RskresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type RskresolverTransactorRaw struct { + Contract *RskresolverTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewRskresolver creates a new instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolver(address common.Address, backend bind.ContractBackend) (*Rskresolver, error) { + contract, err := bindRskresolver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Rskresolver{RskresolverCaller: RskresolverCaller{contract: contract}, RskresolverTransactor: RskresolverTransactor{contract: contract}, RskresolverFilterer: RskresolverFilterer{contract: contract}}, nil +} + +// NewRskresolverCaller creates a new read-only instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverCaller(address common.Address, caller bind.ContractCaller) (*RskresolverCaller, error) { + contract, err := bindRskresolver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RskresolverCaller{contract: contract}, nil +} + +// NewRskresolverTransactor creates a new write-only instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*RskresolverTransactor, error) { + contract, err := bindRskresolver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RskresolverTransactor{contract: contract}, nil +} + +// NewRskresolverFilterer creates a new log filterer instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*RskresolverFilterer, error) { + contract, err := bindRskresolver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RskresolverFilterer{contract: contract}, nil +} + +// bindRskresolver binds a generic wrapper to an already deployed contract. +func bindRskresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(RskresolverABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rskresolver *RskresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Rskresolver.Contract.RskresolverCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rskresolver *RskresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rskresolver.Contract.RskresolverTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rskresolver *RskresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rskresolver.Contract.RskresolverTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rskresolver *RskresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Rskresolver.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rskresolver *RskresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rskresolver.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rskresolver *RskresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rskresolver.Contract.contract.Transact(opts, method, params...) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "addr", node) + return *ret0, err +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverSession) Addr(node [32]byte) (common.Address, error) { + return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverCallerSession) Addr(node [32]byte) (common.Address, error) { + return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "content", node) + return *ret0, err +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverSession) Content(node [32]byte) ([32]byte, error) { + return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverCallerSession) Content(node [32]byte) ([32]byte, error) { + return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverCaller) Has(opts *bind.CallOpts, node [32]byte, kind [32]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "has", node, kind) + return *ret0, err +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverSession) Has(node [32]byte, kind [32]byte) (bool, error) { + return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverCallerSession) Has(node [32]byte, kind [32]byte) (bool, error) { + return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "supportsInterface", interfaceID) + return *ret0, err +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.contract.Transact(opts, "setAddr", node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.contract.Transact(opts, "setContent", node, hash) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) +} diff --git a/vendor/github.com/caarlos0/env/utils/utils.go b/vendor/github.com/caarlos0/env/utils/utils.go new file mode 100644 index 0000000000..c831dbf4c9 --- /dev/null +++ b/vendor/github.com/caarlos0/env/utils/utils.go @@ -0,0 +1,35 @@ +package utils + +import ( + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// DomainToHashedByteArray takes a string containing a domain, hashes it and returns it as an array of 32 bytes. +func DomainToHashedByteArray(domain string) [32]byte { + var byteArrayAddress [32]byte + + hashedAddress := RnsNode(domain) + byteSliceAddress := hashedAddress.Bytes() + copy(byteArrayAddress[:], byteSliceAddress[:32]) + + return byteArrayAddress +} + +// RnsNode takes a string containing a domain, hashes it and returns it as a Keccak256Hash. +func RnsNode(name string) common.Hash { + parentNode, parentLabel := rnsParentNode(name) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) +} + +func rnsParentNode(name string) (common.Hash, common.Hash) { + parts := strings.SplitN(name, ".", 2) + label := crypto.Keccak256Hash([]byte(parts[0])) + if len(parts) == 1 { + return [32]byte{}, label + } + parentNode, parentLabel := rnsParentNode(parts[1]) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label +} diff --git a/vendor/github.com/rds-swarm/config/config.go b/vendor/github.com/rds-swarm/config/config.go new file mode 100644 index 0000000000..1884f140ea --- /dev/null +++ b/vendor/github.com/rds-swarm/config/config.go @@ -0,0 +1,38 @@ +package config + +import ( + "github.com/caarlos0/env" +) + +func init() { + env.Parse(&cfg) + env.Parse(&cfg.ResolverAddresses) +} + +// Configuration is the struct that holds the values of the network configuration +// env and envDefault are required by env library +// it corresponds with the os environment variable name and also its default value if omitted +type Configuration struct { + NetworkNodeAddress string `env:"RNS_NETWORK_NODE_ADDRESS" envDefault:"https://public-node.rsk.co"` + ResolverAddresses struct { + RSK string `env:"RNS_RESOLVER_ADDRESS_RSK" envDefault:"0x4efd25e3d348f8f25a14fb7655fba6f72edfe93a"` + MultiChain string `env:"RNS_RESOLVER_ADDRESS_MULTICHAIN" envDefault:"0x99a12be4C89CbF6CFD11d1F2c029904a7B644368"` + } +} + +var cfg Configuration = Configuration{} + +// GetConfiguration loads the environment variables into a Configuration struct and returns it. +func GetConfiguration() Configuration { + return cfg +} + +// SetRSKConfiguration overrides endpoint and contract to rns node +func SetRSKConfiguration(endpoint string, contract string) { + if endpoint != "" { + cfg.NetworkNodeAddress = endpoint + } + if contract != "" { + cfg.ResolverAddresses.RSK = contract + } +} diff --git a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json new file mode 100644 index 0000000000..962eb5dd95 --- /dev/null +++ b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json @@ -0,0 +1,336 @@ +[ + { + "inputs": [ + { + "name": "_rns", + "type": "address" + }, + { + "name": "_publicResolver", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": false, + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "content", + "type": "bytes32" + } + ], + "name": "ContentChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "chain", + "type": "bytes4" + }, + { + "indexed": false, + "name": "metadata", + "type": "bytes32" + } + ], + "name": "ChainMetadataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "chain", + "type": "bytes4" + }, + { + "indexed": false, + "name": "addr", + "type": "string" + } + ], + "name": "ChainAddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "addr", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addrValue", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "content", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "contentValue", + "type": "bytes32" + } + ], + "name": "setContent", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainAddr", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "addrValue", + "type": "string" + } + ], + "name": "setChainAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainMetadata", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "metadataValue", + "type": "bytes32" + } + ], + "name": "setChainMetadata", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + } + ], + "name": "chainAddrAndMetadata", + "outputs": [ + { + "name": "", + "type": "string" + }, + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "chain", + "type": "bytes4" + }, + { + "name": "addrValue", + "type": "string" + }, + { + "name": "metadataValue", + "type": "bytes32" + } + ], + "name": "setChainAddrWithMetadata", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go new file mode 100644 index 0000000000..0e4b1a3a21 --- /dev/null +++ b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go @@ -0,0 +1,996 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package multichainresolver + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// MultichainresolverABI is the input ABI used to generate the binding from. +const MultichainresolverABI = "[{\"inputs\":[{\"name\":\"_rns\",\"type\":\"address\"},{\"name\":\"_publicResolver\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"content\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"metadata\",\"type\":\"bytes32\"}],\"name\":\"ChainMetadataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"string\"}],\"name\":\"ChainAddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentValue\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddr\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"}],\"name\":\"setChainAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddrAndMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainAddrWithMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" + +// Multichainresolver is an auto generated Go binding around an Ethereum contract. +type Multichainresolver struct { + MultichainresolverCaller // Read-only binding to the contract + MultichainresolverTransactor // Write-only binding to the contract + MultichainresolverFilterer // Log filterer for contract events +} + +// MultichainresolverCaller is an auto generated read-only Go binding around an Ethereum contract. +type MultichainresolverCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. +type MultichainresolverTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type MultichainresolverFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MultichainresolverSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type MultichainresolverSession struct { + Contract *Multichainresolver // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MultichainresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type MultichainresolverCallerSession struct { + Contract *MultichainresolverCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// MultichainresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type MultichainresolverTransactorSession struct { + Contract *MultichainresolverTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MultichainresolverRaw is an auto generated low-level Go binding around an Ethereum contract. +type MultichainresolverRaw struct { + Contract *Multichainresolver // Generic contract binding to access the raw methods on +} + +// MultichainresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type MultichainresolverCallerRaw struct { + Contract *MultichainresolverCaller // Generic read-only contract binding to access the raw methods on +} + +// MultichainresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type MultichainresolverTransactorRaw struct { + Contract *MultichainresolverTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewMultichainresolver creates a new instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolver(address common.Address, backend bind.ContractBackend) (*Multichainresolver, error) { + contract, err := bindMultichainresolver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Multichainresolver{MultichainresolverCaller: MultichainresolverCaller{contract: contract}, MultichainresolverTransactor: MultichainresolverTransactor{contract: contract}, MultichainresolverFilterer: MultichainresolverFilterer{contract: contract}}, nil +} + +// NewMultichainresolverCaller creates a new read-only instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverCaller(address common.Address, caller bind.ContractCaller) (*MultichainresolverCaller, error) { + contract, err := bindMultichainresolver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MultichainresolverCaller{contract: contract}, nil +} + +// NewMultichainresolverTransactor creates a new write-only instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*MultichainresolverTransactor, error) { + contract, err := bindMultichainresolver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MultichainresolverTransactor{contract: contract}, nil +} + +// NewMultichainresolverFilterer creates a new log filterer instance of Multichainresolver, bound to a specific deployed contract. +func NewMultichainresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*MultichainresolverFilterer, error) { + contract, err := bindMultichainresolver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MultichainresolverFilterer{contract: contract}, nil +} + +// bindMultichainresolver binds a generic wrapper to an already deployed contract. +func bindMultichainresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(MultichainresolverABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Multichainresolver *MultichainresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Multichainresolver.Contract.MultichainresolverCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Multichainresolver *MultichainresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Multichainresolver *MultichainresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Multichainresolver *MultichainresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Multichainresolver.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Multichainresolver *MultichainresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Multichainresolver.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Multichainresolver *MultichainresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Multichainresolver.Contract.contract.Transact(opts, method, params...) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "addr", node) + return *ret0, err +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverSession) Addr(node [32]byte) (common.Address, error) { + return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Multichainresolver *MultichainresolverCallerSession) Addr(node [32]byte) (common.Address, error) { + return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverCaller) ChainAddr(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, error) { + var ( + ret0 = new(string) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "chainAddr", node, chain) + return *ret0, err +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { + return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. +// +// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) +func (_Multichainresolver *MultichainresolverCallerSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { + return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverCaller) ChainAddrAndMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, [32]byte, error) { + var ( + ret0 = new(string) + ret1 = new([32]byte) + ) + out := &[]interface{}{ + ret0, + ret1, + } + err := _Multichainresolver.contract.Call(opts, out, "chainAddrAndMetadata", node, chain) + return *ret0, *ret1, err +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { + return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. +// +// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { + return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCaller) ChainMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "chainMetadata", node, chain) + return *ret0, err +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { + return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. +// +// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { + return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "content", node) + return *ret0, err +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverSession) Content(node [32]byte) ([32]byte, error) { + return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Multichainresolver *MultichainresolverCallerSession) Content(node [32]byte) ([32]byte, error) { + return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Multichainresolver.contract.Call(opts, out, "supportsInterface", interfaceId) + return *ret0, err +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) +func (_Multichainresolver *MultichainresolverCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setAddr", node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainAddr(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainAddr", node, chain, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) +} + +// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. +// +// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainAddrWithMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainAddrWithMetadata", node, chain, addrValue, metadataValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) +} + +// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. +// +// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetChainMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setChainMetadata", node, chain, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) +} + +// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. +// +// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.contract.Transact(opts, "setContent", node, contentValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() +func (_Multichainresolver *MultichainresolverTransactorSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { + return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) +} + +// MultichainresolverAddrChangedIterator is returned from FilterAddrChanged and is used to iterate over the raw logs and unpacked data for AddrChanged events raised by the Multichainresolver contract. +type MultichainresolverAddrChangedIterator struct { + Event *MultichainresolverAddrChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverAddrChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverAddrChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverAddrChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverAddrChanged represents a AddrChanged event raised by the Multichainresolver contract. +type MultichainresolverAddrChanged struct { + Node [32]byte + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddrChanged is a free log retrieval operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) FilterAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverAddrChangedIterator, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "AddrChanged", nodeRule) + if err != nil { + return nil, err + } + return &MultichainresolverAddrChangedIterator{contract: _Multichainresolver.contract, event: "AddrChanged", logs: logs, sub: sub}, nil +} + +// WatchAddrChanged is a free log subscription operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) WatchAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverAddrChanged, node [][32]byte) (event.Subscription, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "AddrChanged", nodeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddrChanged is a log parse operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. +// +// Solidity: event AddrChanged(bytes32 indexed node, address addr) +func (_Multichainresolver *MultichainresolverFilterer) ParseAddrChanged(log types.Log) (*MultichainresolverAddrChanged, error) { + event := new(MultichainresolverAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverChainAddrChangedIterator is returned from FilterChainAddrChanged and is used to iterate over the raw logs and unpacked data for ChainAddrChanged events raised by the Multichainresolver contract. +type MultichainresolverChainAddrChangedIterator struct { + Event *MultichainresolverChainAddrChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverChainAddrChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainAddrChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverChainAddrChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverChainAddrChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverChainAddrChanged represents a ChainAddrChanged event raised by the Multichainresolver contract. +type MultichainresolverChainAddrChanged struct { + Node [32]byte + Chain [4]byte + Addr string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChainAddrChanged is a free log retrieval operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) FilterChainAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverChainAddrChangedIterator, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainAddrChanged", nodeRule) + if err != nil { + return nil, err + } + return &MultichainresolverChainAddrChangedIterator{contract: _Multichainresolver.contract, event: "ChainAddrChanged", logs: logs, sub: sub}, nil +} + +// WatchChainAddrChanged is a free log subscription operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) WatchChainAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainAddrChanged, node [][32]byte) (event.Subscription, error) { + + var nodeRule []interface{} + for _, nodeItem := range node { + nodeRule = append(nodeRule, nodeItem) + } + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainAddrChanged", nodeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverChainAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChainAddrChanged is a log parse operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. +// +// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) +func (_Multichainresolver *MultichainresolverFilterer) ParseChainAddrChanged(log types.Log) (*MultichainresolverChainAddrChanged, error) { + event := new(MultichainresolverChainAddrChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverChainMetadataChangedIterator is returned from FilterChainMetadataChanged and is used to iterate over the raw logs and unpacked data for ChainMetadataChanged events raised by the Multichainresolver contract. +type MultichainresolverChainMetadataChangedIterator struct { + Event *MultichainresolverChainMetadataChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverChainMetadataChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainMetadataChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverChainMetadataChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverChainMetadataChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverChainMetadataChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverChainMetadataChanged represents a ChainMetadataChanged event raised by the Multichainresolver contract. +type MultichainresolverChainMetadataChanged struct { + Node [32]byte + Chain [4]byte + Metadata [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChainMetadataChanged is a free log retrieval operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) FilterChainMetadataChanged(opts *bind.FilterOpts) (*MultichainresolverChainMetadataChangedIterator, error) { + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainMetadataChanged") + if err != nil { + return nil, err + } + return &MultichainresolverChainMetadataChangedIterator{contract: _Multichainresolver.contract, event: "ChainMetadataChanged", logs: logs, sub: sub}, nil +} + +// WatchChainMetadataChanged is a free log subscription operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) WatchChainMetadataChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainMetadataChanged) (event.Subscription, error) { + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainMetadataChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverChainMetadataChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChainMetadataChanged is a log parse operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. +// +// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) +func (_Multichainresolver *MultichainresolverFilterer) ParseChainMetadataChanged(log types.Log) (*MultichainresolverChainMetadataChanged, error) { + event := new(MultichainresolverChainMetadataChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { + return nil, err + } + return event, nil +} + +// MultichainresolverContentChangedIterator is returned from FilterContentChanged and is used to iterate over the raw logs and unpacked data for ContentChanged events raised by the Multichainresolver contract. +type MultichainresolverContentChangedIterator struct { + Event *MultichainresolverContentChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *MultichainresolverContentChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultichainresolverContentChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(MultichainresolverContentChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *MultichainresolverContentChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *MultichainresolverContentChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// MultichainresolverContentChanged represents a ContentChanged event raised by the Multichainresolver contract. +type MultichainresolverContentChanged struct { + Node [32]byte + Content [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterContentChanged is a free log retrieval operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) FilterContentChanged(opts *bind.FilterOpts) (*MultichainresolverContentChangedIterator, error) { + + logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ContentChanged") + if err != nil { + return nil, err + } + return &MultichainresolverContentChangedIterator{contract: _Multichainresolver.contract, event: "ContentChanged", logs: logs, sub: sub}, nil +} + +// WatchContentChanged is a free log subscription operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) WatchContentChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverContentChanged) (event.Subscription, error) { + + logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ContentChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(MultichainresolverContentChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseContentChanged is a log parse operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. +// +// Solidity: event ContentChanged(bytes32 node, bytes32 content) +func (_Multichainresolver *MultichainresolverFilterer) ParseContentChanged(log types.Log) (*MultichainresolverContentChanged, error) { + event := new(MultichainresolverContentChanged) + if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { + return nil, err + } + return event, nil +} diff --git a/vendor/github.com/rds-swarm/resolver/resolver.go b/vendor/github.com/rds-swarm/resolver/resolver.go new file mode 100644 index 0000000000..0699762308 --- /dev/null +++ b/vendor/github.com/rds-swarm/resolver/resolver.go @@ -0,0 +1,153 @@ +package resolver + +import ( + "errors" + + config "github.com/rsksmart/rds-swarm/config" + multichainresolver "github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver" + rskresolver "github.com/rsksmart/rds-swarm/resolver/rsk_resolver" + "github.com/rsksmart/rds-swarm/utils" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// ErrNoAddress is returned when there is no registered address through RNS +var ErrNoAddress = errors.New("domain without registered address in RNS") + +// ErrNoContent is returned when there is no registered content through RNS +var ErrNoContent = errors.New("domain without registered content in RNS") + +// Resolver interface is implemented by all types which can resolve both the address of a domain as well as its content. +type Resolver interface { + Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) + Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) +} + +func getPublicResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { + resolverAddress := common.HexToAddress(configuration.ResolverAddresses.RSK) + resolver, resolverError := rskresolver.NewRskresolver(resolverAddress, client) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func getMultiChainResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { + resolverAddress := common.HexToAddress(configuration.ResolverAddresses.MultiChain) + resolver, resolverError := multichainresolver.NewMultichainresolver(resolverAddress, client) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func setUpResolver(resolverConstructor func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (Resolver, error) { + configuration := config.GetConfiguration() + + client, clientError := ethclient.Dial(configuration.NetworkNodeAddress) + if clientError != nil { + return nil, clientError + } + defer client.Close() + + resolver, resolverError := resolverConstructor(client, configuration) + if resolverError != nil { + return nil, resolverError + } + + return resolver, nil +} + +func resolveAddressFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (common.Address, error) { + var emptyAddress common.Address + + resolver, resolverError := setUpResolver(getResolverFunction) + if resolverError != nil { + return emptyAddress, resolverError + } + + resolvedAddress, resolutionError := resolveAddress(domainAddress, resolver) + if resolutionError != nil { + return emptyAddress, resolutionError + } + + return resolvedAddress, nil +} + +func resolveAddress(byteArrayAddress [32]byte, resolver Resolver) (common.Address, error) { + return resolver.Addr(&bind.CallOpts{}, byteArrayAddress) +} + +func resolveContentFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) ([32]byte, error) { + var emptyContent [32]byte + + resolver, resolverError := setUpResolver(getResolverFunction) + if resolverError != nil { + return emptyContent, resolverError + } + + resolvedContent, resolutionError := resolveContent(domainAddress, resolver) + if resolutionError != nil { + return emptyContent, resolutionError + } + + return resolvedContent, nil +} + +func resolveContent(byteArrayAddress [32]byte, resolver Resolver) ([32]byte, error) { + return resolver.Content(&bind.CallOpts{}, byteArrayAddress) +} + +// ResolveDomainAddress receives a domain string and returns its RNS-resolved hex address. +// It will attempt to solve the address through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty address. +func ResolveDomainAddress(domain string) (common.Address, error) { + domainAddress := utils.DomainToHashedByteArray(domain) + var emptyAddress, resolvedAddress common.Address + var resolvedError error + + resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getMultiChainResolver) + if resolvedError != nil { + return emptyAddress, resolvedError + } + + if resolvedAddress == emptyAddress { + resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getPublicResolver) + if resolvedError != nil { + return emptyAddress, resolvedError + } + } + + if resolvedAddress == emptyAddress { + resolvedError = ErrNoAddress + } + return resolvedAddress, resolvedError +} + +// ResolveDomainContent receives a domain string and returns its RNS-resolved associated content hash. +// It will attempt to solve the content through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty content. +func ResolveDomainContent(domain string) (common.Hash, error) { + domainAddress := utils.DomainToHashedByteArray(domain) + var emptyContent, resolvedContent [32]byte + var resolvedError error + + resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getMultiChainResolver) + if resolvedError != nil { + return emptyContent, resolvedError + } + + if resolvedContent == emptyContent { + resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getPublicResolver) + if resolvedError != nil { + return emptyContent, resolvedError + } + } + + if resolvedContent == emptyContent { + resolvedError = ErrNoContent + } + return resolvedContent, resolvedError +} diff --git a/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json b/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json new file mode 100644 index 0000000000..513179bdcb --- /dev/null +++ b/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json @@ -0,0 +1,134 @@ +[ + { + "inputs": [ + { + "name": "rnsAddr", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": false, + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "kind", + "type": "bytes32" + } + ], + "name": "has", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addrValue", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "content", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "hash", + "type": "bytes32" + } + ], + "name": "setContent", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go b/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go new file mode 100644 index 0000000000..3915ef1747 --- /dev/null +++ b/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go @@ -0,0 +1,319 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package rskresolver + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// RskresolverABI is the input ABI used to generate the binding from. +const RskresolverABI = "[{\"inputs\":[{\"name\":\"rnsAddr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"kind\",\"type\":\"bytes32\"}],\"name\":\"has\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" + +// Rskresolver is an auto generated Go binding around an Ethereum contract. +type Rskresolver struct { + RskresolverCaller // Read-only binding to the contract + RskresolverTransactor // Write-only binding to the contract + RskresolverFilterer // Log filterer for contract events +} + +// RskresolverCaller is an auto generated read-only Go binding around an Ethereum contract. +type RskresolverCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. +type RskresolverTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type RskresolverFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RskresolverSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type RskresolverSession struct { + Contract *Rskresolver // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RskresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type RskresolverCallerSession struct { + Contract *RskresolverCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// RskresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type RskresolverTransactorSession struct { + Contract *RskresolverTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RskresolverRaw is an auto generated low-level Go binding around an Ethereum contract. +type RskresolverRaw struct { + Contract *Rskresolver // Generic contract binding to access the raw methods on +} + +// RskresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type RskresolverCallerRaw struct { + Contract *RskresolverCaller // Generic read-only contract binding to access the raw methods on +} + +// RskresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type RskresolverTransactorRaw struct { + Contract *RskresolverTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewRskresolver creates a new instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolver(address common.Address, backend bind.ContractBackend) (*Rskresolver, error) { + contract, err := bindRskresolver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Rskresolver{RskresolverCaller: RskresolverCaller{contract: contract}, RskresolverTransactor: RskresolverTransactor{contract: contract}, RskresolverFilterer: RskresolverFilterer{contract: contract}}, nil +} + +// NewRskresolverCaller creates a new read-only instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverCaller(address common.Address, caller bind.ContractCaller) (*RskresolverCaller, error) { + contract, err := bindRskresolver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RskresolverCaller{contract: contract}, nil +} + +// NewRskresolverTransactor creates a new write-only instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*RskresolverTransactor, error) { + contract, err := bindRskresolver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RskresolverTransactor{contract: contract}, nil +} + +// NewRskresolverFilterer creates a new log filterer instance of Rskresolver, bound to a specific deployed contract. +func NewRskresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*RskresolverFilterer, error) { + contract, err := bindRskresolver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RskresolverFilterer{contract: contract}, nil +} + +// bindRskresolver binds a generic wrapper to an already deployed contract. +func bindRskresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(RskresolverABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rskresolver *RskresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Rskresolver.Contract.RskresolverCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rskresolver *RskresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rskresolver.Contract.RskresolverTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rskresolver *RskresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rskresolver.Contract.RskresolverTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rskresolver *RskresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _Rskresolver.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rskresolver *RskresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rskresolver.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rskresolver *RskresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rskresolver.Contract.contract.Transact(opts, method, params...) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "addr", node) + return *ret0, err +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverSession) Addr(node [32]byte) (common.Address, error) { + return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) +} + +// Addr is a free data retrieval call binding the contract method 0x3b3b57de. +// +// Solidity: function addr(bytes32 node) constant returns(address) +func (_Rskresolver *RskresolverCallerSession) Addr(node [32]byte) (common.Address, error) { + return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "content", node) + return *ret0, err +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverSession) Content(node [32]byte) ([32]byte, error) { + return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) +} + +// Content is a free data retrieval call binding the contract method 0x2dff6941. +// +// Solidity: function content(bytes32 node) constant returns(bytes32) +func (_Rskresolver *RskresolverCallerSession) Content(node [32]byte) ([32]byte, error) { + return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverCaller) Has(opts *bind.CallOpts, node [32]byte, kind [32]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "has", node, kind) + return *ret0, err +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverSession) Has(node [32]byte, kind [32]byte) (bool, error) { + return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) +} + +// Has is a free data retrieval call binding the contract method 0x41b9dc2b. +// +// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) +func (_Rskresolver *RskresolverCallerSession) Has(node [32]byte, kind [32]byte) (bool, error) { + return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Rskresolver.contract.Call(opts, out, "supportsInterface", interfaceID) + return *ret0, err +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) +func (_Rskresolver *RskresolverCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.contract.Transact(opts, "setAddr", node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) +} + +// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. +// +// Solidity: function setAddr(bytes32 node, address addrValue) returns() +func (_Rskresolver *RskresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { + return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.contract.Transact(opts, "setContent", node, hash) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) +} + +// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. +// +// Solidity: function setContent(bytes32 node, bytes32 hash) returns() +func (_Rskresolver *RskresolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { + return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) +} diff --git a/vendor/github.com/rds-swarm/utils/utils.go b/vendor/github.com/rds-swarm/utils/utils.go new file mode 100644 index 0000000000..c831dbf4c9 --- /dev/null +++ b/vendor/github.com/rds-swarm/utils/utils.go @@ -0,0 +1,35 @@ +package utils + +import ( + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// DomainToHashedByteArray takes a string containing a domain, hashes it and returns it as an array of 32 bytes. +func DomainToHashedByteArray(domain string) [32]byte { + var byteArrayAddress [32]byte + + hashedAddress := RnsNode(domain) + byteSliceAddress := hashedAddress.Bytes() + copy(byteArrayAddress[:], byteSliceAddress[:32]) + + return byteArrayAddress +} + +// RnsNode takes a string containing a domain, hashes it and returns it as a Keccak256Hash. +func RnsNode(name string) common.Hash { + parentNode, parentLabel := rnsParentNode(name) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) +} + +func rnsParentNode(name string) (common.Hash, common.Hash) { + parts := strings.SplitN(name, ".", 2) + label := crypto.Keccak256Hash([]byte(parts[0])) + if len(parts) == 1 { + return [32]byte{}, label + } + parentNode, parentLabel := rnsParentNode(parts[1]) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label +} From 8d5e639e8eafb6fd79feea654f5937cc72cdb1f6 Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Mon, 11 Nov 2019 16:51:05 -0300 Subject: [PATCH 21/49] vendor: make vendor --- vendor/github.com/StackExchange/wmi/LICENSE | 20 - vendor/github.com/StackExchange/wmi/README.md | 6 - .../StackExchange/wmi/swbemservices.go | 260 - vendor/github.com/StackExchange/wmi/wmi.go | 501 - .../goarista/monotime/issue15006.s | 2 +- .../goarista/monotime/nanotime.go | 2 +- .../github.com/btcsuite/btcd/btcec/btcec.go | 24 +- .../github.com/btcsuite/btcd/btcec/field.go | 129 + .../btcsuite/btcd/btcec/genprecomps.go | 63 - .../github.com/btcsuite/btcd/btcec/pubkey.go | 59 +- .../btcsuite/btcd/btcec/signature.go | 22 +- vendor/github.com/caarlos0/env/.gitignore | 1 + vendor/github.com/caarlos0/env/.hound.yml | 2 + vendor/github.com/caarlos0/env/.travis.yml | 19 + .../LICENSE => caarlos0/env/LICENSE.md} | 12 +- vendor/github.com/caarlos0/env/README.md | 119 + vendor/github.com/caarlos0/env/env.go | 436 + .../deckarep/golang-set/threadsafe.go | 8 +- .../docker/pkg/archive/example_changes.go | 97 - vendor/github.com/edsrzf/mmap-go/mmap.go | 21 +- vendor/github.com/edsrzf/mmap-go/mmap_unix.go | 50 +- .../github.com/edsrzf/mmap-go/mmap_windows.go | 64 +- .../github.com/edsrzf/mmap-go/msync_netbsd.go | 8 - .../github.com/edsrzf/mmap-go/msync_unix.go | 14 - vendor/github.com/elastic/gosigar/.travis.yml | 3 +- .../github.com/elastic/gosigar/CHANGELOG.md | 43 +- vendor/github.com/elastic/gosigar/README.md | 1 + .../elastic/gosigar/sigar_darwin.go | 12 - .../elastic/gosigar/sigar_darwin_386.go | 18 + .../elastic/gosigar/sigar_darwin_amd64.go | 18 + .../elastic/gosigar/sigar_freebsd.go | 45 + .../elastic/gosigar/sigar_interface.go | 42 +- .../github.com/elastic/gosigar/sigar_linux.go | 25 + .../elastic/gosigar/sigar_linux_common.go | 25 - .../elastic/gosigar/sigar_windows.go | 114 +- .../elastic/gosigar/sys/windows/doc.go | 6 + .../gosigar/sys/windows/syscall_windows.go | 252 +- .../gosigar/sys/windows/zsyscall_windows.go | 198 +- .../ethereum/go-ethereum/.travis.yml | 31 +- .../ethereum/go-ethereum/Dockerfile | 4 +- .../ethereum/go-ethereum/Dockerfile.alltools | 4 +- .../github.com/ethereum/go-ethereum/Makefile | 2 +- .../github.com/ethereum/go-ethereum/README.md | 16 +- .../ethereum/go-ethereum/accounts/abi/abi.go | 6 - .../go-ethereum/accounts/abi/argument.go | 26 +- .../go-ethereum/accounts/abi/bind/base.go | 2 +- .../go-ethereum/accounts/abi/bind/bind.go | 84 +- .../go-ethereum/accounts/abi/bind/template.go | 4 +- .../go-ethereum/accounts/abi/bind/topics.go | 13 +- .../ethereum/go-ethereum/accounts/abi/type.go | 25 +- .../go-ethereum/accounts/usbwallet/ledger.go | 3 +- .../ethereum/go-ethereum/appveyor.yml | 4 +- .../go-ethereum/cmd/utils/customflags.go | 82 +- .../ethereum/go-ethereum/cmd/utils/flags.go | 42 +- .../ethereum/go-ethereum/common/bytes.go | 21 +- .../go-ethereum/common/mclock/mclock.go | 30 +- .../go-ethereum/common/mclock/simclock.go | 72 +- .../ethereum/go-ethereum/common/types.go | 6 +- .../go-ethereum/consensus/clique/clique.go | 10 +- .../ethereum/go-ethereum/consensus/errors.go | 2 +- .../go-ethereum/consensus/ethash/consensus.go | 4 +- .../ethereum/go-ethereum/core/blockchain.go | 52 +- .../ethereum/go-ethereum/core/chain_makers.go | 2 +- .../go-ethereum/core/forkid/forkid.go | 27 +- .../ethereum/go-ethereum/core/genesis.go | 25 +- .../ethereum/go-ethereum/core/headerchain.go | 11 +- .../go-ethereum/core/rawdb/freezer.go | 8 +- .../go-ethereum/core/rawdb/freezer_table.go | 22 +- .../go-ethereum/core/state/state_object.go | 58 +- .../go-ethereum/core/state/statedb.go | 168 +- .../go-ethereum/core/state_processor.go | 10 +- .../go-ethereum/core/state_transition.go | 15 +- .../ethereum/go-ethereum/core/tx_pool.go | 112 +- .../core/types/transaction_signing.go | 6 +- .../ethereum/go-ethereum/core/vm/contracts.go | 71 +- .../ethereum/go-ethereum/core/vm/eips.go | 7 + .../ethereum/go-ethereum/core/vm/gas_table.go | 57 + .../go-ethereum/core/vm/instructions.go | 24 +- .../go-ethereum/core/vm/interpreter.go | 2 + .../go-ethereum/core/vm/jump_table.go | 23 +- .../ethereum/go-ethereum/core/vm/memory.go | 2 +- .../go-ethereum/crypto/blake2b/blake2b.go | 319 + .../crypto/blake2b/blake2bAVX2_amd64.go | 37 + .../crypto/blake2b/blake2bAVX2_amd64.s | 717 ++ .../crypto/blake2b/blake2b_amd64.go | 24 + .../crypto/blake2b/blake2b_amd64.s | 253 + .../crypto/blake2b/blake2b_f_fuzz.go | 57 + .../crypto/blake2b/blake2b_generic.go | 180 + .../go-ethereum/crypto/blake2b/blake2b_ref.go | 11 + .../go-ethereum/crypto/blake2b/blake2x.go | 177 + .../go-ethereum/crypto/blake2b/register.go | 32 + .../ethereum/go-ethereum/crypto/crypto.go | 9 + .../go-ethereum/crypto/signature_cgo.go | 16 +- .../go-ethereum/crypto/signature_nocgo.go | 2 +- .../ethereum/go-ethereum/dashboard/README.md | 4 +- .../go-ethereum/dashboard/dashboard.go | 2 +- .../ethereum/go-ethereum/eth/api.go | 5 + .../ethereum/go-ethereum/eth/api_backend.go | 59 + .../ethereum/go-ethereum/eth/backend.go | 4 +- .../ethereum/go-ethereum/eth/config.go | 3 + .../go-ethereum/eth/downloader/downloader.go | 35 +- .../go-ethereum/eth/downloader/statesync.go | 2 +- .../ethereum/go-ethereum/eth/handler.go | 7 +- .../ethereum/go-ethereum/eth/peer.go | 90 +- .../ethereum/go-ethereum/eth/protocol.go | 44 +- .../go-ethereum/eth/tracers/tracer.go | 4 +- .../go-ethereum/ethdb/leveldb/leveldb.go | 48 +- .../ethereum/go-ethereum/graphql/graphiql.go | 2 +- .../ethereum/go-ethereum/graphql/graphql.go | 248 +- .../go-ethereum/internal/ethapi/api.go | 68 +- .../go-ethereum/internal/ethapi/backend.go | 3 + .../go-ethereum/internal/web3ext/web3ext.go | 6 + .../ethereum/go-ethereum/les/api.go | 14 +- .../ethereum/go-ethereum/les/api_backend.go | 59 +- .../ethereum/go-ethereum/les/balance.go | 8 +- .../ethereum/go-ethereum/les/benchmark.go | 48 +- .../ethereum/go-ethereum/les/bloombits.go | 3 +- .../go-ethereum/les/checkpointoracle.go | 7 +- .../go-ethereum/les/{backend.go => client.go} | 133 +- .../go-ethereum/les/client_handler.go | 403 + .../ethereum/go-ethereum/les/clientpool.go | 625 +- .../ethereum/go-ethereum/les/commons.go | 69 +- .../ethereum/go-ethereum/les/costtracker.go | 54 +- .../ethereum/go-ethereum/les/distributor.go | 51 +- .../ethereum/go-ethereum/les/enr_entry.go | 32 + .../ethereum/go-ethereum/les/fetcher.go | 75 +- .../ethereum/go-ethereum/les/handler.go | 1293 --- .../ethereum/go-ethereum/les/metrics.go | 108 +- .../ethereum/go-ethereum/les/odr.go | 5 +- .../ethereum/go-ethereum/les/peer.go | 56 +- .../ethereum/go-ethereum/les/server.go | 343 +- .../go-ethereum/les/server_handler.go | 950 ++ .../ethereum/go-ethereum/les/serverpool.go | 61 +- .../ethereum/go-ethereum/les/sync.go | 80 +- .../ethereum/go-ethereum/les/test_helper.go | 558 + .../ethereum/go-ethereum/light/lightchain.go | 8 +- .../ethereum/go-ethereum/light/odr_util.go | 6 +- .../ethereum/go-ethereum/light/postprocess.go | 30 +- .../ethereum/go-ethereum/light/txpool.go | 11 +- .../ethereum/go-ethereum/log/README.md | 4 +- .../ethereum/go-ethereum/metrics/README.md | 4 +- .../ethereum/go-ethereum/metrics/gauge.go | 38 + .../ethereum/go-ethereum/miner/worker.go | 2 +- .../ethereum/go-ethereum/p2p/dial.go | 145 +- .../go-ethereum/p2p/discover/common.go | 5 +- .../go-ethereum/p2p/discover/lookup.go | 209 + .../go-ethereum/p2p/discover/v4_udp.go | 169 +- .../ethereum/go-ethereum/p2p/enode/iter.go | 286 + .../ethereum/go-ethereum/p2p/enode/urlv4.go | 12 +- .../ethereum/go-ethereum/p2p/message.go | 6 +- .../ethereum/go-ethereum/p2p/metrics.go | 10 +- .../ethereum/go-ethereum/p2p/peer.go | 8 + .../ethereum/go-ethereum/p2p/protocol.go | 5 + .../ethereum/go-ethereum/p2p/rlpx.go | 14 +- .../ethereum/go-ethereum/p2p/server.go | 35 +- .../p2p/simulations/adapters/types.go | 8 + .../go-ethereum/p2p/simulations/network.go | 122 +- .../ethereum/go-ethereum/params/bootnodes.go | 7 - .../ethereum/go-ethereum/params/config.go | 82 +- .../go-ethereum/params/protocol_params.go | 36 +- .../ethereum/go-ethereum/params/version.go | 2 +- .../ethereum/go-ethereum/rlp/decode.go | 168 +- .../ethereum/go-ethereum/rlp/doc.go | 121 +- .../ethereum/go-ethereum/rlp/encode.go | 127 +- .../ethereum/go-ethereum/rlp/typecache.go | 62 +- .../ethereum/go-ethereum/rpc/gzip.go | 66 + .../ethereum/go-ethereum/rpc/http.go | 1 + .../ethereum/go-ethereum/rpc/types.go | 93 + .../ethereum/go-ethereum/trie/sync.go | 17 +- .../go-ethereum/whisper/whisperv6/doc.go | 14 +- .../gballet/go-libpcsclite/doc_bsd.go | 4 +- .../gballet/go-libpcsclite/doc_darwin.go | 35 + .../gballet/go-libpcsclite/error.go | 182 +- .../gballet/go-libpcsclite/winscard.go | 22 +- vendor/github.com/go-ole/go-ole/.travis.yml | 8 - vendor/github.com/go-ole/go-ole/ChangeLog.md | 49 - vendor/github.com/go-ole/go-ole/LICENSE | 21 - vendor/github.com/go-ole/go-ole/README.md | 46 - vendor/github.com/go-ole/go-ole/appveyor.yml | 54 - vendor/github.com/go-ole/go-ole/com.go | 344 - vendor/github.com/go-ole/go-ole/com_func.go | 174 - vendor/github.com/go-ole/go-ole/connect.go | 192 - vendor/github.com/go-ole/go-ole/constants.go | 153 - vendor/github.com/go-ole/go-ole/error.go | 51 - vendor/github.com/go-ole/go-ole/error_func.go | 8 - .../github.com/go-ole/go-ole/error_windows.go | 24 - vendor/github.com/go-ole/go-ole/go.mod | 3 - vendor/github.com/go-ole/go-ole/guid.go | 284 - .../go-ole/go-ole/iconnectionpoint.go | 20 - .../go-ole/go-ole/iconnectionpoint_func.go | 21 - .../go-ole/go-ole/iconnectionpoint_windows.go | 43 - .../go-ole/iconnectionpointcontainer.go | 17 - .../go-ole/iconnectionpointcontainer_func.go | 11 - .../iconnectionpointcontainer_windows.go | 25 - vendor/github.com/go-ole/go-ole/idispatch.go | 94 - .../go-ole/go-ole/idispatch_func.go | 19 - .../go-ole/go-ole/idispatch_windows.go | 200 - .../github.com/go-ole/go-ole/ienumvariant.go | 19 - .../go-ole/go-ole/ienumvariant_func.go | 19 - .../go-ole/go-ole/ienumvariant_windows.go | 63 - .../github.com/go-ole/go-ole/iinspectable.go | 18 - .../go-ole/go-ole/iinspectable_func.go | 15 - .../go-ole/go-ole/iinspectable_windows.go | 72 - .../go-ole/go-ole/iprovideclassinfo.go | 21 - .../go-ole/go-ole/iprovideclassinfo_func.go | 7 - .../go-ole/iprovideclassinfo_windows.go | 21 - vendor/github.com/go-ole/go-ole/itypeinfo.go | 34 - .../go-ole/go-ole/itypeinfo_func.go | 7 - .../go-ole/go-ole/itypeinfo_windows.go | 21 - vendor/github.com/go-ole/go-ole/iunknown.go | 57 - .../github.com/go-ole/go-ole/iunknown_func.go | 19 - .../go-ole/go-ole/iunknown_windows.go | 58 - vendor/github.com/go-ole/go-ole/ole.go | 157 - .../go-ole/go-ole/oleutil/connection.go | 100 - .../go-ole/go-ole/oleutil/connection_func.go | 10 - .../go-ole/oleutil/connection_windows.go | 58 - .../go-ole/go-ole/oleutil/go-get.go | 6 - .../go-ole/go-ole/oleutil/oleutil.go | 127 - vendor/github.com/go-ole/go-ole/safearray.go | 27 - .../go-ole/go-ole/safearray_func.go | 211 - .../go-ole/go-ole/safearray_windows.go | 337 - .../go-ole/go-ole/safearrayconversion.go | 140 - .../go-ole/go-ole/safearrayslices.go | 33 - vendor/github.com/go-ole/go-ole/utility.go | 101 - vendor/github.com/go-ole/go-ole/variables.go | 16 - vendor/github.com/go-ole/go-ole/variant.go | 105 - .../github.com/go-ole/go-ole/variant_386.go | 11 - .../github.com/go-ole/go-ole/variant_amd64.go | 12 - .../go-ole/go-ole/variant_date_386.go | 22 - .../go-ole/go-ole/variant_date_amd64.go | 20 - .../go-ole/go-ole/variant_ppc64le.go | 12 - .../github.com/go-ole/go-ole/variant_s390x.go | 12 - vendor/github.com/go-ole/go-ole/vt_string.go | 58 - vendor/github.com/go-ole/go-ole/winrt.go | 99 - vendor/github.com/go-ole/go-ole/winrt_doc.go | 36 - vendor/github.com/google/uuid/.travis.yml | 9 + vendor/github.com/google/uuid/CONTRIBUTING.md | 10 + vendor/github.com/google/uuid/CONTRIBUTORS | 9 + vendor/github.com/google/uuid/LICENSE | 27 + vendor/github.com/google/uuid/README.md | 19 + vendor/github.com/google/uuid/dce.go | 80 + vendor/github.com/google/uuid/doc.go | 12 + vendor/github.com/google/uuid/go.mod | 1 + vendor/github.com/google/uuid/hash.go | 53 + vendor/github.com/google/uuid/marshal.go | 37 + vendor/github.com/google/uuid/node.go | 90 + vendor/github.com/google/uuid/node_js.go | 12 + vendor/github.com/google/uuid/node_net.go | 33 + vendor/github.com/google/uuid/sql.go | 59 + vendor/github.com/google/uuid/time.go | 123 + vendor/github.com/google/uuid/util.go | 43 + vendor/github.com/google/uuid/uuid.go | 245 + vendor/github.com/google/uuid/version1.go | 44 + vendor/github.com/google/uuid/version4.go | 38 + .../github.com/gorilla/websocket/.travis.yml | 19 - vendor/github.com/gorilla/websocket/README.md | 10 +- vendor/github.com/gorilla/websocket/client.go | 4 +- vendor/github.com/gorilla/websocket/conn.go | 112 +- vendor/github.com/gorilla/websocket/doc.go | 47 + vendor/github.com/gorilla/websocket/go.mod | 3 + vendor/github.com/gorilla/websocket/go.sum | 2 + vendor/github.com/gorilla/websocket/join.go | 42 + vendor/github.com/gorilla/websocket/proxy.go | 8 +- vendor/github.com/gorilla/websocket/server.go | 4 +- vendor/github.com/gorilla/websocket/util.go | 132 +- vendor/github.com/huin/goupnp/.gitignore | 3 +- vendor/github.com/huin/goupnp/LICENSE | 2 +- vendor/github.com/huin/goupnp/README.md | 12 +- .../huin/goupnp/dcps/internetgateway1/gen.go | 2 + .../dcps/internetgateway1/internetgateway1.go | 208 +- .../huin/goupnp/dcps/internetgateway2/gen.go | 2 + .../dcps/internetgateway2/internetgateway2.go | 396 +- vendor/github.com/huin/goupnp/device.go | 10 +- vendor/github.com/huin/goupnp/go.mod | 7 + vendor/github.com/huin/goupnp/go.sum | 6 + .../huin/goupnp/goupnp.sublime-project | 8 + vendor/github.com/huin/goupnp/httpu/httpu.go | 6 +- vendor/github.com/huin/goupnp/soap/soap.go | 40 +- vendor/github.com/huin/goupnp/soap/types.go | 11 +- vendor/github.com/huin/goupnp/ssdp/ssdp.go | 11 +- .../github.com/jackpal/go-nat-pmp/.travis.yml | 7 + .../github.com/jackpal/go-nat-pmp/natpmp.go | 17 +- .../github.com/jackpal/go-nat-pmp/network.go | 27 +- .../github.com/jackpal/go-nat-pmp/recorder.go | 6 +- vendor/github.com/karalabe/usb/.travis.yml | 4 +- vendor/github.com/karalabe/usb/appveyor.yml | 4 +- .../karalabe/usb/hidapi/windows/hid.c | 4 +- .../mattn/go-runewidth/runewidth.go | 838 +- .../mattn/go-runewidth/runewidth_appengine.go | 8 + .../mattn/go-runewidth/runewidth_js.go | 1 + .../mattn/go-runewidth/runewidth_posix.go | 4 +- .../mattn/go-runewidth/runewidth_windows.go | 3 + .../olekukonko/tablewriter/README.md | 41 +- .../github.com/olekukonko/tablewriter/go.mod | 8 + .../github.com/olekukonko/tablewriter/go.sum | 4 + .../olekukonko/tablewriter/table.go | 66 +- vendor/github.com/pborman/uuid/.travis.yml | 5 +- vendor/github.com/pborman/uuid/README.md | 2 + vendor/github.com/pborman/uuid/doc.go | 7 +- vendor/github.com/pborman/uuid/go.mod | 3 + vendor/github.com/pborman/uuid/go.sum | 2 + vendor/github.com/pborman/uuid/marshal.go | 10 +- vendor/github.com/pborman/uuid/node.go | 77 +- vendor/github.com/pborman/uuid/sql.go | 4 +- vendor/github.com/pborman/uuid/time.go | 87 +- vendor/github.com/pborman/uuid/util.go | 11 - vendor/github.com/pborman/uuid/uuid.go | 89 +- vendor/github.com/pborman/uuid/version1.go | 28 +- vendor/github.com/pborman/uuid/version4.go | 13 +- vendor/github.com/rds-swarm/config/config.go | 38 - .../MultiChainResolverABI.json | 336 - .../multi_chain_resolver.go | 996 -- .../github.com/rds-swarm/resolver/resolver.go | 153 - .../resolver/rsk_resolver/RSKResolverABI.json | 134 - .../resolver/rsk_resolver/rsk_resolver.go | 319 - vendor/github.com/rds-swarm/utils/utils.go | 35 - vendor/github.com/rjeczalik/notify/go.mod | 3 + vendor/github.com/rs/cors/.travis.yml | 9 +- vendor/github.com/rs/cors/README.md | 20 +- vendor/github.com/rs/cors/cors.go | 147 +- vendor/github.com/rs/cors/go.mod | 1 + vendor/github.com/rs/cors/utils.go | 9 +- vendor/github.com/rs/xhandler/.travis.yml | 7 - vendor/github.com/rs/xhandler/README.md | 134 - vendor/github.com/rs/xhandler/chain.go | 121 - vendor/github.com/rs/xhandler/middleware.go | 59 - vendor/github.com/rs/xhandler/xhandler.go | 42 - .../rds-swarm}/config/config.go | 0 .../MultiChainResolverABI.json | 0 .../multi_chain_resolver.go | 0 .../rds-swarm}/resolver/resolver.go | 0 .../resolver/rsk_resolver/RSKResolverABI.json | 0 .../resolver/rsk_resolver/rsk_resolver.go | 0 .../env => rsksmart/rds-swarm}/utils/utils.go | 0 .../syndtr/goleveldb/leveldb/batch.go | 5 + .../github.com/syndtr/goleveldb/leveldb/db.go | 22 +- .../syndtr/goleveldb/leveldb/db_compaction.go | 11 + .../syndtr/goleveldb/leveldb/db_iter.go | 43 +- .../goleveldb/leveldb/db_transaction.go | 14 +- .../syndtr/goleveldb/leveldb/opt/options.go | 21 +- .../goleveldb/leveldb/session_compaction.go | 26 +- .../syndtr/goleveldb/leveldb/session_util.go | 4 +- .../syndtr/goleveldb/leveldb/table.go | 2 + .../syndtr/goleveldb/leveldb/version.go | 3 +- .../tyler-smith/go-bip39/.golangci.yml | 44 + .../tyler-smith/go-bip39/.travis.yml | 24 +- .../github.com/tyler-smith/go-bip39/bip39.go | 43 +- .../x/crypto/curve25519/const_amd64.h | 8 - .../x/crypto/curve25519/const_amd64.s | 20 - .../x/crypto/curve25519/cswap_amd64.s | 65 - .../x/crypto/curve25519/curve25519.go | 881 +- ...mont25519_amd64.go => curve25519_amd64.go} | 2 +- ...{ladderstep_amd64.s => curve25519_amd64.s} | 420 +- .../x/crypto/curve25519/curve25519_generic.go | 828 ++ .../x/crypto/curve25519/curve25519_noasm.go | 11 + vendor/golang.org/x/crypto/curve25519/doc.go | 23 - .../x/crypto/curve25519/freeze_amd64.s | 73 - .../x/crypto/curve25519/mul_amd64.s | 169 - .../x/crypto/curve25519/square_amd64.s | 132 - .../x/crypto/openpgp/packet/encrypted_key.go | 6 +- .../x/crypto/openpgp/packet/private_key.go | 2 +- .../x/crypto/sha3/hashes_generic.go | 2 +- vendor/golang.org/x/crypto/sha3/sha3.go | 23 +- vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 2 +- vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 2 +- .../golang.org/x/crypto/sha3/shake_generic.go | 2 +- vendor/golang.org/x/crypto/sha3/xor.go | 7 + .../golang.org/x/crypto/sha3/xor_unaligned.go | 9 +- vendor/golang.org/x/net/html/atom/gen.go | 712 -- vendor/golang.org/x/net/http2/hpack/encode.go | 2 +- vendor/golang.org/x/net/http2/server.go | 52 +- vendor/golang.org/x/net/http2/transport.go | 26 +- vendor/golang.org/x/net/http2/writesched.go | 8 +- .../x/net/http2/writesched_priority.go | 2 +- .../golang.org/x/net/internal/socks/socks.go | 2 +- vendor/golang.org/x/net/publicsuffix/list.go | 181 + vendor/golang.org/x/net/publicsuffix/table.go | 9962 +++++++++++++++++ vendor/golang.org/x/sys/cpu/byteorder.go | 38 +- vendor/golang.org/x/sys/cpu/cpu.go | 36 + vendor/golang.org/x/sys/cpu/cpu_arm.go | 33 +- vendor/golang.org/x/sys/cpu/cpu_linux.go | 2 +- vendor/golang.org/x/sys/cpu/cpu_linux_arm.go | 39 + .../golang.org/x/sys/unix/affinity_linux.go | 46 +- .../golang.org/x/sys/unix/bluetooth_linux.go | 1 + vendor/golang.org/x/sys/unix/fdset.go | 29 + vendor/golang.org/x/sys/unix/ioctl.go | 41 +- vendor/golang.org/x/sys/unix/mkall.sh | 4 +- vendor/golang.org/x/sys/unix/mkasm_darwin.go | 61 - vendor/golang.org/x/sys/unix/mkerrors.sh | 52 +- vendor/golang.org/x/sys/unix/mkpost.go | 122 - vendor/golang.org/x/sys/unix/mksyscall.go | 407 - .../x/sys/unix/mksyscall_aix_ppc.go | 415 - .../x/sys/unix/mksyscall_aix_ppc64.go | 614 - .../x/sys/unix/mksyscall_solaris.go | 335 - .../golang.org/x/sys/unix/mksysctl_openbsd.go | 355 - vendor/golang.org/x/sys/unix/mksysnum.go | 190 - .../x/sys/unix/sockcmsg_dragonfly.go | 16 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 2 +- vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 36 +- .../x/sys/unix/sockcmsg_unix_other.go | 38 + vendor/golang.org/x/sys/unix/syscall_aix.go | 39 +- .../golang.org/x/sys/unix/syscall_aix_ppc.go | 4 + .../x/sys/unix/syscall_aix_ppc64.go | 4 + vendor/golang.org/x/sys/unix/syscall_bsd.go | 4 +- .../x/sys/unix/syscall_darwin.1_12.go | 29 + .../x/sys/unix/syscall_darwin.1_13.go | 101 + .../golang.org/x/sys/unix/syscall_darwin.go | 40 +- .../x/sys/unix/syscall_darwin_386.1_11.go | 9 + .../x/sys/unix/syscall_darwin_386.go | 7 +- .../x/sys/unix/syscall_darwin_amd64.1_11.go | 9 + .../x/sys/unix/syscall_darwin_amd64.go | 7 +- .../x/sys/unix/syscall_darwin_arm.1_11.go | 11 + .../x/sys/unix/syscall_darwin_arm.go | 12 +- .../x/sys/unix/syscall_darwin_arm64.1_11.go | 11 + .../x/sys/unix/syscall_darwin_arm64.go | 12 +- .../x/sys/unix/syscall_darwin_libSystem.go | 2 + .../x/sys/unix/syscall_dragonfly.go | 59 +- .../x/sys/unix/syscall_dragonfly_amd64.go | 4 + .../golang.org/x/sys/unix/syscall_freebsd.go | 48 +- .../x/sys/unix/syscall_freebsd_386.go | 4 + .../x/sys/unix/syscall_freebsd_amd64.go | 4 + .../x/sys/unix/syscall_freebsd_arm.go | 4 + .../x/sys/unix/syscall_freebsd_arm64.go | 4 + vendor/golang.org/x/sys/unix/syscall_linux.go | 175 +- .../x/sys/unix/syscall_linux_386.go | 4 + .../x/sys/unix/syscall_linux_amd64.go | 4 + .../x/sys/unix/syscall_linux_arm.go | 4 + .../x/sys/unix/syscall_linux_arm64.go | 4 + .../x/sys/unix/syscall_linux_mips64x.go | 4 + .../x/sys/unix/syscall_linux_mipsx.go | 4 + .../x/sys/unix/syscall_linux_ppc64x.go | 4 + .../x/sys/unix/syscall_linux_riscv64.go | 4 + .../x/sys/unix/syscall_linux_s390x.go | 4 + .../x/sys/unix/syscall_linux_sparc64.go | 4 + .../golang.org/x/sys/unix/syscall_netbsd.go | 39 +- .../x/sys/unix/syscall_netbsd_386.go | 4 + .../x/sys/unix/syscall_netbsd_amd64.go | 4 + .../x/sys/unix/syscall_netbsd_arm.go | 4 + .../x/sys/unix/syscall_netbsd_arm64.go | 4 + .../golang.org/x/sys/unix/syscall_openbsd.go | 39 +- .../x/sys/unix/syscall_openbsd_386.go | 4 + .../x/sys/unix/syscall_openbsd_amd64.go | 4 + .../x/sys/unix/syscall_openbsd_arm.go | 4 + .../x/sys/unix/syscall_openbsd_arm64.go | 4 + .../golang.org/x/sys/unix/syscall_solaris.go | 34 +- .../x/sys/unix/syscall_solaris_amd64.go | 4 + vendor/golang.org/x/sys/unix/types_aix.go | 237 - vendor/golang.org/x/sys/unix/types_darwin.go | 283 - .../golang.org/x/sys/unix/types_dragonfly.go | 263 - vendor/golang.org/x/sys/unix/types_freebsd.go | 400 - vendor/golang.org/x/sys/unix/types_netbsd.go | 290 - vendor/golang.org/x/sys/unix/types_openbsd.go | 283 - vendor/golang.org/x/sys/unix/types_solaris.go | 266 - .../x/sys/unix/zerrors_darwin_386.go | 3 +- .../x/sys/unix/zerrors_darwin_amd64.go | 3 +- .../x/sys/unix/zerrors_darwin_arm.go | 3 +- .../x/sys/unix/zerrors_darwin_arm64.go | 3 +- .../x/sys/unix/zerrors_dragonfly_amd64.go | 1 + .../x/sys/unix/zerrors_freebsd_386.go | 3 +- .../x/sys/unix/zerrors_freebsd_amd64.go | 3 +- .../x/sys/unix/zerrors_freebsd_arm.go | 3 +- .../x/sys/unix/zerrors_freebsd_arm64.go | 3 +- .../x/sys/unix/zerrors_linux_386.go | 123 +- .../x/sys/unix/zerrors_linux_amd64.go | 123 +- .../x/sys/unix/zerrors_linux_arm.go | 123 +- .../x/sys/unix/zerrors_linux_arm64.go | 125 +- .../x/sys/unix/zerrors_linux_mips.go | 123 +- .../x/sys/unix/zerrors_linux_mips64.go | 123 +- .../x/sys/unix/zerrors_linux_mips64le.go | 123 +- .../x/sys/unix/zerrors_linux_mipsle.go | 123 +- .../x/sys/unix/zerrors_linux_ppc64.go | 123 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 123 +- .../x/sys/unix/zerrors_linux_riscv64.go | 123 +- .../x/sys/unix/zerrors_linux_s390x.go | 123 +- .../x/sys/unix/zerrors_linux_sparc64.go | 123 +- .../x/sys/unix/zerrors_netbsd_386.go | 3 +- .../x/sys/unix/zerrors_netbsd_amd64.go | 3 +- .../x/sys/unix/zerrors_netbsd_arm.go | 3 +- .../x/sys/unix/zerrors_netbsd_arm64.go | 3 +- .../x/sys/unix/zerrors_openbsd_386.go | 17 +- .../x/sys/unix/zerrors_openbsd_amd64.go | 6 +- .../x/sys/unix/zerrors_openbsd_arm.go | 11 +- .../x/sys/unix/zerrors_openbsd_arm64.go | 1 + .../x/sys/unix/zerrors_solaris_amd64.go | 3 +- .../x/sys/unix/zsyscall_darwin_386.1_11.go | 93 +- .../x/sys/unix/zsyscall_darwin_386.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_386.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_386.go | 114 +- .../x/sys/unix/zsyscall_darwin_386.s | 10 +- .../x/sys/unix/zsyscall_darwin_amd64.1_11.go | 93 +- .../x/sys/unix/zsyscall_darwin_amd64.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_amd64.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_amd64.go | 99 +- .../x/sys/unix/zsyscall_darwin_amd64.s | 10 +- .../x/sys/unix/zsyscall_darwin_arm.1_11.go | 49 +- .../x/sys/unix/zsyscall_darwin_arm.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_arm.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_arm.go | 77 +- .../x/sys/unix/zsyscall_darwin_arm.s | 6 +- .../x/sys/unix/zsyscall_darwin_arm64.1_11.go | 49 +- .../x/sys/unix/zsyscall_darwin_arm64.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_arm64.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_arm64.go | 77 +- .../x/sys/unix/zsyscall_darwin_arm64.s | 6 +- .../x/sys/unix/zsyscall_dragonfly_amd64.go | 5 +- .../x/sys/unix/zsyscall_freebsd_386.go | 5 +- .../x/sys/unix/zsyscall_freebsd_amd64.go | 45 +- .../x/sys/unix/zsyscall_freebsd_arm.go | 45 +- .../x/sys/unix/zsyscall_freebsd_arm64.go | 45 +- .../x/sys/unix/zsyscall_linux_386.go | 30 + .../x/sys/unix/zsyscall_linux_amd64.go | 30 + .../x/sys/unix/zsyscall_linux_arm.go | 30 + .../x/sys/unix/zsyscall_linux_arm64.go | 30 + .../x/sys/unix/zsyscall_linux_mips.go | 30 + .../x/sys/unix/zsyscall_linux_mips64.go | 30 + .../x/sys/unix/zsyscall_linux_mips64le.go | 30 + .../x/sys/unix/zsyscall_linux_mipsle.go | 30 + .../x/sys/unix/zsyscall_linux_ppc64.go | 30 + .../x/sys/unix/zsyscall_linux_ppc64le.go | 30 + .../x/sys/unix/zsyscall_linux_riscv64.go | 30 + .../x/sys/unix/zsyscall_linux_s390x.go | 30 + .../x/sys/unix/zsyscall_linux_sparc64.go | 30 + .../x/sys/unix/zsyscall_netbsd_386.go | 37 +- .../x/sys/unix/zsyscall_netbsd_amd64.go | 37 +- .../x/sys/unix/zsyscall_netbsd_arm.go | 37 +- .../x/sys/unix/zsyscall_netbsd_arm64.go | 37 +- .../x/sys/unix/zsyscall_openbsd_386.go | 37 +- .../x/sys/unix/zsyscall_openbsd_amd64.go | 37 +- .../x/sys/unix/zsyscall_openbsd_arm.go | 37 +- .../x/sys/unix/zsyscall_openbsd_arm64.go | 37 +- .../x/sys/unix/zsyscall_solaris_amd64.go | 5 +- .../x/sys/unix/zsysnum_linux_386.go | 2 + .../x/sys/unix/zsysnum_linux_amd64.go | 2 + .../x/sys/unix/zsysnum_linux_arm.go | 2 + .../x/sys/unix/zsysnum_linux_arm64.go | 1 + .../x/sys/unix/zsysnum_linux_mips.go | 1 + .../x/sys/unix/zsysnum_linux_mips64.go | 1 + .../x/sys/unix/zsysnum_linux_mips64le.go | 1 + .../x/sys/unix/zsysnum_linux_mipsle.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64.go | 2 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 2 + .../x/sys/unix/zsysnum_linux_riscv64.go | 2 + .../x/sys/unix/zsysnum_linux_s390x.go | 2 + .../x/sys/unix/zsysnum_linux_sparc64.go | 1 + .../x/sys/unix/ztypes_freebsd_arm64.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 266 +- .../x/sys/unix/ztypes_linux_amd64.go | 266 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 266 +- .../x/sys/unix/ztypes_linux_arm64.go | 266 +- .../x/sys/unix/ztypes_linux_mips.go | 266 +- .../x/sys/unix/ztypes_linux_mips64.go | 266 +- .../x/sys/unix/ztypes_linux_mips64le.go | 266 +- .../x/sys/unix/ztypes_linux_mipsle.go | 266 +- .../x/sys/unix/ztypes_linux_ppc64.go | 266 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 266 +- .../x/sys/unix/ztypes_linux_riscv64.go | 267 +- .../x/sys/unix/ztypes_linux_s390x.go | 266 +- .../x/sys/unix/ztypes_linux_sparc64.go | 266 +- .../x/sys/windows/asm_windows_386.s | 13 - .../x/sys/windows/asm_windows_amd64.s | 13 - .../x/sys/windows/asm_windows_arm.s | 11 - .../golang.org/x/sys/windows/dll_windows.go | 22 +- vendor/golang.org/x/sys/windows/mksyscall.go | 2 +- .../x/sys/windows/security_windows.go | 602 +- .../x/sys/windows/syscall_windows.go | 74 +- .../golang.org/x/sys/windows/types_windows.go | 112 +- .../x/sys/windows/zsyscall_windows.go | 1193 +- .../x/text/encoding/charmap/maketables.go | 556 - .../x/text/encoding/htmlindex/gen.go | 173 - .../text/encoding/internal/identifier/gen.go | 142 - .../x/text/encoding/japanese/maketables.go | 161 - .../x/text/encoding/korean/maketables.go | 143 - .../encoding/simplifiedchinese/maketables.go | 161 - .../encoding/traditionalchinese/maketables.go | 140 - .../x/text/internal/language/compact/gen.go | 64 - .../internal/language/compact/gen_index.go | 113 - .../internal/language/compact/gen_parents.go | 54 - .../x/text/internal/language/gen.go | 1520 --- .../x/text/internal/language/gen_common.go | 20 - vendor/golang.org/x/text/language/gen.go | 305 - vendor/golang.org/x/text/unicode/bidi/gen.go | 133 - .../x/text/unicode/bidi/gen_ranges.go | 57 - .../x/text/unicode/bidi/gen_trieval.go | 64 - .../x/text/unicode/norm/maketables.go | 986 -- .../golang.org/x/text/unicode/norm/triegen.go | 117 - .../google.golang.org/grpc/status/status.go | 15 +- vendor/k8s.io/client-go/pkg/version/base.go | 4 +- vendor/modules.txt | 378 +- 588 files changed, 31571 insertions(+), 25917 deletions(-) delete mode 100644 vendor/github.com/StackExchange/wmi/LICENSE delete mode 100644 vendor/github.com/StackExchange/wmi/README.md delete mode 100644 vendor/github.com/StackExchange/wmi/swbemservices.go delete mode 100644 vendor/github.com/StackExchange/wmi/wmi.go delete mode 100644 vendor/github.com/btcsuite/btcd/btcec/genprecomps.go create mode 100644 vendor/github.com/caarlos0/env/.gitignore create mode 100644 vendor/github.com/caarlos0/env/.hound.yml create mode 100644 vendor/github.com/caarlos0/env/.travis.yml rename vendor/github.com/{rs/xhandler/LICENSE => caarlos0/env/LICENSE.md} (85%) create mode 100644 vendor/github.com/caarlos0/env/README.md create mode 100644 vendor/github.com/caarlos0/env/env.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/example_changes.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/msync_netbsd.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/msync_unix.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_darwin_386.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go rename vendor/github.com/ethereum/go-ethereum/les/{backend.go => client.go} (78%) create mode 100644 vendor/github.com/ethereum/go-ethereum/les/client_handler.go create mode 100644 vendor/github.com/ethereum/go-ethereum/les/enr_entry.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/les/handler.go create mode 100644 vendor/github.com/ethereum/go-ethereum/les/server_handler.go create mode 100644 vendor/github.com/ethereum/go-ethereum/les/test_helper.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/discover/lookup.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/enode/iter.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rpc/gzip.go create mode 100644 vendor/github.com/gballet/go-libpcsclite/doc_darwin.go delete mode 100644 vendor/github.com/go-ole/go-ole/.travis.yml delete mode 100644 vendor/github.com/go-ole/go-ole/ChangeLog.md delete mode 100644 vendor/github.com/go-ole/go-ole/LICENSE delete mode 100644 vendor/github.com/go-ole/go-ole/README.md delete mode 100644 vendor/github.com/go-ole/go-ole/appveyor.yml delete mode 100644 vendor/github.com/go-ole/go-ole/com.go delete mode 100644 vendor/github.com/go-ole/go-ole/com_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/connect.go delete mode 100644 vendor/github.com/go-ole/go-ole/constants.go delete mode 100644 vendor/github.com/go-ole/go-ole/error.go delete mode 100644 vendor/github.com/go-ole/go-ole/error_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/error_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/go.mod delete mode 100644 vendor/github.com/go-ole/go-ole/guid.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/idispatch.go delete mode 100644 vendor/github.com/go-ole/go-ole/idispatch_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/idispatch_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant.go delete mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/iinspectable.go delete mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo.go delete mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo.go delete mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/iunknown.go delete mode 100644 vendor/github.com/go-ole/go-ole/iunknown_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/iunknown_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/ole.go delete mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection.go delete mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/oleutil/go-get.go delete mode 100644 vendor/github.com/go-ole/go-ole/oleutil/oleutil.go delete mode 100644 vendor/github.com/go-ole/go-ole/safearray.go delete mode 100644 vendor/github.com/go-ole/go-ole/safearray_func.go delete mode 100644 vendor/github.com/go-ole/go-ole/safearray_windows.go delete mode 100644 vendor/github.com/go-ole/go-ole/safearrayconversion.go delete mode 100644 vendor/github.com/go-ole/go-ole/safearrayslices.go delete mode 100644 vendor/github.com/go-ole/go-ole/utility.go delete mode 100644 vendor/github.com/go-ole/go-ole/variables.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_386.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_amd64.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_date_386.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_date_amd64.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_ppc64le.go delete mode 100644 vendor/github.com/go-ole/go-ole/variant_s390x.go delete mode 100644 vendor/github.com/go-ole/go-ole/vt_string.go delete mode 100644 vendor/github.com/go-ole/go-ole/winrt.go delete mode 100644 vendor/github.com/go-ole/go-ole/winrt_doc.go create mode 100644 vendor/github.com/google/uuid/.travis.yml create mode 100644 vendor/github.com/google/uuid/CONTRIBUTING.md create mode 100644 vendor/github.com/google/uuid/CONTRIBUTORS create mode 100644 vendor/github.com/google/uuid/LICENSE create mode 100644 vendor/github.com/google/uuid/README.md create mode 100644 vendor/github.com/google/uuid/dce.go create mode 100644 vendor/github.com/google/uuid/doc.go create mode 100644 vendor/github.com/google/uuid/go.mod create mode 100644 vendor/github.com/google/uuid/hash.go create mode 100644 vendor/github.com/google/uuid/marshal.go create mode 100644 vendor/github.com/google/uuid/node.go create mode 100644 vendor/github.com/google/uuid/node_js.go create mode 100644 vendor/github.com/google/uuid/node_net.go create mode 100644 vendor/github.com/google/uuid/sql.go create mode 100644 vendor/github.com/google/uuid/time.go create mode 100644 vendor/github.com/google/uuid/util.go create mode 100644 vendor/github.com/google/uuid/uuid.go create mode 100644 vendor/github.com/google/uuid/version1.go create mode 100644 vendor/github.com/google/uuid/version4.go delete mode 100644 vendor/github.com/gorilla/websocket/.travis.yml create mode 100644 vendor/github.com/gorilla/websocket/go.mod create mode 100644 vendor/github.com/gorilla/websocket/go.sum create mode 100644 vendor/github.com/gorilla/websocket/join.go create mode 100644 vendor/github.com/huin/goupnp/dcps/internetgateway1/gen.go create mode 100644 vendor/github.com/huin/goupnp/dcps/internetgateway2/gen.go create mode 100644 vendor/github.com/huin/goupnp/go.mod create mode 100644 vendor/github.com/huin/goupnp/go.sum create mode 100644 vendor/github.com/huin/goupnp/goupnp.sublime-project create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_appengine.go create mode 100644 vendor/github.com/olekukonko/tablewriter/go.mod create mode 100644 vendor/github.com/olekukonko/tablewriter/go.sum create mode 100644 vendor/github.com/pborman/uuid/go.mod create mode 100644 vendor/github.com/pborman/uuid/go.sum delete mode 100644 vendor/github.com/rds-swarm/config/config.go delete mode 100644 vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json delete mode 100644 vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go delete mode 100644 vendor/github.com/rds-swarm/resolver/resolver.go delete mode 100644 vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json delete mode 100644 vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go delete mode 100644 vendor/github.com/rds-swarm/utils/utils.go create mode 100644 vendor/github.com/rjeczalik/notify/go.mod create mode 100644 vendor/github.com/rs/cors/go.mod delete mode 100644 vendor/github.com/rs/xhandler/.travis.yml delete mode 100644 vendor/github.com/rs/xhandler/README.md delete mode 100644 vendor/github.com/rs/xhandler/chain.go delete mode 100644 vendor/github.com/rs/xhandler/middleware.go delete mode 100644 vendor/github.com/rs/xhandler/xhandler.go rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/config/config.go (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/resolver/multi_chain_resolver/MultiChainResolverABI.json (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/resolver/multi_chain_resolver/multi_chain_resolver.go (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/resolver/resolver.go (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/resolver/rsk_resolver/RSKResolverABI.json (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/resolver/rsk_resolver/rsk_resolver.go (100%) rename vendor/github.com/{caarlos0/env => rsksmart/rds-swarm}/utils/utils.go (100%) create mode 100644 vendor/github.com/tyler-smith/go-bip39/.golangci.yml delete mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.h delete mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s rename vendor/golang.org/x/crypto/curve25519/{mont25519_amd64.go => curve25519_amd64.go} (99%) rename vendor/golang.org/x/crypto/curve25519/{ladderstep_amd64.s => curve25519_amd64.s} (76%) create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_generic.go create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s delete mode 100644 vendor/golang.org/x/net/html/atom/gen.go create mode 100644 vendor/golang.org/x/net/publicsuffix/list.go create mode 100644 vendor/golang.org/x/net/publicsuffix/table.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/fdset.go delete mode 100644 vendor/golang.org/x/sys/unix/mkasm_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/mkpost.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.go delete mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go delete mode 100644 vendor/golang.org/x/sys/unix/types_aix.go delete mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go delete mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s delete mode 100644 vendor/golang.org/x/sys/windows/asm_windows_386.s delete mode 100644 vendor/golang.org/x/sys/windows/asm_windows_amd64.s delete mode 100644 vendor/golang.org/x/sys/windows/asm_windows_arm.s delete mode 100644 vendor/golang.org/x/text/encoding/charmap/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/htmlindex/gen.go delete mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/gen.go delete mode 100644 vendor/golang.org/x/text/encoding/japanese/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/korean/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go delete mode 100644 vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_index.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_parents.go delete mode 100644 vendor/golang.org/x/text/internal/language/gen.go delete mode 100644 vendor/golang.org/x/text/internal/language/gen_common.go delete mode 100644 vendor/golang.org/x/text/language/gen.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE deleted file mode 100644 index ae80b67209..0000000000 --- a/vendor/github.com/StackExchange/wmi/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Stack Exchange - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/StackExchange/wmi/README.md b/vendor/github.com/StackExchange/wmi/README.md deleted file mode 100644 index 426d1a46b4..0000000000 --- a/vendor/github.com/StackExchange/wmi/README.md +++ /dev/null @@ -1,6 +0,0 @@ -wmi -=== - -Package wmi provides a WQL interface to Windows WMI. - -Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. diff --git a/vendor/github.com/StackExchange/wmi/swbemservices.go b/vendor/github.com/StackExchange/wmi/swbemservices.go deleted file mode 100644 index 3ff8756303..0000000000 --- a/vendor/github.com/StackExchange/wmi/swbemservices.go +++ /dev/null @@ -1,260 +0,0 @@ -// +build windows - -package wmi - -import ( - "fmt" - "reflect" - "runtime" - "sync" - - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx -type SWbemServices struct { - //TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance - cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method - sWbemLocatorIUnknown *ole.IUnknown - sWbemLocatorIDispatch *ole.IDispatch - queries chan *queryRequest - closeError chan error - lQueryorClose sync.Mutex -} - -type queryRequest struct { - query string - dst interface{} - args []interface{} - finished chan error -} - -// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI -func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) { - //fmt.Println("InitializeSWbemServices: Starting") - //TODO: implement connectServerArgs as optional argument for init with connectServer call - s := new(SWbemServices) - s.cWMIClient = c - s.queries = make(chan *queryRequest) - initError := make(chan error) - go s.process(initError) - - err, ok := <-initError - if ok { - return nil, err //Send error to caller - } - //fmt.Println("InitializeSWbemServices: Finished") - return s, nil -} - -// Close will clear and release all of the SWbemServices resources -func (s *SWbemServices) Close() error { - s.lQueryorClose.Lock() - if s == nil || s.sWbemLocatorIDispatch == nil { - s.lQueryorClose.Unlock() - return fmt.Errorf("SWbemServices is not Initialized") - } - if s.queries == nil { - s.lQueryorClose.Unlock() - return fmt.Errorf("SWbemServices has been closed") - } - //fmt.Println("Close: sending close request") - var result error - ce := make(chan error) - s.closeError = ce //Race condition if multiple callers to close. May need to lock here - close(s.queries) //Tell background to shut things down - s.lQueryorClose.Unlock() - err, ok := <-ce - if ok { - result = err - } - //fmt.Println("Close: finished") - return result -} - -func (s *SWbemServices) process(initError chan error) { - //fmt.Println("process: starting background thread initialization") - //All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) - if err != nil { - oleCode := err.(*ole.OleError).Code() - if oleCode != ole.S_OK && oleCode != S_FALSE { - initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err) - return - } - } - defer ole.CoUninitialize() - - unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") - if err != nil { - initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err) - return - } else if unknown == nil { - initError <- ErrNilCreateObject - return - } - defer unknown.Release() - s.sWbemLocatorIUnknown = unknown - - dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch) - if err != nil { - initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err) - return - } - defer dispatch.Release() - s.sWbemLocatorIDispatch = dispatch - - // we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs - //fmt.Println("process: initialized. closing initError") - close(initError) - //fmt.Println("process: waiting for queries") - for q := range s.queries { - //fmt.Printf("process: new query: len(query)=%d\n", len(q.query)) - errQuery := s.queryBackground(q) - //fmt.Println("process: s.queryBackground finished") - if errQuery != nil { - q.finished <- errQuery - } - close(q.finished) - } - //fmt.Println("process: queries channel closed") - s.queries = nil //set channel to nil so we know it is closed - //TODO: I think the Release/Clear calls can panic if things are in a bad state. - //TODO: May need to recover from panics and send error to method caller instead. - close(s.closeError) -} - -// Query runs the WQL query using a SWbemServices instance and appends the values to dst. -// -// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in -// the query must have the same name in dst. Supported types are all signed and -// unsigned integers, time.Time, string, bool, or a pointer to one of those. -// Array types are not supported. -// -// By default, the local machine and default namespace are used. These can be -// changed using connectServerArgs. See -// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. -func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { - s.lQueryorClose.Lock() - if s == nil || s.sWbemLocatorIDispatch == nil { - s.lQueryorClose.Unlock() - return fmt.Errorf("SWbemServices is not Initialized") - } - if s.queries == nil { - s.lQueryorClose.Unlock() - return fmt.Errorf("SWbemServices has been closed") - } - - //fmt.Println("Query: Sending query request") - qr := queryRequest{ - query: query, - dst: dst, - args: connectServerArgs, - finished: make(chan error), - } - s.queries <- &qr - s.lQueryorClose.Unlock() - err, ok := <-qr.finished - if ok { - //fmt.Println("Query: Finished with error") - return err //Send error to caller - } - //fmt.Println("Query: Finished") - return nil -} - -func (s *SWbemServices) queryBackground(q *queryRequest) error { - if s == nil || s.sWbemLocatorIDispatch == nil { - return fmt.Errorf("SWbemServices is not Initialized") - } - wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart - //fmt.Println("queryBackground: Starting") - - dv := reflect.ValueOf(q.dst) - if dv.Kind() != reflect.Ptr || dv.IsNil() { - return ErrInvalidEntityType - } - dv = dv.Elem() - mat, elemType := checkMultiArg(dv) - if mat == multiArgTypeInvalid { - return ErrInvalidEntityType - } - - // service is a SWbemServices - serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...) - if err != nil { - return err - } - service := serviceRaw.ToIDispatch() - defer serviceRaw.Clear() - - // result is a SWBemObjectSet - resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query) - if err != nil { - return err - } - result := resultRaw.ToIDispatch() - defer resultRaw.Clear() - - count, err := oleInt64(result, "Count") - if err != nil { - return err - } - - enumProperty, err := result.GetProperty("_NewEnum") - if err != nil { - return err - } - defer enumProperty.Clear() - - enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return err - } - if enum == nil { - return fmt.Errorf("can't get IEnumVARIANT, enum is nil") - } - defer enum.Release() - - // Initialize a slice with Count capacity - dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) - - var errFieldMismatch error - for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { - if err != nil { - return err - } - - err := func() error { - // item is a SWbemObject, but really a Win32_Process - item := itemRaw.ToIDispatch() - defer item.Release() - - ev := reflect.New(elemType) - if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil { - if _, ok := err.(*ErrFieldMismatch); ok { - // We continue loading entities even in the face of field mismatch errors. - // If we encounter any other error, that other error is returned. Otherwise, - // an ErrFieldMismatch is returned. - errFieldMismatch = err - } else { - return err - } - } - if mat != multiArgTypeStructPtr { - ev = ev.Elem() - } - dv.Set(reflect.Append(dv, ev)) - return nil - }() - if err != nil { - return err - } - } - //fmt.Println("queryBackground: Finished") - return errFieldMismatch -} diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go deleted file mode 100644 index eab18cbfee..0000000000 --- a/vendor/github.com/StackExchange/wmi/wmi.go +++ /dev/null @@ -1,501 +0,0 @@ -// +build windows - -/* -Package wmi provides a WQL interface for WMI on Windows. - -Example code to print names of running processes: - - type Win32_Process struct { - Name string - } - - func main() { - var dst []Win32_Process - q := wmi.CreateQuery(&dst, "") - err := wmi.Query(q, &dst) - if err != nil { - log.Fatal(err) - } - for i, v := range dst { - println(i, v.Name) - } - } - -*/ -package wmi - -import ( - "bytes" - "errors" - "fmt" - "log" - "os" - "reflect" - "runtime" - "strconv" - "strings" - "sync" - "time" - - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -var l = log.New(os.Stdout, "", log.LstdFlags) - -var ( - ErrInvalidEntityType = errors.New("wmi: invalid entity type") - // ErrNilCreateObject is the error returned if CreateObject returns nil even - // if the error was nil. - ErrNilCreateObject = errors.New("wmi: create object returned nil") - lock sync.Mutex -) - -// S_FALSE is returned by CoInitializeEx if it was already called on this thread. -const S_FALSE = 0x00000001 - -// QueryNamespace invokes Query with the given namespace on the local machine. -func QueryNamespace(query string, dst interface{}, namespace string) error { - return Query(query, dst, nil, namespace) -} - -// Query runs the WQL query and appends the values to dst. -// -// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in -// the query must have the same name in dst. Supported types are all signed and -// unsigned integers, time.Time, string, bool, or a pointer to one of those. -// Array types are not supported. -// -// By default, the local machine and default namespace are used. These can be -// changed using connectServerArgs. See -// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. -// -// Query is a wrapper around DefaultClient.Query. -func Query(query string, dst interface{}, connectServerArgs ...interface{}) error { - if DefaultClient.SWbemServicesClient == nil { - return DefaultClient.Query(query, dst, connectServerArgs...) - } - return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...) -} - -// A Client is an WMI query client. -// -// Its zero value (DefaultClient) is a usable client. -type Client struct { - // NonePtrZero specifies if nil values for fields which aren't pointers - // should be returned as the field types zero value. - // - // Setting this to true allows stucts without pointer fields to be used - // without the risk failure should a nil value returned from WMI. - NonePtrZero bool - - // PtrNil specifies if nil values for pointer fields should be returned - // as nil. - // - // Setting this to true will set pointer fields to nil where WMI - // returned nil, otherwise the types zero value will be returned. - PtrNil bool - - // AllowMissingFields specifies that struct fields not present in the - // query result should not result in an error. - // - // Setting this to true allows custom queries to be used with full - // struct definitions instead of having to define multiple structs. - AllowMissingFields bool - - // SWbemServiceClient is an optional SWbemServices object that can be - // initialized and then reused across multiple queries. If it is null - // then the method will initialize a new temporary client each time. - SWbemServicesClient *SWbemServices -} - -// DefaultClient is the default Client and is used by Query, QueryNamespace -var DefaultClient = &Client{} - -// Query runs the WQL query and appends the values to dst. -// -// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in -// the query must have the same name in dst. Supported types are all signed and -// unsigned integers, time.Time, string, bool, or a pointer to one of those. -// Array types are not supported. -// -// By default, the local machine and default namespace are used. These can be -// changed using connectServerArgs. See -// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. -func (c *Client) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { - dv := reflect.ValueOf(dst) - if dv.Kind() != reflect.Ptr || dv.IsNil() { - return ErrInvalidEntityType - } - dv = dv.Elem() - mat, elemType := checkMultiArg(dv) - if mat == multiArgTypeInvalid { - return ErrInvalidEntityType - } - - lock.Lock() - defer lock.Unlock() - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) - if err != nil { - oleCode := err.(*ole.OleError).Code() - if oleCode != ole.S_OK && oleCode != S_FALSE { - return err - } - } - defer ole.CoUninitialize() - - unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") - if err != nil { - return err - } else if unknown == nil { - return ErrNilCreateObject - } - defer unknown.Release() - - wmi, err := unknown.QueryInterface(ole.IID_IDispatch) - if err != nil { - return err - } - defer wmi.Release() - - // service is a SWbemServices - serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", connectServerArgs...) - if err != nil { - return err - } - service := serviceRaw.ToIDispatch() - defer serviceRaw.Clear() - - // result is a SWBemObjectSet - resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query) - if err != nil { - return err - } - result := resultRaw.ToIDispatch() - defer resultRaw.Clear() - - count, err := oleInt64(result, "Count") - if err != nil { - return err - } - - enumProperty, err := result.GetProperty("_NewEnum") - if err != nil { - return err - } - defer enumProperty.Clear() - - enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return err - } - if enum == nil { - return fmt.Errorf("can't get IEnumVARIANT, enum is nil") - } - defer enum.Release() - - // Initialize a slice with Count capacity - dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) - - var errFieldMismatch error - for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { - if err != nil { - return err - } - - err := func() error { - // item is a SWbemObject, but really a Win32_Process - item := itemRaw.ToIDispatch() - defer item.Release() - - ev := reflect.New(elemType) - if err = c.loadEntity(ev.Interface(), item); err != nil { - if _, ok := err.(*ErrFieldMismatch); ok { - // We continue loading entities even in the face of field mismatch errors. - // If we encounter any other error, that other error is returned. Otherwise, - // an ErrFieldMismatch is returned. - errFieldMismatch = err - } else { - return err - } - } - if mat != multiArgTypeStructPtr { - ev = ev.Elem() - } - dv.Set(reflect.Append(dv, ev)) - return nil - }() - if err != nil { - return err - } - } - return errFieldMismatch -} - -// ErrFieldMismatch is returned when a field is to be loaded into a different -// type than the one it was stored from, or when a field is missing or -// unexported in the destination struct. -// StructType is the type of the struct pointed to by the destination argument. -type ErrFieldMismatch struct { - StructType reflect.Type - FieldName string - Reason string -} - -func (e *ErrFieldMismatch) Error() string { - return fmt.Sprintf("wmi: cannot load field %q into a %q: %s", - e.FieldName, e.StructType, e.Reason) -} - -var timeType = reflect.TypeOf(time.Time{}) - -// loadEntity loads a SWbemObject into a struct pointer. -func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) { - v := reflect.ValueOf(dst).Elem() - for i := 0; i < v.NumField(); i++ { - f := v.Field(i) - of := f - isPtr := f.Kind() == reflect.Ptr - if isPtr { - ptr := reflect.New(f.Type().Elem()) - f.Set(ptr) - f = f.Elem() - } - n := v.Type().Field(i).Name - if !f.CanSet() { - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "CanSet() is false", - } - } - prop, err := oleutil.GetProperty(src, n) - if err != nil { - if !c.AllowMissingFields { - errFieldMismatch = &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "no such struct field", - } - } - continue - } - defer prop.Clear() - - if prop.VT == 0x1 { //VT_NULL - continue - } - - switch val := prop.Value().(type) { - case int8, int16, int32, int64, int: - v := reflect.ValueOf(val).Int() - switch f.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - f.SetInt(v) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - f.SetUint(uint64(v)) - default: - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "not an integer class", - } - } - case uint8, uint16, uint32, uint64: - v := reflect.ValueOf(val).Uint() - switch f.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - f.SetInt(int64(v)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - f.SetUint(v) - default: - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "not an integer class", - } - } - case string: - switch f.Kind() { - case reflect.String: - f.SetString(val) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - iv, err := strconv.ParseInt(val, 10, 64) - if err != nil { - return err - } - f.SetInt(iv) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - uv, err := strconv.ParseUint(val, 10, 64) - if err != nil { - return err - } - f.SetUint(uv) - case reflect.Struct: - switch f.Type() { - case timeType: - if len(val) == 25 { - mins, err := strconv.Atoi(val[22:]) - if err != nil { - return err - } - val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60) - } - t, err := time.Parse("20060102150405.000000-0700", val) - if err != nil { - return err - } - f.Set(reflect.ValueOf(t)) - } - } - case bool: - switch f.Kind() { - case reflect.Bool: - f.SetBool(val) - default: - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "not a bool", - } - } - case float32: - switch f.Kind() { - case reflect.Float32: - f.SetFloat(float64(val)) - default: - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: "not a Float32", - } - } - default: - if f.Kind() == reflect.Slice { - switch f.Type().Elem().Kind() { - case reflect.String: - safeArray := prop.ToArray() - if safeArray != nil { - arr := safeArray.ToValueArray() - fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) - for i, v := range arr { - s := fArr.Index(i) - s.SetString(v.(string)) - } - f.Set(fArr) - } - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - safeArray := prop.ToArray() - if safeArray != nil { - arr := safeArray.ToValueArray() - fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) - for i, v := range arr { - s := fArr.Index(i) - s.SetUint(reflect.ValueOf(v).Uint()) - } - f.Set(fArr) - } - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - safeArray := prop.ToArray() - if safeArray != nil { - arr := safeArray.ToValueArray() - fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) - for i, v := range arr { - s := fArr.Index(i) - s.SetInt(reflect.ValueOf(v).Int()) - } - f.Set(fArr) - } - default: - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: fmt.Sprintf("unsupported slice type (%T)", val), - } - } - } else { - typeof := reflect.TypeOf(val) - if typeof == nil && (isPtr || c.NonePtrZero) { - if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) { - of.Set(reflect.Zero(of.Type())) - } - break - } - return &ErrFieldMismatch{ - StructType: of.Type(), - FieldName: n, - Reason: fmt.Sprintf("unsupported type (%T)", val), - } - } - } - } - return errFieldMismatch -} - -type multiArgType int - -const ( - multiArgTypeInvalid multiArgType = iota - multiArgTypeStruct - multiArgTypeStructPtr -) - -// checkMultiArg checks that v has type []S, []*S for some struct type S. -// -// It returns what category the slice's elements are, and the reflect.Type -// that represents S. -func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) { - if v.Kind() != reflect.Slice { - return multiArgTypeInvalid, nil - } - elemType = v.Type().Elem() - switch elemType.Kind() { - case reflect.Struct: - return multiArgTypeStruct, elemType - case reflect.Ptr: - elemType = elemType.Elem() - if elemType.Kind() == reflect.Struct { - return multiArgTypeStructPtr, elemType - } - } - return multiArgTypeInvalid, nil -} - -func oleInt64(item *ole.IDispatch, prop string) (int64, error) { - v, err := oleutil.GetProperty(item, prop) - if err != nil { - return 0, err - } - defer v.Clear() - - i := int64(v.Val) - return i, nil -} - -// CreateQuery returns a WQL query string that queries all columns of src. where -// is an optional string that is appended to the query, to be used with WHERE -// clauses. In such a case, the "WHERE" string should appear at the beginning. -func CreateQuery(src interface{}, where string) string { - var b bytes.Buffer - b.WriteString("SELECT ") - s := reflect.Indirect(reflect.ValueOf(src)) - t := s.Type() - if s.Kind() == reflect.Slice { - t = t.Elem() - } - if t.Kind() != reflect.Struct { - return "" - } - var fields []string - for i := 0; i < t.NumField(); i++ { - fields = append(fields, t.Field(i).Name) - } - b.WriteString(strings.Join(fields, ", ")) - b.WriteString(" FROM ") - b.WriteString(t.Name()) - b.WriteString(" " + where) - return b.String() -} diff --git a/vendor/github.com/aristanetworks/goarista/monotime/issue15006.s b/vendor/github.com/aristanetworks/goarista/monotime/issue15006.s index 66109f4f31..0d11d8d6a0 100644 --- a/vendor/github.com/aristanetworks/goarista/monotime/issue15006.s +++ b/vendor/github.com/aristanetworks/goarista/monotime/issue15006.s @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Arista Networks, Inc. +// Copyright (c) 2016 Arista Networks, Inc. // Use of this source code is governed by the Apache License 2.0 // that can be found in the COPYING file. diff --git a/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go b/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go index 5f5fbc7ae5..d999a42b72 100644 --- a/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go +++ b/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Arista Networks, Inc. +// Copyright (c) 2016 Arista Networks, Inc. // Use of this source code is governed by the Apache License 2.0 // that can be found in the COPYING file. diff --git a/vendor/github.com/btcsuite/btcd/btcec/btcec.go b/vendor/github.com/btcsuite/btcd/btcec/btcec.go index 5e7ce875fd..de93a255a4 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/btcec.go +++ b/vendor/github.com/btcsuite/btcd/btcec/btcec.go @@ -36,10 +36,17 @@ var ( // interface from crypto/elliptic. type KoblitzCurve struct { *elliptic.CurveParams - q *big.Int + + // q is the value (P+1)/4 used to compute the square root of field + // elements. + q *big.Int + H int // cofactor of the curve. halfOrder *big.Int // half the order N + // fieldB is the constant B of the curve as a fieldVal. + fieldB *fieldVal + // byteSize is simply the bit size / 8 and is provided for convenience // since it is calculated repeatedly. byteSize int @@ -879,12 +886,22 @@ func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { return curve.fieldJacobianToBigAffine(qx, qy, qz) } -// QPlus1Div4 returns the Q+1/4 constant for the curve for use in calculating -// square roots via exponention. +// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating +// square roots via exponentiation. +// +// DEPRECATED: The actual value returned is (P+1)/4, where as the original +// method name implies that this value is (((P+1)/4)+1)/4. This method is kept +// to maintain backwards compatibility of the API. Use Q() instead. func (curve *KoblitzCurve) QPlus1Div4() *big.Int { return curve.q } +// Q returns the (P+1)/4 constant for the curve for use in calculating square +// roots via exponentiation. +func (curve *KoblitzCurve) Q() *big.Int { + return curve.q +} + var initonce sync.Once var secp256k1 KoblitzCurve @@ -917,6 +934,7 @@ func initS256() { big.NewInt(1)), big.NewInt(4)) secp256k1.H = 1 secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1) + secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes()) // Provided for convenience since this gets computed repeatedly. secp256k1.byteSize = secp256k1.BitSize / 8 diff --git a/vendor/github.com/btcsuite/btcd/btcec/field.go b/vendor/github.com/btcsuite/btcd/btcec/field.go index 0f2be74c0c..c2bb84b3fe 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/field.go +++ b/vendor/github.com/btcsuite/btcd/btcec/field.go @@ -102,6 +102,20 @@ const ( fieldPrimeWordOne = 0x3ffffbf ) +var ( + // fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This + // value is used to efficiently compute the square root of values in the + // field via exponentiation. The value of Q in hex is: + // + // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c + fieldQBytes = []byte{ + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x0c, + } +) + // fieldVal implements optimized fixed-precision arithmetic over the // secp256k1 finite field. This means all arithmetic is performed modulo // 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It @@ -1221,3 +1235,118 @@ func (f *fieldVal) Inverse() *fieldVal { f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320) return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2) } + +// SqrtVal computes the square root of x modulo the curve's prime, and stores +// the result in f. The square root is computed via exponentiation of x by the +// value Q = (P+1)/4 using the curve's precomputed big-endian representation of +// the Q. This method uses a modified version of square-and-multiply +// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits, +// which offers better performance over both big.Int exponentiation and bit-wise +// square-and-multiply. +// +// NOTE: This method only works when P is intended to be the secp256k1 prime and +// is not constant time. The returned value is of magnitude 1, but is +// denormalized. +func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal { + // The following computation iteratively computes x^((P+1)/4) = x^Q + // using the recursive, piece-wise definition: + // + // x^n = (x^2)^(n/2) mod P if n is even + // x^n = x(x^2)^(n-1/2) mod P if n is odd + // + // Given n in its big-endian representation b_k, ..., b_0, x^n can be + // computed by defining the sequence r_k+1, ..., r_0, where: + // + // r_k+1 = 1 + // r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0 + // + // The final value r_0 = x^n. + // + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more + // details. + // + // This can be further optimized, by observing that the value of Q in + // secp256k1 has the value: + // + // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c + // + // We can unroll the typical bit-wise interpretation of the + // exponentiation algorithm above to instead operate on bytes. + // This reduces the number of comparisons by an order of magnitude, + // reducing the overhead of failed branch predictions and additional + // comparisons in this method. + // + // Since there there are only 4 unique bytes of Q, this keeps the jump + // table small without the need to handle all possible 8-bit values. + // Further, we observe that 29 of the 32 bytes are 0xff; making the + // first case handle 0xff therefore optimizes the hot path. + f.SetInt(1) + for _, b := range fieldQBytes { + switch b { + + // Most common case, where all 8 bits are set. + case 0xff: + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // First byte of Q (0x3f), where all but the top two bits are + // set. Note that this case only applies six operations, since + // the highest bit of Q resides in bit six of the first byte. We + // ignore the first two bits, since squaring for these bits will + // result in an invalid result. We forgo squaring f before the + // first multiply, since 1^2 = 1. + case 0x3f: + f.Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // Byte 28 of Q (0xbf), where only bit 7 is unset. + case 0xbf: + f.Square().Mul(x) + f.Square() + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // Byte 31 of Q (0x0c), where only bits 3 and 4 are set. + default: + f.Square() + f.Square() + f.Square() + f.Square() + f.Square().Mul(x) + f.Square().Mul(x) + f.Square() + f.Square() + } + } + + return f +} + +// Sqrt computes the square root of f modulo the curve's prime, and stores the +// result in f. The square root is computed via exponentiation of x by the value +// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q. +// This method uses a modified version of square-and-multiply exponentiation +// over secp256k1 fieldVals to operate on bytes instead of bits, which offers +// better performance over both big.Int exponentiation and bit-wise +// square-and-multiply. +// +// NOTE: This method only works when P is intended to be the secp256k1 prime and +// is not constant time. The returned value is of magnitude 1, but is +// denormalized. +func (f *fieldVal) Sqrt() *fieldVal { + return f.SqrtVal(f) +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go deleted file mode 100644 index d4a9c1b830..0000000000 --- a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -// This file is ignored during the regular build due to the following build tag. -// It is called by go generate and used to automatically generate pre-computed -// tables used to accelerate operations. -// +build ignore - -package main - -import ( - "bytes" - "compress/zlib" - "encoding/base64" - "fmt" - "log" - "os" - - "github.com/btcsuite/btcd/btcec" -) - -func main() { - fi, err := os.Create("secp256k1.go") - if err != nil { - log.Fatal(err) - } - defer fi.Close() - - // Compress the serialized byte points. - serialized := btcec.S256().SerializedBytePoints() - var compressed bytes.Buffer - w := zlib.NewWriter(&compressed) - if _, err := w.Write(serialized); err != nil { - fmt.Println(err) - os.Exit(1) - } - w.Close() - - // Encode the compressed byte points with base64. - encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len())) - base64.StdEncoding.Encode(encoded, compressed.Bytes()) - - fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers") - fmt.Fprintln(fi, "// Use of this source code is governed by an ISC") - fmt.Fprintln(fi, "// license that can be found in the LICENSE file.") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "package btcec") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)") - fmt.Fprintln(fi, "// DO NOT EDIT") - fmt.Fprintln(fi) - fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded)) - - a1, b1, a2, b2 := btcec.S256().EndomorphismVectors() - fmt.Println("The following values are the computed linearly " + - "independent vectors needed to make use of the secp256k1 " + - "endomorphism:") - fmt.Printf("a1: %x\n", a1) - fmt.Printf("b1: %x\n", b1) - fmt.Printf("a2: %x\n", a2) - fmt.Printf("b2: %x\n", b2) -} diff --git a/vendor/github.com/btcsuite/btcd/btcec/pubkey.go b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go index b74917718f..3c9d5d02d2 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/pubkey.go +++ b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go @@ -22,30 +22,40 @@ func isOdd(a *big.Int) bool { return a.Bit(0) == 1 } -// decompressPoint decompresses a point on the given curve given the X point and +// decompressPoint decompresses a point on the secp256k1 curve given the X point and // the solution to use. -func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, error) { - // TODO: This will probably only work for secp256k1 due to - // optimizations. +func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, error) { + var x fieldVal + x.SetByteSlice(bigX.Bytes()) - // Y = +-sqrt(x^3 + B) - x3 := new(big.Int).Mul(x, x) - x3.Mul(x3, x) - x3.Add(x3, curve.Params().B) + // Compute x^3 + B mod p. + var x3 fieldVal + x3.SquareVal(&x).Mul(&x) + x3.Add(curve.fieldB).Normalize() - // now calculate sqrt mod p of x2 + B + // Now calculate sqrt mod p of x^3 + B // This code used to do a full sqrt based on tonelli/shanks, // but this was replaced by the algorithms referenced in // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 - y := new(big.Int).Exp(x3, curve.QPlus1Div4(), curve.Params().P) + var y fieldVal + y.SqrtVal(&x3).Normalize() + if ybit != y.IsOdd() { + y.Negate(1).Normalize() + } - if ybit != isOdd(y) { - y.Sub(curve.Params().P, y) + // Check that y is a square root of x^3 + B. + var y2 fieldVal + y2.SquareVal(&y).Normalize() + if !y2.Equals(&x3) { + return nil, fmt.Errorf("invalid square root") } - if ybit != isOdd(y) { + + // Verify that y-coord has expected parity. + if ybit != y.IsOdd() { return nil, fmt.Errorf("ybit doesn't match oddness") } - return y, nil + + return new(big.Int).SetBytes(y.Bytes()[:]), nil } const ( @@ -91,6 +101,17 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) { return nil, fmt.Errorf("ybit doesn't match oddness") } + + if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey X parameter is >= to P") + } + if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey Y parameter is >= to P") + } + if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { + return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") + } + case PubKeyBytesLenCompressed: // format is 0x2 | solution, // solution determines which solution of the curve we use. @@ -104,20 +125,12 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err if err != nil { return nil, err } + default: // wrong! return nil, fmt.Errorf("invalid pub key length %d", len(pubKeyStr)) } - if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey X parameter is >= to P") - } - if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey Y parameter is >= to P") - } - if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { - return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") - } return &pubkey, nil } diff --git a/vendor/github.com/btcsuite/btcd/btcec/signature.go b/vendor/github.com/btcsuite/btcd/btcec/signature.go index 4392ab41a2..deedd172d8 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/signature.go +++ b/vendor/github.com/btcsuite/btcd/btcec/signature.go @@ -85,6 +85,11 @@ func (sig *Signature) IsEqual(otherSig *Signature) bool { sig.S.Cmp(otherSig.S) == 0 } +// MinSigLen is the minimum length of a DER encoded signature and is when both R +// and S are 1 byte each. +// 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + +const MinSigLen = 8 + func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the // signature, but a number of problems were found with this approach. @@ -98,9 +103,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) signature := &Signature{} - // minimal message is when both numbers are 1 bytes. adding up to: - // 0x30 + len + 0x02 + 0x01 + + 0x2 + 0x01 + - if len(sigStr) < 8 { + if len(sigStr) < MinSigLen { return nil, errors.New("malformed signature: too short") } // 0x30 @@ -112,7 +115,10 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // length of remaining message siglen := sigStr[index] index++ - if int(siglen+2) > len(sigStr) { + + // siglen should be less than the entire message and greater than + // the minimal message size. + if int(siglen+2) > len(sigStr) || int(siglen+2) < MinSigLen { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. @@ -269,8 +275,8 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int { return ret } -// recoverKeyFromSignature recoves a public key from the signature "sig" on the -// given message hash "msg". Based on the algorithm found in section 5.1.5 of +// recoverKeyFromSignature recovers a public key from the signature "sig" on the +// given message hash "msg". Based on the algorithm found in section 4.1.6 of // SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details // in the inner loop in Step 1. The counter provided is actually the j parameter // of the loop * 2 - on the first iteration of j we do the R case, else the -R @@ -421,9 +427,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { k := nonceRFC6979(privkey.D, hash) inv := new(big.Int).ModInverse(k, N) r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) - if r.Cmp(N) == 1 { - r.Sub(r, N) - } + r.Mod(r, N) if r.Sign() == 0 { return nil, errors.New("calculated R is zero") diff --git a/vendor/github.com/caarlos0/env/.gitignore b/vendor/github.com/caarlos0/env/.gitignore new file mode 100644 index 0000000000..2d830686d4 --- /dev/null +++ b/vendor/github.com/caarlos0/env/.gitignore @@ -0,0 +1 @@ +coverage.out diff --git a/vendor/github.com/caarlos0/env/.hound.yml b/vendor/github.com/caarlos0/env/.hound.yml new file mode 100644 index 0000000000..e5c719dd29 --- /dev/null +++ b/vendor/github.com/caarlos0/env/.hound.yml @@ -0,0 +1,2 @@ +go: + enabled: true diff --git a/vendor/github.com/caarlos0/env/.travis.yml b/vendor/github.com/caarlos0/env/.travis.yml new file mode 100644 index 0000000000..5a5a2c823f --- /dev/null +++ b/vendor/github.com/caarlos0/env/.travis.yml @@ -0,0 +1,19 @@ +language: go +go: + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 + - '1.10.x' + - '1.11.x' + - tip +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - go test -v -cover -race -coverprofile=coverage.out +after_script: + - go get github.com/mattn/goveralls + - goveralls -coverprofile=coverage.out -service=travis-ci -repotoken='eCcizKmTdSaJCz8Ih33WDppdqb9kioYwi' diff --git a/vendor/github.com/rs/xhandler/LICENSE b/vendor/github.com/caarlos0/env/LICENSE.md similarity index 85% rename from vendor/github.com/rs/xhandler/LICENSE rename to vendor/github.com/caarlos0/env/LICENSE.md index 47c5e9d2d2..b7398672ff 100644 --- a/vendor/github.com/rs/xhandler/LICENSE +++ b/vendor/github.com/caarlos0/env/LICENSE.md @@ -1,11 +1,13 @@ -Copyright (c) 2015 Olivier Poitrey +The MIT License (MIT) + +Copyright (c) 2015-2016 Carlos Alexandro Becker Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. @@ -15,5 +17,5 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/caarlos0/env/README.md b/vendor/github.com/caarlos0/env/README.md new file mode 100644 index 0000000000..ef50e91a55 --- /dev/null +++ b/vendor/github.com/caarlos0/env/README.md @@ -0,0 +1,119 @@ +# env [![Build Status](https://travis-ci.org/caarlos0/env.svg?branch=master)](https://travis-ci.org/caarlos0/env) [![Coverage Status](https://coveralls.io/repos/caarlos0/env/badge.svg?branch=master&service=github)](https://coveralls.io/github/caarlos0/env?branch=master) [![](https://godoc.org/github.com/caarlos0/env?status.svg)](http://godoc.org/github.com/caarlos0/env) [![](http://goreportcard.com/badge/caarlos0/env)](http://goreportcard.com/report/caarlos0/env) [![SayThanks.io](https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg?style=flat-square)](https://saythanks.io/to/caarlos0) + +A KISS way to deal with environment variables in Go. + +## Why + +At first, it was boring for me to write down an entire function just to +get some `var` from the environment and default to another in case it's missing. + +For that manner, I wrote a `GetOr` function in the +[go-idioms](https://github.com/caarlos0/go-idioms) project. + +Then, I got pissed about writing `os.Getenv`, `os.Setenv`, `os.Unsetenv`... +it kind of make more sense to me write it as `env.Get`, `env.Set`, `env.Unset`. +So I did. + +Then I got a better idea: to use `struct` tags to do all that work for me. + +## Example + +A very basic example (check the `examples` folder): + +```go +package main + +import ( + "fmt" + "time" + + "github.com/caarlos0/env" +) + +type config struct { + Home string `env:"HOME"` + Port int `env:"PORT" envDefault:"3000"` + IsProduction bool `env:"PRODUCTION"` + Hosts []string `env:"HOSTS" envSeparator:":"` + Duration time.Duration `env:"DURATION"` + TempFolder string `env:"TEMP_FOLDER" envDefault:"${HOME}/tmp" envExpand:"true"` +} + +func main() { + cfg := config{} + err := env.Parse(&cfg) + if err != nil { + fmt.Printf("%+v\n", err) + } + fmt.Printf("%+v\n", cfg) +} +``` + +You can run it like this: + +```sh +$ PRODUCTION=true HOSTS="host1:host2:host3" DURATION=1s go run examples/first.go +{Home:/your/home Port:3000 IsProduction:true Hosts:[host1 host2 host3] Duration:1s} +``` + +## Supported types and defaults + +The library has built-in support for the following types: + +* `string` +* `int` +* `uint` +* `int64` +* `bool` +* `float32` +* `float64` +* `time.Duration` +* `[]string` +* `[]int` +* `[]bool` +* `[]float32` +* `[]float64` +* `[]time.Duration` +* .. or use/define a [custom parser func](#custom-parser-funcs) for any other type + +If you set the `envDefault` tag for something, this value will be used in the +case of absence of it in the environment. If you don't do that AND the +environment variable is also not set, the zero-value +of the type will be used: empty for `string`s, `false` for `bool`s +and `0` for `int`s. + +By default, slice types will split the environment value on `,`; you can change this behavior by setting the `envSeparator` tag. + +If you set the `envExpand` tag, environment variables (either in `${var}` or `$var` format) +in the string will be replaced according with the actual value of the variable. + +## Custom Parser Funcs + +If you have a type that is not supported out of the box by the lib, you are able +to use (or define) and pass custom parsers (and their associated `reflect.Type`) to the +`env.ParseWithFuncs()` function. + +In addition to accepting a struct pointer (same as `Parse()`), this function also +accepts a `env.CustomParsers` arg that under the covers is a `map[reflect.Type]env.ParserFunc`. + +To see what this looks like in practice, take a look at the [commented block in the example](https://github.com/caarlos0/env/blob/master/examples/first.go#L35-L39). + +`env` also ships with some pre-built custom parser funcs for common types. You +can check them out [here](parsers/). + +## Required fields + +The `env` tag option `required` (e.g., `env:"tagKey,required"`) can be added +to ensure that some environment variable is set. In the example above, +an error is returned if the `config` struct is changed to: + + +```go +type config struct { + Home string `env:"HOME"` + Port int `env:"PORT" envDefault:"3000"` + IsProduction bool `env:"PRODUCTION"` + Hosts []string `env:"HOSTS" envSeparator:":"` + SecretKey string `env:"SECRET_KEY,required"` +} +``` diff --git a/vendor/github.com/caarlos0/env/env.go b/vendor/github.com/caarlos0/env/env.go new file mode 100644 index 0000000000..9e29045da3 --- /dev/null +++ b/vendor/github.com/caarlos0/env/env.go @@ -0,0 +1,436 @@ +package env + +import ( + "encoding" + "errors" + "fmt" + "os" + "reflect" + "strconv" + "strings" + "time" +) + +var ( + // ErrNotAStructPtr is returned if you pass something that is not a pointer to a + // Struct to Parse + ErrNotAStructPtr = errors.New("Expected a pointer to a Struct") + // ErrUnsupportedType if the struct field type is not supported by env + ErrUnsupportedType = errors.New("Type is not supported") + // ErrUnsupportedSliceType if the slice element type is not supported by env + ErrUnsupportedSliceType = errors.New("Unsupported slice type") + // OnEnvVarSet is an optional convenience callback, such as for logging purposes. + // If not nil, it's called after successfully setting the given field from the given value. + OnEnvVarSet func(reflect.StructField, string) + // Friendly names for reflect types + sliceOfInts = reflect.TypeOf([]int(nil)) + sliceOfInt64s = reflect.TypeOf([]int64(nil)) + sliceOfUint64s = reflect.TypeOf([]uint64(nil)) + sliceOfStrings = reflect.TypeOf([]string(nil)) + sliceOfBools = reflect.TypeOf([]bool(nil)) + sliceOfFloat32s = reflect.TypeOf([]float32(nil)) + sliceOfFloat64s = reflect.TypeOf([]float64(nil)) + sliceOfDurations = reflect.TypeOf([]time.Duration(nil)) +) + +// CustomParsers is a friendly name for the type that `ParseWithFuncs()` accepts +type CustomParsers map[reflect.Type]ParserFunc + +// ParserFunc defines the signature of a function that can be used within `CustomParsers` +type ParserFunc func(v string) (interface{}, error) + +// Parse parses a struct containing `env` tags and loads its values from +// environment variables. +func Parse(v interface{}) error { + ptrRef := reflect.ValueOf(v) + if ptrRef.Kind() != reflect.Ptr { + return ErrNotAStructPtr + } + ref := ptrRef.Elem() + if ref.Kind() != reflect.Struct { + return ErrNotAStructPtr + } + return doParse(ref, make(map[reflect.Type]ParserFunc, 0)) +} + +// ParseWithFuncs is the same as `Parse` except it also allows the user to pass +// in custom parsers. +func ParseWithFuncs(v interface{}, funcMap CustomParsers) error { + ptrRef := reflect.ValueOf(v) + if ptrRef.Kind() != reflect.Ptr { + return ErrNotAStructPtr + } + ref := ptrRef.Elem() + if ref.Kind() != reflect.Struct { + return ErrNotAStructPtr + } + return doParse(ref, funcMap) +} + +func doParse(ref reflect.Value, funcMap CustomParsers) error { + refType := ref.Type() + var errorList []string + + for i := 0; i < refType.NumField(); i++ { + refField := ref.Field(i) + if reflect.Ptr == refField.Kind() && !refField.IsNil() && refField.CanSet() { + err := Parse(refField.Interface()) + if nil != err { + return err + } + continue + } + refTypeField := refType.Field(i) + value, err := get(refTypeField) + if err != nil { + errorList = append(errorList, err.Error()) + continue + } + if value == "" { + continue + } + if err := set(refField, refTypeField, value, funcMap); err != nil { + errorList = append(errorList, err.Error()) + continue + } + if OnEnvVarSet != nil { + OnEnvVarSet(refTypeField, value) + } + } + if len(errorList) == 0 { + return nil + } + return errors.New(strings.Join(errorList, ". ")) +} + +func get(field reflect.StructField) (string, error) { + var ( + val string + err error + ) + + key, opts := parseKeyForOption(field.Tag.Get("env")) + + defaultValue := field.Tag.Get("envDefault") + val = getOr(key, defaultValue) + + expandVar := field.Tag.Get("envExpand") + if strings.ToLower(expandVar) == "true" { + val = os.ExpandEnv(val) + } + + if len(opts) > 0 { + for _, opt := range opts { + // The only option supported is "required". + switch opt { + case "": + break + case "required": + val, err = getRequired(key) + default: + err = fmt.Errorf("env tag option %q not supported", opt) + } + } + } + + return val, err +} + +// split the env tag's key into the expected key and desired option, if any. +func parseKeyForOption(key string) (string, []string) { + opts := strings.Split(key, ",") + return opts[0], opts[1:] +} + +func getRequired(key string) (string, error) { + if value, ok := os.LookupEnv(key); ok { + return value, nil + } + return "", fmt.Errorf("required environment variable %q is not set", key) +} + +func getOr(key, defaultValue string) string { + value, ok := os.LookupEnv(key) + if ok { + return value + } + return defaultValue +} + +func set(field reflect.Value, refType reflect.StructField, value string, funcMap CustomParsers) error { + // use custom parser if configured for this type + parserFunc, ok := funcMap[refType.Type] + if ok { + val, err := parserFunc(value) + if err != nil { + return fmt.Errorf("Custom parser error: %v", err) + } + field.Set(reflect.ValueOf(val)) + return nil + } + + // fall back to built-in parsers + switch field.Kind() { + case reflect.Slice: + separator := refType.Tag.Get("envSeparator") + return handleSlice(field, value, separator) + case reflect.String: + field.SetString(value) + case reflect.Bool: + bvalue, err := strconv.ParseBool(value) + if err != nil { + return err + } + field.SetBool(bvalue) + case reflect.Int: + intValue, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return err + } + field.SetInt(intValue) + case reflect.Uint: + uintValue, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return err + } + field.SetUint(uintValue) + case reflect.Float32: + v, err := strconv.ParseFloat(value, 32) + if err != nil { + return err + } + field.SetFloat(v) + case reflect.Float64: + v, err := strconv.ParseFloat(value, 64) + if err != nil { + return err + } + field.Set(reflect.ValueOf(v)) + case reflect.Int64: + if refType.Type.String() == "time.Duration" { + dValue, err := time.ParseDuration(value) + if err != nil { + return err + } + field.Set(reflect.ValueOf(dValue)) + } else { + intValue, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return err + } + field.SetInt(intValue) + } + case reflect.Uint64: + uintValue, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return err + } + field.SetUint(uintValue) + default: + return handleTextUnmarshaler(field, value) + } + return nil +} + +func handleSlice(field reflect.Value, value, separator string) error { + if separator == "" { + separator = "," + } + + splitData := strings.Split(value, separator) + + switch field.Type() { + case sliceOfStrings: + field.Set(reflect.ValueOf(splitData)) + case sliceOfInts: + intData, err := parseInts(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(intData)) + case sliceOfInt64s: + int64Data, err := parseInt64s(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(int64Data)) + case sliceOfUint64s: + uint64Data, err := parseUint64s(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(uint64Data)) + case sliceOfFloat32s: + data, err := parseFloat32s(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(data)) + case sliceOfFloat64s: + data, err := parseFloat64s(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(data)) + case sliceOfBools: + boolData, err := parseBools(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(boolData)) + case sliceOfDurations: + durationData, err := parseDurations(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(durationData)) + default: + elemType := field.Type().Elem() + // Ensure we test *type as we can always address elements in a slice. + if elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + } + if _, ok := reflect.New(elemType).Interface().(encoding.TextUnmarshaler); !ok { + return ErrUnsupportedSliceType + } + return parseTextUnmarshalers(field, splitData) + + } + return nil +} + +func handleTextUnmarshaler(field reflect.Value, value string) error { + if reflect.Ptr == field.Kind() { + if field.IsNil() { + field.Set(reflect.New(field.Type().Elem())) + } + } else if field.CanAddr() { + field = field.Addr() + } + + tm, ok := field.Interface().(encoding.TextUnmarshaler) + if !ok { + return ErrUnsupportedType + } + + return tm.UnmarshalText([]byte(value)) +} + +func parseInts(data []string) ([]int, error) { + intSlice := make([]int, 0, len(data)) + + for _, v := range data { + intValue, err := strconv.ParseInt(v, 10, 32) + if err != nil { + return nil, err + } + intSlice = append(intSlice, int(intValue)) + } + return intSlice, nil +} + +func parseInt64s(data []string) ([]int64, error) { + intSlice := make([]int64, 0, len(data)) + + for _, v := range data { + intValue, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return nil, err + } + intSlice = append(intSlice, int64(intValue)) + } + return intSlice, nil +} + +func parseUint64s(data []string) ([]uint64, error) { + var uintSlice []uint64 + + for _, v := range data { + uintValue, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return nil, err + } + uintSlice = append(uintSlice, uint64(uintValue)) + } + return uintSlice, nil +} + +func parseFloat32s(data []string) ([]float32, error) { + float32Slice := make([]float32, 0, len(data)) + + for _, v := range data { + data, err := strconv.ParseFloat(v, 32) + if err != nil { + return nil, err + } + float32Slice = append(float32Slice, float32(data)) + } + return float32Slice, nil +} + +func parseFloat64s(data []string) ([]float64, error) { + float64Slice := make([]float64, 0, len(data)) + + for _, v := range data { + data, err := strconv.ParseFloat(v, 64) + if err != nil { + return nil, err + } + float64Slice = append(float64Slice, float64(data)) + } + return float64Slice, nil +} + +func parseBools(data []string) ([]bool, error) { + boolSlice := make([]bool, 0, len(data)) + + for _, v := range data { + bvalue, err := strconv.ParseBool(v) + if err != nil { + return nil, err + } + + boolSlice = append(boolSlice, bvalue) + } + return boolSlice, nil +} + +func parseDurations(data []string) ([]time.Duration, error) { + durationSlice := make([]time.Duration, 0, len(data)) + + for _, v := range data { + dvalue, err := time.ParseDuration(v) + if err != nil { + return nil, err + } + + durationSlice = append(durationSlice, dvalue) + } + return durationSlice, nil +} + +func parseTextUnmarshalers(field reflect.Value, data []string) error { + s := len(data) + elemType := field.Type().Elem() + slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s) + for i, v := range data { + sv := slice.Index(i) + kind := sv.Kind() + if kind == reflect.Ptr { + sv = reflect.New(elemType.Elem()) + } else { + sv = sv.Addr() + } + tm := sv.Interface().(encoding.TextUnmarshaler) + if err := tm.UnmarshalText([]byte(v)); err != nil { + return err + } + if kind == reflect.Ptr { + slice.Index(i).Set(sv) + } + } + + field.Set(slice) + + return nil +} diff --git a/vendor/github.com/deckarep/golang-set/threadsafe.go b/vendor/github.com/deckarep/golang-set/threadsafe.go index 002e06af1f..269b4ab0cb 100644 --- a/vendor/github.com/deckarep/golang-set/threadsafe.go +++ b/vendor/github.com/deckarep/golang-set/threadsafe.go @@ -226,8 +226,14 @@ func (set *threadSafeSet) String() string { func (set *threadSafeSet) PowerSet() Set { set.RLock() - ret := set.s.PowerSet() + unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet) set.RUnlock() + + ret := &threadSafeSet{s: newThreadUnsafeSet()} + for subset := range unsafePowerSet.Iter() { + unsafeSubset := subset.(*threadUnsafeSet) + ret.Add(&threadSafeSet{s: *unsafeSubset}) + } return ret } diff --git a/vendor/github.com/docker/docker/pkg/archive/example_changes.go b/vendor/github.com/docker/docker/pkg/archive/example_changes.go deleted file mode 100644 index 495db809e9..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/example_changes.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build ignore - -// Simple tool to create an archive stream from an old and new directory -// -// By default it will stream the comparison of two temporary directories with junk files -package main - -import ( - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path" - - "github.com/docker/docker/pkg/archive" - "github.com/sirupsen/logrus" -) - -var ( - flDebug = flag.Bool("D", false, "debugging output") - flNewDir = flag.String("newdir", "", "") - flOldDir = flag.String("olddir", "", "") - log = logrus.New() -) - -func main() { - flag.Usage = func() { - fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") - fmt.Printf("%s [OPTIONS]\n", os.Args[0]) - flag.PrintDefaults() - } - flag.Parse() - log.Out = os.Stderr - if (len(os.Getenv("DEBUG")) > 0) || *flDebug { - logrus.SetLevel(logrus.DebugLevel) - } - var newDir, oldDir string - - if len(*flNewDir) == 0 { - var err error - newDir, err = ioutil.TempDir("", "docker-test-newDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(newDir) - if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { - log.Fatal(err) - } - } else { - newDir = *flNewDir - } - - if len(*flOldDir) == 0 { - oldDir, err := ioutil.TempDir("", "docker-test-oldDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(oldDir) - } else { - oldDir = *flOldDir - } - - changes, err := archive.ChangesDirs(newDir, oldDir) - if err != nil { - log.Fatal(err) - } - - a, err := archive.ExportChanges(newDir, changes) - if err != nil { - log.Fatal(err) - } - defer a.Close() - - i, err := io.Copy(os.Stdout, a) - if err != nil && err != io.EOF { - log.Fatal(err) - } - fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) -} - -func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { - fileData := []byte("fooo") - for n := 0; n < numberOfFiles; n++ { - fileName := fmt.Sprintf("file-%d", n) - if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { - return 0, err - } - if makeLinks { - if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { - return 0, err - } - } - } - totalSize := numberOfFiles * len(fileData) - return totalSize, nil -} diff --git a/vendor/github.com/edsrzf/mmap-go/mmap.go b/vendor/github.com/edsrzf/mmap-go/mmap.go index 7bb4965ed5..29655bd222 100644 --- a/vendor/github.com/edsrzf/mmap-go/mmap.go +++ b/vendor/github.com/edsrzf/mmap-go/mmap.go @@ -54,6 +54,10 @@ func Map(f *os.File, prot, flags int) (MMap, error) { // If length < 0, the entire file will be mapped. // If ANON is set in flags, f is ignored. func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) { + if offset%int64(os.Getpagesize()) != 0 { + return nil, errors.New("offset parameter must be a multiple of the system's page size") + } + var fd uintptr if flags&ANON == 0 { fd = uintptr(f.Fd()) @@ -77,25 +81,27 @@ func (m *MMap) header() *reflect.SliceHeader { return (*reflect.SliceHeader)(unsafe.Pointer(m)) } +func (m *MMap) addrLen() (uintptr, uintptr) { + header := m.header() + return header.Data, uintptr(header.Len) +} + // Lock keeps the mapped region in physical memory, ensuring that it will not be // swapped out. func (m MMap) Lock() error { - dh := m.header() - return lock(dh.Data, uintptr(dh.Len)) + return m.lock() } // Unlock reverses the effect of Lock, allowing the mapped region to potentially // be swapped out. // If m is already unlocked, aan error will result. func (m MMap) Unlock() error { - dh := m.header() - return unlock(dh.Data, uintptr(dh.Len)) + return m.unlock() } // Flush synchronizes the mapping's contents to the file's contents on disk. func (m MMap) Flush() error { - dh := m.header() - return flush(dh.Data, uintptr(dh.Len)) + return m.flush() } // Unmap deletes the memory mapped region, flushes any remaining changes, and sets @@ -105,8 +111,7 @@ func (m MMap) Flush() error { // Unmap should only be called on the slice value that was originally returned from // a call to Map. Calling Unmap on a derived slice may cause errors. func (m *MMap) Unmap() error { - dh := m.header() - err := unmap(dh.Data, uintptr(dh.Len)) + err := m.unmap() *m = nil return err } diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_unix.go b/vendor/github.com/edsrzf/mmap-go/mmap_unix.go index 4af98420d5..25b13e51fd 100644 --- a/vendor/github.com/edsrzf/mmap-go/mmap_unix.go +++ b/vendor/github.com/edsrzf/mmap-go/mmap_unix.go @@ -7,61 +7,45 @@ package mmap import ( - "syscall" + "golang.org/x/sys/unix" ) func mmap(len int, inprot, inflags, fd uintptr, off int64) ([]byte, error) { - flags := syscall.MAP_SHARED - prot := syscall.PROT_READ + flags := unix.MAP_SHARED + prot := unix.PROT_READ switch { case inprot© != 0: - prot |= syscall.PROT_WRITE - flags = syscall.MAP_PRIVATE + prot |= unix.PROT_WRITE + flags = unix.MAP_PRIVATE case inprot&RDWR != 0: - prot |= syscall.PROT_WRITE + prot |= unix.PROT_WRITE } if inprot&EXEC != 0 { - prot |= syscall.PROT_EXEC + prot |= unix.PROT_EXEC } if inflags&ANON != 0 { - flags |= syscall.MAP_ANON + flags |= unix.MAP_ANON } - b, err := syscall.Mmap(int(fd), off, len, prot, flags) + b, err := unix.Mmap(int(fd), off, len, prot, flags) if err != nil { return nil, err } return b, nil } -func flush(addr, len uintptr) error { - _, _, errno := syscall.Syscall(_SYS_MSYNC, addr, len, _MS_SYNC) - if errno != 0 { - return syscall.Errno(errno) - } - return nil +func (m MMap) flush() error { + return unix.Msync([]byte(m), unix.MS_SYNC) } -func lock(addr, len uintptr) error { - _, _, errno := syscall.Syscall(syscall.SYS_MLOCK, addr, len, 0) - if errno != 0 { - return syscall.Errno(errno) - } - return nil +func (m MMap) lock() error { + return unix.Mlock([]byte(m)) } -func unlock(addr, len uintptr) error { - _, _, errno := syscall.Syscall(syscall.SYS_MUNLOCK, addr, len, 0) - if errno != 0 { - return syscall.Errno(errno) - } - return nil +func (m MMap) unlock() error { + return unix.Munlock([]byte(m)) } -func unmap(addr, len uintptr) error { - _, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, len, 0) - if errno != 0 { - return syscall.Errno(errno) - } - return nil +func (m MMap) unmap() error { + return unix.Munmap([]byte(m)) } diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_windows.go b/vendor/github.com/edsrzf/mmap-go/mmap_windows.go index c3d2d02d3f..7910da2577 100644 --- a/vendor/github.com/edsrzf/mmap-go/mmap_windows.go +++ b/vendor/github.com/edsrzf/mmap-go/mmap_windows.go @@ -8,7 +8,8 @@ import ( "errors" "os" "sync" - "syscall" + + "golang.org/x/sys/windows" ) // mmap on Windows is a two-step process. @@ -19,23 +20,29 @@ import ( // not a struct, so it's convenient to manipulate. // We keep this map so that we can get back the original handle from the memory address. + +type addrinfo struct { + file windows.Handle + mapview windows.Handle +} + var handleLock sync.Mutex -var handleMap = map[uintptr]syscall.Handle{} +var handleMap = map[uintptr]*addrinfo{} func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) { - flProtect := uint32(syscall.PAGE_READONLY) - dwDesiredAccess := uint32(syscall.FILE_MAP_READ) + flProtect := uint32(windows.PAGE_READONLY) + dwDesiredAccess := uint32(windows.FILE_MAP_READ) switch { case prot© != 0: - flProtect = syscall.PAGE_WRITECOPY - dwDesiredAccess = syscall.FILE_MAP_COPY + flProtect = windows.PAGE_WRITECOPY + dwDesiredAccess = windows.FILE_MAP_COPY case prot&RDWR != 0: - flProtect = syscall.PAGE_READWRITE - dwDesiredAccess = syscall.FILE_MAP_WRITE + flProtect = windows.PAGE_READWRITE + dwDesiredAccess = windows.FILE_MAP_WRITE } if prot&EXEC != 0 { flProtect <<= 4 - dwDesiredAccess |= syscall.FILE_MAP_EXECUTE + dwDesiredAccess |= windows.FILE_MAP_EXECUTE } // The maximum size is the area of the file, starting from 0, @@ -45,7 +52,7 @@ func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) { maxSizeHigh := uint32((off + int64(len)) >> 32) maxSizeLow := uint32((off + int64(len)) & 0xFFFFFFFF) // TODO: Do we need to set some security attributes? It might help portability. - h, errno := syscall.CreateFileMapping(syscall.Handle(hfile), nil, flProtect, maxSizeHigh, maxSizeLow, nil) + h, errno := windows.CreateFileMapping(windows.Handle(hfile), nil, flProtect, maxSizeHigh, maxSizeLow, nil) if h == 0 { return nil, os.NewSyscallError("CreateFileMapping", errno) } @@ -54,12 +61,15 @@ func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) { // is the length the user requested. fileOffsetHigh := uint32(off >> 32) fileOffsetLow := uint32(off & 0xFFFFFFFF) - addr, errno := syscall.MapViewOfFile(h, dwDesiredAccess, fileOffsetHigh, fileOffsetLow, uintptr(len)) + addr, errno := windows.MapViewOfFile(h, dwDesiredAccess, fileOffsetHigh, fileOffsetLow, uintptr(len)) if addr == 0 { return nil, os.NewSyscallError("MapViewOfFile", errno) } handleLock.Lock() - handleMap[addr] = h + handleMap[addr] = &addrinfo{ + file: windows.Handle(hfile), + mapview: h, + } handleLock.Unlock() m := MMap{} @@ -71,8 +81,9 @@ func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) { return m, nil } -func flush(addr, len uintptr) error { - errno := syscall.FlushViewOfFile(addr, len) +func (m MMap) flush() error { + addr, len := m.addrLen() + errno := windows.FlushViewOfFile(addr, len) if errno != nil { return os.NewSyscallError("FlushViewOfFile", errno) } @@ -85,22 +96,29 @@ func flush(addr, len uintptr) error { return errors.New("unknown base address") } - errno = syscall.FlushFileBuffers(handle) + errno = windows.FlushFileBuffers(handle.file) return os.NewSyscallError("FlushFileBuffers", errno) } -func lock(addr, len uintptr) error { - errno := syscall.VirtualLock(addr, len) +func (m MMap) lock() error { + addr, len := m.addrLen() + errno := windows.VirtualLock(addr, len) return os.NewSyscallError("VirtualLock", errno) } -func unlock(addr, len uintptr) error { - errno := syscall.VirtualUnlock(addr, len) +func (m MMap) unlock() error { + addr, len := m.addrLen() + errno := windows.VirtualUnlock(addr, len) return os.NewSyscallError("VirtualUnlock", errno) } -func unmap(addr, len uintptr) error { - flush(addr, len) +func (m MMap) unmap() error { + err := m.flush() + if err != nil { + return err + } + + addr := m.header().Data // Lock the UnmapViewOfFile along with the handleMap deletion. // As soon as we unmap the view, the OS is free to give the // same addr to another new map. We don't want another goroutine @@ -108,7 +126,7 @@ func unmap(addr, len uintptr) error { // we're trying to remove our old addr/handle pair. handleLock.Lock() defer handleLock.Unlock() - err := syscall.UnmapViewOfFile(addr) + err = windows.UnmapViewOfFile(addr) if err != nil { return err } @@ -120,6 +138,6 @@ func unmap(addr, len uintptr) error { } delete(handleMap, addr) - e := syscall.CloseHandle(syscall.Handle(handle)) + e := windows.CloseHandle(windows.Handle(handle.mapview)) return os.NewSyscallError("CloseHandle", e) } diff --git a/vendor/github.com/edsrzf/mmap-go/msync_netbsd.go b/vendor/github.com/edsrzf/mmap-go/msync_netbsd.go deleted file mode 100644 index a64b003e2d..0000000000 --- a/vendor/github.com/edsrzf/mmap-go/msync_netbsd.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2011 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mmap - -const _SYS_MSYNC = 277 -const _MS_SYNC = 0x04 diff --git a/vendor/github.com/edsrzf/mmap-go/msync_unix.go b/vendor/github.com/edsrzf/mmap-go/msync_unix.go deleted file mode 100644 index 91ee5f40f1..0000000000 --- a/vendor/github.com/edsrzf/mmap-go/msync_unix.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2011 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux openbsd solaris - -package mmap - -import ( - "syscall" -) - -const _SYS_MSYNC = syscall.SYS_MSYNC -const _MS_SYNC = syscall.MS_SYNC diff --git a/vendor/github.com/elastic/gosigar/.travis.yml b/vendor/github.com/elastic/gosigar/.travis.yml index 30f58bfcf4..fe804624d2 100644 --- a/vendor/github.com/elastic/gosigar/.travis.yml +++ b/vendor/github.com/elastic/gosigar/.travis.yml @@ -5,7 +5,8 @@ os: - osx go: - - 1.8.3 + - 1.8.x + - 1.10.x env: global: diff --git a/vendor/github.com/elastic/gosigar/CHANGELOG.md b/vendor/github.com/elastic/gosigar/CHANGELOG.md index 45262e7b8d..ae848ffb1a 100644 --- a/vendor/github.com/elastic/gosigar/CHANGELOG.md +++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md @@ -8,12 +8,51 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- Added missing runtime import for FreeBSD. #104 - ### Changed ### Deprecated +## [0.10.5] + +### Fixed + +- Fixed uptime calculation under Windows. #126 +- Fixed compilation issue for darwin/386. #128 + +### Changed + +- Load DLLs only from Windows system directory. #132 + +## [0.10.4] + +### Fixed + +- Fixed a crash when splitting command-line arguments under Windows. #124 + +## [0.10.3] + +### Fixed +- ProcState.Get() doesn't fail under Windows when it cannot obtain process ownership information. #121 + +## [0.10.2] + +### Fixed +- Fix memory leak when getting process arguments. #119 + +## [0.10.1] + +### Fixed +- Replaced the WMI queries with win32 apis due to high CPU usage. #116 + +## [0.10.0] + +### Added +- List filesystems on Windows that have an access path but not an assigned letter. #112 + +### Fixed +- Added missing runtime import for FreeBSD. #104 +- Handle nil command line in Windows processes. #110 + ## [0.9.0] ### Added diff --git a/vendor/github.com/elastic/gosigar/README.md b/vendor/github.com/elastic/gosigar/README.md index ecdfc1c3c5..ca1854bf22 100644 --- a/vendor/github.com/elastic/gosigar/README.md +++ b/vendor/github.com/elastic/gosigar/README.md @@ -37,6 +37,7 @@ The features vary by operating system. | ProcMem | X | X | X | | X | | ProcState | X | X | X | | X | | ProcTime | X | X | X | | X | +| Rusage | X | | X | | | | Swap | X | X | | X | X | | Uptime | X | X | | X | X | diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin.go b/vendor/github.com/elastic/gosigar/sigar_darwin.go index a90b998c2e..4a8309521b 100644 --- a/vendor/github.com/elastic/gosigar/sigar_darwin.go +++ b/vendor/github.com/elastic/gosigar/sigar_darwin.go @@ -40,18 +40,6 @@ func (self *LoadAverage) Get() error { return nil } -func (self *Uptime) Get() error { - tv := syscall.Timeval32{} - - if err := sysctlbyname("kern.boottime", &tv); err != nil { - return err - } - - self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds() - - return nil -} - func (self *Mem) Get() error { var vmstat C.vm_statistics_data_t diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin_386.go b/vendor/github.com/elastic/gosigar/sigar_darwin_386.go new file mode 100644 index 0000000000..92c7ff040e --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_darwin_386.go @@ -0,0 +1,18 @@ +package gosigar + +import ( + "syscall" + "time" +) + +func (self *Uptime) Get() error { + tv := syscall.Timeval{} + + if err := sysctlbyname("kern.boottime", &tv); err != nil { + return err + } + + self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds() + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go b/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go new file mode 100644 index 0000000000..29e5b604a9 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go @@ -0,0 +1,18 @@ +package gosigar + +import ( + "syscall" + "time" +) + +func (self *Uptime) Get() error { + tv := syscall.Timeval32{} + + if err := sysctlbyname("kern.boottime", &tv); err != nil { + return err + } + + self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds() + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_freebsd.go b/vendor/github.com/elastic/gosigar/sigar_freebsd.go index 9b2af639b6..51dd84aae2 100644 --- a/vendor/github.com/elastic/gosigar/sigar_freebsd.go +++ b/vendor/github.com/elastic/gosigar/sigar_freebsd.go @@ -111,3 +111,48 @@ func parseCpuStat(self *Cpu, line string) error { self.Idle, _ = strtoull(fields[4]) return nil } + +func (self *Mem) Get() error { + val := C.uint32_t(0) + sc := C.size_t(4) + + name := C.CString("vm.stats.vm.v_page_count") + _, err := C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) + C.free(unsafe.Pointer(name)) + if err != nil { + return err + } + pagecount := uint64(val) + + name = C.CString("vm.stats.vm.v_page_size") + _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) + C.free(unsafe.Pointer(name)) + if err != nil { + return err + } + pagesize := uint64(val) + + name = C.CString("vm.stats.vm.v_free_count") + _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) + C.free(unsafe.Pointer(name)) + if err != nil { + return err + } + self.Free = uint64(val) * pagesize + + name = C.CString("vm.stats.vm.v_inactive_count") + _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) + C.free(unsafe.Pointer(name)) + if err != nil { + return err + } + kern := uint64(val) + + self.Total = uint64(pagecount * pagesize) + + self.Used = self.Total - self.Free + self.ActualFree = self.Free + (kern * pagesize) + self.ActualUsed = self.Used - (kern * pagesize) + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_interface.go b/vendor/github.com/elastic/gosigar/sigar_interface.go index df79ae08d2..57501b9692 100644 --- a/vendor/github.com/elastic/gosigar/sigar_interface.go +++ b/vendor/github.com/elastic/gosigar/sigar_interface.go @@ -4,6 +4,7 @@ import ( "time" ) +// ErrNotImplemented is returned when a particular statistic isn't implemented on the host OS. type ErrNotImplemented struct { OS string } @@ -12,6 +13,7 @@ func (e ErrNotImplemented) Error() string { return "not implemented on " + e.OS } +// IsNotImplemented returns true if the error is ErrNotImplemented func IsNotImplemented(err error) bool { switch err.(type) { case ErrNotImplemented, *ErrNotImplemented: @@ -21,6 +23,7 @@ func IsNotImplemented(err error) bool { } } +// Sigar is an interface for gathering system host stats type Sigar interface { CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{}) GetLoadAverage() (LoadAverage, error) @@ -32,6 +35,7 @@ type Sigar interface { GetRusage(who int) (Rusage, error) } +// Cpu contains CPU time stats type Cpu struct { User uint64 Nice uint64 @@ -43,11 +47,13 @@ type Cpu struct { Stolen uint64 } +// Total returns total CPU time func (cpu *Cpu) Total() uint64 { return cpu.User + cpu.Nice + cpu.Sys + cpu.Idle + cpu.Wait + cpu.Irq + cpu.SoftIrq + cpu.Stolen } +// Delta returns the difference between two Cpu stat objects func (cpu Cpu) Delta(other Cpu) Cpu { return Cpu{ User: cpu.User - other.User, @@ -61,14 +67,17 @@ func (cpu Cpu) Delta(other Cpu) Cpu { } } +// LoadAverage reports standard load averages type LoadAverage struct { One, Five, Fifteen float64 } +// Uptime reports system uptime type Uptime struct { Length float64 } +// Mem contains host memory stats type Mem struct { Total uint64 Used uint64 @@ -77,12 +86,14 @@ type Mem struct { ActualUsed uint64 } +// Swap contains stats on swap space type Swap struct { Total uint64 Used uint64 Free uint64 } +// HugeTLBPages contains HugePages stats type HugeTLBPages struct { Total uint64 Free uint64 @@ -92,16 +103,19 @@ type HugeTLBPages struct { TotalAllocatedSize uint64 } +// CpuList contains a list of CPUs on the host system type CpuList struct { List []Cpu } +// FDUsage contains stats on filesystem usage type FDUsage struct { Open uint64 Unused uint64 Max uint64 } +// FileSystem contains basic information about a given mounted filesystem type FileSystem struct { DirName string DevName string @@ -111,10 +125,12 @@ type FileSystem struct { Flags uint32 } +// FileSystemList gets a list of mounted filesystems type FileSystemList struct { List []FileSystem } +// FileSystemUsage contains basic stats for the specified filesystem type FileSystemUsage struct { Total uint64 Used uint64 @@ -124,21 +140,30 @@ type FileSystemUsage struct { FreeFiles uint64 } +// ProcList contains a list of processes found on the host system type ProcList struct { List []int } +// RunState is a byte-long code used to specify the current runtime state of a process type RunState byte const ( - RunStateSleep = 'S' - RunStateRun = 'R' - RunStateStop = 'T' - RunStateZombie = 'Z' - RunStateIdle = 'D' + // RunStateSleep corresponds to a sleep state + RunStateSleep = 'S' + // RunStateRun corresponds to a running state + RunStateRun = 'R' + // RunStateStop corresponds to a stopped state + RunStateStop = 'T' + // RunStateZombie marks a zombie process + RunStateZombie = 'Z' + // RunStateIdle corresponds to an idle state + RunStateIdle = 'D' + // RunStateUnknown corresponds to a process in an unknown state RunStateUnknown = '?' ) +// ProcState contains basic metadata and process ownership info for the specified process type ProcState struct { Name string Username string @@ -151,6 +176,7 @@ type ProcState struct { Processor int } +// ProcMem contains memory statistics for a specified process type ProcMem struct { Size uint64 Resident uint64 @@ -160,6 +186,7 @@ type ProcMem struct { PageFaults uint64 } +// ProcTime contains run time statistics for a specified process type ProcTime struct { StartTime uint64 User uint64 @@ -167,26 +194,31 @@ type ProcTime struct { Total uint64 } +// ProcArgs contains a list of args for a specified process type ProcArgs struct { List []string } +// ProcEnv contains a map of environment variables for specified process type ProcEnv struct { Vars map[string]string } +// ProcExe contains basic data about a specified process type ProcExe struct { Name string Cwd string Root string } +// ProcFDUsage contains data on file limits and usage type ProcFDUsage struct { Open uint64 SoftLimit uint64 HardLimit uint64 } +// Rusage contains data on resource usage for a specified process type Rusage struct { Utime time.Duration Stime time.Duration diff --git a/vendor/github.com/elastic/gosigar/sigar_linux.go b/vendor/github.com/elastic/gosigar/sigar_linux.go index 09f2e30b2f..e04e8a97ee 100644 --- a/vendor/github.com/elastic/gosigar/sigar_linux.go +++ b/vendor/github.com/elastic/gosigar/sigar_linux.go @@ -106,3 +106,28 @@ func parseCpuStat(self *Cpu, line string) error { return nil } + +func (self *Mem) Get() error { + + table, err := parseMeminfo() + if err != nil { + return err + } + + self.Total, _ = table["MemTotal"] + self.Free, _ = table["MemFree"] + buffers, _ := table["Buffers"] + cached, _ := table["Cached"] + + if available, ok := table["MemAvailable"]; ok { + // MemAvailable is in /proc/meminfo (kernel 3.14+) + self.ActualFree = available + } else { + self.ActualFree = self.Free + buffers + cached + } + + self.Used = self.Total - self.Free + self.ActualUsed = self.Total - self.ActualFree + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_linux_common.go b/vendor/github.com/elastic/gosigar/sigar_linux_common.go index 7ca6497622..e2c5e246d5 100644 --- a/vendor/github.com/elastic/gosigar/sigar_linux_common.go +++ b/vendor/github.com/elastic/gosigar/sigar_linux_common.go @@ -51,31 +51,6 @@ func (self *LoadAverage) Get() error { return nil } -func (self *Mem) Get() error { - - table, err := parseMeminfo() - if err != nil { - return err - } - - self.Total, _ = table["MemTotal"] - self.Free, _ = table["MemFree"] - buffers, _ := table["Buffers"] - cached, _ := table["Cached"] - - if available, ok := table["MemAvailable"]; ok { - // MemAvailable is in /proc/meminfo (kernel 3.14+) - self.ActualFree = available - } else { - self.ActualFree = self.Free + buffers + cached - } - - self.Used = self.Total - self.Free - self.ActualUsed = self.Total - self.ActualFree - - return nil -} - func (self *Swap) Get() error { table, err := parseMeminfo() diff --git a/vendor/github.com/elastic/gosigar/sigar_windows.go b/vendor/github.com/elastic/gosigar/sigar_windows.go index c2b54d8d7f..d1204b80e4 100644 --- a/vendor/github.com/elastic/gosigar/sigar_windows.go +++ b/vendor/github.com/elastic/gosigar/sigar_windows.go @@ -8,30 +8,13 @@ import ( "path/filepath" "runtime" "strings" - "sync" "syscall" "time" - "github.com/StackExchange/wmi" "github.com/elastic/gosigar/sys/windows" "github.com/pkg/errors" ) -// Win32_Process represents a process on the Windows operating system. If -// additional fields are added here (that match the Windows struct) they will -// automatically be populated when calling getWin32Process. -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372(v=vs.85).aspx -type Win32_Process struct { - CommandLine string -} - -// Win32_OperatingSystem WMI class represents a Windows-based operating system -// installed on a computer. -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394239(v=vs.85).aspx -type Win32_OperatingSystem struct { - LastBootUpTime time.Time -} - var ( // version is Windows version of the host OS. version = windows.GetWindowsVersion() @@ -40,11 +23,6 @@ var ( // 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer // OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION. processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION - - // bootTime is the time when the OS was last booted. This value may be nil - // on operating systems that do not support the WMI query used to obtain it. - bootTime *time.Time - bootTimeLock sync.Mutex ) func init() { @@ -79,18 +57,11 @@ func (self *Uptime) Get() error { if !version.IsWindowsVistaOrGreater() { return ErrNotImplemented{runtime.GOOS} } - - bootTimeLock.Lock() - defer bootTimeLock.Unlock() - if bootTime == nil { - os, err := getWin32OperatingSystem() - if err != nil { - return errors.Wrap(err, "failed to get boot time using WMI") - } - bootTime = &os.LastBootUpTime + uptimeMs, err := windows.GetTickCount64() + if err != nil { + return errors.Wrap(err, "failed to get boot time using GetTickCount64 api") } - - self.Length = time.Since(*bootTime).Seconds() + self.Length = float64(time.Duration(uptimeMs)*time.Millisecond) / float64(time.Second) return nil } @@ -155,9 +126,9 @@ func (self *CpuList) Get() error { } func (self *FileSystemList) Get() error { - drives, err := windows.GetLogicalDriveStrings() + drives, err := windows.GetAccessPaths() if err != nil { - return errors.Wrap(err, "GetLogicalDriveStrings failed") + return errors.Wrap(err, "GetAccessPaths failed") } for _, drive := range drives { @@ -209,10 +180,11 @@ func (self *ProcState) Get(pid int) error { errs = append(errs, errors.Wrap(err, "getParentPid failed")) } - self.Username, err = getProcCredName(pid) - if err != nil { - errs = append(errs, errors.Wrap(err, "getProcCredName failed")) - } + // getProcCredName will often fail when run as a non-admin user. This is + // caused by strict ACL of the process token belonging to other users. + // Instead of failing completely, ignore this error and still return most + // data with an empty Username. + self.Username, _ = getProcCredName(pid) if len(errs) > 0 { errStrs := make([]string, 0, len(errs)) @@ -251,7 +223,7 @@ func getProcStatus(pid int) (RunState, error) { var exitCode uint32 err = syscall.GetExitCodeProcess(handle, &exitCode) if err != nil { - return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v") + return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v", pid) } if exitCode == 259 { //still active @@ -289,6 +261,8 @@ func getProcCredName(pid int) (string, error) { if err != nil { return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid) } + // Close token to prevent handle leaks. + defer token.Close() // Find the token user. tokenUser, err := token.GetTokenUser() @@ -296,12 +270,6 @@ func getProcCredName(pid int) (string, error) { return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid) } - // Close token to prevent handle leaks. - err = token.Close() - if err != nil { - return "", errors.Wrapf(err, "failed while closing process token handle for pid=%v", pid) - } - // Look up domain account by SID. account, domain, _, err := tokenUser.User.Sid.LookupAccount("") if err != nil { @@ -371,13 +339,28 @@ func (self *ProcArgs) Get(pid int) error { if !version.IsWindowsVistaOrGreater() { return ErrNotImplemented{runtime.GOOS} } - - process, err := getWin32Process(int32(pid)) + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid)) if err != nil { - return errors.Wrapf(err, "ProcArgs failed for pid=%v", pid) + return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + pbi, err := windows.NtQueryProcessBasicInformation(handle) + if err != nil { + return errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid) + } + if err != nil { + return nil + } + userProcParams, err := windows.GetUserProcessParams(handle, pbi) + if err != nil { + return nil + } + if argsW, err := windows.ReadProcessUnicodeString(handle, &userProcParams.CommandLine); err == nil { + self.List, err = windows.ByteSliceToStringSlice(argsW) + if err != nil { + return err + } } - - self.List = []string{process.CommandLine} return nil } @@ -394,35 +377,6 @@ func (self *FileSystemUsage) Get(path string) error { return nil } -// getWin32Process gets information about the process with the given process ID. -// It uses a WMI query to get the information from the local system. -func getWin32Process(pid int32) (Win32_Process, error) { - var dst []Win32_Process - query := fmt.Sprintf("WHERE ProcessId = %d", pid) - q := wmi.CreateQuery(&dst, query) - err := wmi.Query(q, &dst) - if err != nil { - return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: %v", query, err) - } - if len(dst) < 1 { - return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: Process not found", query) - } - return dst[0], nil -} - -func getWin32OperatingSystem() (Win32_OperatingSystem, error) { - var dst []Win32_OperatingSystem - q := wmi.CreateQuery(&dst, "") - err := wmi.Query(q, &dst) - if err != nil { - return Win32_OperatingSystem{}, errors.Wrap(err, "wmi query for Win32_OperatingSystem failed") - } - if len(dst) != 1 { - return Win32_OperatingSystem{}, errors.New("wmi query for Win32_OperatingSystem failed") - } - return dst[0], nil -} - func (self *Rusage) Get(who int) error { if who != 0 { return ErrNotImplemented{runtime.GOOS} diff --git a/vendor/github.com/elastic/gosigar/sys/windows/doc.go b/vendor/github.com/elastic/gosigar/sys/windows/doc.go index dda57aa830..9dca125040 100644 --- a/vendor/github.com/elastic/gosigar/sys/windows/doc.go +++ b/vendor/github.com/elastic/gosigar/sys/windows/doc.go @@ -1,2 +1,8 @@ // Package windows contains various Windows system call. package windows + +// Use "go generate -v -x ." to generate the source. + +// Add -trace to enable debug prints around syscalls. +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -systemdll=true -output zsyscall_windows.go syscall_windows.go +//go:generate go run fix_generated.go -input zsyscall_windows.go diff --git a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go index 88df0febfa..371eb256ba 100644 --- a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go +++ b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go @@ -23,6 +23,10 @@ const ( PROCESS_VM_READ uint32 = 0x0010 ) +// SizeOfRtlUserProcessParameters gives the size +// of the RtlUserProcessParameters struct. +const SizeOfRtlUserProcessParameters = unsafe.Sizeof(RtlUserProcessParameters{}) + // MAX_PATH is the maximum length for a path in Windows. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx const MAX_PATH = 260 @@ -43,6 +47,26 @@ const ( DRIVE_RAMDISK ) +// UnicodeString is Go's equivalent for the _UNICODE_STRING struct. +type UnicodeString struct { + Size uint16 + MaximumLength uint16 + Buffer uintptr +} + +// RtlUserProcessParameters is Go's equivalent for the +// _RTL_USER_PROCESS_PARAMETERS struct. +// A few undocumented fields are exposed. +type RtlUserProcessParameters struct { + Reserved1 [16]byte + Reserved2 [5]uintptr + CurrentDirectoryPath UnicodeString + CurrentDirectoryHandle uintptr + DllPath UnicodeString + ImagePathName UnicodeString + CommandLine UnicodeString +} + func (dt DriveType) String() string { names := map[DriveType]string{ DRIVE_UNKNOWN: "unknown", @@ -151,25 +175,81 @@ func GetLogicalDriveStrings() ([]string, error) { return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed") } - // Split the uint16 slice at null-terminators. - var startIdx int - var drivesUTF16 [][]uint16 - for i, value := range buffer { - if value == 0 { - drivesUTF16 = append(drivesUTF16, buffer[startIdx:i]) - startIdx = i + 1 + return UTF16SliceToStringSlice(buffer), nil +} + +// GetAccessPaths returns the list of access paths for volumes in the system. +func GetAccessPaths() ([]string, error) { + volumes, err := GetVolumes() + if err != nil { + return nil, errors.Wrap(err, "GetVolumes failed") + } + + var paths []string + for _, volumeName := range volumes { + volumePaths, err := GetVolumePathsForVolume(volumeName) + if err != nil { + return nil, errors.Wrapf(err, "failed to get list of access paths for volume '%s'", volumeName) + } + if len(volumePaths) == 0 { + continue } + + // Get only the first path + paths = append(paths, volumePaths[0]) } - // Convert the utf16 slices to strings. - drives := make([]string, 0, len(drivesUTF16)) - for _, driveUTF16 := range drivesUTF16 { - if len(driveUTF16) > 0 { - drives = append(drives, syscall.UTF16ToString(driveUTF16)) + return paths, nil +} + +// GetVolumes returs the list of volumes in the system. +// https://docs.microsoft.com/es-es/windows/desktop/api/fileapi/nf-fileapi-findfirstvolumew +func GetVolumes() ([]string, error) { + buffer := make([]uint16, MAX_PATH+1) + + var volumes []string + + h, err := _FindFirstVolume(&buffer[0], uint32(len(buffer))) + if err != nil { + return nil, errors.Wrap(err, "FindFirstVolumeW failed") + } + defer _FindVolumeClose(h) + + for { + volumes = append(volumes, syscall.UTF16ToString(buffer)) + + err = _FindNextVolume(h, &buffer[0], uint32(len(buffer))) + if err != nil { + if errors.Cause(err) == syscall.ERROR_NO_MORE_FILES { + break + } + return nil, errors.Wrap(err, "FindNextVolumeW failed") } } - return drives, nil + return volumes, nil +} + +// GetVolumePathsForVolume returns the list of volume paths for a volume. +// https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-getvolumepathnamesforvolumenamew +func GetVolumePathsForVolume(volumeName string) ([]string, error) { + var length uint32 + err := _GetVolumePathNamesForVolumeName(volumeName, nil, 0, &length) + if errors.Cause(err) != syscall.ERROR_MORE_DATA { + return nil, errors.Wrap(err, "GetVolumePathNamesForVolumeNameW failed to get needed buffer length") + } + if length == 0 { + // Not mounted, no paths, that's ok + return nil, nil + } + + buffer := make([]uint16, length*(MAX_PATH+1)) + err = _GetVolumePathNamesForVolumeName(volumeName, &buffer[0], length, &length) + if err != nil { + return nil, errors.Wrap(err, "GetVolumePathNamesForVolumeNameW failed") + } + + return UTF16SliceToStringSlice(buffer), nil } // GlobalMemoryStatusEx retrieves information about the system's current usage @@ -361,10 +441,144 @@ func Process32Next(handle syscall.Handle) (ProcessEntry32, error) { return processEntry32, nil } -// Use "GOOS=windows go generate -v -x ." to generate the source. +// UTF16SliceToStringSlice converts slice of uint16 containing a list of UTF16 +// strings to a slice of strings. +func UTF16SliceToStringSlice(buffer []uint16) []string { + // Split the uint16 slice at null-terminators. + var startIdx int + var stringsUTF16 [][]uint16 + for i, value := range buffer { + if value == 0 { + stringsUTF16 = append(stringsUTF16, buffer[startIdx:i]) + startIdx = i + 1 + } + } + + // Convert the utf16 slices to strings. + result := make([]string, 0, len(stringsUTF16)) + for _, stringUTF16 := range stringsUTF16 { + if len(stringUTF16) > 0 { + result = append(result, syscall.UTF16ToString(stringUTF16)) + } + } + + return result +} + +func GetUserProcessParams(handle syscall.Handle, pbi ProcessBasicInformation) (params RtlUserProcessParameters, err error) { + const is32bitProc = unsafe.Sizeof(uintptr(0)) == 4 + + // Offset of params field within PEB structure. + // This structure is different in 32 and 64 bit. + paramsOffset := 0x20 + if is32bitProc { + paramsOffset = 0x10 + } + + // Read the PEB from the target process memory + pebSize := paramsOffset + 8 + peb := make([]byte, pebSize) + nRead, err := ReadProcessMemory(handle, pbi.PebBaseAddress, peb) + if err != nil { + return params, err + } + if nRead != uintptr(pebSize) { + return params, errors.Errorf("PEB: short read (%d/%d)", nRead, pebSize) + } + + // Get the RTL_USER_PROCESS_PARAMETERS struct pointer from the PEB + paramsAddr := *(*uintptr)(unsafe.Pointer(&peb[paramsOffset])) -// Add -trace to enable debug prints around syscalls. -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go + // Read the RTL_USER_PROCESS_PARAMETERS from the target process memory + paramsBuf := make([]byte, SizeOfRtlUserProcessParameters) + nRead, err = ReadProcessMemory(handle, paramsAddr, paramsBuf) + if err != nil { + return params, err + } + if nRead != uintptr(SizeOfRtlUserProcessParameters) { + return params, errors.Errorf("RTL_USER_PROCESS_PARAMETERS: short read (%d/%d)", nRead, SizeOfRtlUserProcessParameters) + } + + params = *(*RtlUserProcessParameters)(unsafe.Pointer(¶msBuf[0])) + return params, nil +} + +// ReadProcessUnicodeString returns a zero-terminated UTF-16 string from another +// process's memory. +func ReadProcessUnicodeString(handle syscall.Handle, s *UnicodeString) ([]byte, error) { + // Allocate an extra UTF-16 null character at the end in case the read string + // is not terminated. + extra := 2 + if s.Size&1 != 0 { + extra = 3 // If size is odd, need 3 nulls to terminate. + } + buf := make([]byte, int(s.Size)+extra) + nRead, err := ReadProcessMemory(handle, s.Buffer, buf[:s.Size]) + if err != nil { + return nil, err + } + if nRead != uintptr(s.Size) { + return nil, errors.Errorf("unicode string: short read: (%d/%d)", nRead, s.Size) + } + return buf, nil +} + +// ByteSliceToStringSlice uses CommandLineToArgv API to split an UTF-16 command +// line string into a list of parameters. +func ByteSliceToStringSlice(utf16 []byte) ([]string, error) { + n := len(utf16) + // Discard odd byte + if n&1 != 0 { + n-- + utf16 = utf16[:n] + } + if n == 0 { + return nil, nil + } + terminated := false + for i := 0; i < n && !terminated; i += 2 { + terminated = utf16[i] == 0 && utf16[i+1] == 0 + } + if !terminated { + // Append a null uint16 at the end if terminator is missing + utf16 = append(utf16, 0, 0) + } + var numArgs int32 + argsWide, err := syscall.CommandLineToArgv((*uint16)(unsafe.Pointer(&utf16[0])), &numArgs) + if err != nil { + return nil, err + } + + // Free memory allocated for CommandLineToArgvW arguments. + defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(argsWide))) + + args := make([]string, numArgs) + for idx := range args { + args[idx] = syscall.UTF16ToString(argsWide[idx][:]) + } + return args, nil +} + +// ReadProcessMemory reads from another process memory. The Handle needs to have +// the PROCESS_VM_READ right. +// A zero-byte read is a no-op, no error is returned. +func ReadProcessMemory(handle syscall.Handle, baseAddress uintptr, dest []byte) (numRead uintptr, err error) { + n := len(dest) + if n == 0 { + return 0, nil + } + if err = _ReadProcessMemory(handle, baseAddress, uintptr(unsafe.Pointer(&dest[0])), uintptr(n), &numRead); err != nil { + return 0, err + } + return numRead, nil +} + +func GetTickCount64() (uptime uint64, err error) { + if uptime, err = _GetTickCount64(); err != nil { + return 0, err + } + return uptime, nil +} // Windows API calls //sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx @@ -383,3 +597,9 @@ func Process32Next(handle syscall.Handle) (ProcessEntry32, error) { //sys _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW //sys _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) = advapi32.LookupPrivilegeValueW //sys _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges +//sys _FindFirstVolume(volumeName *uint16, size uint32) (handle syscall.Handle, err error) = kernel32.FindFirstVolumeW +//sys _FindNextVolume(handle syscall.Handle, volumeName *uint16, size uint32) (err error) = kernel32.FindNextVolumeW +//sys _FindVolumeClose(handle syscall.Handle) (err error) = kernel32.FindVolumeClose +//sys _GetVolumePathNamesForVolumeName(volumeName string, buffer *uint16, bufferSize uint32, length *uint32) (err error) = kernel32.GetVolumePathNamesForVolumeNameW +//sys _ReadProcessMemory(handle syscall.Handle, baseAddress uintptr, buffer uintptr, size uintptr, numRead *uintptr) (err error) = kernel32.ReadProcessMemory +//sys _GetTickCount64() (uptime uint64, err error) = kernel32.GetTickCount64 diff --git a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go index 53fae4e3ba..75f19c0ea3 100644 --- a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go +++ b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go @@ -1,41 +1,76 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT +// Code generated by 'go generate'; DO NOT EDIT. package windows -import "unsafe" -import "syscall" +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) var _ unsafe.Pointer +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + var ( - modkernel32 = syscall.NewLazyDLL("kernel32.dll") - modpsapi = syscall.NewLazyDLL("psapi.dll") - modntdll = syscall.NewLazyDLL("ntdll.dll") - modadvapi32 = syscall.NewLazyDLL("advapi32.dll") - - procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx") - procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") - procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") - procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW") - procGetSystemTimes = modkernel32.NewProc("GetSystemTimes") - procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") - procEnumProcesses = modpsapi.NewProc("EnumProcesses") - procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") - procProcess32FirstW = modkernel32.NewProc("Process32FirstW") - procProcess32NextW = modkernel32.NewProc("Process32NextW") - procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") - procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") - procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") - procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + modpsapi = windows.NewLazySystemDLL("psapi.dll") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") + + procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx") + procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") + procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW") + procGetSystemTimes = modkernel32.NewProc("GetSystemTimes") + procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") + procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") + procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") + procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") + procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") + procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") + procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") + procGetTickCount64 = modkernel32.NewProc("GetTickCount64") ) func _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) { r1, _, e1 := syscall.Syscall(procGlobalMemoryStatusEx.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -48,7 +83,7 @@ func _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint3 length = uint32(r0) if length == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -60,7 +95,7 @@ func _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCo r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(psmemCounters)), uintptr(cb)) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -73,7 +108,7 @@ func _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, s length = uint32(r0) if length == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -85,7 +120,7 @@ func _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, u r1, _, e1 := syscall.Syscall(procGetSystemTimes.Addr(), 3, uintptr(unsafe.Pointer(idleTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -98,7 +133,7 @@ func _GetDriveType(rootPathName *uint16) (dt DriveType, err error) { dt = DriveType(r0) if dt == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -110,7 +145,7 @@ func _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(processIds)), uintptr(sizeBytes), uintptr(unsafe.Pointer(bytesReturned))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -122,7 +157,7 @@ func _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, tota r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailable)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -134,7 +169,7 @@ func _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -146,7 +181,7 @@ func _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -159,7 +194,7 @@ func _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.H handle = syscall.Handle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -172,7 +207,7 @@ func _NtQuerySystemInformation(systemInformationClass uint32, systemInformation ntstatus = uint32(r0) if ntstatus == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -185,7 +220,7 @@ func _NtQueryInformationProcess(processHandle syscall.Handle, processInformation ntstatus = uint32(r0) if ntstatus == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -206,7 +241,7 @@ func __LookupPrivilegeName(systemName *uint16, luid *int64, buffer *uint16, size r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -232,7 +267,7 @@ func __LookupPrivilegeValue(systemName *uint16, name *uint16, luid *int64) (err r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -251,7 +286,90 @@ func _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, o success = r0 != 0 if true { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _FindFirstVolume(volumeName *uint16, size uint32) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procFindFirstVolumeW.Addr(), 2, uintptr(unsafe.Pointer(volumeName)), uintptr(size), 0) + handle = syscall.Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _FindNextVolume(handle syscall.Handle, volumeName *uint16, size uint32) (err error) { + r1, _, e1 := syscall.Syscall(procFindNextVolumeW.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(volumeName)), uintptr(size)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _FindVolumeClose(handle syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetVolumePathNamesForVolumeName(volumeName string, buffer *uint16, bufferSize uint32, length *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(volumeName) + if err != nil { + return + } + return __GetVolumePathNamesForVolumeName(_p0, buffer, bufferSize, length) +} + +func __GetVolumePathNamesForVolumeName(volumeName *uint16, buffer *uint16, bufferSize uint32, length *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetVolumePathNamesForVolumeNameW.Addr(), 4, uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(buffer)), uintptr(bufferSize), uintptr(unsafe.Pointer(length)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _ReadProcessMemory(handle syscall.Handle, baseAddress uintptr, buffer uintptr, size uintptr, numRead *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(handle), uintptr(baseAddress), uintptr(buffer), uintptr(size), uintptr(unsafe.Pointer(numRead)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetTickCount64() (uptime uint64, err error) { + r0, _, e1 := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0) + uptime = uint64(r0) + if uptime == 0 { + if e1 != 0 { + err = errnoErr(e1) } else { err = syscall.EINVAL } diff --git a/vendor/github.com/ethereum/go-ethereum/.travis.yml b/vendor/github.com/ethereum/go-ethereum/.travis.yml index 3a40ff5834..4acd00bc9f 100644 --- a/vendor/github.com/ethereum/go-ethereum/.travis.yml +++ b/vendor/github.com/ethereum/go-ethereum/.travis.yml @@ -7,7 +7,7 @@ jobs: - stage: lint os: linux dist: xenial - go: 1.12.x + go: 1.13.x env: - lint git: @@ -18,15 +18,15 @@ jobs: - stage: build os: linux dist: xenial - go: 1.10.x + go: 1.11.x script: - - go run build/ci.go install - - go run build/ci.go test -coverage $TEST_PACKAGES + - go run build/ci.go install + - go run build/ci.go test -coverage $TEST_PACKAGES - stage: build os: linux dist: xenial - go: 1.11.x + go: 1.12.x script: - go run build/ci.go install - go run build/ci.go test -coverage $TEST_PACKAGES @@ -35,14 +35,14 @@ jobs: - stage: build os: linux dist: xenial - go: 1.12.x + go: 1.13.x script: - go run build/ci.go install - go run build/ci.go test -coverage $TEST_PACKAGES - stage: build os: osx - go: 1.12.x + go: 1.13.x script: - echo "Increase the maximum number of open file descriptors on macOS" - NOFILE=20480 @@ -61,7 +61,7 @@ jobs: if: type = push os: linux dist: xenial - go: 1.12.x + go: 1.13.x env: - ubuntu-ppa git: @@ -75,9 +75,12 @@ jobs: - fakeroot - python-bzrlib - python-paramiko + cache: + directories: + - $HOME/.gobundle script: - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts - - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " + - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " -goversion 1.13.4 -gohash 95dbeab442ee2746b9acf0934c8e2fc26414a0565c008631b04addb8c02e7624 -gobundle $HOME/.gobundle/go.tar.gz # This builder does the Linux Azure uploads - stage: build @@ -85,7 +88,7 @@ jobs: os: linux dist: xenial sudo: required - go: 1.12.x + go: 1.13.x env: - azure-linux git: @@ -121,7 +124,7 @@ jobs: dist: xenial services: - docker - go: 1.12.x + go: 1.13.x env: - azure-linux-mips git: @@ -167,7 +170,7 @@ jobs: git: submodules: false # avoid cloning ethereum/tests before_install: - - curl https://dl.google.com/go/go1.12.linux-amd64.tar.gz | tar -xz + - curl https://dl.google.com/go/go1.13.linux-amd64.tar.gz | tar -xz - export PATH=`pwd`/go/bin:$PATH - export GOROOT=`pwd`/go - export GOPATH=$HOME/go @@ -185,7 +188,7 @@ jobs: - stage: build if: type = push os: osx - go: 1.12.x + go: 1.13.x env: - azure-osx - azure-ios @@ -216,7 +219,7 @@ jobs: if: type = cron os: linux dist: xenial - go: 1.12.x + go: 1.13.x env: - azure-purge git: diff --git a/vendor/github.com/ethereum/go-ethereum/Dockerfile b/vendor/github.com/ethereum/go-ethereum/Dockerfile index c766576a8f..114e762058 100644 --- a/vendor/github.com/ethereum/go-ethereum/Dockerfile +++ b/vendor/github.com/ethereum/go-ethereum/Dockerfile @@ -1,5 +1,5 @@ # Build Geth in a stock Go builder container -FROM golang:1.12-alpine as builder +FROM golang:1.13-alpine as builder RUN apk add --no-cache make gcc musl-dev linux-headers git @@ -12,5 +12,5 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/ -EXPOSE 8545 8546 30303 30303/udp +EXPOSE 8545 8546 8547 30303 30303/udp ENTRYPOINT ["geth"] diff --git a/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools b/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools index a4adba9d5b..2f661ba01c 100644 --- a/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools +++ b/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools @@ -1,5 +1,5 @@ # Build Geth in a stock Go builder container -FROM golang:1.12-alpine as builder +FROM golang:1.13-alpine as builder RUN apk add --no-cache make gcc musl-dev linux-headers git @@ -12,4 +12,4 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/ -EXPOSE 8545 8546 30303 30303/udp +EXPOSE 8545 8546 8547 30303 30303/udp diff --git a/vendor/github.com/ethereum/go-ethereum/Makefile b/vendor/github.com/ethereum/go-ethereum/Makefile index 4bf52f5c96..5d4a82de83 100644 --- a/vendor/github.com/ethereum/go-ethereum/Makefile +++ b/vendor/github.com/ethereum/go-ethereum/Makefile @@ -8,7 +8,7 @@ .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 .PHONY: geth-windows geth-windows-386 geth-windows-amd64 -GOBIN = $(shell pwd)/build/bin +GOBIN = ./build/bin GO ?= latest geth: diff --git a/vendor/github.com/ethereum/go-ethereum/README.md b/vendor/github.com/ethereum/go-ethereum/README.md index fd25941543..92a7125b49 100644 --- a/vendor/github.com/ethereum/go-ethereum/README.md +++ b/vendor/github.com/ethereum/go-ethereum/README.md @@ -98,7 +98,7 @@ Specifying the `--testnet` flag, however, will reconfigure your `geth` instance this. * Instead of connecting the main Ethereum network, the client will connect to the test network, which uses different P2P bootnodes, different network IDs and genesis states. - + *Note: Although there are some internal protective measures to prevent transactions from crossing over between the main network and test network, you should make sure to always use separate accounts for play-money and real-money. Unless you manually move @@ -210,10 +210,14 @@ aware of and agree upon. This consists of a small JSON file (e.g. call it `genes ```json { "config": { - "chainId": 0, + "chainId": , "homesteadBlock": 0, + "eip150Block": 0, "eip155Block": 0, - "eip158Block": 0 + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0 }, "alloc": {}, "coinbase": "0x0000000000000000000000000000000000000000", @@ -229,8 +233,8 @@ aware of and agree upon. This consists of a small JSON file (e.g. call it `genes The above fields should be fine for most purposes, although we'd recommend changing the `nonce` to some random value so you prevent unknown remote nodes from being able -to connect to you. If you'd like to pre-fund some accounts for easier testing, you can -populate the `alloc` field with account configs: +to connect to you. If you'd like to pre-fund some accounts for easier testing, create +the accounts and populate the `alloc` field with their addresses. ```json "alloc": { @@ -299,7 +303,7 @@ ones either). To start a `geth` instance for mining, run it with all your usual by: ```shell -$ geth --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000 +$ geth --mine --miner.threads=1 --etherbase=0x0000000000000000000000000000000000000000 ``` Which will start mining blocks and transactions on a single CPU thread, crediting all diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go index 7831a5ed33..603e956b9d 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go @@ -75,9 +75,6 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { // Unpack output in v according to the abi specification func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) { - if len(data) == 0 { - return fmt.Errorf("abi: unmarshalling empty output") - } // since there can't be naming collisions with contracts and events, // we need to decide whether we're calling a method or an event if method, ok := abi.Methods[name]; ok { @@ -94,9 +91,6 @@ func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) { // UnpackIntoMap unpacks a log into the provided map[string]interface{} func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) { - if len(data) == 0 { - return fmt.Errorf("abi: unmarshalling empty output") - } // since there can't be naming collisions with contracts and events, // we need to decide whether we're calling a method or an event if method, ok := abi.Methods[name]; ok { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go index 4dae586535..f8ec11b9fa 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go @@ -34,10 +34,11 @@ type Argument struct { type Arguments []Argument type ArgumentMarshaling struct { - Name string - Type string - Components []ArgumentMarshaling - Indexed bool + Name string + Type string + InternalType string + Components []ArgumentMarshaling + Indexed bool } // UnmarshalJSON implements json.Unmarshaler interface @@ -48,7 +49,7 @@ func (argument *Argument) UnmarshalJSON(data []byte) error { return fmt.Errorf("argument json err: %v", err) } - argument.Type, err = NewType(arg.Type, arg.Components) + argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components) if err != nil { return err } @@ -88,6 +89,13 @@ func (arguments Arguments) isTuple() bool { // Unpack performs the operation hexdata -> Go format func (arguments Arguments) Unpack(v interface{}, data []byte) error { + if len(data) == 0 { + if len(arguments) != 0 { + return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") + } else { + return nil // Nothing to unmarshal, return + } + } // make sure the passed value is arguments pointer if reflect.Ptr != reflect.ValueOf(v).Kind() { return fmt.Errorf("abi: Unpack(non-pointer %T)", v) @@ -104,11 +112,17 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error { // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { + if len(data) == 0 { + if len(arguments) != 0 { + return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") + } else { + return nil // Nothing to unmarshal, return + } + } marshalledValues, err := arguments.UnpackValues(data) if err != nil { return err } - return arguments.unpackIntoMap(v, marshalledValues) } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go index f74a0af211..499b4bda07 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go @@ -218,7 +218,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i } } // If the contract surely has code (or code is not needed), estimate the transaction - msg := ethereum.CallMsg{From: opts.From, To: contract, Value: value, Data: input} + msg := ethereum.CallMsg{From: opts.From, To: contract, GasPrice: gasPrice, Value: value, Data: input} gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg) if err != nil { return nil, fmt.Errorf("failed to estimate gas needed: %v", err) diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go index dc51e2a7ec..7bda997a61 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go @@ -86,7 +86,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] if input.Name == "" { normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) } - if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist { + if hasStruct(input.Type) { bindStructType[lang](input.Type, structs) } } @@ -96,7 +96,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] if output.Name != "" { normalized.Outputs[j].Name = capitalise(output.Name) } - if _, exist := structs[output.Type.String()]; output.Type.T == abi.TupleTy && !exist { + if hasStruct(output.Type) { bindStructType[lang](output.Type, structs) } } @@ -119,14 +119,11 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] normalized.Inputs = make([]abi.Argument, len(original.Inputs)) copy(normalized.Inputs, original.Inputs) for j, input := range normalized.Inputs { - // Indexed fields are input, non-indexed ones are outputs - if input.Indexed { - if input.Name == "" { - normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) - } - if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist { - bindStructType[lang](input.Type, structs) - } + if input.Name == "" { + normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) + } + if hasStruct(input.Type) { + bindStructType[lang](input.Type, structs) } } // Append the event to the accumulator list @@ -244,7 +241,7 @@ func bindBasicTypeGo(kind abi.Type) string { func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { switch kind.T { case abi.TupleTy: - return structs[kind.String()].Name + return structs[kind.TupleRawName+kind.String()].Name case abi.ArrayTy: return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem, structs) case abi.SliceTy: @@ -321,7 +318,7 @@ func pluralizeJavaType(typ string) string { func bindTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { switch kind.T { case abi.TupleTy: - return structs[kind.String()].Name + return structs[kind.TupleRawName+kind.String()].Name case abi.ArrayTy, abi.SliceTy: return pluralizeJavaType(bindTypeJava(*kind.Elem, structs)) default: @@ -340,6 +337,13 @@ var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) // funcionality as for simple types, but dynamic types get converted to hashes. func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { bound := bindTypeGo(kind, structs) + + // todo(rjl493456442) according solidity documentation, indexed event + // parameters that are not value types i.e. arrays and structs are not + // stored directly but instead a keccak256-hash of an encoding is stored. + // + // We only convert stringS and bytes to hash, still need to deal with + // array(both fixed-size and dynamic-size) and struct. if bound == "string" || bound == "[]byte" { bound = "common.Hash" } @@ -350,6 +354,13 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { // funcionality as for simple types, but dynamic types get converted to hashes. func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { bound := bindTypeJava(kind, structs) + + // todo(rjl493456442) according solidity documentation, indexed event + // parameters that are not value types i.e. arrays and structs are not + // stored directly but instead a keccak256-hash of an encoding is stored. + // + // We only convert stringS and bytes to hash, still need to deal with + // array(both fixed-size and dynamic-size) and struct. if bound == "String" || bound == "byte[]" { bound = "Hash" } @@ -369,7 +380,14 @@ var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { switch kind.T { case abi.TupleTy: - if s, exist := structs[kind.String()]; exist { + // We compose raw struct name and canonical parameter expression + // together here. The reason is before solidity v0.5.11, kind.TupleRawName + // is empty, so we use canonical parameter expression to distinguish + // different struct definition. From the consideration of backward + // compatibility, we concat these two together so that if kind.TupleRawName + // is not empty, it can have unique id. + id := kind.TupleRawName + kind.String() + if s, exist := structs[id]; exist { return s.Name } var fields []*tmplField @@ -377,8 +395,11 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { field := bindStructTypeGo(*elem, structs) fields = append(fields, &tmplField{Type: field, Name: capitalise(kind.TupleRawNames[i]), SolKind: *elem}) } - name := fmt.Sprintf("Struct%d", len(structs)) - structs[kind.String()] = &tmplStruct{ + name := kind.TupleRawName + if name == "" { + name = fmt.Sprintf("Struct%d", len(structs)) + } + structs[id] = &tmplStruct{ Name: name, Fields: fields, } @@ -398,7 +419,14 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { switch kind.T { case abi.TupleTy: - if s, exist := structs[kind.String()]; exist { + // We compose raw struct name and canonical parameter expression + // together here. The reason is before solidity v0.5.11, kind.TupleRawName + // is empty, so we use canonical parameter expression to distinguish + // different struct definition. From the consideration of backward + // compatibility, we concat these two together so that if kind.TupleRawName + // is not empty, it can have unique id. + id := kind.TupleRawName + kind.String() + if s, exist := structs[id]; exist { return s.Name } var fields []*tmplField @@ -406,8 +434,11 @@ func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { field := bindStructTypeJava(*elem, structs) fields = append(fields, &tmplField{Type: field, Name: decapitalise(kind.TupleRawNames[i]), SolKind: *elem}) } - name := fmt.Sprintf("Class%d", len(structs)) - structs[kind.String()] = &tmplStruct{ + name := kind.TupleRawName + if name == "" { + name = fmt.Sprintf("Class%d", len(structs)) + } + structs[id] = &tmplStruct{ Name: name, Fields: fields, } @@ -497,6 +528,21 @@ func structured(args abi.Arguments) bool { return true } +// hasStruct returns an indicator whether the given type is struct, struct slice +// or struct array. +func hasStruct(t abi.Type) bool { + switch t.T { + case abi.SliceTy: + return hasStruct(*t.Elem) + case abi.ArrayTy: + return hasStruct(*t.Elem) + case abi.TupleTy: + return true + default: + return false + } +} + // resolveArgName converts a raw argument representation into a user friendly format. func resolveArgName(arg abi.Argument, structs map[string]*tmplStruct) string { var ( @@ -512,7 +558,7 @@ loop: case abi.ArrayTy: prefix += fmt.Sprintf("[%d]", typ.Size) default: - embedded = typ.String() + embedded = typ.TupleRawName + typ.String() break loop } typ = typ.Elem diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go index 4ec65474b0..5b35b1badc 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go @@ -65,7 +65,7 @@ type tmplField struct { // tmplStruct is a wrapper around an abi.tuple contains a auto-generated // struct name. type tmplStruct struct { - Name string // Auto-generated struct name(We can't obtain the raw struct name through abi) + Name string // Auto-generated struct name(before solidity v0.5.11) or raw name. Fields []*tmplField // Struct fields definition depends on the binding language. } @@ -483,7 +483,7 @@ var ( // Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} + // Solidity: {{formatevent .Original $structs}} func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) { event := new({{$contract.Type}}{{.Normalized.Name}}) if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go index c7657b4a41..e27fa54842 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go @@ -80,15 +80,19 @@ func makeTopics(query ...[]interface{}) ([][]common.Hash, error) { copy(topic[:], hash[:]) default: + // todo(rjl493456442) according solidity documentation, indexed event + // parameters that are not value types i.e. arrays and structs are not + // stored directly but instead a keccak256-hash of an encoding is stored. + // + // We only convert stringS and bytes to hash, still need to deal with + // array(both fixed-size and dynamic-size) and struct. + // Attempt to generate the topic from funky types val := reflect.ValueOf(rule) - switch { - // static byte array case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val) - default: return nil, fmt.Errorf("unsupported indexed type: %T", rule) } @@ -162,6 +166,7 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er default: // Ran out of plain primitive types, try custom types + switch field.Type() { case reflectHash: // Also covers all dynamic types field.Set(reflect.ValueOf(topics[0])) @@ -178,11 +183,9 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er default: // Ran out of custom types, try the crazies switch { - // static byte array case arg.Type.T == abi.FixedBytesTy: reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size])) - default: return fmt.Errorf("unsupported indexed type: %v", arg.Type) } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go index 597d314392..4792283ee8 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go @@ -53,6 +53,7 @@ type Type struct { stringKind string // holds the unparsed string for deriving signatures // Tuple relative fields + TupleRawName string // Raw struct name defined in source code, may be empty. TupleElems []*Type // Type information of all tuple fields TupleRawNames []string // Raw field name of all tuple fields } @@ -63,7 +64,7 @@ var ( ) // NewType creates a new reflection type of abi type given in t. -func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { +func NewType(t string, internalType string, components []ArgumentMarshaling) (typ Type, err error) { // check that array brackets are equal if they exist if strings.Count(t, "[") != strings.Count(t, "]") { return Type{}, fmt.Errorf("invalid arg type in abi") @@ -73,9 +74,14 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { // if there are brackets, get ready to go into slice/array mode and // recursively create the type if strings.Count(t, "[") != 0 { - i := strings.LastIndex(t, "[") + // Note internalType can be empty here. + subInternal := internalType + if i := strings.LastIndex(internalType, "["); i != -1 { + subInternal = subInternal[:i] + } // recursively embed the type - embeddedType, err := NewType(t[:i], components) + i := strings.LastIndex(t, "[") + embeddedType, err := NewType(t[:i], subInternal, components) if err != nil { return Type{}, err } @@ -173,7 +179,7 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { ) expression += "(" for idx, c := range components { - cType, err := NewType(c.Type, c.Components) + cType, err := NewType(c.Type, c.InternalType, c.Components) if err != nil { return Type{}, err } @@ -199,6 +205,17 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { typ.TupleRawNames = names typ.T = TupleTy typ.stringKind = expression + + const structPrefix = "struct " + // After solidity 0.5.10, a new field of abi "internalType" + // is introduced. From that we can obtain the struct name + // user defined in the source code. + if internalType != "" && strings.HasPrefix(internalType, structPrefix) { + // Foo.Bar type definition is not allowed in golang, + // convert the format to FooBar + typ.TupleRawName = strings.Replace(internalType[len(structPrefix):], ".", "", -1) + } + case "function": typ.Kind = reflect.Array typ.T = FunctionTy diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go index c30903b5b7..17ca9223ff 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction op = ledgerP1ContTransactionData } // Extract the Ethereum signature and do a sanity validation - if len(reply) != 65 { + if len(reply) != crypto.SignatureLength { return common.Address{}, nil, errors.New("reply lacks signature") } signature := append(reply[1:], reply[0]) diff --git a/vendor/github.com/ethereum/go-ethereum/appveyor.yml b/vendor/github.com/ethereum/go-ethereum/appveyor.yml index 8f840c190e..0f230bac14 100644 --- a/vendor/github.com/ethereum/go-ethereum/appveyor.yml +++ b/vendor/github.com/ethereum/go-ethereum/appveyor.yml @@ -23,8 +23,8 @@ environment: install: - git submodule update --init - rmdir C:\go /s /q - - appveyor DownloadFile https://dl.google.com/go/go1.12.7.windows-%GETH_ARCH%.zip - - 7z x go1.12.7.windows-%GETH_ARCH%.zip -y -oC:\ > NUL + - appveyor DownloadFile https://dl.google.com/go/go1.13.4.windows-%GETH_ARCH%.zip + - 7z x go1.13.4.windows-%GETH_ARCH%.zip -y -oC:\ > NUL - go version - gcc --version diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go b/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go index e5bf8724c1..66ebf9ab04 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go @@ -20,7 +20,6 @@ import ( "encoding" "errors" "flag" - "fmt" "math/big" "os" "os/user" @@ -34,33 +33,44 @@ import ( // Custom type which is registered in the flags library which cli uses for // argument parsing. This allows us to expand Value to an absolute path when // the argument is parsed -type DirectoryString struct { - Value string -} +type DirectoryString string -func (self *DirectoryString) String() string { - return self.Value +func (s *DirectoryString) String() string { + return string(*s) } -func (self *DirectoryString) Set(value string) error { - self.Value = expandPath(value) +func (s *DirectoryString) Set(value string) error { + *s = DirectoryString(expandPath(value)) return nil } // Custom cli.Flag type which expand the received string to an absolute path. // e.g. ~/.ethereum -> /home/username/.ethereum type DirectoryFlag struct { - Name string - Value DirectoryString - Usage string + Name string + Value DirectoryString + Usage string + EnvVar string } -func (self DirectoryFlag) String() string { - fmtString := "%s %v\t%v" - if len(self.Value.Value) > 0 { - fmtString = "%s \"%v\"\t%v" - } - return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) +func (f DirectoryFlag) String() string { + return cli.FlagStringer(f) +} + +// called by cli library, grabs variable from environment (if in env) +// and adds variable to flag set for parsing. +func (f DirectoryFlag) Apply(set *flag.FlagSet) { + eachName(f.Name, func(name string) { + set.Var(&f.Value, f.Name, f.Usage) + }) +} + +func (f DirectoryFlag) GetName() string { + return f.Name +} + +func (f *DirectoryFlag) Set(value string) { + f.Value.Set(value) } func eachName(longName string, fn func(string)) { @@ -71,14 +81,6 @@ func eachName(longName string, fn func(string)) { } } -// called by cli library, grabs variable from environment (if in env) -// and adds variable to flag set for parsing. -func (self DirectoryFlag) Apply(set *flag.FlagSet) { - eachName(self.Name, func(name string) { - set.Var(&self.Value, self.Name, self.Usage) - }) -} - type TextMarshaler interface { encoding.TextMarshaler encoding.TextUnmarshaler @@ -103,9 +105,10 @@ func (v textMarshalerVal) Set(s string) error { // TextMarshalerFlag wraps a TextMarshaler value. type TextMarshalerFlag struct { - Name string - Value TextMarshaler - Usage string + Name string + Value TextMarshaler + Usage string + EnvVar string } func (f TextMarshalerFlag) GetName() string { @@ -113,7 +116,7 @@ func (f TextMarshalerFlag) GetName() string { } func (f TextMarshalerFlag) String() string { - return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage) + return cli.FlagStringer(f) } func (f TextMarshalerFlag) Apply(set *flag.FlagSet) { @@ -134,9 +137,10 @@ func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { // BigFlag is a command line flag that accepts 256 bit big integers in decimal or // hexadecimal syntax. type BigFlag struct { - Name string - Value *big.Int - Usage string + Name string + Value *big.Int + Usage string + EnvVar string } // bigValue turns *big.Int into a flag.Value @@ -163,11 +167,7 @@ func (f BigFlag) GetName() string { } func (f BigFlag) String() string { - fmtString := "%s %v\t%v" - if f.Value != nil { - fmtString = "%s \"%v\"\t%v" - } - return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) + return cli.FlagStringer(f) } func (f BigFlag) Apply(set *flag.FlagSet) { @@ -207,14 +207,6 @@ func prefixedNames(fullName string) (prefixed string) { return } -func (self DirectoryFlag) GetName() string { - return self.Name -} - -func (self *DirectoryFlag) Set(value string) { - self.Value.Value = value -} - // Expands a file path // 1. replace tilde with users home dir // 2. expands embedded environment variables diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go b/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go index 7e28dff79a..42424bcb52 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go @@ -21,12 +21,15 @@ import ( "crypto/ecdsa" "errors" "fmt" + "io" "io/ioutil" "math/big" "os" "path/filepath" "strconv" "strings" + "text/tabwriter" + "text/template" "time" "github.com/ethereum/go-ethereum/accounts" @@ -90,8 +93,8 @@ GLOBAL OPTIONS: {{range .Flags}}{{.}} {{end}}{{end}} ` - cli.CommandHelpTemplate = CommandHelpTemplate + cli.HelpPrinter = printHelp } // NewApp creates an app with sane defaults. @@ -105,6 +108,17 @@ func NewApp(gitCommit, gitDate, usage string) *cli.App { return app } +func printHelp(out io.Writer, templ string, data interface{}) { + funcMap := template.FuncMap{"join": strings.Join} + t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0) + err := t.Execute(w, data) + if err != nil { + panic(err) + } + w.Flush() +} + // These are all the command line flags we support. // If you add to this list, please remember to include the // flag in the appropriate command definition. @@ -117,7 +131,7 @@ var ( DataDirFlag = DirectoryFlag{ Name: "datadir", Usage: "Data directory for the databases and keystore", - Value: DirectoryString{node.DefaultDataDir()}, + Value: DirectoryString(node.DefaultDataDir()), } AncientFlag = DirectoryFlag{ Name: "datadir.ancient", @@ -168,7 +182,7 @@ var ( DocRootFlag = DirectoryFlag{ Name: "docroot", Usage: "Document Root for HTTPClient file scheme", - Value: DirectoryString{homeDir()}, + Value: DirectoryString(homeDir()), } ExitWhenSyncedFlag = cli.BoolFlag{ Name: "exitwhensynced", @@ -209,6 +223,10 @@ var ( Name: "whitelist", Usage: "Comma separated block number-to-hash mappings to enforce (=)", } + OverrideIstanbulFlag = cli.Uint64Flag{ + Name: "override.istanbul", + Usage: "Manually specify Istanbul fork-block, overriding the bundled setting", + } // Light server and client settings LightLegacyServFlag = cli.IntFlag{ // Deprecated in favor of light.serve, remove in 2021 Name: "lightserv", @@ -291,8 +309,8 @@ var ( } EthashDatasetDirFlag = DirectoryFlag{ Name: "ethash.dagdir", - Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", - Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir}, + Usage: "Directory to store the ethash mining DAGs", + Value: DirectoryString(eth.DefaultConfig.Ethash.DatasetDir), } EthashDatasetsInMemoryFlag = cli.IntFlag{ Name: "ethash.dagsinmem", @@ -1091,6 +1109,11 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { if ctx.GlobalIsSet(LightMaxPeersFlag.Name) { lightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name) } + if lightClient && !ctx.GlobalIsSet(LightLegacyPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { + // dynamic default - for clients we use 1/10th of the default for servers + lightPeers /= 10 + } + if ctx.GlobalIsSet(MaxPeersFlag.Name) { cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) if lightServer && !ctx.GlobalIsSet(LightLegacyPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { @@ -1430,9 +1453,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } - cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" - cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name) - + if ctx.GlobalIsSet(GCModeFlag.Name) { + cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" + } + if ctx.GlobalIsSet(CacheNoPrefetchFlag.Name) { + cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name) + } if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 } diff --git a/vendor/github.com/ethereum/go-ethereum/common/bytes.go b/vendor/github.com/ethereum/go-ethereum/common/bytes.go index c82e616241..fa457b92cf 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/bytes.go +++ b/vendor/github.com/ethereum/go-ethereum/common/bytes.go @@ -43,10 +43,8 @@ func ToHexArray(b [][]byte) []string { // FromHex returns the bytes represented by the hexadecimal string s. // s may be prefixed with "0x". func FromHex(s string) []byte { - if len(s) > 1 { - if s[0:2] == "0x" || s[0:2] == "0X" { - s = s[2:] - } + if has0xPrefix(s) { + s = s[2:] } if len(s)%2 == 1 { s = "0" + s @@ -65,8 +63,8 @@ func CopyBytes(b []byte) (copiedBytes []byte) { return } -// hasHexPrefix validates str begins with '0x' or '0X'. -func hasHexPrefix(str string) bool { +// has0xPrefix validates str begins with '0x' or '0X'. +func has0xPrefix(str string) bool { return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') } @@ -136,3 +134,14 @@ func LeftPadBytes(slice []byte, l int) []byte { return padded } + +// TrimLeftZeroes returns a subslice of s without leading zeroes +func TrimLeftZeroes(s []byte) []byte { + idx := 0 + for ; idx < len(s); idx++ { + if s[idx] != 0 { + break + } + } + return s[idx:] +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go b/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go index 0c941082f3..d0e0cd78be 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go +++ b/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go @@ -36,47 +36,39 @@ func (t AbsTime) Add(d time.Duration) AbsTime { return t + AbsTime(d) } -// Clock interface makes it possible to replace the monotonic system clock with +// The Clock interface makes it possible to replace the monotonic system clock with // a simulated clock. type Clock interface { Now() AbsTime Sleep(time.Duration) After(time.Duration) <-chan time.Time - AfterFunc(d time.Duration, f func()) Event + AfterFunc(d time.Duration, f func()) Timer } -// Event represents a cancellable event returned by AfterFunc -type Event interface { - Cancel() bool +// Timer represents a cancellable event returned by AfterFunc +type Timer interface { + Stop() bool } // System implements Clock using the system clock. type System struct{} -// Now implements Clock. +// Now returns the current monotonic time. func (System) Now() AbsTime { return AbsTime(monotime.Now()) } -// Sleep implements Clock. +// Sleep blocks for the given duration. func (System) Sleep(d time.Duration) { time.Sleep(d) } -// After implements Clock. +// After returns a channel which receives the current time after d has elapsed. func (System) After(d time.Duration) <-chan time.Time { return time.After(d) } -// AfterFunc implements Clock. -func (System) AfterFunc(d time.Duration, f func()) Event { - return (*SystemEvent)(time.AfterFunc(d, f)) -} - -// SystemEvent implements Event using time.Timer. -type SystemEvent time.Timer - -// Cancel implements Event. -func (e *SystemEvent) Cancel() bool { - return (*time.Timer)(e).Stop() +// AfterFunc runs f on a new goroutine after the duration has elapsed. +func (System) AfterFunc(d time.Duration, f func()) Timer { + return time.AfterFunc(d, f) } diff --git a/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go b/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go index af0f71c430..4d351252ff 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go +++ b/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go @@ -32,22 +32,17 @@ import ( // the timeout using a channel or semaphore. type Simulated struct { now AbsTime - scheduled []event + scheduled []*simTimer mu sync.RWMutex cond *sync.Cond lastId uint64 } -type event struct { +// simTimer implements Timer on the virtual clock. +type simTimer struct { do func() at AbsTime id uint64 -} - -// SimulatedEvent implements Event for a virtual clock. -type SimulatedEvent struct { - at AbsTime - id uint64 s *Simulated } @@ -75,6 +70,7 @@ func (s *Simulated) Run(d time.Duration) { } } +// ActiveTimers returns the number of timers that haven't fired. func (s *Simulated) ActiveTimers() int { s.mu.RLock() defer s.mu.RUnlock() @@ -82,6 +78,7 @@ func (s *Simulated) ActiveTimers() int { return len(s.scheduled) } +// WaitForTimers waits until the clock has at least n scheduled timers. func (s *Simulated) WaitForTimers(n int) { s.mu.Lock() defer s.mu.Unlock() @@ -92,7 +89,7 @@ func (s *Simulated) WaitForTimers(n int) { } } -// Now implements Clock. +// Now returns the current virtual time. func (s *Simulated) Now() AbsTime { s.mu.RLock() defer s.mu.RUnlock() @@ -100,12 +97,13 @@ func (s *Simulated) Now() AbsTime { return s.now } -// Sleep implements Clock. +// Sleep blocks until the clock has advanced by d. func (s *Simulated) Sleep(d time.Duration) { <-s.After(d) } -// After implements Clock. +// After returns a channel which receives the current time after the clock +// has advanced by d. func (s *Simulated) After(d time.Duration) <-chan time.Time { after := make(chan time.Time, 1) s.AfterFunc(d, func() { @@ -114,8 +112,9 @@ func (s *Simulated) After(d time.Duration) <-chan time.Time { return after } -// AfterFunc implements Clock. -func (s *Simulated) AfterFunc(d time.Duration, do func()) Event { +// AfterFunc runs fn after the clock has advanced by d. Unlike with the system +// clock, fn runs on the goroutine that calls Run. +func (s *Simulated) AfterFunc(d time.Duration, fn func()) Timer { s.mu.Lock() defer s.mu.Unlock() s.init() @@ -133,44 +132,31 @@ func (s *Simulated) AfterFunc(d time.Duration, do func()) Event { l = m + 1 } } - s.scheduled = append(s.scheduled, event{}) + ev := &simTimer{do: fn, at: at, s: s} + s.scheduled = append(s.scheduled, nil) copy(s.scheduled[l+1:], s.scheduled[l:ll]) - e := event{do: do, at: at, id: id} - s.scheduled[l] = e + s.scheduled[l] = ev s.cond.Broadcast() - return &SimulatedEvent{at: at, id: id, s: s} -} - -func (s *Simulated) init() { - if s.cond == nil { - s.cond = sync.NewCond(&s.mu) - } + return ev } -// Cancel implements Event. -func (e *SimulatedEvent) Cancel() bool { - s := e.s +func (ev *simTimer) Stop() bool { + s := ev.s s.mu.Lock() defer s.mu.Unlock() - l, h := 0, len(s.scheduled) - ll := h - for l != h { - m := (l + h) / 2 - if e.id == s.scheduled[m].id { - l = m - break - } - if (e.at < s.scheduled[m].at) || ((e.at == s.scheduled[m].at) && (e.id < s.scheduled[m].id)) { - h = m - } else { - l = m + 1 + for i := 0; i < len(s.scheduled); i++ { + if s.scheduled[i] == ev { + s.scheduled = append(s.scheduled[:i], s.scheduled[i+1:]...) + s.cond.Broadcast() + return true } } - if l >= ll || s.scheduled[l].id != e.id { - return false + return false +} + +func (s *Simulated) init() { + if s.cond == nil { + s.cond = sync.NewCond(&s.mu) } - copy(s.scheduled[l:ll-1], s.scheduled[l+1:]) - s.scheduled = s.scheduled[:ll-1] - return true } diff --git a/vendor/github.com/ethereum/go-ethereum/common/types.go b/vendor/github.com/ethereum/go-ethereum/common/types.go index 98c83edd4f..8ca51a05f8 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/types.go +++ b/vendor/github.com/ethereum/go-ethereum/common/types.go @@ -149,7 +149,7 @@ func (h *Hash) UnmarshalGraphQL(input interface{}) error { var err error switch input := input.(type) { case string: - *h = HexToHash(input) + err = h.UnmarshalText([]byte(input)) default: err = fmt.Errorf("Unexpected type for Bytes32: %v", input) } @@ -193,7 +193,7 @@ func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } // IsHexAddress verifies whether a string can represent a valid hex-encoded // Ethereum address or not. func IsHexAddress(s string) bool { - if hasHexPrefix(s) { + if has0xPrefix(s) { s = s[2:] } return len(s) == 2*AddressLength && isHex(s) @@ -288,7 +288,7 @@ func (a *Address) UnmarshalGraphQL(input interface{}) error { var err error switch input := input.(type) { case string: - *a = HexToAddress(input) + err = a.UnmarshalText([]byte(input)) default: err = fmt.Errorf("Unexpected type for Address: %v", input) } diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go b/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go index 084009a066..100c205292 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go @@ -55,8 +55,8 @@ const ( var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity + extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. @@ -311,7 +311,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainReader, header *type if number == 0 { return nil } - // Ensure that the block's timestamp isn't too close to it's parent + // Ensure that the block's timestamp isn't too close to its parent var parent *types.Header if len(parents) > 0 { parent = parents[len(parents)-1] @@ -522,7 +522,7 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro // Set the correct difficulty header.Difficulty = CalcDifficulty(snap, c.signer) - // Ensure the extra data has all it's components + // Ensure the extra data has all its components if len(header.Extra) < extraVanity { header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) } @@ -728,7 +728,7 @@ func encodeSigHeader(w io.Writer, header *types.Header) { header.GasLimit, header.GasUsed, header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short header.MixDigest, header.Nonce, }) diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/errors.go b/vendor/github.com/ethereum/go-ethereum/consensus/errors.go index a005c5f63d..ac5242fb54 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/errors.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/errors.go @@ -31,7 +31,7 @@ var ( // to the current node. ErrFutureBlock = errors.New("block in the future") - // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's + // ErrInvalidNumber is returned if a block's number doesn't equal its parent's // plus one. ErrInvalidNumber = errors.New("invalid block number") ) diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go index d271518f4f..3cff2d9fe5 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go @@ -86,7 +86,7 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.He if ethash.config.PowMode == ModeFullFake { return nil } - // Short circuit if the header is known, or it's parent not + // Short circuit if the header is known, or its parent not number := header.Number.Uint64() if chain.GetHeader(header.Hash(), number) != nil { return nil @@ -252,7 +252,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * if header.Time <= parent.Time { return errZeroBlockTime } - // Verify the block's difficulty based in it's timestamp and parent's difficulty + // Verify the block's difficulty based in its timestamp and parent's difficulty expected := ethash.CalcDifficulty(chain, header.Time, parent) if expected.Cmp(header.Difficulty) != 0 { diff --git a/vendor/github.com/ethereum/go-ethereum/core/blockchain.go b/vendor/github.com/ethereum/go-ethereum/core/blockchain.go index 59be355895..9fb02b1482 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/blockchain.go +++ b/vendor/github.com/ethereum/go-ethereum/core/blockchain.go @@ -64,6 +64,8 @@ var ( blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil) blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil) blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil) + blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) + blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) @@ -75,6 +77,7 @@ const ( bodyCacheLimit = 256 blockCacheLimit = 256 receiptsCacheLimit = 32 + txLookupCacheLimit = 1024 maxFutureBlocks = 256 maxTimeFutureBlocks = 30 badBlockLimit = 10 @@ -155,6 +158,7 @@ type BlockChain struct { bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format receiptsCache *lru.Cache // Cache for the most recent receipts per block blockCache *lru.Cache // Cache for the most recent entire blocks + txLookupCache *lru.Cache // Cache for the most recent transaction lookup data. futureBlocks *lru.Cache // future blocks are blocks added for later processing quit chan struct{} // blockchain quit channel @@ -189,6 +193,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) blockCache, _ := lru.New(blockCacheLimit) + txLookupCache, _ := lru.New(txLookupCacheLimit) futureBlocks, _ := lru.New(maxFutureBlocks) badBlocks, _ := lru.New(badBlockLimit) @@ -204,6 +209,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par bodyRLPCache: bodyRLPCache, receiptsCache: receiptsCache, blockCache: blockCache, + txLookupCache: txLookupCache, futureBlocks: futureBlocks, engine: engine, vmConfig: vmConfig, @@ -222,10 +228,16 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par if bc.genesisBlock == nil { return nil, ErrNoGenesis } + + var nilBlock *types.Block + bc.currentBlock.Store(nilBlock) + bc.currentFastBlock.Store(nilBlock) + // Initialize the chain with ancient data if it isn't empty. if bc.empty() { rawdb.InitDatabaseFromFreezer(bc.db) } + if err := bc.loadLastState(); err != nil { return nil, err } @@ -440,6 +452,7 @@ func (bc *BlockChain) SetHead(head uint64) error { bc.bodyRLPCache.Purge() bc.receiptsCache.Purge() bc.blockCache.Purge() + bc.txLookupCache.Purge() bc.futureBlocks.Purge() return bc.loadLastState() @@ -921,6 +934,7 @@ func (bc *BlockChain) truncateAncient(head uint64) error { bc.bodyRLPCache.Purge() bc.receiptsCache.Purge() bc.blockCache.Purge() + bc.txLookupCache.Purge() bc.futureBlocks.Purge() log.Info("Rewind ancient data", "number", head) @@ -1541,6 +1555,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] // Some other error occurred, abort case err != nil: + bc.futureBlocks.Remove(block.Hash()) stats.ignored += len(it.chain) bc.reportBlock(block, nil, err) return it.index, events, coalescedLogs, err @@ -1742,6 +1757,11 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i canonical := bc.GetBlockByNumber(number) if canonical != nil && canonical.Hash() == block.Hash() { // Not a sidechain block, this is a re-import of a canon block which has it's state pruned + + // Collect the TD of the block. Since we know it's a canon one, + // we can get it directly, and not (like further below) use + // the parent and then add the block on top + externTd = bc.GetTd(block.Hash(), block.NumberU64()) continue } if canonical != nil && canonical.Root() == block.Root() { @@ -1922,12 +1942,16 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } // Ensure the user sees large reorgs if len(oldChain) > 0 && len(newChain) > 0 { - logFn := log.Debug + logFn := log.Info + msg := "Chain reorg detected" if len(oldChain) > 63 { + msg = "Large chain reorg detected" logFn = log.Warn } - logFn("Chain split detected", "number", commonBlock.Number(), "hash", commonBlock.Hash(), + logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(), "drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash()) + blockReorgAddMeter.Mark(int64(len(newChain))) + blockReorgDropMeter.Mark(int64(len(oldChain))) } else { log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash()) } @@ -2122,6 +2146,11 @@ func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { return bc.hc.HasHeader(hash, number) } +// GetCanonicalHash returns the canonical hash for a given block number +func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash { + return bc.hc.GetCanonicalHash(number) +} + // GetBlockHashesFromHash retrieves a number of block hashes starting at a given // hash, fetching towards the genesis block. func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { @@ -2134,9 +2163,6 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com // // Note: ancestor == 0 returns the same block, 1 returns its parent and so on. func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - bc.chainmu.RLock() - defer bc.chainmu.RUnlock() - return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) } @@ -2146,6 +2172,22 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { return bc.hc.GetHeaderByNumber(number) } +// GetTransactionLookup retrieves the lookup associate with the given transaction +// hash from the cache or database. +func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry { + // Short circuit if the txlookup already in the cache, retrieve otherwise + if lookup, exist := bc.txLookupCache.Get(hash); exist { + return lookup.(*rawdb.LegacyTxLookupEntry) + } + tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) + if tx == nil { + return nil + } + lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} + bc.txLookupCache.Add(hash, lookup) + return lookup +} + // Config retrieves the chain's fork configuration. func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } diff --git a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go index 17f4042116..0b0fcdb4aa 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go +++ b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go @@ -103,7 +103,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.SetCoinbase(common.Address{}) } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) + receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) if err != nil { panic(err) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go b/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go index 8c1700879a..1e2d7a7441 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go +++ b/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go @@ -50,6 +50,9 @@ type ID struct { Next uint64 // Block number of the next upcoming fork, or 0 if no forks are known } +// Filter is a fork id filter to validate a remotely advertised ID. +type Filter func(id ID) error + // NewID calculates the Ethereum fork ID from the chain config and head. func NewID(chain *core.BlockChain) ID { return newID( @@ -80,9 +83,9 @@ func newID(config *params.ChainConfig, genesis common.Hash, head uint64) ID { return ID{Hash: checksumToBytes(hash), Next: next} } -// NewFilter creates an filter that returns if a fork ID should be rejected or not +// NewFilter creates a filter that returns if a fork ID should be rejected or not // based on the local chain's status. -func NewFilter(chain *core.BlockChain) func(id ID) error { +func NewFilter(chain *core.BlockChain) Filter { return newFilter( chain.Config(), chain.Genesis().Hash(), @@ -92,10 +95,16 @@ func NewFilter(chain *core.BlockChain) func(id ID) error { ) } +// NewStaticFilter creates a filter at block zero. +func NewStaticFilter(config *params.ChainConfig, genesis common.Hash) Filter { + head := func() uint64 { return 0 } + return newFilter(config, genesis, head) +} + // newFilter is the internal version of NewFilter, taking closures as its arguments // instead of a chain. The reason is to allow testing it without having to simulate // an entire blockchain. -func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() uint64) func(id ID) error { +func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() uint64) Filter { // Calculate the all the valid fork hash and fork next combos var ( forks = gatherForks(config) @@ -114,10 +123,13 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui // Create a validator that will filter out incompatible chains return func(id ID) error { // Run the fork checksum validation ruleset: - // 1. If local and remote FORK_CSUM matches, connect. + // 1. If local and remote FORK_CSUM matches, compare local head to FORK_NEXT. // The two nodes are in the same fork state currently. They might know // of differing future forks, but that's not relevant until the fork // triggers (might be postponed, nodes might be updated to match). + // 1a. A remotely announced but remotely not passed block is already passed + // locally, disconnect, since the chains are incompatible. + // 1b. No remotely announced fork; or not yet passed locally, connect. // 2. If the remote FORK_CSUM is a subset of the local past forks and the // remote FORK_NEXT matches with the locally following fork block number, // connect. @@ -139,7 +151,12 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui // Found the first unpassed fork block, check if our current state matches // the remote checksum (rule #1). if sums[i] == id.Hash { - // Yay, fork checksum matched, ignore any upcoming fork + // Fork checksum matched, check if a remote future fork block already passed + // locally without the local node being aware of it (rule #1a). + if id.Next > 0 && head >= id.Next { + return ErrLocalIncompatibleOrStale + } + // Haven't passed locally a remote-only fork, accept the connection (rule #1b). return nil } // The local and remote nodes are in different forks currently, check if the diff --git a/vendor/github.com/ethereum/go-ethereum/core/genesis.go b/vendor/github.com/ethereum/go-ethereum/core/genesis.go index 87bab25201..df0c967980 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/genesis.go +++ b/vendor/github.com/ethereum/go-ethereum/core/genesis.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -151,6 +152,10 @@ func (e *GenesisMismatchError) Error() string { // // The returned chain configuration is never nil. func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { + return SetupGenesisBlockWithOverride(db, genesis, nil) +} + +func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideIstanbul *big.Int) (*params.ChainConfig, common.Hash, error) { if genesis != nil && genesis.Config == nil { return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig } @@ -199,6 +204,12 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig // Get the existing chain configuration. newcfg := genesis.configOrDefault(stored) + if overrideIstanbul != nil { + newcfg.IstanbulBlock = overrideIstanbul + } + if err := newcfg.CheckConfigForkOrder(); err != nil { + return newcfg, common.Hash{}, err + } storedcfg := rawdb.ReadChainConfig(db, stored) if storedcfg == nil { log.Warn("Found genesis block without chain config") @@ -287,6 +298,13 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { if block.Number().Sign() != 0 { return nil, fmt.Errorf("can't commit genesis block with number > 0") } + config := g.Config + if config == nil { + config = params.AllEthashProtocolChanges + } + if err := config.CheckConfigForkOrder(); err != nil { + return nil, err + } rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty) rawdb.WriteBlock(db, block) rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) @@ -294,11 +312,6 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { rawdb.WriteHeadBlockHash(db, block.Hash()) rawdb.WriteHeadFastBlockHash(db, block.Hash()) rawdb.WriteHeadHeaderHash(db, block.Hash()) - - config := g.Config - if config == nil { - config = params.AllEthashProtocolChanges - } rawdb.WriteChainConfig(db, block.Hash(), config) return block, nil } @@ -377,7 +390,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { // Assemble and return the genesis with the precompiles and faucet pre-funded return &Genesis{ Config: &config, - ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...), + ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), GasLimit: 6283185, Difficulty: big.NewInt(1), Alloc: map[common.Address]GenesisAccount{ diff --git a/vendor/github.com/ethereum/go-ethereum/core/headerchain.go b/vendor/github.com/ethereum/go-ethereum/core/headerchain.go index 034858f651..4682069cff 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/headerchain.go +++ b/vendor/github.com/ethereum/go-ethereum/core/headerchain.go @@ -349,8 +349,11 @@ func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, ma } for ancestor != 0 { if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { - number -= ancestor - return rawdb.ReadCanonicalHash(hc.chainDb, number), number + ancestorHash := rawdb.ReadCanonicalHash(hc.chainDb, number-ancestor) + if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { + number -= ancestor + return ancestorHash, number + } } if *maxNonCanonical == 0 { return common.Hash{}, 0 @@ -445,6 +448,10 @@ func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header { return hc.GetHeader(hash, number) } +func (hc *HeaderChain) GetCanonicalHash(number uint64) common.Hash { + return rawdb.ReadCanonicalHash(hc.chainDb, number) +} + // CurrentHeader retrieves the current head header of the canonical chain. The // header is retrieved from the HeaderChain's internal cache. func (hc *HeaderChain) CurrentHeader() *types.Header { diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go index 41677fbba2..5497c59d49 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go @@ -80,9 +80,9 @@ type freezer struct { func newFreezer(datadir string, namespace string) (*freezer, error) { // Create the initial freezer object var ( - readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil) - writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil) - sizeCounter = metrics.NewRegisteredCounter(namespace+"ancient/size", nil) + readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil) + writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil) + sizeGauge = metrics.NewRegisteredGauge(namespace+"ancient/size", nil) ) // Ensure the datadir is not a symbolic link if it exists. if info, err := os.Lstat(datadir); !os.IsNotExist(err) { @@ -103,7 +103,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) { instanceLock: lock, } for name, disableSnappy := range freezerNoSnappy { - table, err := newTable(datadir, name, readMeter, writeMeter, sizeCounter, disableSnappy) + table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy) if err != nil { for _, table := range freezer.tables { table.Close() diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go index 61804f1f2b..9fb341f025 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go @@ -94,18 +94,18 @@ type freezerTable struct { // to count how many historic items have gone missing. itemOffset uint32 // Offset (number of discarded items) - headBytes uint32 // Number of bytes written to the head file - readMeter metrics.Meter // Meter for measuring the effective amount of data read - writeMeter metrics.Meter // Meter for measuring the effective amount of data written - sizeCounter metrics.Counter // Counter for tracking the combined size of all freezer tables + headBytes uint32 // Number of bytes written to the head file + readMeter metrics.Meter // Meter for measuring the effective amount of data read + writeMeter metrics.Meter // Meter for measuring the effective amount of data written + sizeGauge metrics.Gauge // Gauge for tracking the combined size of all freezer tables logger log.Logger // Logger with database path and table name ambedded lock sync.RWMutex // Mutex protecting the data file descriptors } // newTable opens a freezer table with default settings - 2G files -func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeCounter metrics.Counter, disableSnappy bool) (*freezerTable, error) { - return newCustomTable(path, name, readMeter, writeMeter, sizeCounter, 2*1000*1000*1000, disableSnappy) +func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeGauge metrics.Gauge, disableSnappy bool) (*freezerTable, error) { + return newCustomTable(path, name, readMeter, writeMeter, sizeGauge, 2*1000*1000*1000, disableSnappy) } // openFreezerFileForAppend opens a freezer table file and seeks to the end @@ -149,7 +149,7 @@ func truncateFreezerFile(file *os.File, size int64) error { // newCustomTable opens a freezer table, creating the data and index files if they are // non existent. Both files are truncated to the shortest common length to ensure // they don't go out of sync. -func newCustomTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeCounter metrics.Counter, maxFilesize uint32, noCompression bool) (*freezerTable, error) { +func newCustomTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeGauge metrics.Gauge, maxFilesize uint32, noCompression bool) (*freezerTable, error) { // Ensure the containing directory exists and open the indexEntry file if err := os.MkdirAll(path, 0755); err != nil { return nil, err @@ -172,7 +172,7 @@ func newCustomTable(path string, name string, readMeter metrics.Meter, writeMete files: make(map[uint32]*os.File), readMeter: readMeter, writeMeter: writeMeter, - sizeCounter: sizeCounter, + sizeGauge: sizeGauge, name: name, path: path, logger: log.New("database", path, "table", name), @@ -189,7 +189,7 @@ func newCustomTable(path string, name string, readMeter metrics.Meter, writeMete tab.Close() return nil, err } - tab.sizeCounter.Inc(int64(size)) + tab.sizeGauge.Inc(int64(size)) return tab, nil } @@ -378,7 +378,7 @@ func (t *freezerTable) truncate(items uint64) error { if err != nil { return err } - t.sizeCounter.Dec(int64(oldSize - newSize)) + t.sizeGauge.Dec(int64(oldSize - newSize)) return nil } @@ -510,7 +510,7 @@ func (t *freezerTable) Append(item uint64, blob []byte) error { t.index.Write(idx.marshallBinary()) t.writeMeter.Mark(int64(bLen + indexEntrySize)) - t.sizeCounter.Inc(int64(bLen + indexEntrySize)) + t.sizeGauge.Inc(int64(bLen + indexEntrySize)) atomic.AddUint64(&t.items, 1) return nil diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go index 45ae95a2a9..8680de021f 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go @@ -79,9 +79,10 @@ type stateObject struct { trie Trie // storage trie, which becomes non-nil on first access code Code // contract bytecode, which gets set when code is loaded - originStorage Storage // Storage cache of original entries to dedup rewrites - dirtyStorage Storage // Storage entries that need to be flushed to disk - fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. + originStorage Storage // Storage cache of original entries to dedup rewrites, reset for every transaction + pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block + dirtyStorage Storage // Storage entries that have been modified in the current transaction execution + fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. // Cache flags. // When an object is marked suicided it will be delete from the trie @@ -113,13 +114,17 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject { if data.CodeHash == nil { data.CodeHash = emptyCodeHash } + if data.Root == (common.Hash{}) { + data.Root = emptyRoot + } return &stateObject{ - db: db, - address: address, - addrHash: crypto.Keccak256Hash(address[:]), - data: data, - originStorage: make(Storage), - dirtyStorage: make(Storage), + db: db, + address: address, + addrHash: crypto.Keccak256Hash(address[:]), + data: data, + originStorage: make(Storage), + pendingStorage: make(Storage), + dirtyStorage: make(Storage), } } @@ -183,9 +188,11 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has if s.fakeStorage != nil { return s.fakeStorage[key] } - // If we have the original value cached, return that - value, cached := s.originStorage[key] - if cached { + // If we have a pending write or clean cached, return that + if value, pending := s.pendingStorage[key]; pending { + return value + } + if value, cached := s.originStorage[key]; cached { return value } // Track the amount of time wasted on reading the storage trie @@ -198,6 +205,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has s.setError(err) return common.Hash{} } + var value common.Hash if len(enc) > 0 { _, content, _, err := rlp.Split(enc) if err != nil { @@ -252,17 +260,29 @@ func (s *stateObject) setState(key, value common.Hash) { s.dirtyStorage[key] = value } +// finalise moves all dirty storage slots into the pending area to be hashed or +// committed later. It is invoked at the end of every transaction. +func (s *stateObject) finalise() { + for key, value := range s.dirtyStorage { + s.pendingStorage[key] = value + } + if len(s.dirtyStorage) > 0 { + s.dirtyStorage = make(Storage) + } +} + // updateTrie writes cached storage modifications into the object's storage trie. func (s *stateObject) updateTrie(db Database) Trie { + // Make sure all dirty slots are finalized into the pending storage area + s.finalise() + // Track the amount of time wasted on updating the storge trie if metrics.EnabledExpensive { defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) } - // Update all the dirty slots in the trie + // Insert all the pending updates into the trie tr := s.getTrie(db) - for key, value := range s.dirtyStorage { - delete(s.dirtyStorage, key) - + for key, value := range s.pendingStorage { // Skip noop changes, persist actual changes if value == s.originStorage[key] { continue @@ -274,9 +294,12 @@ func (s *stateObject) updateTrie(db Database) Trie { continue } // Encoding []byte cannot fail, ok to ignore the error. - v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) + v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) s.setError(tr.TryUpdate(key[:], v)) } + if len(s.pendingStorage) > 0 { + s.pendingStorage = make(Storage) + } return tr } @@ -356,6 +379,7 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject { stateObject.code = s.code stateObject.dirtyStorage = s.dirtyStorage.Copy() stateObject.originStorage = s.originStorage.Copy() + stateObject.pendingStorage = s.pendingStorage.Copy() stateObject.suicided = s.suicided stateObject.dirtyCode = s.dirtyCode stateObject.deleted = s.deleted diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go index b07f08fd21..4b4f374c92 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go @@ -67,8 +67,9 @@ type StateDB struct { trie Trie // This map holds 'live' objects, which will get modified while processing a state transition. - stateObjects map[common.Address]*stateObject - stateObjectsDirty map[common.Address]struct{} + stateObjects map[common.Address]*stateObject + stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie + stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution // DB error. // State objects are used by the consensus core and VM which are @@ -111,13 +112,14 @@ func New(root common.Hash, db Database) (*StateDB, error) { return nil, err } return &StateDB{ - db: db, - trie: tr, - stateObjects: make(map[common.Address]*stateObject), - stateObjectsDirty: make(map[common.Address]struct{}), - logs: make(map[common.Hash][]*types.Log), - preimages: make(map[common.Hash][]byte), - journal: newJournal(), + db: db, + trie: tr, + stateObjects: make(map[common.Address]*stateObject), + stateObjectsPending: make(map[common.Address]struct{}), + stateObjectsDirty: make(map[common.Address]struct{}), + logs: make(map[common.Hash][]*types.Log), + preimages: make(map[common.Hash][]byte), + journal: newJournal(), }, nil } @@ -141,6 +143,7 @@ func (self *StateDB) Reset(root common.Hash) error { } self.trie = tr self.stateObjects = make(map[common.Address]*stateObject) + self.stateObjectsPending = make(map[common.Address]struct{}) self.stateObjectsDirty = make(map[common.Address]struct{}) self.thash = common.Hash{} self.bhash = common.Hash{} @@ -421,15 +424,15 @@ func (self *StateDB) Suicide(addr common.Address) bool { // // updateStateObject writes the given object to the trie. -func (s *StateDB) updateStateObject(stateObject *stateObject) { +func (s *StateDB) updateStateObject(obj *stateObject) { // Track the amount of time wasted on updating the account from the trie if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) } // Encode the account and update the account trie - addr := stateObject.Address() + addr := obj.Address() - data, err := rlp.EncodeToBytes(stateObject) + data, err := rlp.EncodeToBytes(obj) if err != nil { panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) } @@ -437,25 +440,33 @@ func (s *StateDB) updateStateObject(stateObject *stateObject) { } // deleteStateObject removes the given object from the state trie. -func (s *StateDB) deleteStateObject(stateObject *stateObject) { +func (s *StateDB) deleteStateObject(obj *stateObject) { // Track the amount of time wasted on deleting the account from the trie if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) } // Delete the account from the trie - stateObject.deleted = true - - addr := stateObject.Address() + addr := obj.Address() s.setError(s.trie.TryDelete(addr[:])) } -// Retrieve a state object given by the address. Returns nil if not found. -func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { - // Prefer live objects +// getStateObject retrieves a state object given by the address, returning nil if +// the object is not found or was deleted in this execution context. If you need +// to differentiate between non-existent/just-deleted, use getDeletedStateObject. +func (s *StateDB) getStateObject(addr common.Address) *stateObject { + if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { + return obj + } + return nil +} + +// getDeletedStateObject is similar to getStateObject, but instead of returning +// nil for a deleted state object, it returns the actual object with the deleted +// flag set. This is needed by the state journal to revert to the correct self- +// destructed object instead of wiping all knowledge about the state object. +func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { + // Prefer live objects if any is available if obj := s.stateObjects[addr]; obj != nil { - if obj.deleted { - return nil - } return obj } // Track the amount of time wasted on loading the object from the database @@ -486,7 +497,7 @@ func (self *StateDB) setStateObject(object *stateObject) { // Retrieve a state object or create a new state object if nil. func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { stateObject := self.getStateObject(addr) - if stateObject == nil || stateObject.deleted { + if stateObject == nil { stateObject, _ = self.createObject(addr) } return stateObject @@ -495,7 +506,8 @@ func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { // createObject creates a new state object. If there is an existing account with // the given address, it is overwritten and returned as the second return value. func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { - prev = self.getStateObject(addr) + prev = self.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! + newobj = newObject(self, addr, Account{}) newobj.setNonce(0) // sets the object to dirty if prev == nil { @@ -558,15 +570,16 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common func (self *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ - db: self.db, - trie: self.db.CopyTrie(self.trie), - stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), - stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), - refund: self.refund, - logs: make(map[common.Hash][]*types.Log, len(self.logs)), - logSize: self.logSize, - preimages: make(map[common.Hash][]byte, len(self.preimages)), - journal: newJournal(), + db: self.db, + trie: self.db.CopyTrie(self.trie), + stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), + stateObjectsPending: make(map[common.Address]struct{}, len(self.stateObjectsPending)), + stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), + refund: self.refund, + logs: make(map[common.Hash][]*types.Log, len(self.logs)), + logSize: self.logSize, + preimages: make(map[common.Hash][]byte, len(self.preimages)), + journal: newJournal(), } // Copy the dirty states, logs, and preimages for addr := range self.journal.dirties { @@ -575,18 +588,29 @@ func (self *StateDB) Copy() *StateDB { // in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for // nil if object, exist := self.stateObjects[addr]; exist { + // Even though the original object is dirty, we are not copying the journal, + // so we need to make sure that anyside effect the journal would have caused + // during a commit (or similar op) is already applied to the copy. state.stateObjects[addr] = object.deepCopy(state) - state.stateObjectsDirty[addr] = struct{}{} + + state.stateObjectsDirty[addr] = struct{}{} // Mark the copy dirty to force internal (code/state) commits + state.stateObjectsPending[addr] = struct{}{} // Mark the copy pending to force external (account) commits } } // Above, we don't copy the actual journal. This means that if the copy is copied, the // loop above will be a no-op, since the copy's journal is empty. // Thus, here we iterate over stateObjects, to enable copies of copies + for addr := range self.stateObjectsPending { + if _, exist := state.stateObjects[addr]; !exist { + state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) + } + state.stateObjectsPending[addr] = struct{}{} + } for addr := range self.stateObjectsDirty { if _, exist := state.stateObjects[addr]; !exist { state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) - state.stateObjectsDirty[addr] = struct{}{} } + state.stateObjectsDirty[addr] = struct{}{} } for hash, logs := range self.logs { cpy := make([]*types.Log, len(logs)) @@ -631,11 +655,12 @@ func (self *StateDB) GetRefund() uint64 { return self.refund } -// Finalise finalises the state by removing the self destructed objects -// and clears the journal as well as the refunds. +// Finalise finalises the state by removing the self destructed objects and clears +// the journal as well as the refunds. Finalise, however, will not push any updates +// into the tries just yet. Only IntermediateRoot or Commit will do that. func (s *StateDB) Finalise(deleteEmptyObjects bool) { for addr := range s.journal.dirties { - stateObject, exist := s.stateObjects[addr] + obj, exist := s.stateObjects[addr] if !exist { // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the @@ -645,13 +670,12 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // Thus, we can safely ignore it here continue } - - if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { - s.deleteStateObject(stateObject) + if obj.suicided || (deleteEmptyObjects && obj.empty()) { + obj.deleted = true } else { - stateObject.updateRoot(s.db) - s.updateStateObject(stateObject) + obj.finalise() } + s.stateObjectsPending[addr] = struct{}{} s.stateObjectsDirty[addr] = struct{}{} } // Invalidate journal because reverting across transactions is not allowed. @@ -662,8 +686,21 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // It is called in between transactions to get the root hash that // goes into transaction receipts. func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { + // Finalise all the dirty storage states and write them into the tries s.Finalise(deleteEmptyObjects) + for addr := range s.stateObjectsPending { + obj := s.stateObjects[addr] + if obj.deleted { + s.deleteStateObject(obj) + } else { + obj.updateRoot(s.db) + s.updateStateObject(obj) + } + } + if len(s.stateObjectsPending) > 0 { + s.stateObjectsPending = make(map[common.Address]struct{}) + } // Track the amount of time wasted on hashing the account trie if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now()) @@ -680,46 +717,40 @@ func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { } func (s *StateDB) clearJournalAndRefund() { - s.journal = newJournal() - s.validRevisions = s.validRevisions[:0] - s.refund = 0 + if len(s.journal.entries) > 0 { + s.journal = newJournal() + s.refund = 0 + } + s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entires } // Commit writes the state to the underlying in-memory trie database. -func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { - defer s.clearJournalAndRefund() +func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { + // Finalize any pending changes and merge everything into the tries + s.IntermediateRoot(deleteEmptyObjects) - for addr := range s.journal.dirties { - s.stateObjectsDirty[addr] = struct{}{} - } // Commit objects to the trie, measuring the elapsed time - for addr, stateObject := range s.stateObjects { - _, isDirty := s.stateObjectsDirty[addr] - switch { - case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): - // If the object has been removed, don't bother syncing it - // and just mark it for deletion in the trie. - s.deleteStateObject(stateObject) - case isDirty: + for addr := range s.stateObjectsDirty { + if obj := s.stateObjects[addr]; !obj.deleted { // Write any contract code associated with the state object - if stateObject.code != nil && stateObject.dirtyCode { - s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code) - stateObject.dirtyCode = false + if obj.code != nil && obj.dirtyCode { + s.db.TrieDB().InsertBlob(common.BytesToHash(obj.CodeHash()), obj.code) + obj.dirtyCode = false } - // Write any storage changes in the state object to its storage trie. - if err := stateObject.CommitTrie(s.db); err != nil { + // Write any storage changes in the state object to its storage trie + if err := obj.CommitTrie(s.db); err != nil { return common.Hash{}, err } - // Update the object in the main account trie. - s.updateStateObject(stateObject) } - delete(s.stateObjectsDirty, addr) + } + if len(s.stateObjectsDirty) > 0 { + s.stateObjectsDirty = make(map[common.Address]struct{}) } // Write the account trie changes, measuing the amount of wasted time if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now()) } - root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { + return s.trie.Commit(func(leaf []byte, parent common.Hash) error { var account Account if err := rlp.DecodeBytes(leaf, &account); err != nil { return nil @@ -733,5 +764,4 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) } return nil }) - return root, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state_processor.go b/vendor/github.com/ethereum/go-ethereum/core/state_processor.go index bed6a07306..cfe17d587b 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state_processor.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state_processor.go @@ -68,7 +68,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Iterate over and process the individual transactions for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) - receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) + receipt, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) if err != nil { return nil, nil, 0, err } @@ -85,10 +85,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { - return nil, 0, err + return nil, err } // Create a new context to be used in the EVM environment context := NewEVMContext(msg, header, bc, author) @@ -98,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Apply the transaction to the current state (included in the env) _, gas, failed, err := ApplyMessage(vmenv, msg, gp) if err != nil { - return nil, 0, err + return nil, err } // Update the state with pending changes var root []byte @@ -125,5 +125,5 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) - return receipt, gas, err + return receipt, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state_transition.go b/vendor/github.com/ethereum/go-ethereum/core/state_transition.go index fda081b7d1..bef6e9b0eb 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state_transition.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state_transition.go @@ -76,10 +76,10 @@ type Message interface { } // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. -func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) { +func IntrinsicGas(data []byte, contractCreation, isEIP155 bool, isEIP2028 bool) (uint64, error) { // Set the starting gas for the raw transaction var gas uint64 - if contractCreation && homestead { + if contractCreation && isEIP155 { gas = params.TxGasContractCreation } else { gas = params.TxGas @@ -94,10 +94,14 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) } } // Make sure we don't exceed uint64 for all data combinations - if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz { + nonZeroGas := params.TxDataNonZeroGasFrontier + if isEIP2028 { + nonZeroGas = params.TxDataNonZeroGasEIP2028 + } + if (math.MaxUint64-gas)/nonZeroGas < nz { return 0, vm.ErrOutOfGas } - gas += nz * params.TxDataNonZeroGas + gas += nz * nonZeroGas z := uint64(len(data)) - nz if (math.MaxUint64-gas)/params.TxDataZeroGas < z { @@ -187,10 +191,11 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo msg := st.msg sender := vm.AccountRef(msg.From()) homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber) + istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.BlockNumber) contractCreation := msg.To() == nil // Pay intrinsic gas - gas, err := IntrinsicGas(st.data, contractCreation, homestead) + gas, err := IntrinsicGas(st.data, contractCreation, homestead, istanbul) if err != nil { return nil, 0, false, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go index 0c422dd99d..f7032dbd1e 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go +++ b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go @@ -97,13 +97,14 @@ var ( queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds // General tx metrics - validMeter = metrics.NewRegisteredMeter("txpool/valid", nil) + knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil) + validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil) invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) - pendingCounter = metrics.NewRegisteredCounter("txpool/pending", nil) - queuedCounter = metrics.NewRegisteredCounter("txpool/queued", nil) - localCounter = metrics.NewRegisteredCounter("txpool/local", nil) + pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) + queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) + localGauge = metrics.NewRegisteredGauge("txpool/local", nil) ) // TxStatus is the current status of a transaction as seen by the pool. @@ -217,6 +218,8 @@ type TxPool struct { signer types.Signer mu sync.RWMutex + istanbul bool // Fork indicator whether we are in the istanbul stage. + currentState *state.StateDB // Current state in the blockchain head pendingNonces *txNoncer // Pending state tracking virtual nonces currentMaxGas uint64 // Current gas limit for transaction caps @@ -540,7 +543,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { return ErrInsufficientFunds } // Ensure the transaction has more gas than the basic tx fee. - intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, true) + intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, true, pool.istanbul) if err != nil { return err } @@ -562,16 +565,15 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e hash := tx.Hash() if pool.all.Get(hash) != nil { log.Trace("Discarding already known transaction", "hash", hash) + knownTxMeter.Mark(1) return false, fmt.Errorf("known transaction: %x", hash) } - // If the transaction fails basic validation, discard it if err := pool.validateTx(tx, local); err != nil { log.Trace("Discarding invalid transaction", "hash", hash, "err", err) invalidTxMeter.Mark(1) return false, err } - // If the transaction pool is full, discard underpriced transactions if uint64(pool.all.Count()) >= pool.config.GlobalSlots+pool.config.GlobalQueue { // If the new transaction is underpriced, don't accept it @@ -588,7 +590,6 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e pool.removeTx(tx.Hash(), false) } } - // Try to replace an existing transaction in the pending pool from, _ := types.Sender(pool.signer, tx) // already validated if list := pool.pending[from]; list != nil && list.Overlaps(tx) { @@ -611,13 +612,11 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) return old != nil, nil } - // New transaction isn't replacing a pending one, push into queue replaced, err = pool.enqueueTx(hash, tx) if err != nil { return false, err } - // Mark local addresses and journal local transactions if local { if !pool.locals.contains(from) { @@ -626,7 +625,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e } } if local || pool.locals.contains(from) { - localCounter.Inc(1) + localGauge.Inc(1) } pool.journalTx(from, tx) @@ -656,7 +655,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, er queuedReplaceMeter.Mark(1) } else { // Nothing was replaced, bump the queued counter - queuedCounter.Inc(1) + queuedGauge.Inc(1) } if pool.all.Get(hash) == nil { pool.all.Add(tx) @@ -705,7 +704,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T pendingReplaceMeter.Mark(1) } else { // Nothing was replaced, bump the pending counter - pendingCounter.Inc(1) + pendingGauge.Inc(1) } // Failsafe to work around direct pending inserts (tests) if pool.all.Get(hash) == nil { @@ -766,15 +765,41 @@ func (pool *TxPool) AddRemote(tx *types.Transaction) error { // addTxs attempts to queue a batch of transactions if they are valid. func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { + // Filter out known ones without obtaining the pool lock or recovering signatures + var ( + errs = make([]error, len(txs)) + news = make([]*types.Transaction, 0, len(txs)) + ) + for i, tx := range txs { + // If the transaction is known, pre-set the error slot + if pool.all.Get(tx.Hash()) != nil { + errs[i] = fmt.Errorf("known transaction: %x", tx.Hash()) + knownTxMeter.Mark(1) + continue + } + // Accumulate all unknown transactions for deeper processing + news = append(news, tx) + } + if len(news) == 0 { + return errs + } // Cache senders in transactions before obtaining lock (pool.signer is immutable) - for _, tx := range txs { + for _, tx := range news { types.Sender(pool.signer, tx) } - + // Process all the new transaction and merge any errors into the original slice pool.mu.Lock() - errs, dirtyAddrs := pool.addTxsLocked(txs, local) + newErrs, dirtyAddrs := pool.addTxsLocked(news, local) pool.mu.Unlock() + var nilSlot = 0 + for _, err := range newErrs { + for errs[nilSlot] != nil { + nilSlot++ + } + errs[nilSlot] = err + } + // Reorg the pool internals if needed and return done := pool.requestPromoteExecutables(dirtyAddrs) if sync { <-done @@ -794,26 +819,29 @@ func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, dirty.addTx(tx) } } - validMeter.Mark(int64(len(dirty.accounts))) + validTxMeter.Mark(int64(len(dirty.accounts))) return errs, dirty } // Status returns the status (unknown/pending/queued) of a batch of transactions // identified by their hashes. func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { - pool.mu.RLock() - defer pool.mu.RUnlock() - status := make([]TxStatus, len(hashes)) for i, hash := range hashes { - if tx := pool.all.Get(hash); tx != nil { - from, _ := types.Sender(pool.signer, tx) // already validated - if pool.pending[from] != nil && pool.pending[from].txs.items[tx.Nonce()] != nil { - status[i] = TxStatusPending - } else { - status[i] = TxStatusQueued - } + tx := pool.Get(hash) + if tx == nil { + continue + } + from, _ := types.Sender(pool.signer, tx) // already validated + pool.mu.RLock() + if txList := pool.pending[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { + status[i] = TxStatusPending + } else if txList := pool.queue[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { + status[i] = TxStatusQueued } + // implicit else: the tx may have been included into a block between + // checking pool.Get and obtaining the lock. In that case, TxStatusUnknown is correct + pool.mu.RUnlock() } return status } @@ -839,7 +867,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { pool.priced.Removed(1) } if pool.locals.contains(addr) { - localCounter.Dec(1) + localGauge.Dec(1) } // Remove the transaction from the pending lists and reset the account nonce if pending := pool.pending[addr]; pending != nil { @@ -856,7 +884,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { // Update the account nonce if needed pool.pendingNonces.setIfLower(addr, tx.Nonce()) // Reduce the pending counter - pendingCounter.Dec(int64(1 + len(invalids))) + pendingGauge.Dec(int64(1 + len(invalids))) return } } @@ -864,7 +892,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { if future := pool.queue[addr]; future != nil { if removed, _ := future.Remove(tx); removed { // Reduce the queued counter - queuedCounter.Dec(1) + queuedGauge.Dec(1) } if future.Empty() { delete(pool.queue, addr) @@ -1118,6 +1146,10 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { log.Debug("Reinjecting stale transactions", "count", len(reinject)) senderCacher.recover(pool.signer, reinject) pool.addTxsLocked(reinject, false) + + // Update all fork indicator by next pending block number. + next := new(big.Int).Add(newHead.Number, big.NewInt(1)) + pool.istanbul = pool.chainconfig.IsIstanbul(next) } // promoteExecutables moves transactions that have become processable from the @@ -1158,7 +1190,7 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Trans promoted = append(promoted, tx) } } - queuedCounter.Dec(int64(len(readies))) + queuedGauge.Dec(int64(len(readies))) // Drop all transactions over the allowed limit var caps types.Transactions @@ -1173,9 +1205,9 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Trans } // Mark all the items dropped as removed pool.priced.Removed(len(forwards) + len(drops) + len(caps)) - queuedCounter.Dec(int64(len(forwards) + len(drops) + len(caps))) + queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) if pool.locals.contains(addr) { - localCounter.Dec(int64(len(forwards) + len(drops) + len(caps))) + localGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) } // Delete the entire queue entry if it became empty. if list.Empty() { @@ -1234,9 +1266,9 @@ func (pool *TxPool) truncatePending() { log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) } pool.priced.Removed(len(caps)) - pendingCounter.Dec(int64(len(caps))) + pendingGauge.Dec(int64(len(caps))) if pool.locals.contains(offenders[i]) { - localCounter.Dec(int64(len(caps))) + localGauge.Dec(int64(len(caps))) } pending-- } @@ -1261,9 +1293,9 @@ func (pool *TxPool) truncatePending() { log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) } pool.priced.Removed(len(caps)) - pendingCounter.Dec(int64(len(caps))) + pendingGauge.Dec(int64(len(caps))) if pool.locals.contains(addr) { - localCounter.Dec(int64(len(caps))) + localGauge.Dec(int64(len(caps))) } pending-- } @@ -1347,9 +1379,9 @@ func (pool *TxPool) demoteUnexecutables() { log.Trace("Demoting pending transaction", "hash", hash) pool.enqueueTx(hash, tx) } - pendingCounter.Dec(int64(len(olds) + len(drops) + len(invalids))) + pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) if pool.locals.contains(addr) { - localCounter.Dec(int64(len(olds) + len(drops) + len(invalids))) + localGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) } // If there's a gap in front, alert (should never happen) and postpone all transactions if list.Len() > 0 && list.txs.Get(nonce) == nil { @@ -1359,7 +1391,7 @@ func (pool *TxPool) demoteUnexecutables() { log.Error("Demoting invalidated transaction", "hash", hash) pool.enqueueTx(hash, tx) } - pendingCounter.Dec(int64(len(gapped))) + pendingGauge.Dec(int64(len(gapped))) } // Delete the entire queue entry if it became empty. if list.Empty() { diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go b/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go index 63132048ee..842fedbd03 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go @@ -193,8 +193,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool { // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - if len(sig) != 65 { - panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig))) + if len(sig) != crypto.SignatureLength { + panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)) } r = new(big.Int).SetBytes(sig[:32]) s = new(big.Int).SetBytes(sig[32:64]) @@ -229,7 +229,7 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo } // encode the signature in uncompressed format r, s := R.Bytes(), S.Bytes() - sig := make([]byte, 65) + sig := make([]byte, crypto.SignatureLength) copy(sig[32-len(r):32], r) copy(sig[64-len(s):64], s) sig[64] = V diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go b/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go index 0e4fe01981..9b0ba09ed1 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go @@ -18,12 +18,14 @@ package vm import ( "crypto/sha256" + "encoding/binary" "errors" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/blake2b" "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/params" "golang.org/x/crypto/ripemd160" @@ -70,6 +72,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, } // RunPrecompiledContract runs and evaluates the output of a precompiled contract. @@ -103,8 +106,13 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) { if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) { return nil, nil } + // We must make sure not to modify the 'input', so placing the 'v' along with + // the signature needs to be done on a new allocation + sig := make([]byte, 65) + copy(sig, input[64:128]) + sig[64] = v // v needs to be at the end for libsecp256k1 - pubKey, err := crypto.Ecrecover(input[:32], append(input[64:128], v)) + pubKey, err := crypto.Ecrecover(input[:32], sig) // make sure the public key is a valid one if err != nil { return nil, nil @@ -431,3 +439,64 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { return runBn256Pairing(input) } + +type blake2F struct{} + +func (c *blake2F) RequiredGas(input []byte) uint64 { + // If the input is malformed, we can't calculate the gas, return 0 and let the + // actual call choke and fault. + if len(input) != blake2FInputLength { + return 0 + } + return uint64(binary.BigEndian.Uint32(input[0:4])) +} + +const ( + blake2FInputLength = 213 + blake2FFinalBlockBytes = byte(1) + blake2FNonFinalBlockBytes = byte(0) +) + +var ( + errBlake2FInvalidInputLength = errors.New("invalid input length") + errBlake2FInvalidFinalFlag = errors.New("invalid final flag") +) + +func (c *blake2F) Run(input []byte) ([]byte, error) { + // Make sure the input is valid (correct lenth and final flag) + if len(input) != blake2FInputLength { + return nil, errBlake2FInvalidInputLength + } + if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { + return nil, errBlake2FInvalidFinalFlag + } + // Parse the input into the Blake2b call parameters + var ( + rounds = binary.BigEndian.Uint32(input[0:4]) + final = (input[212] == blake2FFinalBlockBytes) + + h [8]uint64 + m [16]uint64 + t [2]uint64 + ) + for i := 0; i < 8; i++ { + offset := 4 + i*8 + h[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + for i := 0; i < 16; i++ { + offset := 68 + i*8 + m[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + t[0] = binary.LittleEndian.Uint64(input[196:204]) + t[1] = binary.LittleEndian.Uint64(input[204:212]) + + // Execute the compression function, extract and return the result + blake2b.F(&h, m, t, final, rounds) + + output := make([]byte, 64) + for i := 0; i < 8; i++ { + offset := i * 8 + binary.LittleEndian.PutUint64(output[offset:offset+8], h[i]) + } + return output, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go b/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go index 6e7259d405..075f5b7606 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go @@ -27,6 +27,8 @@ import ( // defined jump tables are not polluted. func EnableEIP(eipNum int, jt *JumpTable) error { switch eipNum { + case 2200: + enable2200(jt) case 1884: enable1884(jt) case 1344: @@ -83,3 +85,8 @@ func opChainID(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo stack.push(chainId) return nil, nil } + +// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE) +func enable2200(jt *JumpTable) { + jt[SSTORE].dynamicGas = gasSStoreEIP2200 +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go index b2999fdea7..1d3c4f1003 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go @@ -17,6 +17,8 @@ package vm import ( + "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" @@ -160,6 +162,61 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi return params.NetSstoreDirtyGas, nil } +// 0. If *gasleft* is less than or equal to 2300, fail the current call. +// 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted. +// 2. If current value does not equal new value: +// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context): +// 2.1.1. If original value is 0, SSTORE_INIT_GAS gas is deducted. +// 2.1.2. Otherwise, SSTORE_CLEAN_GAS gas is deducted. If new value is 0, add SSTORE_CLEAR_REFUND to refund counter. +// 2.2. If original value does not equal current value (this storage slot is dirty), SSTORE_DIRTY_GAS gas is deducted. Apply both of the following clauses: +// 2.2.1. If original value is not 0: +// 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEAR_REFUND gas from refund counter. We can prove that refund counter will never go below 0. +// 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEAR_REFUND gas to refund counter. +// 2.2.2. If original value equals new value (this storage slot is reset): +// 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter. +// 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter. +func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // If we fail the minimum gas availability invariant, fail (0) + if contract.Gas <= params.SstoreSentryGasEIP2200 { + return 0, errors.New("not enough gas for reentrancy sentry") + } + // Gas sentry honoured, do the actual gas calculation based on the stored value + var ( + y, x = stack.Back(1), stack.Back(0) + current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) + ) + value := common.BigToHash(y) + + if current == value { // noop (1) + return params.SstoreNoopGasEIP2200, nil + } + original := evm.StateDB.GetCommittedState(contract.Address(), common.BigToHash(x)) + if original == current { + if original == (common.Hash{}) { // create slot (2.1.1) + return params.SstoreInitGasEIP2200, nil + } + if value == (common.Hash{}) { // delete slot (2.1.2b) + evm.StateDB.AddRefund(params.SstoreClearRefundEIP2200) + } + return params.SstoreCleanGasEIP2200, nil // write existing slot (2.1.2) + } + if original != (common.Hash{}) { + if current == (common.Hash{}) { // recreate slot (2.2.1.1) + evm.StateDB.SubRefund(params.SstoreClearRefundEIP2200) + } else if value == (common.Hash{}) { // delete slot (2.2.1.2) + evm.StateDB.AddRefund(params.SstoreClearRefundEIP2200) + } + } + if original == value { + if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1) + evm.StateDB.AddRefund(params.SstoreInitRefundEIP2200) + } else { // reset to original existing slot (2.2.2.2) + evm.StateDB.AddRefund(params.SstoreCleanRefundEIP2200) + } + } + return params.SstoreDirtyGasEIP2200, nil // dirty update (2.2) +} + func makeGasLog(n uint64) gasFunc { return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { requestedSize, overflow := bigUint64(stack.Back(1)) diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go index 7b6909c927..d65664b67d 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go @@ -384,7 +384,7 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory * func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { offset, size := stack.pop(), stack.pop() - data := memory.Get(offset.Int64(), size.Int64()) + data := memory.GetPtr(offset.Int64(), size.Int64()) if interpreter.hasher == nil { interpreter.hasher = sha3.NewLegacyKeccak256().(keccakState) @@ -602,11 +602,9 @@ func opPop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory * } func opMload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - offset := stack.pop() - val := interpreter.intPool.get().SetBytes(memory.Get(offset.Int64(), 32)) - stack.push(val) - - interpreter.intPool.put(offset) + v := stack.peek() + offset := v.Int64() + v.SetBytes(memory.GetPtr(offset, 32)) return nil, nil } @@ -691,7 +689,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor var ( value = stack.pop() offset, size = stack.pop(), stack.pop() - input = memory.Get(offset.Int64(), size.Int64()) + input = memory.GetCopy(offset.Int64(), size.Int64()) gas = contract.Gas ) if interpreter.evm.chainRules.IsEIP150 { @@ -725,7 +723,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo endowment = stack.pop() offset, size = stack.pop(), stack.pop() salt = stack.pop() - input = memory.Get(offset.Int64(), size.Int64()) + input = memory.GetCopy(offset.Int64(), size.Int64()) gas = contract.Gas ) @@ -757,7 +755,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory toAddr := common.BigToAddress(addr) value = math.U256(value) // Get the arguments from the memory. - args := memory.Get(inOffset.Int64(), inSize.Int64()) + args := memory.GetPtr(inOffset.Int64(), inSize.Int64()) if value.Sign() != 0 { gas += params.CallStipend @@ -786,7 +784,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem toAddr := common.BigToAddress(addr) value = math.U256(value) // Get arguments from the memory. - args := memory.Get(inOffset.Int64(), inSize.Int64()) + args := memory.GetPtr(inOffset.Int64(), inSize.Int64()) if value.Sign() != 0 { gas += params.CallStipend @@ -814,7 +812,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() toAddr := common.BigToAddress(addr) // Get arguments from the memory. - args := memory.Get(inOffset.Int64(), inSize.Int64()) + args := memory.GetPtr(inOffset.Int64(), inSize.Int64()) ret, returnGas, err := interpreter.evm.DelegateCall(contract, toAddr, args, gas) if err != nil { @@ -839,7 +837,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, m addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() toAddr := common.BigToAddress(addr) // Get arguments from the memory. - args := memory.Get(inOffset.Int64(), inSize.Int64()) + args := memory.GetPtr(inOffset.Int64(), inSize.Int64()) ret, returnGas, err := interpreter.evm.StaticCall(contract, toAddr, args, gas) if err != nil { @@ -895,7 +893,7 @@ func makeLog(size int) executionFunc { topics[i] = common.BigToHash(stack.pop()) } - d := memory.Get(mStart.Int64(), mSize.Int64()) + d := memory.GetCopy(mStart.Int64(), mSize.Int64()) interpreter.evm.StateDB.AddLog(&types.Log{ Address: contract.Address(), Topics: topics, diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go b/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go index be6e00a6e6..fe06492de3 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go @@ -93,6 +93,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { if !cfg.JumpTable[STOP].valid { var jt JumpTable switch { + case evm.chainRules.IsIstanbul: + jt = istanbulInstructionSet case evm.chainRules.IsConstantinople: jt = constantinopleInstructionSet case evm.chainRules.IsByzantium: diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go index da532541c6..b26b55284c 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go @@ -60,15 +60,27 @@ var ( spuriousDragonInstructionSet = newSpuriousDragonInstructionSet() byzantiumInstructionSet = newByzantiumInstructionSet() constantinopleInstructionSet = newConstantinopleInstructionSet() + istanbulInstructionSet = newIstanbulInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. type JumpTable [256]operation -// NewConstantinopleInstructionSet returns the frontier, homestead +// newIstanbulInstructionSet returns the frontier, homestead +// byzantium, contantinople and petersburg instructions. +func newIstanbulInstructionSet() JumpTable { + instructionSet := newConstantinopleInstructionSet() + + enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344 + enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884 + enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200 + + return instructionSet +} + +// newConstantinopleInstructionSet returns the frontier, homestead // byzantium and contantinople instructions. func newConstantinopleInstructionSet() JumpTable { - // instructions that can be executed during the byzantium phase. instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = operation{ execute: opSHL, @@ -112,10 +124,9 @@ func newConstantinopleInstructionSet() JumpTable { return instructionSet } -// NewByzantiumInstructionSet returns the frontier, homestead and +// newByzantiumInstructionSet returns the frontier, homestead and // byzantium instructions. func newByzantiumInstructionSet() JumpTable { - // instructions that can be executed during the homestead phase. instructionSet := newSpuriousDragonInstructionSet() instructionSet[STATICCALL] = operation{ execute: opStaticCall, @@ -177,7 +188,7 @@ func newTangerineWhistleInstructionSet() JumpTable { return instructionSet } -// NewHomesteadInstructionSet returns the frontier and homestead +// newHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. func newHomesteadInstructionSet() JumpTable { instructionSet := newFrontierInstructionSet() @@ -194,7 +205,7 @@ func newHomesteadInstructionSet() JumpTable { return instructionSet } -// NewFrontierInstructionSet returns the frontier instructions +// newFrontierInstructionSet returns the frontier instructions // that can be executed during the frontier phase. func newFrontierInstructionSet() JumpTable { return JumpTable{ diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/memory.go b/vendor/github.com/ethereum/go-ethereum/core/vm/memory.go index 7e6f0eb940..496a4024ba 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/memory.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/memory.go @@ -70,7 +70,7 @@ func (m *Memory) Resize(size uint64) { } // Get returns offset + size as a new slice -func (m *Memory) Get(offset, size int64) (cpy []byte) { +func (m *Memory) GetCopy(offset, size int64) (cpy []byte) { if size == 0 { return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go new file mode 100644 index 0000000000..5da50cab6f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go @@ -0,0 +1,319 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xb. +// +// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf +// and for BLAKE2Xb see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). +// If you need a secret-key MAC (message authentication code), use the New512 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 64 bytes. It +// can produce hash values between 0 and 4 GiB. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var ( + errKeySize = errors.New("blake2b: invalid key size") + errHashSize = errors.New("blake2b: invalid hash size") +) + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. +// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. +// The hash size can be a value between 1 and 64 but it is highly recommended to use +// values equal or greater than: +// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). +// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. +func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } + +// F is a compression function for BLAKE2b. It takes as an argument the state +// vector `h`, message block vector `m`, offset counter `t`, final block indicator +// flag `f`, and number of rounds `rounds`. The state vector provided as the first +// parameter is modified by the function. +func F(h *[8]uint64, m [16]uint64, c [2]uint64, final bool, rounds uint32) { + var flag uint64 + if final { + flag = 0xFFFFFFFFFFFFFFFF + } + f(h, &m, c[0], c[1], flag, uint64(rounds)) +} + +func newDigest(hashSize int, key []byte) (*digest, error) { + if hashSize < 1 || hashSize > Size { + return nil, errHashSize + } + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + f(h, &m, c0, c1, flag, 12) + } + c[0], c[1] = c0, c1 +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint64(hash[8*i:], v) + } +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 0000000000..0d52b18699 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +//go:noescape +func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +//go:noescape +func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + switch { + case useAVX2: + fAVX2(h, m, c0, c1, flag, rounds) + case useAVX: + fAVX(h, m, c0, c1, flag, rounds) + case useSSE4: + fSSE4(h, m, c0, c1, flag, rounds) + default: + fGeneric(h, m, c0, c1, flag, rounds) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 0000000000..4998af37dd --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,717 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 + +#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 +#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 +#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e +#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 +#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 + +#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ + VPADDQ m0, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m1, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y1_Y1; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y3_Y3; \ + VPADDQ m2, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m3, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y3_Y3; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y1_Y1 + +#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E +#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 +#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E +#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 +#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E + +#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n +#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n +#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n +#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n +#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n + +#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 +#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 +#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 +#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 +#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 + +#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 + +#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 +#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 + +// load msg: Y12 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y12, Y12 + +// load msg: Y13 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ + VMOVQ_SI_X13(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X13(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y13, Y13 + +// load msg: Y14 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ + VMOVQ_SI_X14(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X14(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y14, Y14 + +// load msg: Y15 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ + VMOVQ_SI_X15(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X15(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X11(6*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ + LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) + +#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ + LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ + LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ + VMOVQ_SI_X11(11*8); \ + VPSHUFD $0x4E, 0*8(SI), X14; \ + VPINSRQ_1_SI_X11(5*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) + +#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ + VMOVQ_SI_X11(5*8); \ + VMOVDQU 11*8(SI), X12; \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + VMOVQ_SI_X13(8*8); \ + VMOVQ_SI_X11(2*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X11(13*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) + +#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ + LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ + LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ + LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ + VMOVQ_SI_X15(6*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X15(10*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ + LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X13(7*8); \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) + +#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ + LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) + +#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ + LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ + LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ + VMOVQ_SI_X14_0; \ + VPSHUFD $0x4E, 8*8(SI), X11; \ + VPINSRQ_1_SI_X14(6*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) + +#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ + LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ + LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ + LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ + VMOVQ_SI_X15_0; \ + VMOVQ_SI_X11(6*8); \ + VPINSRQ_1_SI_X15(4*8); \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ + VMOVQ_SI_X12(6*8); \ + VMOVQ_SI_X11(11*8); \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ + VMOVQ_SI_X11(1*8); \ + VMOVDQU 12*8(SI), X14; \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + VMOVQ_SI_X15(2*8); \ + VMOVDQU 4*8(SI), X11; \ + VPINSRQ_1_SI_X15(7*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ + LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ + VMOVQ_SI_X13(2*8); \ + VPSHUFD $0x4E, 5*8(SI), X11; \ + VPINSRQ_1_SI_X13(4*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ + VMOVQ_SI_X15(11*8); \ + VMOVQ_SI_X11(12*8); \ + VPINSRQ_1_SI_X15(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y15, Y15 + +// func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fAVX2(SB), 4, $64-48 // frame size = 32 + 32 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, DX + MOVQ SP, R10 + ADDQ $31, R10 + ANDQ $~31, R10 + MOVQ R10, SP + + MOVQ CX, 16(SP) + XORQ CX, CX + MOVQ CX, 24(SP) + + VMOVDQU ·AVX2_c40<>(SB), Y4 + VMOVDQU ·AVX2_c48<>(SB), Y5 + + VMOVDQU 0(AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>(SB), Y6 + VMOVDQU ·AVX2_iv1<>(SB), Y7 + + MOVQ R8, 0(SP) + MOVQ R9, 8(SP) + + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR 0(SP), Y7, Y3 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + JMP loop + +done: + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + + VMOVDQU Y8, 0(AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + + MOVQ DX, SP + RET + +#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA +#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB +#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF +#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD +#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE + +#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF +#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF + +#define SHUFFLE_AVX() \ + VMOVDQA X6, X13; \ + VMOVDQA X2, X14; \ + VMOVDQA X4, X6; \ + VPUNPCKLQDQ_X13_X13_X15; \ + VMOVDQA X5, X4; \ + VMOVDQA X6, X5; \ + VPUNPCKHQDQ_X15_X7_X6; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X13_X7; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VPUNPCKHQDQ_X15_X2_X2; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X3_X3; \ + +#define SHUFFLE_AVX_INV() \ + VMOVDQA X2, X13; \ + VMOVDQA X4, X14; \ + VPUNPCKLQDQ_X2_X2_X15; \ + VMOVDQA X5, X4; \ + VPUNPCKHQDQ_X15_X3_X2; \ + VMOVDQA X14, X5; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VMOVDQA X6, X14; \ + VPUNPCKHQDQ_X15_X13_X3; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X6_X6; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X7_X7; \ + +#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + VPADDQ m0, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m1, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFD $-79, v6, v6; \ + VPSHUFD $-79, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPSHUFB c40, v2, v2; \ + VPSHUFB c40, v3, v3; \ + VPADDQ m2, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m3, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFB c48, v6, v6; \ + VPSHUFB c48, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPADDQ v2, v2, t0; \ + VPSRLQ $63, v2, v2; \ + VPXOR t0, v2, v2; \ + VPADDQ v3, v3, t0; \ + VPSRLQ $63, v3, v3; \ + VPXOR t0, v3, v3 + +// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X13(i2*8); \ + VMOVQ_SI_X14(i4*8); \ + VMOVQ_SI_X15(i6*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X13(i3*8); \ + VPINSRQ_1_SI_X14(i5*8); \ + VPINSRQ_1_SI_X15(i7*8) + +// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(1*8); \ + VMOVQ_SI_X15(5*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X13(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(7*8) + +// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ + VPSHUFD $0x4E, 0*8(SI), X12; \ + VMOVQ_SI_X13(11*8); \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(7*8); \ + VPINSRQ_1_SI_X13(5*8); \ + VPINSRQ_1_SI_X14(2*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ + VMOVDQU 11*8(SI), X12; \ + VMOVQ_SI_X13(5*8); \ + VMOVQ_SI_X14(8*8); \ + VMOVQ_SI_X15(2*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14_0; \ + VPINSRQ_1_SI_X15(13*8) + +// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(6*8); \ + VMOVQ_SI_X15_0; \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ + VMOVQ_SI_X12(9*8); \ + VMOVQ_SI_X13(2*8); \ + VMOVQ_SI_X14_0; \ + VMOVQ_SI_X15(4*8); \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VPINSRQ_1_SI_X15(15*8) + +// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(11*8); \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X13(8*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ + MOVQ 0*8(SI), X12; \ + VPSHUFD $0x4E, 8*8(SI), X13; \ + MOVQ 7*8(SI), X14; \ + MOVQ 2*8(SI), X15; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(11*8) + +// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ + MOVQ 6*8(SI), X12; \ + MOVQ 11*8(SI), X13; \ + MOVQ 15*8(SI), X14; \ + MOVQ 3*8(SI), X15; \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X14(9*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ + MOVQ 5*8(SI), X12; \ + MOVQ 8*8(SI), X13; \ + MOVQ 0*8(SI), X14; \ + MOVQ 6*8(SI), X15; \ + VPINSRQ_1_SI_X12(15*8); \ + VPINSRQ_1_SI_X13(2*8); \ + VPINSRQ_1_SI_X14(4*8); \ + VPINSRQ_1_SI_X15(10*8) + +// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ + VMOVDQU 12*8(SI), X12; \ + MOVQ 1*8(SI), X13; \ + MOVQ 2*8(SI), X14; \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VMOVDQU 4*8(SI), X15 + +// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ + MOVQ 15*8(SI), X12; \ + MOVQ 3*8(SI), X13; \ + MOVQ 11*8(SI), X14; \ + MOVQ 12*8(SI), X15; \ + VPINSRQ_1_SI_X12(9*8); \ + VPINSRQ_1_SI_X13(13*8); \ + VPINSRQ_1_SI_X14(14*8); \ + VPINSRQ_1_SI_X15_0 + +// func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fAVX(SB), 4, $24-48 // frame size = 8 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, BP + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + MOVQ R10, SP + + VMOVDQU ·AVX_c40<>(SB), X0 + VMOVDQU ·AVX_c48<>(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + + VMOVDQU ·AVX_iv3<>(SB), X0 + VMOVDQA X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU 0(AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + + VMOVQ_R8_X15 + VPINSRQ_1_R9_X15 + + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>(SB), X4 + VMOVDQU ·AVX_iv1<>(SB), X5 + VMOVDQU ·AVX_iv2<>(SB), X6 + + VPXOR X15, X6, X6 + VMOVDQA 0(SP), X7 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + JMP loop + +done: + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + + VMOVDQU X10, 0(AX) + VMOVDQU X11, 16(AX) + VZEROUPPER + + MOVQ BP, SP + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go new file mode 100644 index 0000000000..4dbe90da8f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go @@ -0,0 +1,24 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7,amd64,!gccgo,!appengine + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + if useSSE4 { + fSSE4(h, m, c0, c1, flag, rounds) + } else { + fGeneric(h, m, c0, c1, flag, rounds) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 0000000000..ce4b56d105 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,253 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + PADDQ m0, v0; \ + PADDQ m1, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v6, v6; \ + PSHUFD $0xB1, v7, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + PSHUFB c40, v2; \ + PSHUFB c40, v3; \ + PADDQ m2, v0; \ + PADDQ m3, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFB c48, v6; \ + PSHUFB c48, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + MOVOU v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVOU v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG(m0, m1, m2, m3, i0, i1, i2, i3, i4, i5, i6, i7) \ + MOVQ i0*8(SI), m0; \ + PINSRQ $1, i1*8(SI), m0; \ + MOVQ i2*8(SI), m1; \ + PINSRQ $1, i3*8(SI), m1; \ + MOVQ i4*8(SI), m2; \ + PINSRQ $1, i5*8(SI), m2; \ + MOVQ i6*8(SI), m3; \ + PINSRQ $1, i7*8(SI), m3 + +// func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fSSE4(SB), 4, $24-48 // frame size = 8 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, BP + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + MOVQ R10, SP + + MOVOU ·iv3<>(SB), X0 + MOVO X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) + + MOVOU ·c40<>(SB), X13 + MOVOU ·c48<>(SB), X14 + + MOVOU 0(AX), X12 + MOVOU 16(AX), X15 + + MOVQ R8, X8 + PINSRQ $1, R9, X8 + + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>(SB), X4 + MOVOU ·iv1<>(SB), X5 + MOVOU ·iv2<>(SB), X6 + + PXOR X8, X6 + MOVO 0(SP), X7 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 0, 2, 4, 6, 1, 3, 5, 7) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 8, 10, 12, 14, 9, 11, 13, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 14, 4, 9, 13, 10, 8, 15, 6) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 1, 0, 11, 5, 12, 2, 7, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + JMP loop + +done: + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + + MOVOU X12, 0(AX) + MOVOU X15, 16(AX) + + MOVQ BP, SP + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go new file mode 100644 index 0000000000..ab73342803 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go @@ -0,0 +1,57 @@ +// +build gofuzz + +package blake2b + +import ( + "encoding/binary" +) + +func Fuzz(data []byte) int { + // Make sure the data confirms to the input model + if len(data) != 211 { + return 0 + } + // Parse everything and call all the implementations + var ( + rounds = binary.BigEndian.Uint16(data[0:2]) + + h [8]uint64 + m [16]uint64 + t [2]uint64 + f uint64 + ) + for i := 0; i < 8; i++ { + offset := 2 + i*8 + h[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) + } + for i := 0; i < 16; i++ { + offset := 66 + i*8 + m[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) + } + t[0] = binary.LittleEndian.Uint64(data[194:202]) + t[1] = binary.LittleEndian.Uint64(data[202:210]) + + if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1 + f = 0xFFFFFFFFFFFFFFFF + } + // Run the blake2b compression on all instruction sets and cross reference + want := h + fGeneric(&want, &m, t[0], t[1], f, uint64(rounds)) + + have := h + fSSE4(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("SSE4 mismatches generic algo") + } + have = h + fAVX(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("AVX mismatches generic algo") + } + have = h + fAVX2(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("AVX2 mismatches generic algo") + } + return 1 +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go new file mode 100644 index 0000000000..35c40cc924 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,180 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "math/bits" +) + +// the precomputed values for BLAKE2b +// there are 10 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [10][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + fGeneric(h, &m, c0, c1, flag, 12) + } + c[0], c[1] = c0, c1 +} + +func fGeneric(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for i := 0; i < int(rounds); i++ { + s := &(precomputed[i%10]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -32) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -24) + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -32) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -24) + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -32) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -24) + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -32) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -24) + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -16) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -63) + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -16) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -63) + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -16) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -63) + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -16) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -63) + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -32) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -24) + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -32) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -24) + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -32) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -24) + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -32) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -24) + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -16) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -63) + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -16) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -63) + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -16) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -63) + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -16) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -63) + } + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go new file mode 100644 index 0000000000..9d0ade473a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine gccgo + +package blake2b + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + fGeneric(h, m, c0, c1, flag, rounds) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go new file mode 100644 index 0000000000..52c414db0e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go @@ -0,0 +1,177 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = (1 << 32) - 1 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 64 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 256GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint32, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^32-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2b: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint32 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2b: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length + x.cfg[17] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[1] ^= uint64(x.length) << 32 + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go new file mode 100644 index 0000000000..efd689af4b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go @@ -0,0 +1,32 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package blake2b + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + newHash384 := func() hash.Hash { + h, _ := New384(nil) + return h + } + + newHash512 := func() hash.Hash { + h, _ := New512(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) + crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) + crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go index 4567fafc72..2869b4c191 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go @@ -34,6 +34,15 @@ import ( "golang.org/x/crypto/sha3" ) +//SignatureLength indicates the byte length required to carry a signature with recovery id. +const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id + +// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id. +const RecoveryIDOffset = 64 + +// DigestLength sets the signature digest exact length +const DigestLength = 32 + var ( secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2)) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go index aadf028d26..1fe84509e7 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go @@ -47,24 +47,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // // This function is susceptible to chosen plaintext attacks that can leak // information about the private key that is used for signing. Callers must -// be aware that the given hash cannot be chosen by an adversery. Common +// be aware that the given digest cannot be chosen by an adversery. Common // solution is to hash any input before calculating the signature. // // The produced signature is in the [R || S || V] format where V is 0 or 1. -func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - if len(hash) != 32 { - return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) +func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { + if len(digestHash) != DigestLength { + return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash)) } seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8) defer zeroBytes(seckey) - return secp256k1.Sign(hash, seckey) + return secp256k1.Sign(digestHash, seckey) } -// VerifySignature checks that the given public key created signature over hash. +// VerifySignature checks that the given public key created signature over digest. // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. // The signature should have the 64 byte [R || S] format. -func VerifySignature(pubkey, hash, signature []byte) bool { - return secp256k1.VerifySignature(pubkey, hash, signature) +func VerifySignature(pubkey, digestHash, signature []byte) bool { + return secp256k1.VerifySignature(pubkey, digestHash, signature) } // DecompressPubkey parses a public key in the 33-byte compressed format. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go index 90d072cda7..067d32e13c 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go @@ -41,7 +41,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) { // SigToPub returns the public key that created the given signature. func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // Convert to btcec input format with 'recovery id' v at the beginning. - btcsig := make([]byte, 65) + btcsig := make([]byte, SignatureLength) btcsig[0] = sig[64] + 27 copy(btcsig[1:], sig) diff --git a/vendor/github.com/ethereum/go-ethereum/dashboard/README.md b/vendor/github.com/ethereum/go-ethereum/dashboard/README.md index 641c5f44bc..67b65bda36 100644 --- a/vendor/github.com/ethereum/go-ethereum/dashboard/README.md +++ b/vendor/github.com/ethereum/go-ethereum/dashboard/README.md @@ -48,8 +48,8 @@ For more IDE support install the `linter-eslint` package too, which finds the `. [ESLint]: https://eslint.org/ [Airbnb]: https://github.com/airbnb/javascript/tree/master/react [Webpack]: https://webpack.github.io/ -[WA]: http://webpack.github.io/analyse/ -[WV]: http://chrisbateman.github.io/webpack-visualizer/ +[WA]: https://webpack.github.io/analyse/ +[WV]: https://chrisbateman.github.io/webpack-visualizer/ [Node.js]: https://nodejs.org/en/ [Flow]: https://flow.org/ [Atom]: https://atom.io/ diff --git a/vendor/github.com/ethereum/go-ethereum/dashboard/dashboard.go b/vendor/github.com/ethereum/go-ethereum/dashboard/dashboard.go index d69a750f10..b576293bc9 100644 --- a/vendor/github.com/ethereum/go-ethereum/dashboard/dashboard.go +++ b/vendor/github.com/ethereum/go-ethereum/dashboard/dashboard.go @@ -125,7 +125,7 @@ func (db *Dashboard) APIs() []rpc.API { return nil } // Start starts the data collection thread and the listening server of the dashboard. // Implements the node.Service interface. func (db *Dashboard) Start(server *p2p.Server) error { - log.Info("Starting dashboard") + log.Info("Starting dashboard", "url", fmt.Sprintf("http://%s:%d", db.config.Host, db.config.Port)) db.wg.Add(3) go db.collectSystemData() diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api.go b/vendor/github.com/ethereum/go-ethereum/eth/api.go index 98c2f5874f..f8c51c09bd 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/api.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/api.go @@ -168,6 +168,11 @@ func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI { // ExportChain exports the current blockchain into a local file. func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) { + if _, err := os.Stat(file); err == nil { + // File already exists. Allowing overwrite could be a DoS vecotor, + // since the 'file' may point to arbitrary paths on the drive + return false, errors.New("location would overwrite an existing file") + } // Make sure we can create the file to export into out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) if err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go index 69904a70f2..4b74ccff51 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go @@ -72,6 +72,23 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil } +func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.HeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header := b.eth.blockchain.GetHeaderByHash(hash) + if header == nil { + return nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + return header, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { return b.eth.blockchain.GetHeaderByHash(hash), nil } @@ -93,6 +110,27 @@ func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ return b.eth.blockchain.GetBlockByHash(hash), nil } +func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.BlockByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header := b.eth.blockchain.GetHeaderByHash(hash) + if header == nil { + return nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64()) + if block == nil { + return nil, errors.New("header found, but block body is missing") + } + return block, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { // Pending state is only known by the miner if number == rpc.PendingBlockNumber { @@ -111,6 +149,27 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B return stateDb, header, err } +func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.StateAndHeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header, err := b.HeaderByHash(ctx, hash) + if err != nil { + return nil, nil, err + } + if header == nil { + return nil, nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, nil, errors.New("hash is not currently canonical") + } + stateDb, err := b.eth.BlockChain().StateAt(header.Root) + return stateDb, header, err + } + return nil, nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { return b.eth.blockchain.GetReceiptsByHash(hash), nil } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/backend.go b/vendor/github.com/ethereum/go-ethereum/eth/backend.go index dc4ff8ade8..83e05e96a8 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/backend.go @@ -69,8 +69,6 @@ type Ethereum struct { // Channel for shutting down the service shutdownChan chan bool - server *p2p.Server - // Handlers txPool *core.TxPool blockchain *core.BlockChain @@ -137,7 +135,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideIstanbul) if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/config.go b/vendor/github.com/ethereum/go-ethereum/eth/config.go index 6887872276..5094a533bf 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/config.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/config.go @@ -154,4 +154,7 @@ type Config struct { // CheckpointOracle is the configuration for checkpoint oracle. CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` + + // Istanbul block override (TODO: remove after the fork) + OverrideIstanbul *big.Int } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go index edd0eb4d95..f8982f696f 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go @@ -1574,13 +1574,14 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error { func (d *Downloader) processFastSyncContent(latest *types.Header) error { // Start syncing state of the reported head block. This should get us most of // the state of the pivot block. - stateSync := d.syncState(latest.Root) - defer stateSync.Cancel() - go func() { - if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled { + sync := d.syncState(latest.Root) + defer sync.Cancel() + closeOnErr := func(s *stateSync) { + if err := s.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled { d.queue.Close() // wake up Results } - }() + } + go closeOnErr(sync) // Figure out the ideal pivot block. Note, that this goalpost may move if the // sync takes long enough for the chain head to move significantly. pivot := uint64(0) @@ -1600,12 +1601,12 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { if len(results) == 0 { // If pivot sync is done, stop if oldPivot == nil { - return stateSync.Cancel() + return sync.Cancel() } // If sync failed, stop select { case <-d.cancelCh: - stateSync.Cancel() + sync.Cancel() return errCanceled default: } @@ -1625,28 +1626,24 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { } } P, beforeP, afterP := splitAroundPivot(pivot, results) - if err := d.commitFastSyncData(beforeP, stateSync); err != nil { + if err := d.commitFastSyncData(beforeP, sync); err != nil { return err } if P != nil { // If new pivot block found, cancel old state retrieval and restart if oldPivot != P { - stateSync.Cancel() + sync.Cancel() - stateSync = d.syncState(P.Header.Root) - defer stateSync.Cancel() - go func() { - if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled { - d.queue.Close() // wake up Results - } - }() + sync = d.syncState(P.Header.Root) + defer sync.Cancel() + go closeOnErr(sync) oldPivot = P } // Wait for completion, occasionally checking for pivot staleness select { - case <-stateSync.done: - if stateSync.err != nil { - return stateSync.err + case <-sync.done: + if sync.err != nil { + return sync.err } if err := d.commitPivotBlock(P); err != nil { return err diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go index b422557d58..f875b3a84c 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go @@ -347,7 +347,7 @@ func (s *stateSync) commit(force bool) error { } start := time.Now() b := s.d.stateDB.NewBatch() - if written, err := s.sched.Commit(b); written == 0 || err != nil { + if err := s.sched.Commit(b); err != nil { return err } if err := b.Write(); err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/eth/handler.go b/vendor/github.com/ethereum/go-ethereum/eth/handler.go index 4ce2d1c82f..d2355a8768 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/handler.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/handler.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/fetcher" @@ -63,7 +64,8 @@ func errResp(code errCode, format string, v ...interface{}) error { } type ProtocolManager struct { - networkID uint64 + networkID uint64 + forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks) acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing) @@ -103,6 +105,7 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh // Create the protocol manager with the base fields manager := &ProtocolManager{ networkID: networkID, + forkFilter: forkid.NewFilter(blockchain), eventMux: mux, txpool: txpool, blockchain: blockchain, @@ -304,7 +307,7 @@ func (pm *ProtocolManager) handle(p *peer) error { number = head.Number.Uint64() td = pm.blockchain.GetTd(hash, number) ) - if err := p.Handshake(pm.networkID, td, hash, genesis.Hash()); err != nil { + if err := p.Handshake(pm.networkID, td, hash, genesis.Hash(), forkid.NewID(pm.blockchain), pm.forkFilter); err != nil { p.Log().Debug("Ethereum handshake failed", "err", err) return err } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/peer.go b/vendor/github.com/ethereum/go-ethereum/eth/peer.go index 814c787b8c..0beec1d844 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/peer.go @@ -25,6 +25,7 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rlp" @@ -353,22 +354,46 @@ func (p *peer) RequestReceipts(hashes []common.Hash) error { // Handshake executes the eth protocol handshake, negotiating version number, // network IDs, difficulties, head and genesis blocks. -func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash) error { +func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { // Send out own handshake in a new thread errc := make(chan error, 2) - var status statusData // safe to read after two values have been received from errc + var ( + status63 statusData63 // safe to read after two values have been received from errc + status statusData // safe to read after two values have been received from errc + ) go func() { - errc <- p2p.Send(p.rw, StatusMsg, &statusData{ - ProtocolVersion: uint32(p.version), - NetworkId: network, - TD: td, - CurrentBlock: head, - GenesisBlock: genesis, - }) + switch { + case p.version == eth63: + errc <- p2p.Send(p.rw, StatusMsg, &statusData63{ + ProtocolVersion: uint32(p.version), + NetworkId: network, + TD: td, + CurrentBlock: head, + GenesisBlock: genesis, + }) + case p.version == eth64: + errc <- p2p.Send(p.rw, StatusMsg, &statusData{ + ProtocolVersion: uint32(p.version), + NetworkID: network, + TD: td, + Head: head, + Genesis: genesis, + ForkID: forkID, + }) + default: + panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) + } }() go func() { - errc <- p.readStatus(network, &status, genesis) + switch { + case p.version == eth63: + errc <- p.readStatusLegacy(network, &status63, genesis) + case p.version == eth64: + errc <- p.readStatus(network, &status, genesis, forkFilter) + default: + panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) + } }() timeout := time.NewTimer(handshakeTimeout) defer timeout.Stop() @@ -382,11 +407,18 @@ func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis return p2p.DiscReadTimeout } } - p.td, p.head = status.TD, status.CurrentBlock + switch { + case p.version == eth63: + p.td, p.head = status63.TD, status63.CurrentBlock + case p.version == eth64: + p.td, p.head = status.TD, status.Head + default: + panic(fmt.Sprintf("unsupported eth protocol version: %d", p.version)) + } return nil } -func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash) (err error) { +func (p *peer) readStatusLegacy(network uint64, status *statusData63, genesis common.Hash) error { msg, err := p.rw.ReadMsg() if err != nil { return err @@ -402,10 +434,10 @@ func (p *peer) readStatus(network uint64, status *statusData, genesis common.Has return errResp(ErrDecode, "msg %v: %v", msg, err) } if status.GenesisBlock != genesis { - return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) + return errResp(ErrGenesisMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8]) } if status.NetworkId != network { - return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network) + return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkId, network) } if int(status.ProtocolVersion) != p.version { return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) @@ -413,6 +445,36 @@ func (p *peer) readStatus(network uint64, status *statusData, genesis common.Has return nil } +func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash, forkFilter forkid.Filter) error { + msg, err := p.rw.ReadMsg() + if err != nil { + return err + } + if msg.Code != StatusMsg { + return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) + } + if msg.Size > protocolMaxMsgSize { + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) + } + // Decode the handshake and make sure everything matches + if err := msg.Decode(&status); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + if status.NetworkID != network { + return errResp(ErrNetworkIDMismatch, "%d (!= %d)", status.NetworkID, network) + } + if int(status.ProtocolVersion) != p.version { + return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version) + } + if status.Genesis != genesis { + return errResp(ErrGenesisMismatch, "%x (!= %x)", status.Genesis, genesis) + } + if err := forkFilter(status.ForkID); err != nil { + return errResp(ErrForkIDRejected, "%v", err) + } + return nil +} + // String implements fmt.Stringer. func (p *peer) String() string { return fmt.Sprintf("Peer %s [%s]", p.id, diff --git a/vendor/github.com/ethereum/go-ethereum/eth/protocol.go b/vendor/github.com/ethereum/go-ethereum/eth/protocol.go index de0c979d89..62e4d13d14 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/protocol.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/protocol.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/rlp" @@ -30,24 +31,23 @@ import ( // Constants to match up protocol versions and messages const ( - eth62 = 62 eth63 = 63 + eth64 = 64 ) // protocolName is the official short name of the protocol used during capability negotiation. const protocolName = "eth" // ProtocolVersions are the supported versions of the eth protocol (first is primary). -var ProtocolVersions = []uint{eth63} +var ProtocolVersions = []uint{eth64, eth63} // protocolLengths are the number of implemented message corresponding to different protocol versions. -var protocolLengths = map[uint]uint64{eth63: 17, eth62: 8} +var protocolLengths = map[uint]uint64{eth64: 17, eth63: 17} const protocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message // eth protocol message codes const ( - // Protocol messages belonging to eth/62 StatusMsg = 0x00 NewBlockHashesMsg = 0x01 TxMsg = 0x02 @@ -56,12 +56,10 @@ const ( GetBlockBodiesMsg = 0x05 BlockBodiesMsg = 0x06 NewBlockMsg = 0x07 - - // Protocol messages belonging to eth/63 - GetNodeDataMsg = 0x0d - NodeDataMsg = 0x0e - GetReceiptsMsg = 0x0f - ReceiptsMsg = 0x10 + GetNodeDataMsg = 0x0d + NodeDataMsg = 0x0e + GetReceiptsMsg = 0x0f + ReceiptsMsg = 0x10 ) type errCode int @@ -71,11 +69,11 @@ const ( ErrDecode ErrInvalidMsgCode ErrProtocolVersionMismatch - ErrNetworkIdMismatch - ErrGenesisBlockMismatch + ErrNetworkIDMismatch + ErrGenesisMismatch + ErrForkIDRejected ErrNoStatusMsg ErrExtraStatusMsg - ErrSuspendedPeer ) func (e errCode) String() string { @@ -88,11 +86,11 @@ var errorToString = map[int]string{ ErrDecode: "Invalid message", ErrInvalidMsgCode: "Invalid message code", ErrProtocolVersionMismatch: "Protocol version mismatch", - ErrNetworkIdMismatch: "NetworkId mismatch", - ErrGenesisBlockMismatch: "Genesis block mismatch", + ErrNetworkIDMismatch: "Network ID mismatch", + ErrGenesisMismatch: "Genesis mismatch", + ErrForkIDRejected: "Fork ID rejected", ErrNoStatusMsg: "No status message", ErrExtraStatusMsg: "Extra status message", - ErrSuspendedPeer: "Suspended peer", } type txPool interface { @@ -108,8 +106,8 @@ type txPool interface { SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription } -// statusData is the network packet for the status message. -type statusData struct { +// statusData63 is the network packet for the status message for eth/63. +type statusData63 struct { ProtocolVersion uint32 NetworkId uint64 TD *big.Int @@ -117,6 +115,16 @@ type statusData struct { GenesisBlock common.Hash } +// statusData is the network packet for the status message for eth/64 and later. +type statusData struct { + ProtocolVersion uint32 + NetworkID uint64 + TD *big.Int + Head common.Hash + Genesis common.Hash + ForkID forkid.ID +} + // newBlockHashesData is the network packet for the block announcements. type newBlockHashesData []struct { Hash common.Hash // Hash of one particular block being announced diff --git a/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go b/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go index 9d6701868c..724c5443a6 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go @@ -99,7 +99,7 @@ func (mw *memoryWrapper) slice(begin, end int64) []byte { log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", begin, "size", end-begin) return nil } - return mw.memory.Get(begin, end-begin) + return mw.memory.GetCopy(begin, end-begin) } // getUint returns the 32 bytes at the specified address interpreted as a uint. @@ -390,7 +390,7 @@ func New(code string) (*Tracer, error) { return 1 }) tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int { - _, ok := vm.PrecompiledContractsByzantium[common.BytesToAddress(popSlice(ctx))] + _, ok := vm.PrecompiledContractsIstanbul[common.BytesToAddress(popSlice(ctx))] ctx.PushBoolean(ok) return 1 }) diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go index aba6593c7a..378d4c3cd2 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go @@ -62,14 +62,18 @@ type Database struct { fn string // filename for reporting db *leveldb.DB // LevelDB instance - compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskSizeGauge metrics.Gauge // Gauge for tracking the size of all the levels in the database - diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written + compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction + compReadMeter metrics.Meter // Meter for measuring the data read during compaction + compWriteMeter metrics.Meter // Meter for measuring the data written during compaction + writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction + writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction + diskSizeGauge metrics.Gauge // Gauge for tracking the size of all the levels in the database + diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read + diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written + memCompGauge metrics.Gauge // Gauge for tracking the number of memory compaction + level0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in level0 + nonlevel0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in non0 level + seekCompGauge metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt quitLock sync.Mutex // Mutex protecting the quit channel access quitChan chan chan error // Quit channel to stop the metrics collection before closing the database @@ -96,6 +100,7 @@ func New(file string, cache int, handles int, namespace string) (*Database, erro BlockCacheCapacity: cache / 2 * opt.MiB, WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally Filter: filter.NewBloomFilter(10), + DisableSeeksCompaction: true, }) if _, corrupted := err.(*errors.ErrCorrupted); corrupted { db, err = leveldb.RecoverFile(file, nil) @@ -118,6 +123,10 @@ func New(file string, cache int, handles int, namespace string) (*Database, erro ldb.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil) ldb.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil) ldb.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil) + ldb.memCompGauge = metrics.NewRegisteredGauge(namespace+"compact/memory", nil) + ldb.level0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/level0", nil) + ldb.nonlevel0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/nonlevel0", nil) + ldb.seekCompGauge = metrics.NewRegisteredGauge(namespace+"compact/seek", nil) // Start up the metrics gathering and return go ldb.meter(metricsGatheringInterval) @@ -375,6 +384,29 @@ func (db *Database) meter(refresh time.Duration) { } iostats[0], iostats[1] = nRead, nWrite + compCount, err := db.db.GetProperty("leveldb.compcount") + if err != nil { + db.log.Error("Failed to read database iostats", "err", err) + merr = err + continue + } + + var ( + memComp uint32 + level0Comp uint32 + nonLevel0Comp uint32 + seekComp uint32 + ) + if n, err := fmt.Sscanf(compCount, "MemComp:%d Level0Comp:%d NonLevel0Comp:%d SeekComp:%d", &memComp, &level0Comp, &nonLevel0Comp, &seekComp); n != 4 || err != nil { + db.log.Error("Compaction count statistic not found") + merr = err + continue + } + db.memCompGauge.Update(int64(memComp)) + db.level0CompGauge.Update(int64(level0Comp)) + db.nonlevel0CompGauge.Update(int64(nonLevel0Comp)) + db.seekCompGauge.Update(int64(seekComp)) + // Sleep a bit, then repeat the stats collection select { case errc = <-db.quitChan: diff --git a/vendor/github.com/ethereum/go-ethereum/graphql/graphiql.go b/vendor/github.com/ethereum/go-ethereum/graphql/graphiql.go index 483d4cea3b..864ebf57df 100644 --- a/vendor/github.com/ethereum/go-ethereum/graphql/graphiql.go +++ b/vendor/github.com/ethereum/go-ethereum/graphql/graphiql.go @@ -52,7 +52,7 @@ func (h GraphiQL) ServeHTTP(w http.ResponseWriter, r *http.Request) { respond(w, errorJSON("only GET requests are supported"), http.StatusMethodNotAllowed) return } - + w.Header().Set("Content-Type", "text/html") w.Write(graphiql) } diff --git a/vendor/github.com/ethereum/go-ethereum/graphql/graphql.go b/vendor/github.com/ethereum/go-ethereum/graphql/graphql.go index df279f42b1..ddd928dff1 100644 --- a/vendor/github.com/ethereum/go-ethereum/graphql/graphql.go +++ b/vendor/github.com/ethereum/go-ethereum/graphql/graphql.go @@ -36,20 +36,19 @@ import ( ) var ( - errOnlyOnMainChain = errors.New("this operation is only available for blocks on the canonical chain") - errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") + errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") ) // Account represents an Ethereum account at a particular block. type Account struct { - backend ethapi.Backend - address common.Address - blockNumber rpc.BlockNumber + backend ethapi.Backend + address common.Address + blockNrOrHash rpc.BlockNumberOrHash } // getState fetches the StateDB object for an account. func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { - state, _, err := a.backend.StateAndHeaderByNumber(ctx, a.blockNumber) + state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) return state, err } @@ -102,9 +101,9 @@ func (l *Log) Transaction(ctx context.Context) *Transaction { func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { return &Account{ - backend: l.backend, - address: l.log.Address, - blockNumber: args.Number(), + backend: l.backend, + address: l.log.Address, + blockNrOrHash: args.NumberOrLatest(), } } @@ -136,10 +135,10 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, error) { tx, blockHash, _, index := rawdb.ReadTransaction(t.backend.ChainDb(), t.hash) if tx != nil { t.tx = tx + blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) t.block = &Block{ - backend: t.backend, - hash: blockHash, - canonical: unknown, + backend: t.backend, + numberOrHash: &blockNrOrHash, } t.index = index } else { @@ -203,9 +202,9 @@ func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) (*Account, e return nil, nil } return &Account{ - backend: t.backend, - address: *to, - blockNumber: args.Number(), + backend: t.backend, + address: *to, + blockNrOrHash: args.NumberOrLatest(), }, nil } @@ -221,9 +220,9 @@ func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) (*Account, from, _ := types.Sender(signer, tx) return &Account{ - backend: t.backend, - address: from, - blockNumber: args.Number(), + backend: t.backend, + address: from, + blockNrOrHash: args.NumberOrLatest(), }, nil } @@ -293,9 +292,9 @@ func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) return nil, err } return &Account{ - backend: t.backend, - address: receipt.ContractAddress, - blockNumber: args.Number(), + backend: t.backend, + address: receipt.ContractAddress, + blockNrOrHash: args.NumberOrLatest(), }, nil } @@ -317,45 +316,16 @@ func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) { type BlockType int -const ( - unknown BlockType = iota - isCanonical - notCanonical -) - // Block represents an Ethereum block. -// backend, and either num or hash are mandatory. All other fields are lazily fetched +// backend, and numberOrHash are mandatory. All other fields are lazily fetched // when required. type Block struct { - backend ethapi.Backend - num *rpc.BlockNumber - hash common.Hash - header *types.Header - block *types.Block - receipts []*types.Receipt - canonical BlockType // Indicates if this block is on the main chain or not. -} - -func (b *Block) onMainChain(ctx context.Context) error { - if b.canonical == unknown { - header, err := b.resolveHeader(ctx) - if err != nil { - return err - } - canonHeader, err := b.backend.HeaderByNumber(ctx, rpc.BlockNumber(header.Number.Uint64())) - if err != nil { - return err - } - if header.Hash() == canonHeader.Hash() { - b.canonical = isCanonical - } else { - b.canonical = notCanonical - } - } - if b.canonical != isCanonical { - return errOnlyOnMainChain - } - return nil + backend ethapi.Backend + numberOrHash *rpc.BlockNumberOrHash + hash common.Hash + header *types.Header + block *types.Block + receipts []*types.Receipt } // resolve returns the internal Block object representing this block, fetching @@ -364,14 +334,17 @@ func (b *Block) resolve(ctx context.Context) (*types.Block, error) { if b.block != nil { return b.block, nil } - var err error - if b.hash != (common.Hash{}) { - b.block, err = b.backend.BlockByHash(ctx, b.hash) - } else { - b.block, err = b.backend.BlockByNumber(ctx, *b.num) + if b.numberOrHash == nil { + latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + b.numberOrHash = &latest } + var err error + b.block, err = b.backend.BlockByNumberOrHash(ctx, *b.numberOrHash) if b.block != nil && b.header == nil { b.header = b.block.Header() + if hash, ok := b.numberOrHash.Hash(); ok { + b.hash = hash + } } return b.block, err } @@ -380,7 +353,7 @@ func (b *Block) resolve(ctx context.Context) (*types.Block, error) { // if necessary. Call this function instead of `resolve` unless you need the // additional data (transactions and uncles). func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) { - if b.num == nil && b.hash == (common.Hash{}) { + if b.numberOrHash == nil && b.hash == (common.Hash{}) { return nil, errBlockInvariant } var err error @@ -388,7 +361,7 @@ func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) { if b.hash != (common.Hash{}) { b.header, err = b.backend.HeaderByHash(ctx, b.hash) } else { - b.header, err = b.backend.HeaderByNumber(ctx, *b.num) + b.header, err = b.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash) } } return b.header, err @@ -416,15 +389,12 @@ func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) { } func (b *Block) Number(ctx context.Context) (hexutil.Uint64, error) { - if b.num == nil || *b.num == rpc.LatestBlockNumber { - header, err := b.resolveHeader(ctx) - if err != nil { - return 0, err - } - num := rpc.BlockNumber(header.Number.Uint64()) - b.num = &num + header, err := b.resolveHeader(ctx) + if err != nil { + return 0, err } - return hexutil.Uint64(*b.num), nil + + return hexutil.Uint64(header.Number.Uint64()), nil } func (b *Block) Hash(ctx context.Context) (common.Hash, error) { @@ -456,26 +426,17 @@ func (b *Block) GasUsed(ctx context.Context) (hexutil.Uint64, error) { func (b *Block) Parent(ctx context.Context) (*Block, error) { // If the block header hasn't been fetched, and we'll need it, fetch it. - if b.num == nil && b.hash != (common.Hash{}) && b.header == nil { + if b.numberOrHash == nil && b.header == nil { if _, err := b.resolveHeader(ctx); err != nil { return nil, err } } if b.header != nil && b.header.Number.Uint64() > 0 { - num := rpc.BlockNumber(b.header.Number.Uint64() - 1) + num := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(b.header.Number.Uint64() - 1)) return &Block{ - backend: b.backend, - num: &num, - hash: b.header.ParentHash, - canonical: unknown, - }, nil - } - if b.num != nil && *b.num != 0 { - num := *b.num - 1 - return &Block{ - backend: b.backend, - num: &num, - canonical: isCanonical, + backend: b.backend, + numberOrHash: &num, + hash: b.header.ParentHash, }, nil } return nil, nil @@ -561,13 +522,11 @@ func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) { } ret := make([]*Block, 0, len(block.Uncles())) for _, uncle := range block.Uncles() { - blockNumber := rpc.BlockNumber(uncle.Number.Uint64()) + blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) ret = append(ret, &Block{ - backend: b.backend, - num: &blockNumber, - hash: uncle.Hash(), - header: uncle, - canonical: notCanonical, + backend: b.backend, + numberOrHash: &blockNumberOrHash, + header: uncle, }) } return &ret, nil @@ -603,16 +562,26 @@ func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) { // BlockNumberArgs encapsulates arguments to accessors that specify a block number. type BlockNumberArgs struct { + // TODO: Ideally we could use input unions to allow the query to specify the + // block parameter by hash, block number, or tag but input unions aren't part of the + // standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488 Block *hexutil.Uint64 } -// Number returns the provided block number, or rpc.LatestBlockNumber if none +// NumberOr returns the provided block number argument, or the "current" block number or hash if none // was provided. -func (a BlockNumberArgs) Number() rpc.BlockNumber { +func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { if a.Block != nil { - return rpc.BlockNumber(*a.Block) + blockNr := rpc.BlockNumber(*a.Block) + return rpc.BlockNumberOrHashWithNumber(blockNr) } - return rpc.LatestBlockNumber + return current +} + +// NumberOrLatest returns the provided block number argument, or the "latest" block number if none +// was provided. +func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash { + return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) } func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) { @@ -621,9 +590,9 @@ func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, erro return nil, err } return &Account{ - backend: b.backend, - address: header.Coinbase, - blockNumber: args.Number(), + backend: b.backend, + address: header.Coinbase, + blockNrOrHash: args.NumberOrLatest(), }, nil } @@ -683,13 +652,11 @@ func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block return nil, nil } uncle := uncles[args.Index] - blockNumber := rpc.BlockNumber(uncle.Number.Uint64()) + blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) return &Block{ - backend: b.backend, - num: &blockNumber, - hash: uncle.Hash(), - header: uncle, - canonical: notCanonical, + backend: b.backend, + numberOrHash: &blockNumberOrHash, + header: uncle, }, nil } @@ -757,20 +724,16 @@ func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteri func (b *Block) Account(ctx context.Context, args struct { Address common.Address }) (*Account, error) { - err := b.onMainChain(ctx) - if err != nil { - return nil, err - } - if b.num == nil { + if b.numberOrHash == nil { _, err := b.resolveHeader(ctx) if err != nil { return nil, err } } return &Account{ - backend: b.backend, - address: args.Address, - blockNumber: *b.num, + backend: b.backend, + address: args.Address, + blockNrOrHash: *b.numberOrHash, }, nil } @@ -807,17 +770,13 @@ func (c *CallResult) Status() hexutil.Uint64 { func (b *Block) Call(ctx context.Context, args struct { Data ethapi.CallArgs }) (*CallResult, error) { - err := b.onMainChain(ctx) - if err != nil { - return nil, err - } - if b.num == nil { - _, err := b.resolveHeader(ctx) + if b.numberOrHash == nil { + _, err := b.resolve(ctx) if err != nil { return nil, err } } - result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.num, nil, vm.Config{}, 5*time.Second, b.backend.RPCGasCap()) + result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, vm.Config{}, 5*time.Second, b.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 @@ -832,17 +791,13 @@ func (b *Block) Call(ctx context.Context, args struct { func (b *Block) EstimateGas(ctx context.Context, args struct { Data ethapi.CallArgs }) (hexutil.Uint64, error) { - err := b.onMainChain(ctx) - if err != nil { - return hexutil.Uint64(0), err - } - if b.num == nil { + if b.numberOrHash == nil { _, err := b.resolveHeader(ctx) if err != nil { return hexutil.Uint64(0), err } } - gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.num, b.backend.RPCGasCap()) + gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.numberOrHash, b.backend.RPCGasCap()) return gas, err } @@ -875,17 +830,19 @@ func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) { func (p *Pending) Account(ctx context.Context, args struct { Address common.Address }) *Account { + pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) return &Account{ - backend: p.backend, - address: args.Address, - blockNumber: rpc.PendingBlockNumber, + backend: p.backend, + address: args.Address, + blockNrOrHash: pendingBlockNr, } } func (p *Pending) Call(ctx context.Context, args struct { Data ethapi.CallArgs }) (*CallResult, error) { - result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, rpc.PendingBlockNumber, nil, vm.Config{}, 5*time.Second, p.backend.RPCGasCap()) + pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, vm.Config{}, 5*time.Second, p.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 @@ -900,7 +857,8 @@ func (p *Pending) Call(ctx context.Context, args struct { func (p *Pending) EstimateGas(ctx context.Context, args struct { Data ethapi.CallArgs }) (hexutil.Uint64, error) { - return ethapi.DoEstimateGas(ctx, p.backend, args.Data, rpc.PendingBlockNumber, p.backend.RPCGasCap()) + pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + return ethapi.DoEstimateGas(ctx, p.backend, args.Data, pendingBlockNr, p.backend.RPCGasCap()) } // Resolver is the top-level object in the GraphQL hierarchy. @@ -914,24 +872,23 @@ func (r *Resolver) Block(ctx context.Context, args struct { }) (*Block, error) { var block *Block if args.Number != nil { - num := rpc.BlockNumber(uint64(*args.Number)) + number := rpc.BlockNumber(uint64(*args.Number)) + numberOrHash := rpc.BlockNumberOrHashWithNumber(number) block = &Block{ - backend: r.backend, - num: &num, - canonical: isCanonical, + backend: r.backend, + numberOrHash: &numberOrHash, } } else if args.Hash != nil { + numberOrHash := rpc.BlockNumberOrHashWithHash(*args.Hash, false) block = &Block{ - backend: r.backend, - hash: *args.Hash, - canonical: unknown, + backend: r.backend, + numberOrHash: &numberOrHash, } } else { - num := rpc.LatestBlockNumber + numberOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) block = &Block{ - backend: r.backend, - num: &num, - canonical: isCanonical, + backend: r.backend, + numberOrHash: &numberOrHash, } } // Resolve the header, return nil if it doesn't exist. @@ -963,11 +920,10 @@ func (r *Resolver) Blocks(ctx context.Context, args struct { } ret := make([]*Block, 0, to-from+1) for i := from; i <= to; i++ { - num := i + numberOrHash := rpc.BlockNumberOrHashWithNumber(i) ret = append(ret, &Block{ - backend: r.backend, - num: &num, - canonical: isCanonical, + backend: r.backend, + numberOrHash: &numberOrHash, }) } return ret, nil diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go index 05204e5478..ea7bb7fc86 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go @@ -427,7 +427,7 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c log.Warn("Failed data sign attempt", "address", addr, "err", err) return nil, err } - signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper + signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper return signature, nil } @@ -442,13 +442,13 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { - if len(sig) != 65 { - return common.Address{}, fmt.Errorf("signature must be 65 bytes long") + if len(sig) != crypto.SignatureLength { + return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) } - if sig[64] != 27 && sig[64] != 28 { + if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") } - sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 + sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 rpk, err := crypto.SigToPub(accounts.TextHash(data), sig) if err != nil { @@ -530,8 +530,8 @@ func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 { // GetBalance returns the amount of wei for the given address in the state of the // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta // block numbers are also allowed. -func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Big, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) +func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) { + state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } @@ -555,8 +555,8 @@ type StorageResult struct { } // GetProof returns the Merkle-proof for a given account and optionally some storage keys. -func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNr rpc.BlockNumber) (*AccountResult, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) +func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { + state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } @@ -712,8 +712,8 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, bloc } // GetCode returns the code stored at the given address in the state for the given block number. -func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) +func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { + state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } @@ -724,8 +724,8 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres // GetStorageAt returns the storage from the state at the given address, key and // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block // numbers are also allowed. -func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) +func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { + state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } @@ -757,10 +757,10 @@ type account struct { StateDiff *map[common.Hash]common.Hash `json:"stateDiff"` } -func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, overrides map[common.Address]account, vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int) ([]byte, uint64, bool, error) { +func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides map[common.Address]account, vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int) ([]byte, uint64, bool, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) - state, header, err := b.StateAndHeaderByNumber(ctx, blockNr) + state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, 0, false, err } @@ -874,16 +874,16 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb // // Note, this function doesn't make and changes in the state/blockchain and is // useful to execute and retrieve values. -func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, overrides *map[common.Address]account) (hexutil.Bytes, error) { +func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *map[common.Address]account) (hexutil.Bytes, error) { var accounts map[common.Address]account if overrides != nil { accounts = *overrides } - result, _, _, err := DoCall(ctx, s.b, args, blockNr, accounts, vm.Config{}, 5*time.Second, s.b.RPCGasCap()) + result, _, _, err := DoCall(ctx, s.b, args, blockNrOrHash, accounts, vm.Config{}, 5*time.Second, s.b.RPCGasCap()) return (hexutil.Bytes)(result), err } -func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, gasCap *big.Int) (hexutil.Uint64, error) { +func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap *big.Int) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( lo uint64 = params.TxGas - 1 @@ -894,7 +894,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl hi = uint64(*args.Gas) } else { // Retrieve the block to act as the gas ceiling - block, err := b.BlockByNumber(ctx, blockNr) + block, err := b.BlockByNumberOrHash(ctx, blockNrOrHash) if err != nil { return 0, err } @@ -910,7 +910,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl executable := func(gas uint64) bool { args.Gas = (*hexutil.Uint64)(&gas) - _, _, failed, err := DoCall(ctx, b, args, rpc.PendingBlockNumber, nil, vm.Config{}, 0, gasCap) + _, _, failed, err := DoCall(ctx, b, args, blockNrOrHash, nil, vm.Config{}, 0, gasCap) if err != nil || failed { return false } @@ -937,7 +937,8 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl // EstimateGas returns an estimate of the amount of gas needed to execute the // given transaction against the current pending block. func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) { - return DoEstimateGas(ctx, s.b, args, rpc.PendingBlockNumber, s.b.RPCGasCap()) + blockNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + return DoEstimateGas(ctx, s.b, args, blockNrOrHash, s.b.RPCGasCap()) } // ExecutionResult groups all structured logs emitted by the EVM @@ -1224,9 +1225,9 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx cont } // GetTransactionCount returns the number of transactions the given address has sent for the given block number -func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) { +func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) { // Ask transaction pool for the nonce which includes pending transactions - if blockNr == rpc.PendingBlockNumber { + if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber { nonce, err := s.b.GetPoolNonce(ctx, address) if err != nil { return nil, err @@ -1234,7 +1235,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr return (*hexutil.Uint64)(&nonce), nil } // Resolve block number and use its state to ask for the nonce - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err } @@ -1405,7 +1406,8 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error { Value: args.Value, Data: input, } - estimated, err := DoEstimateGas(ctx, b, callArgs, rpc.PendingBlockNumber, b.RPCGasCap()) + pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, b.RPCGasCap()) if err != nil { return err } @@ -1479,6 +1481,22 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen return SubmitTransaction(ctx, s.b, signed) } +// FillTransaction fills the defaults (nonce, gas, gasPrice) on a given unsigned transaction, +// and returns it to the caller for further processing (signing + broadcast) +func (s *PublicTransactionPoolAPI) FillTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) { + // Set some sanity defaults and terminate on failure + if err := args.setDefaults(ctx, s.b); err != nil { + return nil, err + } + // Assemble the transaction and obtain rlp + tx := args.toTransaction() + data, err := rlp.EncodeToBytes(tx) + if err != nil { + return nil, err + } + return &SignTransactionResult{data, tx}, nil +} + // SendRawTransaction will add the signed transaction to the transaction pool. // The sender is responsible for signing the transaction and using the correct nonce. func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) { diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go index 06c6db33b1..73b6c89cea 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go @@ -52,9 +52,12 @@ type Backend interface { SetHead(number uint64) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) + HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) + StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(hash common.Hash) *big.Int GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) diff --git a/vendor/github.com/ethereum/go-ethereum/internal/web3ext/web3ext.go b/vendor/github.com/ethereum/go-ethereum/internal/web3ext/web3ext.go index 4a5d4b4ddb..86e5754392 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/web3ext/web3ext.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/web3ext/web3ext.go @@ -483,6 +483,12 @@ web3._extend({ params: 1, inputFormatter: [web3._extend.formatters.inputTransactionFormatter] }), + new web3._extend.Method({ + name: 'fillTransaction', + call: 'eth_fillTransaction', + params: 1, + inputFormatter: [web3._extend.formatters.inputTransactionFormatter] + }), new web3._extend.Method({ name: 'getHeaderByNumber', call: 'eth_getHeaderByNumber', diff --git a/vendor/github.com/ethereum/go-ethereum/les/api.go b/vendor/github.com/ethereum/go-ethereum/les/api.go index e20f72cad0..bbef771f04 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/api.go +++ b/vendor/github.com/ethereum/go-ethereum/les/api.go @@ -30,15 +30,11 @@ var ( // PrivateLightAPI provides an API to access the LES light server or light client. type PrivateLightAPI struct { backend *lesCommons - reg *checkpointOracle } // NewPrivateLightAPI creates a new LES service API. -func NewPrivateLightAPI(backend *lesCommons, reg *checkpointOracle) *PrivateLightAPI { - return &PrivateLightAPI{ - backend: backend, - reg: reg, - } +func NewPrivateLightAPI(backend *lesCommons) *PrivateLightAPI { + return &PrivateLightAPI{backend: backend} } // LatestCheckpoint returns the latest local checkpoint package. @@ -67,7 +63,7 @@ func (api *PrivateLightAPI) LatestCheckpoint() ([4]string, error) { // result[2], 32 bytes hex encoded latest section bloom trie root hash func (api *PrivateLightAPI) GetCheckpoint(index uint64) ([3]string, error) { var res [3]string - cp := api.backend.getLocalCheckpoint(index) + cp := api.backend.localCheckpoint(index) if cp.Empty() { return res, errNoCheckpoint } @@ -77,8 +73,8 @@ func (api *PrivateLightAPI) GetCheckpoint(index uint64) ([3]string, error) { // GetCheckpointContractAddress returns the contract contract address in hex format. func (api *PrivateLightAPI) GetCheckpointContractAddress() (string, error) { - if api.reg == nil { + if api.backend.oracle == nil { return "", errNotActivated } - return api.reg.config.Address.Hex(), nil + return api.backend.oracle.config.Address.Hex(), nil } diff --git a/vendor/github.com/ethereum/go-ethereum/les/api_backend.go b/vendor/github.com/ethereum/go-ethereum/les/api_backend.go index 07601c2423..e01e1be98b 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/api_backend.go +++ b/vendor/github.com/ethereum/go-ethereum/les/api_backend.go @@ -54,7 +54,7 @@ func (b *LesApiBackend) CurrentBlock() *types.Block { } func (b *LesApiBackend) SetHead(number uint64) { - b.eth.protocolManager.downloader.Cancel() + b.eth.handler.downloader.Cancel() b.eth.blockchain.SetHead(number) } @@ -65,6 +65,26 @@ func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(number)) } +func (b *LesApiBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.HeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header, err := b.HeaderByHash(ctx, hash) + if err != nil { + return nil, err + } + if header == nil { + return nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + return header, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { return b.eth.blockchain.GetHeaderByHash(hash), nil } @@ -81,6 +101,26 @@ func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ return b.eth.blockchain.GetBlockByHash(ctx, hash) } +func (b *LesApiBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.BlockByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + block, err := b.BlockByHash(ctx, hash) + if err != nil { + return nil, err + } + if block == nil { + return nil, errors.New("header found, but block body is missing") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(block.NumberU64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + return block, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { header, err := b.HeaderByNumber(ctx, number) if err != nil { @@ -92,6 +132,23 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B return light.NewState(ctx, header, b.eth.odr), header, nil } +func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.StateAndHeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header := b.eth.blockchain.GetHeaderByHash(hash) + if header == nil { + return nil, nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, nil, errors.New("hash is not currently canonical") + } + return light.NewState(ctx, header, b.eth.odr), header, nil + } + return nil, nil, errors.New("invalid arguments; neither block nor hash specified") +} + func (b *LesApiBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil { return light.GetBlockReceipts(ctx, b.eth.odr, hash, *number) diff --git a/vendor/github.com/ethereum/go-ethereum/les/balance.go b/vendor/github.com/ethereum/go-ethereum/les/balance.go index 4f08a304eb..2813db01c5 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/balance.go +++ b/vendor/github.com/ethereum/go-ethereum/les/balance.go @@ -42,7 +42,7 @@ type balanceTracker struct { negTimeFactor, negRequestFactor float64 sumReqCost uint64 lastUpdate, nextUpdate, initTime mclock.AbsTime - updateEvent mclock.Event + updateEvent mclock.Timer // since only a limited and fixed number of callbacks are needed, they are // stored in a fixed size array ordered by priority threshold. callbacks [balanceCallbackCount]balanceCallback @@ -67,7 +67,7 @@ type balanceCallback struct { // init initializes balanceTracker func (bt *balanceTracker) init(clock mclock.Clock, capacity uint64) { bt.clock = clock - bt.initTime = clock.Now() + bt.initTime, bt.lastUpdate = clock.Now(), clock.Now() // Init timestamps for i := range bt.callbackIndex { bt.callbackIndex[i] = -1 } @@ -86,7 +86,7 @@ func (bt *balanceTracker) stop(now mclock.AbsTime) { bt.timeFactor = 0 bt.requestFactor = 0 if bt.updateEvent != nil { - bt.updateEvent.Cancel() + bt.updateEvent.Stop() bt.updateEvent = nil } } @@ -235,7 +235,7 @@ func (bt *balanceTracker) checkCallbacks(now mclock.AbsTime) { // updateAfter schedules a balance update and callback check in the future func (bt *balanceTracker) updateAfter(dt time.Duration) { - if bt.updateEvent == nil || bt.updateEvent.Cancel() { + if bt.updateEvent == nil || bt.updateEvent.Stop() { if dt == 0 { bt.updateEvent = nil } else { diff --git a/vendor/github.com/ethereum/go-ethereum/les/benchmark.go b/vendor/github.com/ethereum/go-ethereum/les/benchmark.go index 74dfcf7c9e..42eeef10f3 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/benchmark.go +++ b/vendor/github.com/ethereum/go-ethereum/les/benchmark.go @@ -21,6 +21,7 @@ import ( "fmt" "math/big" "math/rand" + "sync" "time" "github.com/ethereum/go-ethereum/common" @@ -39,7 +40,7 @@ import ( // requestBenchmark is an interface for different randomized request generators type requestBenchmark interface { // init initializes the generator for generating the given number of randomized requests - init(pm *ProtocolManager, count int) error + init(h *serverHandler, count int) error // request initiates sending a single request to the given peer request(peer *peer, index int) error } @@ -52,10 +53,10 @@ type benchmarkBlockHeaders struct { hashes []common.Hash } -func (b *benchmarkBlockHeaders) init(pm *ProtocolManager, count int) error { +func (b *benchmarkBlockHeaders) init(h *serverHandler, count int) error { d := int64(b.amount-1) * int64(b.skip+1) b.offset = 0 - b.randMax = pm.blockchain.CurrentHeader().Number.Int64() + 1 - d + b.randMax = h.blockchain.CurrentHeader().Number.Int64() + 1 - d if b.randMax < 0 { return fmt.Errorf("chain is too short") } @@ -65,7 +66,7 @@ func (b *benchmarkBlockHeaders) init(pm *ProtocolManager, count int) error { if b.byHash { b.hashes = make([]common.Hash, count) for i := range b.hashes { - b.hashes[i] = rawdb.ReadCanonicalHash(pm.chainDb, uint64(b.offset+rand.Int63n(b.randMax))) + b.hashes[i] = rawdb.ReadCanonicalHash(h.chainDb, uint64(b.offset+rand.Int63n(b.randMax))) } } return nil @@ -85,11 +86,11 @@ type benchmarkBodiesOrReceipts struct { hashes []common.Hash } -func (b *benchmarkBodiesOrReceipts) init(pm *ProtocolManager, count int) error { - randMax := pm.blockchain.CurrentHeader().Number.Int64() + 1 +func (b *benchmarkBodiesOrReceipts) init(h *serverHandler, count int) error { + randMax := h.blockchain.CurrentHeader().Number.Int64() + 1 b.hashes = make([]common.Hash, count) for i := range b.hashes { - b.hashes[i] = rawdb.ReadCanonicalHash(pm.chainDb, uint64(rand.Int63n(randMax))) + b.hashes[i] = rawdb.ReadCanonicalHash(h.chainDb, uint64(rand.Int63n(randMax))) } return nil } @@ -108,8 +109,8 @@ type benchmarkProofsOrCode struct { headHash common.Hash } -func (b *benchmarkProofsOrCode) init(pm *ProtocolManager, count int) error { - b.headHash = pm.blockchain.CurrentHeader().Hash() +func (b *benchmarkProofsOrCode) init(h *serverHandler, count int) error { + b.headHash = h.blockchain.CurrentHeader().Hash() return nil } @@ -130,11 +131,11 @@ type benchmarkHelperTrie struct { sectionCount, headNum uint64 } -func (b *benchmarkHelperTrie) init(pm *ProtocolManager, count int) error { +func (b *benchmarkHelperTrie) init(h *serverHandler, count int) error { if b.bloom { - b.sectionCount, b.headNum, _ = pm.server.bloomTrieIndexer.Sections() + b.sectionCount, b.headNum, _ = h.server.bloomTrieIndexer.Sections() } else { - b.sectionCount, _, _ = pm.server.chtIndexer.Sections() + b.sectionCount, _, _ = h.server.chtIndexer.Sections() b.headNum = b.sectionCount*params.CHTFrequency - 1 } if b.sectionCount == 0 { @@ -170,7 +171,7 @@ type benchmarkTxSend struct { txs types.Transactions } -func (b *benchmarkTxSend) init(pm *ProtocolManager, count int) error { +func (b *benchmarkTxSend) init(h *serverHandler, count int) error { key, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(key.PublicKey) signer := types.NewEIP155Signer(big.NewInt(18)) @@ -196,7 +197,7 @@ func (b *benchmarkTxSend) request(peer *peer, index int) error { // benchmarkTxStatus implements requestBenchmark type benchmarkTxStatus struct{} -func (b *benchmarkTxStatus) init(pm *ProtocolManager, count int) error { +func (b *benchmarkTxStatus) init(h *serverHandler, count int) error { return nil } @@ -217,7 +218,7 @@ type benchmarkSetup struct { // runBenchmark runs a benchmark cycle for all benchmark types in the specified // number of passes -func (pm *ProtocolManager) runBenchmark(benchmarks []requestBenchmark, passCount int, targetTime time.Duration) []*benchmarkSetup { +func (h *serverHandler) runBenchmark(benchmarks []requestBenchmark, passCount int, targetTime time.Duration) []*benchmarkSetup { setup := make([]*benchmarkSetup, len(benchmarks)) for i, b := range benchmarks { setup[i] = &benchmarkSetup{req: b} @@ -239,7 +240,7 @@ func (pm *ProtocolManager) runBenchmark(benchmarks []requestBenchmark, passCount if next.totalTime > 0 { count = int(uint64(next.totalCount) * uint64(targetTime) / uint64(next.totalTime)) } - if err := pm.measure(next, count); err != nil { + if err := h.measure(next, count); err != nil { next.err = err } } @@ -275,14 +276,15 @@ func (m *meteredPipe) WriteMsg(msg p2p.Msg) error { // measure runs a benchmark for a single type in a single pass, with the given // number of requests -func (pm *ProtocolManager) measure(setup *benchmarkSetup, count int) error { +func (h *serverHandler) measure(setup *benchmarkSetup, count int) error { clientPipe, serverPipe := p2p.MsgPipe() clientMeteredPipe := &meteredPipe{rw: clientPipe} serverMeteredPipe := &meteredPipe{rw: serverPipe} var id enode.ID rand.Read(id[:]) - clientPeer := pm.newPeer(lpv2, NetworkId, p2p.NewPeer(id, "client", nil), clientMeteredPipe) - serverPeer := pm.newPeer(lpv2, NetworkId, p2p.NewPeer(id, "server", nil), serverMeteredPipe) + + clientPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe) + serverPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "server", nil), serverMeteredPipe) serverPeer.sendQueue = newExecQueue(count) serverPeer.announceType = announceTypeNone serverPeer.fcCosts = make(requestCostTable) @@ -291,10 +293,10 @@ func (pm *ProtocolManager) measure(setup *benchmarkSetup, count int) error { serverPeer.fcCosts[code] = c } serverPeer.fcParams = flowcontrol.ServerParams{BufLimit: 1, MinRecharge: 1} - serverPeer.fcClient = flowcontrol.NewClientNode(pm.server.fcManager, serverPeer.fcParams) + serverPeer.fcClient = flowcontrol.NewClientNode(h.server.fcManager, serverPeer.fcParams) defer serverPeer.fcClient.Disconnect() - if err := setup.req.init(pm, count); err != nil { + if err := setup.req.init(h, count); err != nil { return err } @@ -311,7 +313,7 @@ func (pm *ProtocolManager) measure(setup *benchmarkSetup, count int) error { }() go func() { for i := 0; i < count; i++ { - if err := pm.handleMsg(serverPeer); err != nil { + if err := h.handleMsg(serverPeer, &sync.WaitGroup{}); err != nil { errCh <- err return } @@ -336,7 +338,7 @@ func (pm *ProtocolManager) measure(setup *benchmarkSetup, count int) error { if err != nil { return err } - case <-pm.quitSync: + case <-h.closeCh: clientPipe.Close() serverPipe.Close() return fmt.Errorf("Benchmark cancelled") diff --git a/vendor/github.com/ethereum/go-ethereum/les/bloombits.go b/vendor/github.com/ethereum/go-ethereum/les/bloombits.go index aea0fcd5f4..a98524ce2e 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/bloombits.go +++ b/vendor/github.com/ethereum/go-ethereum/les/bloombits.go @@ -46,9 +46,10 @@ const ( func (eth *LightEthereum) startBloomHandlers(sectionSize uint64) { for i := 0; i < bloomServiceThreads; i++ { go func() { + defer eth.wg.Done() for { select { - case <-eth.shutdownChan: + case <-eth.closeCh: return case request := <-eth.bloomRequests: diff --git a/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go b/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go index 4695fbc16c..5494e3d6d9 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go +++ b/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go @@ -35,11 +35,8 @@ type checkpointOracle struct { config *params.CheckpointOracleConfig contract *checkpointoracle.CheckpointOracle - // Whether the contract backend is set. - running int32 - - getLocal func(uint64) params.TrustedCheckpoint // Function used to retrieve local checkpoint - syncDoneHook func() // Function used to notify that light syncing has completed. + running int32 // Flag whether the contract backend is set or not + getLocal func(uint64) params.TrustedCheckpoint // Function used to retrieve local checkpoint } // newCheckpointOracle returns a checkpoint registrar handler. diff --git a/vendor/github.com/ethereum/go-ethereum/les/backend.go b/vendor/github.com/ethereum/go-ethereum/les/client.go similarity index 78% rename from vendor/github.com/ethereum/go-ethereum/les/backend.go rename to vendor/github.com/ethereum/go-ethereum/les/client.go index c067afaea6..b367681f37 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/les/client.go @@ -19,8 +19,6 @@ package les import ( "fmt" - "sync" - "time" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -42,7 +40,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/discv5" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) @@ -50,33 +48,23 @@ import ( type LightEthereum struct { lesCommons - odr *LesOdr - chainConfig *params.ChainConfig - // Channel for shutting down the service - shutdownChan chan bool - - // Handlers - peers *peerSet - txPool *light.TxPool - blockchain *light.LightChain - serverPool *serverPool reqDist *requestDistributor retriever *retrieveManager + odr *LesOdr relay *lesTxRelay + handler *clientHandler + txPool *light.TxPool + blockchain *light.LightChain + serverPool *serverPool bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests - bloomIndexer *core.ChainIndexer - - ApiBackend *LesApiBackend + bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports + ApiBackend *LesApiBackend eventMux *event.TypeMux engine consensus.Engine accountManager *accounts.Manager - - networkId uint64 - netRPCService *ethapi.PublicNetAPI - - wg sync.WaitGroup + netRPCService *ethapi.PublicNetAPI } func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { @@ -84,33 +72,31 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideIstanbul) if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { return nil, genesisErr } log.Info("Initialised chain configuration", "config", chainConfig) peers := newPeerSet() - quitSync := make(chan struct{}) - leth := &LightEthereum{ lesCommons: lesCommons{ - chainDb: chainDb, - config: config, - iConfig: light.DefaultClientIndexerConfig, + genesis: genesisHash, + config: config, + chainConfig: chainConfig, + iConfig: light.DefaultClientIndexerConfig, + chainDb: chainDb, + peers: peers, + closeCh: make(chan struct{}), }, - chainConfig: chainConfig, eventMux: ctx.EventMux, - peers: peers, - reqDist: newRequestDistributor(peers, quitSync, &mclock.System{}), + reqDist: newRequestDistributor(peers, &mclock.System{}), accountManager: ctx.AccountManager, engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb), - shutdownChan: make(chan bool), - networkId: config.NetworkId, bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), + serverPool: newServerPool(chainDb, config.UltraLightServers), } - leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg, leth.config.UltraLightServers) leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool) leth.relay = newLesTxRelay(peers, leth.retriever) @@ -128,11 +114,26 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, checkpoint); err != nil { return nil, err } + leth.chainReader = leth.blockchain + leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) + + // Set up checkpoint oracle. + oracle := config.CheckpointOracle + if oracle == nil { + oracle = params.CheckpointOracles[genesisHash] + } + leth.oracle = newCheckpointOracle(oracle, leth.localCheckpoint) + // Note: AddChildIndexer starts the update process for the child leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) leth.chtIndexer.Start(leth.blockchain) leth.bloomIndexer.Start(leth.blockchain) + leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, checkpoint, leth) + if leth.handler.ulc != nil { + log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.handler.ulc.keys), "minTrustedFraction", leth.handler.ulc.fraction) + leth.blockchain.DisableCheckFreq() + } // Rewind the chain in case of an incompatible config upgrade. if compat, ok := genesisErr.(*params.ConfigCompatError); ok { log.Warn("Rewinding chain to upgrade configuration", "err", compat) @@ -140,41 +141,16 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) } - leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) leth.ApiBackend = &LesApiBackend{ctx.ExtRPCEnabled(), leth, nil} - gpoParams := config.GPO if gpoParams.Default == nil { gpoParams.Default = config.Miner.GasPrice } leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) - oracle := config.CheckpointOracle - if oracle == nil { - oracle = params.CheckpointOracles[genesisHash] - } - registrar := newCheckpointOracle(oracle, leth.getLocalCheckpoint) - if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, checkpoint, light.DefaultClientIndexerConfig, config.UltraLightServers, config.UltraLightFraction, true, config.NetworkId, leth.eventMux, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.serverPool, registrar, quitSync, &leth.wg, nil); err != nil { - return nil, err - } - if leth.protocolManager.ulc != nil { - log.Warn("Ultra light client is enabled", "servers", len(config.UltraLightServers), "fraction", config.UltraLightFraction) - leth.blockchain.DisableCheckFreq() - } return leth, nil } -func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { - var name string - switch protocolVersion { - case lpv2: - name = "LES2" - default: - panic(nil) - } - return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) -} - type LightDummyAPI struct{} // Etherbase is the address that mining rewards will be send to @@ -209,7 +185,7 @@ func (s *LightEthereum) APIs() []rpc.API { }, { Namespace: "eth", Version: "1.0", - Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), + Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), Public: true, }, { Namespace: "eth", @@ -224,7 +200,7 @@ func (s *LightEthereum) APIs() []rpc.API { }, { Namespace: "les", Version: "1.0", - Service: NewPrivateLightAPI(&s.lesCommons, s.protocolManager.reg), + Service: NewPrivateLightAPI(&s.lesCommons), Public: false, }, }...) @@ -238,54 +214,63 @@ func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchai func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool } func (s *LightEthereum) Engine() consensus.Engine { return s.engine } func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) } -func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } +func (s *LightEthereum) Downloader() *downloader.Downloader { return s.handler.downloader } func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux } // Protocols implements node.Service, returning all the currently configured // network protocols to start. func (s *LightEthereum) Protocols() []p2p.Protocol { - return s.makeProtocols(ClientProtocolVersions) + return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { + if p := s.peers.Peer(peerIdToString(id)); p != nil { + return p.Info() + } + return nil + }) } // Start implements node.Service, starting all internal goroutines needed by the -// Ethereum protocol implementation. +// light ethereum protocol implementation. func (s *LightEthereum) Start(srvr *p2p.Server) error { log.Warn("Light client mode is an experimental feature") + + // Start bloom request workers. + s.wg.Add(bloomServiceThreads) s.startBloomHandlers(params.BloomBitsBlocksClient) - s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId) + + s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.config.NetworkId) + // clients are searching for the first advertised protocol in the list protocolVersion := AdvertiseProtocolVersions[0] s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion)) - s.protocolManager.Start(s.config.LightPeers) return nil } // Stop implements node.Service, terminating all internal goroutines used by the // Ethereum protocol. func (s *LightEthereum) Stop() error { + close(s.closeCh) + s.peers.Close() + s.reqDist.close() s.odr.Stop() s.relay.Stop() s.bloomIndexer.Close() s.chtIndexer.Close() s.blockchain.Stop() - s.protocolManager.Stop() + s.handler.stop() s.txPool.Stop() s.engine.Close() - s.eventMux.Stop() - - time.Sleep(time.Millisecond * 200) + s.serverPool.stop() s.chainDb.Close() - close(s.shutdownChan) - + s.wg.Wait() + log.Info("Light ethereum stopped") return nil } // SetClient sets the rpc client and binds the registrar contract. func (s *LightEthereum) SetContractBackend(backend bind.ContractBackend) { - // Short circuit if registrar is nil - if s.protocolManager.reg == nil { + if s.oracle == nil { return } - s.protocolManager.reg.start(backend) + s.oracle.start(backend) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/client_handler.go b/vendor/github.com/ethereum/go-ethereum/les/client_handler.go new file mode 100644 index 0000000000..7fdb165719 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/client_handler.go @@ -0,0 +1,403 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package les + +import ( + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/params" +) + +// clientHandler is responsible for receiving and processing all incoming server +// responses. +type clientHandler struct { + ulc *ulc + checkpoint *params.TrustedCheckpoint + fetcher *lightFetcher + downloader *downloader.Downloader + backend *LightEthereum + + closeCh chan struct{} + wg sync.WaitGroup // WaitGroup used to track all connected peers. + syncDone func() // Test hooks when syncing is done. +} + +func newClientHandler(ulcServers []string, ulcFraction int, checkpoint *params.TrustedCheckpoint, backend *LightEthereum) *clientHandler { + handler := &clientHandler{ + checkpoint: checkpoint, + backend: backend, + closeCh: make(chan struct{}), + } + if ulcServers != nil { + ulc, err := newULC(ulcServers, ulcFraction) + if err != nil { + log.Error("Failed to initialize ultra light client") + } + handler.ulc = ulc + log.Info("Enable ultra light client mode") + } + var height uint64 + if checkpoint != nil { + height = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 + } + handler.fetcher = newLightFetcher(handler) + handler.downloader = downloader.New(height, backend.chainDb, nil, backend.eventMux, nil, backend.blockchain, handler.removePeer) + handler.backend.peers.notify((*downloaderPeerNotify)(handler)) + return handler +} + +func (h *clientHandler) stop() { + close(h.closeCh) + h.downloader.Terminate() + h.fetcher.close() + h.wg.Wait() +} + +// runPeer is the p2p protocol run function for the given version. +func (h *clientHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { + trusted := false + if h.ulc != nil { + trusted = h.ulc.trusted(p.ID()) + } + peer := newPeer(int(version), h.backend.config.NetworkId, trusted, p, newMeteredMsgWriter(rw, int(version))) + peer.poolEntry = h.backend.serverPool.connect(peer, peer.Node()) + if peer.poolEntry == nil { + return p2p.DiscRequested + } + h.wg.Add(1) + defer h.wg.Done() + err := h.handle(peer) + h.backend.serverPool.disconnect(peer.poolEntry) + return err +} + +func (h *clientHandler) handle(p *peer) error { + if h.backend.peers.Len() >= h.backend.config.LightPeers && !p.Peer.Info().Network.Trusted { + return p2p.DiscTooManyPeers + } + p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) + + // Execute the LES handshake + var ( + head = h.backend.blockchain.CurrentHeader() + hash = head.Hash() + number = head.Number.Uint64() + td = h.backend.blockchain.GetTd(hash, number) + ) + if err := p.Handshake(td, hash, number, h.backend.blockchain.Genesis().Hash(), nil); err != nil { + p.Log().Debug("Light Ethereum handshake failed", "err", err) + return err + } + // Register the peer locally + if err := h.backend.peers.Register(p); err != nil { + p.Log().Error("Light Ethereum peer registration failed", "err", err) + return err + } + serverConnectionGauge.Update(int64(h.backend.peers.Len())) + + connectedAt := mclock.Now() + defer func() { + h.backend.peers.Unregister(p.id) + connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) + serverConnectionGauge.Update(int64(h.backend.peers.Len())) + }() + + h.fetcher.announce(p, p.headInfo) + + // pool entry can be nil during the unit test. + if p.poolEntry != nil { + h.backend.serverPool.registered(p.poolEntry) + } + // Spawn a main loop to handle all incoming messages. + for { + if err := h.handleMsg(p); err != nil { + p.Log().Debug("Light Ethereum message handling failed", "err", err) + p.fcServer.DumpLogs() + return err + } + } +} + +// handleMsg is invoked whenever an inbound message is received from a remote +// peer. The remote connection is torn down upon returning any error. +func (h *clientHandler) handleMsg(p *peer) error { + // Read the next message from the remote peer, and ensure it's fully consumed + msg, err := p.rw.ReadMsg() + if err != nil { + return err + } + p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) + + if msg.Size > ProtocolMaxMsgSize { + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + } + defer msg.Discard() + + var deliverMsg *Msg + + // Handle the message depending on its contents + switch msg.Code { + case AnnounceMsg: + p.Log().Trace("Received announce message") + var req announceData + if err := msg.Decode(&req); err != nil { + return errResp(ErrDecode, "%v: %v", msg, err) + } + if err := req.sanityCheck(); err != nil { + return err + } + update, size := req.Update.decode() + if p.rejectUpdate(size) { + return errResp(ErrRequestRejected, "") + } + p.updateFlowControl(update) + + if req.Hash != (common.Hash{}) { + if p.announceType == announceTypeNone { + return errResp(ErrUnexpectedResponse, "") + } + if p.announceType == announceTypeSigned { + if err := req.checkSignature(p.ID(), update); err != nil { + p.Log().Trace("Invalid announcement signature", "err", err) + return err + } + p.Log().Trace("Valid announcement signature") + } + p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) + h.fetcher.announce(p, &req) + } + case BlockHeadersMsg: + p.Log().Trace("Received block header response message") + var resp struct { + ReqID, BV uint64 + Headers []*types.Header + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + if h.fetcher.requestedID(resp.ReqID) { + h.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) + } else { + if err := h.downloader.DeliverHeaders(p.id, resp.Headers); err != nil { + log.Debug("Failed to deliver headers", "err", err) + } + } + case BlockBodiesMsg: + p.Log().Trace("Received block bodies response") + var resp struct { + ReqID, BV uint64 + Data []*types.Body + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgBlockBodies, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case CodeMsg: + p.Log().Trace("Received code response") + var resp struct { + ReqID, BV uint64 + Data [][]byte + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgCode, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case ReceiptsMsg: + p.Log().Trace("Received receipts response") + var resp struct { + ReqID, BV uint64 + Receipts []types.Receipts + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgReceipts, + ReqID: resp.ReqID, + Obj: resp.Receipts, + } + case ProofsV2Msg: + p.Log().Trace("Received les/2 proofs response") + var resp struct { + ReqID, BV uint64 + Data light.NodeList + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgProofsV2, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case HelperTrieProofsMsg: + p.Log().Trace("Received helper trie proof response") + var resp struct { + ReqID, BV uint64 + Data HelperTrieResps + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgHelperTrieProofs, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case TxStatusMsg: + p.Log().Trace("Received tx status response") + var resp struct { + ReqID, BV uint64 + Status []light.TxStatus + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgTxStatus, + ReqID: resp.ReqID, + Obj: resp.Status, + } + case StopMsg: + p.freezeServer(true) + h.backend.retriever.frozen(p) + p.Log().Debug("Service stopped") + case ResumeMsg: + var bv uint64 + if err := msg.Decode(&bv); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ResumeFreeze(bv) + p.freezeServer(false) + p.Log().Debug("Service resumed") + default: + p.Log().Trace("Received invalid message", "code", msg.Code) + return errResp(ErrInvalidMsgCode, "%v", msg.Code) + } + // Deliver the received response to retriever. + if deliverMsg != nil { + if err := h.backend.retriever.deliver(p, deliverMsg); err != nil { + p.responseErrors++ + if p.responseErrors > maxResponseErrors { + return err + } + } + } + return nil +} + +func (h *clientHandler) removePeer(id string) { + h.backend.peers.Unregister(id) +} + +type peerConnection struct { + handler *clientHandler + peer *peer +} + +func (pc *peerConnection) Head() (common.Hash, *big.Int) { + return pc.peer.HeadAndTd() +} + +func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { + rq := &distReq{ + getCost: func(dp distPeer) uint64 { + peer := dp.(*peer) + return peer.GetRequestCost(GetBlockHeadersMsg, amount) + }, + canSend: func(dp distPeer) bool { + return dp.(*peer) == pc.peer + }, + request: func(dp distPeer) func() { + reqID := genReqID() + peer := dp.(*peer) + cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) + peer.fcServer.QueuedRequest(reqID, cost) + return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } + }, + } + _, ok := <-pc.handler.backend.reqDist.queue(rq) + if !ok { + return light.ErrNoPeers + } + return nil +} + +func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { + rq := &distReq{ + getCost: func(dp distPeer) uint64 { + peer := dp.(*peer) + return peer.GetRequestCost(GetBlockHeadersMsg, amount) + }, + canSend: func(dp distPeer) bool { + return dp.(*peer) == pc.peer + }, + request: func(dp distPeer) func() { + reqID := genReqID() + peer := dp.(*peer) + cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) + peer.fcServer.QueuedRequest(reqID, cost) + return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } + }, + } + _, ok := <-pc.handler.backend.reqDist.queue(rq) + if !ok { + return light.ErrNoPeers + } + return nil +} + +// downloaderPeerNotify implements peerSetNotify +type downloaderPeerNotify clientHandler + +func (d *downloaderPeerNotify) registerPeer(p *peer) { + h := (*clientHandler)(d) + pc := &peerConnection{ + handler: h, + peer: p, + } + h.downloader.RegisterLightPeer(p.id, ethVersion, pc) +} + +func (d *downloaderPeerNotify) unregisterPeer(p *peer) { + h := (*clientHandler)(d) + h.downloader.UnregisterPeer(p.id) +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/clientpool.go b/vendor/github.com/ethereum/go-ethereum/les/clientpool.go index 4ee2fd5da6..0b4d1b9612 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/clientpool.go +++ b/vendor/github.com/ethereum/go-ethereum/les/clientpool.go @@ -17,67 +17,81 @@ package les import ( + "encoding/binary" "io" "math" "sync" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rlp" + "github.com/hashicorp/golang-lru" ) const ( - negBalanceExpTC = time.Hour // time constant for exponentially reducing negative balance - fixedPointMultiplier = 0x1000000 // constant to convert logarithms to fixed point format - connectedBias = time.Minute // this bias is applied in favor of already connected clients in order to avoid kicking them out very soon - lazyQueueRefresh = time.Second * 10 // refresh period of the connected queue -) - -var ( - clientPoolDbKey = []byte("clientPool") - clientBalanceDbKey = []byte("clientPool-balance") + negBalanceExpTC = time.Hour // time constant for exponentially reducing negative balance + fixedPointMultiplier = 0x1000000 // constant to convert logarithms to fixed point format + lazyQueueRefresh = time.Second * 10 // refresh period of the connected queue + persistCumulativeTimeRefresh = time.Minute * 5 // refresh period of the cumulative running time persistence + posBalanceCacheLimit = 8192 // the maximum number of cached items in positive balance queue + negBalanceCacheLimit = 8192 // the maximum number of cached items in negative balance queue + + // connectedBias is applied to already connected clients So that + // already connected client won't be kicked out very soon and we + // can ensure all connected clients can have enough time to request + // or sync some data. + // + // todo(rjl493456442) make it configurable. It can be the option of + // free trial time! + connectedBias = time.Minute * 3 ) // clientPool implements a client database that assigns a priority to each client // based on a positive and negative balance. Positive balance is externally assigned // to prioritized clients and is decreased with connection time and processed // requests (unless the price factors are zero). If the positive balance is zero -// then negative balance is accumulated. Balance tracking and priority calculation -// for connected clients is done by balanceTracker. connectedQueue ensures that -// clients with the lowest positive or highest negative balance get evicted when -// the total capacity allowance is full and new clients with a better balance want -// to connect. Already connected nodes receive a small bias in their favor in order -// to avoid accepting and instantly kicking out clients. -// Balances of disconnected clients are stored in posBalanceQueue and negBalanceQueue -// and are also saved in the database. Negative balance is transformed into a -// logarithmic form with a constantly shifting linear offset in order to implement -// an exponential decrease. negBalanceQueue has a limited size and drops the smallest -// values when necessary. Positive balances are stored in the database as long as -// they exist, posBalanceQueue only acts as a cache for recently accessed entries. +// then negative balance is accumulated. +// +// Balance tracking and priority calculation for connected clients is done by +// balanceTracker. connectedQueue ensures that clients with the lowest positive or +// highest negative balance get evicted when the total capacity allowance is full +// and new clients with a better balance want to connect. +// +// Already connected nodes receive a small bias in their favor in order to avoid +// accepting and instantly kicking out clients. In theory, we try to ensure that +// each client can have several minutes of connection time. +// +// Balances of disconnected clients are stored in nodeDB including positive balance +// and negative banalce. Negative balance is transformed into a logarithmic form +// with a constantly shifting linear offset in order to implement an exponential +// decrease. Besides nodeDB will have a background thread to check the negative +// balance of disconnected client. If the balance is low enough, then the record +// will be dropped. type clientPool struct { - db ethdb.Database + ndb *nodeDB lock sync.Mutex clock mclock.Clock - stopCh chan chan struct{} + stopCh chan struct{} closed bool removePeer func(enode.ID) - queueLimit, countLimit int - freeClientCap, capacityLimit, connectedCapacity uint64 + connectedMap map[enode.ID]*clientInfo + connectedQueue *prque.LazyQueue + + posFactors, negFactors priceFactors - connectedMap map[enode.ID]*clientInfo - posBalanceMap map[enode.ID]*posBalance - negBalanceMap map[string]*negBalance - connectedQueue *prque.LazyQueue - posBalanceQueue, negBalanceQueue *prque.Prque - posFactors, negFactors priceFactors - posBalanceAccessCounter int64 - startupTime mclock.AbsTime - logOffsetAtStartup int64 + connLimit int // The maximum number of connections that clientpool can support + capLimit uint64 // The maximum cumulative capacity that clientpool can support + connectedCap uint64 // The sum of the capacity of the current clientpool connected + freeClientCap uint64 // The capacity value of each free client + startTime mclock.AbsTime // The timestamp at which the clientpool started running + cumulativeTime int64 // The cumulative running time of clientpool at the start point. + disableBias bool // Disable connection bias(used in testing) } // clientPeer represents a client in the pool. @@ -138,22 +152,25 @@ type priceFactors struct { } // newClientPool creates a new client pool -func newClientPool(db ethdb.Database, freeClientCap uint64, queueLimit int, clock mclock.Clock, removePeer func(enode.ID)) *clientPool { +func newClientPool(db ethdb.Database, freeClientCap uint64, clock mclock.Clock, removePeer func(enode.ID)) *clientPool { + ndb := newNodeDB(db, clock) pool := &clientPool{ - db: db, - clock: clock, - connectedMap: make(map[enode.ID]*clientInfo), - posBalanceMap: make(map[enode.ID]*posBalance), - negBalanceMap: make(map[string]*negBalance), - connectedQueue: prque.NewLazyQueue(connSetIndex, connPriority, connMaxPriority, clock, lazyQueueRefresh), - negBalanceQueue: prque.New(negSetIndex), - posBalanceQueue: prque.New(posSetIndex), - freeClientCap: freeClientCap, - queueLimit: queueLimit, - removePeer: removePeer, - stopCh: make(chan chan struct{}), - } - pool.loadFromDb() + ndb: ndb, + clock: clock, + connectedMap: make(map[enode.ID]*clientInfo), + connectedQueue: prque.NewLazyQueue(connSetIndex, connPriority, connMaxPriority, clock, lazyQueueRefresh), + freeClientCap: freeClientCap, + removePeer: removePeer, + startTime: clock.Now(), + cumulativeTime: ndb.getCumulativeTime(), + stopCh: make(chan struct{}), + } + // If the negative balance of free client is even lower than 1, + // delete this entry. + ndb.nbEvictCallBack = func(now mclock.AbsTime, b negBalance) bool { + balance := math.Exp(float64(b.logValue-pool.logOffset(now)) / fixedPointMultiplier) + return balance <= 1 + } go func() { for { select { @@ -161,8 +178,9 @@ func newClientPool(db ethdb.Database, freeClientCap uint64, queueLimit int, cloc pool.lock.Lock() pool.connectedQueue.Refresh() pool.lock.Unlock() - case stop := <-pool.stopCh: - close(stop) + case <-clock.After(persistCumulativeTimeRefresh): + pool.ndb.setCumulativeTime(pool.logOffset(clock.Now())) + case <-pool.stopCh: return } } @@ -172,64 +190,70 @@ func newClientPool(db ethdb.Database, freeClientCap uint64, queueLimit int, cloc // stop shuts the client pool down func (f *clientPool) stop() { - stop := make(chan struct{}) - f.stopCh <- stop - <-stop + close(f.stopCh) f.lock.Lock() f.closed = true - f.saveToDb() f.lock.Unlock() -} - -// registerPeer implements peerSetNotify -func (f *clientPool) registerPeer(p *peer) { - c := f.connect(p, 0) - if c != nil { - p.balanceTracker = &c.balanceTracker - } + f.ndb.setCumulativeTime(f.logOffset(f.clock.Now())) + f.ndb.close() } // connect should be called after a successful handshake. If the connection was // rejected, there is no need to call disconnect. -func (f *clientPool) connect(peer clientPeer, capacity uint64) *clientInfo { +func (f *clientPool) connect(peer clientPeer, capacity uint64) bool { f.lock.Lock() defer f.lock.Unlock() + // Short circuit if clientPool is already closed. if f.closed { - return nil + return false } - address := peer.freeClientId() - id := peer.ID() - idStr := peerIdToString(id) + // Dedup connected peers. + id, freeID := peer.ID(), peer.freeClientId() if _, ok := f.connectedMap[id]; ok { clientRejectedMeter.Mark(1) - log.Debug("Client already connected", "address", address, "id", idStr) - return nil - } - now := f.clock.Now() - // create a clientInfo but do not add it yet - e := &clientInfo{pool: f, peer: peer, address: address, queueIndex: -1, id: id} - posBalance := f.getPosBalance(id).value - e.priority = posBalance != 0 - var negBalance uint64 - nb := f.negBalanceMap[address] - if nb != nil { + log.Debug("Client already connected", "address", freeID, "id", peerIdToString(id)) + return false + } + // Create a clientInfo but do not add it yet + var ( + posBalance uint64 + negBalance uint64 + now = f.clock.Now() + ) + pb := f.ndb.getOrNewPB(id) + posBalance = pb.value + e := &clientInfo{pool: f, peer: peer, address: freeID, queueIndex: -1, id: id, priority: posBalance != 0} + + nb := f.ndb.getOrNewNB(freeID) + if nb.logValue != 0 { negBalance = uint64(math.Exp(float64(nb.logValue-f.logOffset(now)) / fixedPointMultiplier)) + negBalance *= uint64(time.Second) } + // If the client is a free client, assign with a low free capacity, + // Otherwise assign with the given value(priority client) if !e.priority { capacity = f.freeClientCap } - // check whether it fits into connectedQueue + // Ensure the capacity will never lower than the free capacity. if capacity < f.freeClientCap { capacity = f.freeClientCap } e.capacity = capacity + + // Starts a balance tracker e.balanceTracker.init(f.clock, capacity) e.balanceTracker.setBalance(posBalance, negBalance) f.setClientPriceFactors(e) - newCapacity := f.connectedCapacity + capacity + + // If the number of clients already connected in the clientpool exceeds its + // capacity, evict some clients with lowest priority. + // + // If the priority of the newly added client is lower than the priority of + // all connected clients, the client is rejected. + newCapacity := f.connectedCap + capacity newCount := f.connectedQueue.Size() + 1 - if newCapacity > f.capacityLimit || newCount > f.countLimit { + if newCapacity > f.capLimit || newCount > f.connLimit { var ( kickList []*clientInfo kickPriority int64 @@ -240,45 +264,44 @@ func (f *clientPool) connect(peer clientPeer, capacity uint64) *clientInfo { kickPriority = priority newCapacity -= c.capacity newCount-- - return newCapacity > f.capacityLimit || newCount > f.countLimit + return newCapacity > f.capLimit || newCount > f.connLimit }) - if newCapacity > f.capacityLimit || newCount > f.countLimit || (e.balanceTracker.estimatedPriority(now+mclock.AbsTime(connectedBias), false)-kickPriority) > 0 { - // reject client + bias := connectedBias + if f.disableBias { + bias = 0 + } + if newCapacity > f.capLimit || newCount > f.connLimit || (e.balanceTracker.estimatedPriority(now+mclock.AbsTime(bias), false)-kickPriority) > 0 { for _, c := range kickList { f.connectedQueue.Push(c) } clientRejectedMeter.Mark(1) - log.Debug("Client rejected", "address", address, "id", idStr) - return nil + log.Debug("Client rejected", "address", freeID, "id", peerIdToString(id)) + return false } // accept new client, drop old ones for _, c := range kickList { f.dropClient(c, now, true) } } - // client accepted, finish setting it up - if nb != nil { - delete(f.negBalanceMap, address) - f.negBalanceQueue.Remove(nb.queueIndex) - } + // Register new client to connection queue. + f.connectedMap[id] = e + f.connectedQueue.Push(e) + f.connectedCap += e.capacity + + // If the current client is a paid client, monitor the status of client, + // downgrade it to normal client if positive balance is used up. if e.priority { e.balanceTracker.addCallback(balanceCallbackZero, 0, func() { f.balanceExhausted(id) }) } - f.connectedMap[id] = e - f.connectedQueue.Push(e) - f.connectedCapacity += e.capacity - totalConnectedGauge.Update(int64(f.connectedCapacity)) + // If the capacity of client is not the default value(free capacity), notify + // it to update capacity. if e.capacity != f.freeClientCap { e.peer.updateCapacity(e.capacity) } + totalConnectedGauge.Update(int64(f.connectedCap)) clientConnectedMeter.Mark(1) - log.Debug("Client accepted", "address", address) - return e -} - -// unregisterPeer implements peerSetNotify -func (f *clientPool) unregisterPeer(p *peer) { - f.disconnect(p) + log.Debug("Client accepted", "address", freeID) + return true } // disconnect should be called when a connection is terminated. If the disconnection @@ -288,15 +311,14 @@ func (f *clientPool) disconnect(p clientPeer) { f.lock.Lock() defer f.lock.Unlock() + // Short circuit if client pool is already closed. if f.closed { return } - address := p.freeClientId() - id := p.ID() // Short circuit if the peer hasn't been registered. - e := f.connectedMap[id] + e := f.connectedMap[p.ID()] if e == nil { - log.Debug("Client not connected", "address", address, "id", peerIdToString(id)) + log.Debug("Client not connected", "address", p.freeClientId(), "id", peerIdToString(p.ID())) return } f.dropClient(e, f.clock.Now(), false) @@ -311,8 +333,8 @@ func (f *clientPool) dropClient(e *clientInfo, now mclock.AbsTime, kick bool) { f.finalizeBalance(e, now) f.connectedQueue.Remove(e.queueIndex) delete(f.connectedMap, e.id) - f.connectedCapacity -= e.capacity - totalConnectedGauge.Update(int64(f.connectedCapacity)) + f.connectedCap -= e.capacity + totalConnectedGauge.Update(int64(f.connectedCap)) if kick { clientKickedMeter.Mark(1) log.Debug("Client kicked out", "address", e.address) @@ -328,18 +350,17 @@ func (f *clientPool) dropClient(e *clientInfo, now mclock.AbsTime, kick bool) { func (f *clientPool) finalizeBalance(c *clientInfo, now mclock.AbsTime) { c.balanceTracker.stop(now) pos, neg := c.balanceTracker.getBalance(now) - pb := f.getPosBalance(c.id) + + pb, nb := f.ndb.getOrNewPB(c.id), f.ndb.getOrNewNB(c.address) pb.value = pos - f.storePosBalance(pb) - if neg < 1 { - neg = 1 - } - nb := &negBalance{address: c.address, queueIndex: -1, logValue: int64(math.Log(float64(neg))*fixedPointMultiplier) + f.logOffset(now)} - f.negBalanceMap[c.address] = nb - f.negBalanceQueue.Push(nb, -nb.logValue) - if f.negBalanceQueue.Size() > f.queueLimit { - nn := f.negBalanceQueue.PopItem().(*negBalance) - delete(f.negBalanceMap, nn.address) + f.ndb.setPB(c.id, pb) + + neg /= uint64(time.Second) // Convert the expanse to second level. + if neg > 1 { + nb.logValue = int64(math.Log(float64(neg))*fixedPointMultiplier) + f.logOffset(now) + f.ndb.setNB(c.address, nb) + } else { + f.ndb.delNB(c.address) // Negative balance is small enough, drop it directly. } } @@ -355,36 +376,52 @@ func (f *clientPool) balanceExhausted(id enode.ID) { } c.priority = false if c.capacity != f.freeClientCap { - f.connectedCapacity += f.freeClientCap - c.capacity - totalConnectedGauge.Update(int64(f.connectedCapacity)) + f.connectedCap += f.freeClientCap - c.capacity + totalConnectedGauge.Update(int64(f.connectedCap)) c.capacity = f.freeClientCap c.peer.updateCapacity(c.capacity) } + f.ndb.delPB(id) } // setConnLimit sets the maximum number and total capacity of connected clients, // dropping some of them if necessary. -func (f *clientPool) setLimits(count int, totalCap uint64) { +func (f *clientPool) setLimits(totalConn int, totalCap uint64) { f.lock.Lock() defer f.lock.Unlock() - f.countLimit = count - f.capacityLimit = totalCap - now := mclock.Now() - f.connectedQueue.MultiPop(func(data interface{}, priority int64) bool { - c := data.(*clientInfo) - f.dropClient(c, now, true) - return f.connectedCapacity > f.capacityLimit || f.connectedQueue.Size() > f.countLimit - }) + f.connLimit = totalConn + f.capLimit = totalCap + if f.connectedCap > f.capLimit || f.connectedQueue.Size() > f.connLimit { + f.connectedQueue.MultiPop(func(data interface{}, priority int64) bool { + f.dropClient(data.(*clientInfo), mclock.Now(), true) + return f.connectedCap > f.capLimit || f.connectedQueue.Size() > f.connLimit + }) + } +} + +// requestCost feeds request cost after serving a request from the given peer. +func (f *clientPool) requestCost(p *peer, cost uint64) { + f.lock.Lock() + defer f.lock.Unlock() + + info, exist := f.connectedMap[p.ID()] + if !exist || f.closed { + return + } + info.balanceTracker.requestCost(cost) } // logOffset calculates the time-dependent offset for the logarithmic // representation of negative balance +// +// From another point of view, the result returned by the function represents +// the total time that the clientpool is cumulatively running(total_hours/multiplier). func (f *clientPool) logOffset(now mclock.AbsTime) int64 { // Note: fixedPointMultiplier acts as a multiplier here; the reason for dividing the divisor // is to avoid int64 overflow. We assume that int64(negBalanceExpTC) >> fixedPointMultiplier. - logDecay := int64((time.Duration(now - f.startupTime)) / (negBalanceExpTC / fixedPointMultiplier)) - return f.logOffsetAtStartup + logDecay + cumulativeTime := int64((time.Duration(now - f.startTime)) / (negBalanceExpTC / fixedPointMultiplier)) + return f.cumulativeTime + cumulativeTime } // setPriceFactors changes pricing factors for both positive and negative balances. @@ -405,100 +442,6 @@ func (f *clientPool) setClientPriceFactors(c *clientInfo) { c.balanceTracker.setFactors(false, f.posFactors.timeFactor+float64(c.capacity)*f.posFactors.capacityFactor/1000000, f.posFactors.requestFactor) } -// clientPoolStorage is the RLP representation of the pool's database storage -type clientPoolStorage struct { - LogOffset uint64 - List []*negBalance -} - -// loadFromDb restores pool status from the database storage -// (automatically called at initialization) -func (f *clientPool) loadFromDb() { - enc, err := f.db.Get(clientPoolDbKey) - if err != nil { - return - } - var storage clientPoolStorage - err = rlp.DecodeBytes(enc, &storage) - if err != nil { - log.Error("Failed to decode client list", "err", err) - return - } - f.logOffsetAtStartup = int64(storage.LogOffset) - f.startupTime = f.clock.Now() - for _, e := range storage.List { - log.Debug("Loaded free client record", "address", e.address, "logValue", e.logValue) - f.negBalanceMap[e.address] = e - f.negBalanceQueue.Push(e, -e.logValue) - } -} - -// saveToDb saves pool status to the database storage -// (automatically called during shutdown) -func (f *clientPool) saveToDb() { - now := f.clock.Now() - storage := clientPoolStorage{ - LogOffset: uint64(f.logOffset(now)), - } - for _, c := range f.connectedMap { - f.finalizeBalance(c, now) - } - i := 0 - storage.List = make([]*negBalance, len(f.negBalanceMap)) - for _, e := range f.negBalanceMap { - storage.List[i] = e - i++ - } - enc, err := rlp.EncodeToBytes(storage) - if err != nil { - log.Error("Failed to encode negative balance list", "err", err) - } else { - f.db.Put(clientPoolDbKey, enc) - } -} - -// storePosBalance stores a single positive balance entry in the database -func (f *clientPool) storePosBalance(b *posBalance) { - if b.value == b.lastStored { - return - } - enc, err := rlp.EncodeToBytes(b) - if err != nil { - log.Error("Failed to encode client balance", "err", err) - } else { - f.db.Put(append(clientBalanceDbKey, b.id[:]...), enc) - b.lastStored = b.value - } -} - -// getPosBalance retrieves a single positive balance entry from cache or the database -func (f *clientPool) getPosBalance(id enode.ID) *posBalance { - if b, ok := f.posBalanceMap[id]; ok { - f.posBalanceQueue.Remove(b.queueIndex) - f.posBalanceAccessCounter-- - f.posBalanceQueue.Push(b, f.posBalanceAccessCounter) - return b - } - balance := &posBalance{} - if enc, err := f.db.Get(append(clientBalanceDbKey, id[:]...)); err == nil { - if err := rlp.DecodeBytes(enc, balance); err != nil { - log.Error("Failed to decode client balance", "err", err) - balance = &posBalance{} - } - } - balance.id = id - balance.queueIndex = -1 - if f.posBalanceQueue.Size() >= f.queueLimit { - b := f.posBalanceQueue.PopItem().(*posBalance) - f.storePosBalance(b) - delete(f.posBalanceMap, b.id) - } - f.posBalanceAccessCounter-- - f.posBalanceQueue.Push(balance, f.posBalanceAccessCounter) - f.posBalanceMap[id] = balance - return balance -} - // addBalance updates the positive balance of a client. // If setTotal is false then the given amount is added to the balance. // If setTotal is true then amount represents the total amount ever added to the @@ -508,11 +451,21 @@ func (f *clientPool) addBalance(id enode.ID, amount uint64, setTotal bool) { f.lock.Lock() defer f.lock.Unlock() - pb := f.getPosBalance(id) + pb := f.ndb.getOrNewPB(id) c := f.connectedMap[id] - var negBalance uint64 if c != nil { - pb.value, negBalance = c.balanceTracker.getBalance(f.clock.Now()) + posBalance, negBalance := c.balanceTracker.getBalance(f.clock.Now()) + pb.value = posBalance + defer func() { + c.balanceTracker.setBalance(pb.value, negBalance) + if !c.priority && pb.value > 0 { + // The capacity should be adjusted based on the requirement, + // but we have no idea about the new capacity, need a second + // call to udpate it. + c.priority = true + c.balanceTracker.addCallback(balanceCallbackZero, 0, func() { f.balanceExhausted(id) }) + } + }() } if setTotal { if pb.value+amount > pb.lastTotal { @@ -525,21 +478,12 @@ func (f *clientPool) addBalance(id enode.ID, amount uint64, setTotal bool) { pb.value += amount pb.lastTotal += amount } - f.storePosBalance(pb) - if c != nil { - c.balanceTracker.setBalance(pb.value, negBalance) - if !c.priority && pb.value > 0 { - c.priority = true - c.balanceTracker.addCallback(balanceCallbackZero, 0, func() { f.balanceExhausted(id) }) - } - } + f.ndb.setPB(id, pb) } // posBalance represents a recently accessed positive balance entry type posBalance struct { - id enode.ID - value, lastStored, lastTotal uint64 - queueIndex int // position in posBalanceQueue + value, lastTotal uint64 } // EncodeRLP implements rlp.Encoder @@ -556,44 +500,207 @@ func (e *posBalance) DecodeRLP(s *rlp.Stream) error { return err } e.value = entry.Value - e.lastStored = entry.Value e.lastTotal = entry.LastTotal return nil } -// posSetIndex callback updates posBalance item index in posBalanceQueue -func posSetIndex(a interface{}, index int) { - a.(*posBalance).queueIndex = index -} - // negBalance represents a negative balance entry of a disconnected client -type negBalance struct { - address string - logValue int64 - queueIndex int // position in negBalanceQueue -} +type negBalance struct{ logValue int64 } // EncodeRLP implements rlp.Encoder func (e *negBalance) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, []interface{}{e.address, uint64(e.logValue)}) + return rlp.Encode(w, []interface{}{uint64(e.logValue)}) } // DecodeRLP implements rlp.Decoder func (e *negBalance) DecodeRLP(s *rlp.Stream) error { var entry struct { - Address string LogValue uint64 } if err := s.Decode(&entry); err != nil { return err } - e.address = entry.Address e.logValue = int64(entry.LogValue) - e.queueIndex = -1 return nil } -// negSetIndex callback updates negBalance item index in negBalanceQueue -func negSetIndex(a interface{}, index int) { - a.(*negBalance).queueIndex = index +const ( + // nodeDBVersion is the version identifier of the node data in db + nodeDBVersion = 0 + + // dbCleanupCycle is the cycle of db for useless data cleanup + dbCleanupCycle = time.Hour +) + +var ( + positiveBalancePrefix = []byte("pb:") // dbVersion(uint16 big endian) + positiveBalancePrefix + id -> balance + negativeBalancePrefix = []byte("nb:") // dbVersion(uint16 big endian) + negativeBalancePrefix + ip -> balance + cumulativeRunningTimeKey = []byte("cumulativeTime:") // dbVersion(uint16 big endian) + cumulativeRunningTimeKey -> cumulativeTime +) + +type nodeDB struct { + db ethdb.Database + pcache *lru.Cache + ncache *lru.Cache + auxbuf []byte // 37-byte auxiliary buffer for key encoding + verbuf [2]byte // 2-byte auxiliary buffer for db version + nbEvictCallBack func(mclock.AbsTime, negBalance) bool // Callback to determine whether the negative balance can be evicted. + clock mclock.Clock + closeCh chan struct{} + cleanupHook func() // Test hook used for testing +} + +func newNodeDB(db ethdb.Database, clock mclock.Clock) *nodeDB { + pcache, _ := lru.New(posBalanceCacheLimit) + ncache, _ := lru.New(negBalanceCacheLimit) + ndb := &nodeDB{ + db: db, + pcache: pcache, + ncache: ncache, + auxbuf: make([]byte, 37), + clock: clock, + closeCh: make(chan struct{}), + } + binary.BigEndian.PutUint16(ndb.verbuf[:], uint16(nodeDBVersion)) + go ndb.expirer() + return ndb +} + +func (db *nodeDB) close() { + close(db.closeCh) +} + +func (db *nodeDB) key(id []byte, neg bool) []byte { + prefix := positiveBalancePrefix + if neg { + prefix = negativeBalancePrefix + } + if len(prefix)+len(db.verbuf)+len(id) > len(db.auxbuf) { + db.auxbuf = append(db.auxbuf, make([]byte, len(prefix)+len(db.verbuf)+len(id)-len(db.auxbuf))...) + } + copy(db.auxbuf[:len(db.verbuf)], db.verbuf[:]) + copy(db.auxbuf[len(db.verbuf):len(db.verbuf)+len(prefix)], prefix) + copy(db.auxbuf[len(prefix)+len(db.verbuf):len(prefix)+len(db.verbuf)+len(id)], id) + return db.auxbuf[:len(prefix)+len(db.verbuf)+len(id)] +} + +func (db *nodeDB) getCumulativeTime() int64 { + blob, err := db.db.Get(append(cumulativeRunningTimeKey, db.verbuf[:]...)) + if err != nil || len(blob) == 0 { + return 0 + } + return int64(binary.BigEndian.Uint64(blob)) +} + +func (db *nodeDB) setCumulativeTime(v int64) { + binary.BigEndian.PutUint64(db.auxbuf[:8], uint64(v)) + db.db.Put(append(cumulativeRunningTimeKey, db.verbuf[:]...), db.auxbuf[:8]) +} + +func (db *nodeDB) getOrNewPB(id enode.ID) posBalance { + key := db.key(id.Bytes(), false) + item, exist := db.pcache.Get(string(key)) + if exist { + return item.(posBalance) + } + var balance posBalance + if enc, err := db.db.Get(key); err == nil { + if err := rlp.DecodeBytes(enc, &balance); err != nil { + log.Error("Failed to decode positive balance", "err", err) + } + } + db.pcache.Add(string(key), balance) + return balance +} + +func (db *nodeDB) setPB(id enode.ID, b posBalance) { + key := db.key(id.Bytes(), false) + enc, err := rlp.EncodeToBytes(&(b)) + if err != nil { + log.Error("Failed to encode positive balance", "err", err) + return + } + db.db.Put(key, enc) + db.pcache.Add(string(key), b) +} + +func (db *nodeDB) delPB(id enode.ID) { + key := db.key(id.Bytes(), false) + db.db.Delete(key) + db.pcache.Remove(string(key)) +} + +func (db *nodeDB) getOrNewNB(id string) negBalance { + key := db.key([]byte(id), true) + item, exist := db.ncache.Get(string(key)) + if exist { + return item.(negBalance) + } + var balance negBalance + if enc, err := db.db.Get(key); err == nil { + if err := rlp.DecodeBytes(enc, &balance); err != nil { + log.Error("Failed to decode negative balance", "err", err) + } + } + db.ncache.Add(string(key), balance) + return balance +} + +func (db *nodeDB) setNB(id string, b negBalance) { + key := db.key([]byte(id), true) + enc, err := rlp.EncodeToBytes(&(b)) + if err != nil { + log.Error("Failed to encode negative balance", "err", err) + return + } + db.db.Put(key, enc) + db.ncache.Add(string(key), b) +} + +func (db *nodeDB) delNB(id string) { + key := db.key([]byte(id), true) + db.db.Delete(key) + db.ncache.Remove(string(key)) +} + +func (db *nodeDB) expirer() { + for { + select { + case <-db.clock.After(dbCleanupCycle): + db.expireNodes() + case <-db.closeCh: + return + } + } +} + +// expireNodes iterates the whole node db and checks whether the negative balance +// entry can deleted. +// +// The rationale behind this is: server doesn't need to keep the negative balance +// records if they are low enough. +func (db *nodeDB) expireNodes() { + var ( + visited int + deleted int + start = time.Now() + ) + iter := db.db.NewIteratorWithPrefix(append(db.verbuf[:], negativeBalancePrefix...)) + for iter.Next() { + visited += 1 + var balance negBalance + if err := rlp.DecodeBytes(iter.Value(), &balance); err != nil { + log.Error("Failed to decode negative balance", "err", err) + continue + } + if db.nbEvictCallBack != nil && db.nbEvictCallBack(db.clock.Now(), balance) { + deleted += 1 + db.db.Delete(iter.Key()) + } + } + // Invoke testing hook if it's not nil. + if db.cleanupHook != nil { + db.cleanupHook() + } + log.Debug("Expire nodes", "visited", visited, "deleted", deleted, "elapsed", common.PrettyDuration(time.Since(start))) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/commons.go b/vendor/github.com/ethereum/go-ethereum/les/commons.go index ef3c470e58..ad3c5aef3d 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/commons.go +++ b/vendor/github.com/ethereum/go-ethereum/les/commons.go @@ -17,25 +17,56 @@ package les import ( + "fmt" "math/big" + "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" ) +func errResp(code errCode, format string, v ...interface{}) error { + return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) +} + +func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { + var name string + switch protocolVersion { + case lpv2: + name = "LES2" + default: + panic(nil) + } + return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) +} + +type chainReader interface { + CurrentHeader() *types.Header +} + // lesCommons contains fields needed by both server and client. type lesCommons struct { + genesis common.Hash config *eth.Config + chainConfig *params.ChainConfig iConfig *light.IndexerConfig chainDb ethdb.Database - protocolManager *ProtocolManager + peers *peerSet + chainReader chainReader chtIndexer, bloomTrieIndexer *core.ChainIndexer + oracle *checkpointOracle + + closeCh chan struct{} + wg sync.WaitGroup } // NodeInfo represents a short summary of the Ethereum sub-protocol metadata @@ -50,7 +81,7 @@ type NodeInfo struct { } // makeProtocols creates protocol descriptors for the given LES versions. -func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { +func (c *lesCommons) makeProtocols(versions []uint, runPeer func(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error, peerInfo func(id enode.ID) interface{}) []p2p.Protocol { protos := make([]p2p.Protocol, len(versions)) for i, version := range versions { version := version @@ -59,15 +90,10 @@ func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { Version: version, Length: ProtocolLengths[version], NodeInfo: c.nodeInfo, - Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - return c.protocolManager.runPeer(version, p, rw) - }, - PeerInfo: func(id enode.ID) interface{} { - if p := c.protocolManager.peers.Peer(peerIdToString(id)); p != nil { - return p.Info() - } - return nil + Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error { + return runPeer(version, peer, rw) }, + PeerInfo: peerInfo, } } return protos @@ -75,22 +101,21 @@ func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { // nodeInfo retrieves some protocol metadata about the running host node. func (c *lesCommons) nodeInfo() interface{} { - chain := c.protocolManager.blockchain - head := chain.CurrentHeader() + head := c.chainReader.CurrentHeader() hash := head.Hash() return &NodeInfo{ Network: c.config.NetworkId, - Difficulty: chain.GetTd(hash, head.Number.Uint64()), - Genesis: chain.Genesis().Hash(), - Config: chain.Config(), - Head: chain.CurrentHeader().Hash(), + Difficulty: rawdb.ReadTd(c.chainDb, hash, head.Number.Uint64()), + Genesis: c.genesis, + Config: c.chainConfig, + Head: hash, CHT: c.latestLocalCheckpoint(), } } -// latestLocalCheckpoint finds the common stored section index and returns a set of -// post-processed trie roots (CHT and BloomTrie) associated with -// the appropriate section index and head hash as a local checkpoint package. +// latestLocalCheckpoint finds the common stored section index and returns a set +// of post-processed trie roots (CHT and BloomTrie) associated with the appropriate +// section index and head hash as a local checkpoint package. func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { sections, _, _ := c.chtIndexer.Sections() sections2, _, _ := c.bloomTrieIndexer.Sections() @@ -102,15 +127,15 @@ func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { // No checkpoint information can be provided. return params.TrustedCheckpoint{} } - return c.getLocalCheckpoint(sections - 1) + return c.localCheckpoint(sections - 1) } -// getLocalCheckpoint returns a set of post-processed trie roots (CHT and BloomTrie) +// localCheckpoint returns a set of post-processed trie roots (CHT and BloomTrie) // associated with the appropriate head hash by specific section index. // // The returned checkpoint is only the checkpoint generated by the local indexers, // not the stable checkpoint registered in the registrar contract. -func (c *lesCommons) getLocalCheckpoint(index uint64) params.TrustedCheckpoint { +func (c *lesCommons) localCheckpoint(index uint64) params.TrustedCheckpoint { sectionHead := c.chtIndexer.SectionHead(index) return params.TrustedCheckpoint{ SectionIndex: index, diff --git a/vendor/github.com/ethereum/go-ethereum/les/costtracker.go b/vendor/github.com/ethereum/go-ethereum/les/costtracker.go index d1bb172e40..81da045660 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/costtracker.go +++ b/vendor/github.com/ethereum/go-ethereum/les/costtracker.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" ) const makeCostStats = false // make request cost statistics during operation @@ -81,12 +82,13 @@ var ( ) const ( - maxCostFactor = 2 // ratio of maximum and average cost estimates + maxCostFactor = 2 // ratio of maximum and average cost estimates + bufLimitRatio = 6000 // fixed bufLimit/MRR ratio gfUsageThreshold = 0.5 gfUsageTC = time.Second gfRaiseTC = time.Second * 200 gfDropTC = time.Second * 50 - gfDbKey = "_globalCostFactorV3" + gfDbKey = "_globalCostFactorV6" ) // costTracker is responsible for calculating costs and cost estimates on the @@ -127,6 +129,10 @@ type costTracker struct { totalRechargeCh chan uint64 stats map[uint64][]uint64 // Used for testing purpose. + + // TestHooks + testing bool // Disable real cost evaluation for testing purpose. + testCostList RequestCostList // Customized cost table for testing purpose. } // newCostTracker creates a cost tracker and loads the cost factor statistics from the database. @@ -221,6 +227,9 @@ type reqInfo struct { // servingTime is the CPU time corresponding to the actual processing of // the request. servingTime float64 + + // msgCode indicates the type of request. + msgCode uint64 } // gfLoop starts an event loop which updates the global cost factor which is @@ -264,10 +273,43 @@ func (ct *costTracker) gfLoop() { for { select { case r := <-ct.reqInfoCh: + relCost := int64(factor * r.servingTime * 100 / r.avgTimeCost) // Convert the value to a percentage form + + // Record more metrics if we are debugging + if metrics.EnabledExpensive { + switch r.msgCode { + case GetBlockHeadersMsg: + relativeCostHeaderHistogram.Update(relCost) + case GetBlockBodiesMsg: + relativeCostBodyHistogram.Update(relCost) + case GetReceiptsMsg: + relativeCostReceiptHistogram.Update(relCost) + case GetCodeMsg: + relativeCostCodeHistogram.Update(relCost) + case GetProofsV2Msg: + relativeCostProofHistogram.Update(relCost) + case GetHelperTrieProofsMsg: + relativeCostHelperProofHistogram.Update(relCost) + case SendTxV2Msg: + relativeCostSendTxHistogram.Update(relCost) + case GetTxStatusMsg: + relativeCostTxStatusHistogram.Update(relCost) + } + } + // SendTxV2 and GetTxStatus requests are two special cases. + // All other requests will only put pressure on the database, and + // the corresponding delay is relatively stable. While these two + // requests involve txpool query, which is usually unstable. + // + // TODO(rjl493456442) fixes this. + if r.msgCode == SendTxV2Msg || r.msgCode == GetTxStatusMsg { + continue + } requestServedMeter.Mark(int64(r.servingTime)) - requestEstimatedMeter.Mark(int64(r.avgTimeCost / factor)) requestServedTimer.Update(time.Duration(r.servingTime)) - relativeCostHistogram.Update(int64(r.avgTimeCost / factor / r.servingTime)) + requestEstimatedMeter.Mark(int64(r.avgTimeCost / factor)) + requestEstimatedTimer.Update(time.Duration(r.avgTimeCost / factor)) + relativeCostHistogram.Update(relCost) now := mclock.Now() dt := float64(now - expUpdate) @@ -318,12 +360,12 @@ func (ct *costTracker) gfLoop() { default: } } + globalFactorGauge.Update(int64(1000 * factor)) log.Debug("global cost factor updated", "factor", factor) } } recentServedGauge.Update(int64(recentTime)) recentEstimatedGauge.Update(int64(recentAvg)) - totalRechargeGauge.Update(int64(totalRecharge)) case <-saveTicker.C: saveCostFactor() @@ -370,7 +412,7 @@ func (ct *costTracker) updateStats(code, amount, servingTime, realCost uint64) { avg := reqAvgTimeCost[code] avgTimeCost := avg.baseCost + amount*avg.reqCost select { - case ct.reqInfoCh <- reqInfo{float64(avgTimeCost), float64(servingTime)}: + case ct.reqInfoCh <- reqInfo{float64(avgTimeCost), float64(servingTime), code}: default: } if makeCostStats { diff --git a/vendor/github.com/ethereum/go-ethereum/les/distributor.go b/vendor/github.com/ethereum/go-ethereum/les/distributor.go index 9235adc03f..6d81149720 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/distributor.go +++ b/vendor/github.com/ethereum/go-ethereum/les/distributor.go @@ -28,14 +28,17 @@ import ( // suitable peers, obeying flow control rules and prioritizing them in creation // order (even when a resend is necessary). type requestDistributor struct { - clock mclock.Clock - reqQueue *list.List - lastReqOrder uint64 - peers map[distPeer]struct{} - peerLock sync.RWMutex - stopChn, loopChn chan struct{} - loopNextSent bool - lock sync.Mutex + clock mclock.Clock + reqQueue *list.List + lastReqOrder uint64 + peers map[distPeer]struct{} + peerLock sync.RWMutex + loopChn chan struct{} + loopNextSent bool + lock sync.Mutex + + closeCh chan struct{} + wg sync.WaitGroup } // distPeer is an LES server peer interface for the request distributor. @@ -66,20 +69,22 @@ type distReq struct { sentChn chan distPeer element *list.Element waitForPeers mclock.AbsTime + enterQueue mclock.AbsTime } // newRequestDistributor creates a new request distributor -func newRequestDistributor(peers *peerSet, stopChn chan struct{}, clock mclock.Clock) *requestDistributor { +func newRequestDistributor(peers *peerSet, clock mclock.Clock) *requestDistributor { d := &requestDistributor{ clock: clock, reqQueue: list.New(), loopChn: make(chan struct{}, 2), - stopChn: stopChn, + closeCh: make(chan struct{}), peers: make(map[distPeer]struct{}), } if peers != nil { peers.notify(d) } + d.wg.Add(1) go d.loop() return d } @@ -105,19 +110,22 @@ func (d *requestDistributor) registerTestPeer(p distPeer) { d.peerLock.Unlock() } -// distMaxWait is the maximum waiting time after which further necessary waiting -// times are recalculated based on new feedback from the servers -const distMaxWait = time.Millisecond * 50 +var ( + // distMaxWait is the maximum waiting time after which further necessary waiting + // times are recalculated based on new feedback from the servers + distMaxWait = time.Millisecond * 50 -// waitForPeers is the time window in which a request does not fail even if it -// has no suitable peers to send to at the moment -const waitForPeers = time.Second * 3 + // waitForPeers is the time window in which a request does not fail even if it + // has no suitable peers to send to at the moment + waitForPeers = time.Second * 3 +) // main event loop func (d *requestDistributor) loop() { + defer d.wg.Done() for { select { - case <-d.stopChn: + case <-d.closeCh: d.lock.Lock() elem := d.reqQueue.Front() for elem != nil { @@ -140,6 +148,7 @@ func (d *requestDistributor) loop() { send := req.request(peer) if send != nil { peer.queueSend(send) + requestSendDelay.Update(time.Duration(d.clock.Now() - req.enterQueue)) } chn <- peer close(chn) @@ -249,6 +258,9 @@ func (d *requestDistributor) queue(r *distReq) chan distPeer { r.reqOrder = d.lastReqOrder r.waitForPeers = d.clock.Now() + mclock.AbsTime(waitForPeers) } + // Assign the timestamp when the request is queued no matter it's + // a new one or re-queued one. + r.enterQueue = d.clock.Now() back := d.reqQueue.Back() if back == nil || r.reqOrder > back.Value.(*distReq).reqOrder { @@ -294,3 +306,8 @@ func (d *requestDistributor) remove(r *distReq) { r.element = nil } } + +func (d *requestDistributor) close() { + close(d.closeCh) + d.wg.Wait() +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go b/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go new file mode 100644 index 0000000000..c2a92dd999 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go @@ -0,0 +1,32 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package les + +import ( + "github.com/ethereum/go-ethereum/rlp" +) + +// lesEntry is the "les" ENR entry. This is set for LES servers only. +type lesEntry struct { + // Ignore additional fields (for forward compatibility). + Rest []rlp.RawValue `rlp:"tail"` +} + +// ENRKey implements enr.Entry. +func (e lesEntry) ENRKey() string { + return "les" +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/fetcher.go b/vendor/github.com/ethereum/go-ethereum/les/fetcher.go index 76e4f076a7..df76c56d70 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/fetcher.go +++ b/vendor/github.com/ethereum/go-ethereum/les/fetcher.go @@ -40,9 +40,8 @@ const ( // ODR system to ensure that we only request data related to a certain block from peers who have already processed // and announced that block. type lightFetcher struct { - pm *ProtocolManager - odr *LesOdr - chain lightChain + handler *clientHandler + chain *light.LightChain lock sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests maxConfirmedTd *big.Int @@ -58,13 +57,9 @@ type lightFetcher struct { requestTriggered bool requestTrigger chan struct{} lastTrustedHeader *types.Header -} -// lightChain extends the BlockChain interface by locking. -type lightChain interface { - BlockChain - LockChain() - UnlockChain() + closeCh chan struct{} + wg sync.WaitGroup } // fetcherPeerInfo holds fetcher-specific information about each active peer @@ -114,32 +109,37 @@ type fetchResponse struct { } // newLightFetcher creates a new light fetcher -func newLightFetcher(pm *ProtocolManager) *lightFetcher { +func newLightFetcher(h *clientHandler) *lightFetcher { f := &lightFetcher{ - pm: pm, - chain: pm.blockchain.(*light.LightChain), - odr: pm.odr, + handler: h, + chain: h.backend.blockchain, peers: make(map[*peer]*fetcherPeerInfo), deliverChn: make(chan fetchResponse, 100), requested: make(map[uint64]fetchRequest), timeoutChn: make(chan uint64), requestTrigger: make(chan struct{}, 1), syncDone: make(chan *peer), + closeCh: make(chan struct{}), maxConfirmedTd: big.NewInt(0), } - pm.peers.notify(f) + h.backend.peers.notify(f) - f.pm.wg.Add(1) + f.wg.Add(1) go f.syncLoop() return f } +func (f *lightFetcher) close() { + close(f.closeCh) + f.wg.Wait() +} + // syncLoop is the main event loop of the light fetcher func (f *lightFetcher) syncLoop() { - defer f.pm.wg.Done() + defer f.wg.Done() for { select { - case <-f.pm.quitSync: + case <-f.closeCh: return // request loop keeps running until no further requests are necessary or possible case <-f.requestTrigger: @@ -156,7 +156,7 @@ func (f *lightFetcher) syncLoop() { f.lock.Unlock() if rq != nil { - if _, ok := <-f.pm.reqDist.queue(rq); ok { + if _, ok := <-f.handler.backend.reqDist.queue(rq); ok { if syncing { f.lock.Lock() f.syncing = true @@ -187,9 +187,9 @@ func (f *lightFetcher) syncLoop() { } f.reqMu.Unlock() if ok { - f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true) + f.handler.backend.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true) req.peer.Log().Debug("Fetching data timed out hard") - go f.pm.removePeer(req.peer.id) + go f.handler.removePeer(req.peer.id) } case resp := <-f.deliverChn: f.reqMu.Lock() @@ -202,12 +202,12 @@ func (f *lightFetcher) syncLoop() { } f.reqMu.Unlock() if ok { - f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout) + f.handler.backend.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout) } f.lock.Lock() if !ok || !(f.syncing || f.processResponse(req, resp)) { resp.peer.Log().Debug("Failed processing response") - go f.pm.removePeer(resp.peer.id) + go f.handler.removePeer(resp.peer.id) } f.lock.Unlock() case p := <-f.syncDone: @@ -264,7 +264,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) { if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 { // announced tds should be strictly monotonic p.Log().Debug("Received non-monotonic td", "current", head.Td, "previous", fp.lastAnnounced.td) - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) return } @@ -297,7 +297,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) { // if one of root's children is canonical, keep it, delete other branches and root itself var newRoot *fetcherTreeNode for i, nn := range fp.root.children { - if rawdb.ReadCanonicalHash(f.pm.chainDb, nn.number) == nn.hash { + if rawdb.ReadCanonicalHash(f.handler.backend.chainDb, nn.number) == nn.hash { fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...) nn.parent = nil newRoot = nn @@ -390,7 +390,7 @@ func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, ha // // when syncing, just check if it is part of the known chain, there is nothing better we // can do since we do not know the most recent block hash yet - return rawdb.ReadCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.pm.chainDb, number) == hash + return rawdb.ReadCanonicalHash(f.handler.backend.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.handler.backend.chainDb, number) == hash } // requestAmount calculates the amount of headers to be downloaded starting @@ -453,8 +453,7 @@ func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint6 if f.checkKnownNode(p, n) || n.requested { continue } - - //if ulc mode is disabled, isTrustedHash returns true + // if ulc mode is disabled, isTrustedHash returns true amount := f.requestAmount(p, n) if (bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount) && (f.isTrustedHash(hash) || f.maxConfirmedTd.Int64() == 0) { bestHash = hash @@ -470,7 +469,7 @@ func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint6 // isTrustedHash checks if the block can be trusted by the minimum trusted fraction. func (f *lightFetcher) isTrustedHash(hash common.Hash) bool { // If ultra light cliet mode is disabled, trust all hashes - if f.pm.ulc == nil { + if f.handler.ulc == nil { return true } // Ultra light enabled, only trust after enough confirmations @@ -480,7 +479,7 @@ func (f *lightFetcher) isTrustedHash(hash common.Hash) bool { agreed++ } } - return 100*agreed/len(f.pm.ulc.keys) >= f.pm.ulc.fraction + return 100*agreed/len(f.handler.ulc.keys) >= f.handler.ulc.fraction } func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { @@ -500,14 +499,14 @@ func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { return fp != nil && fp.nodeByHash[bestHash] != nil }, request: func(dp distPeer) func() { - if f.pm.ulc != nil { + if f.handler.ulc != nil { // Keep last trusted header before sync f.setLastTrustedHeader(f.chain.CurrentHeader()) } go func() { p := dp.(*peer) p.Log().Debug("Synchronisation started") - f.pm.synchronise(p) + f.handler.synchronise(p) f.syncDone <- p }() return nil @@ -607,7 +606,7 @@ func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) { for p, fp := range f.peers { if !f.checkAnnouncedHeaders(fp, headers, tds) { p.Log().Debug("Inconsistent announcement") - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) } if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) { maxTd = fp.confirmedTd @@ -705,7 +704,7 @@ func (f *lightFetcher) checkSyncedHeaders(p *peer) { node = fp.lastAnnounced td *big.Int ) - if f.pm.ulc != nil { + if f.handler.ulc != nil { // Roll back untrusted blocks h, unapproved := f.lastTrustedTreeNode(p) f.chain.Rollback(unapproved) @@ -721,7 +720,7 @@ func (f *lightFetcher) checkSyncedHeaders(p *peer) { // Now node is the latest downloaded/approved header after syncing if node == nil { p.Log().Debug("Synchronisation failed") - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) return } header := f.chain.GetHeader(node.hash, node.number) @@ -741,7 +740,7 @@ func (f *lightFetcher) lastTrustedTreeNode(p *peer) (*types.Header, []common.Has if canonical.Number.Uint64() > f.lastTrustedHeader.Number.Uint64() { canonical = f.chain.GetHeaderByNumber(f.lastTrustedHeader.Number.Uint64()) } - commonAncestor := rawdb.FindCommonAncestor(f.pm.chainDb, canonical, f.lastTrustedHeader) + commonAncestor := rawdb.FindCommonAncestor(f.handler.backend.chainDb, canonical, f.lastTrustedHeader) if commonAncestor == nil { log.Error("Common ancestor of last trusted header and canonical header is nil", "canonical hash", canonical.Hash(), "trusted hash", f.lastTrustedHeader.Hash()) return current, unapprovedHashes @@ -787,7 +786,7 @@ func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool { } if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) { p.Log().Debug("Inconsistent announcement") - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) } if fp.confirmedTd != nil { f.updateMaxConfirmedTd(fp.confirmedTd) @@ -880,12 +879,12 @@ func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) { fp.firstUpdateStats = newEntry } for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) { - f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout) + f.handler.backend.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout) fp.firstUpdateStats = fp.firstUpdateStats.next } if fp.confirmedTd != nil { for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 { - f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time)) + f.handler.backend.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time)) fp.firstUpdateStats = fp.firstUpdateStats.next } } diff --git a/vendor/github.com/ethereum/go-ethereum/les/handler.go b/vendor/github.com/ethereum/go-ethereum/les/handler.go deleted file mode 100644 index 807065e55d..0000000000 --- a/vendor/github.com/ethereum/go-ethereum/les/handler.go +++ /dev/null @@ -1,1293 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package les - -import ( - "encoding/binary" - "encoding/json" - "errors" - "fmt" - "math/big" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/light" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/discv5" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -var errTooManyInvalidRequest = errors.New("too many invalid requests made") - -const ( - softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. - estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header - - ethVersion = 63 // equivalent eth version for the downloader - - MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request - MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request - MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request - MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request - MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request - MaxHelperTrieProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request - MaxTxSend = 64 // Amount of transactions to be send per request - MaxTxStatus = 256 // Amount of transactions to queried per request - - disableClientRemovePeer = false -) - -func errResp(code errCode, format string, v ...interface{}) error { - return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) -} - -type BlockChain interface { - Config() *params.ChainConfig - HasHeader(hash common.Hash, number uint64) bool - GetHeader(hash common.Hash, number uint64) *types.Header - GetHeaderByHash(hash common.Hash) *types.Header - CurrentHeader() *types.Header - GetTd(hash common.Hash, number uint64) *big.Int - StateCache() state.Database - InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) - Rollback(chain []common.Hash) - GetHeaderByNumber(number uint64) *types.Header - GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) - Genesis() *types.Block - SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription -} - -type txPool interface { - AddRemotes(txs []*types.Transaction) []error - AddRemotesSync(txs []*types.Transaction) []error - Status(hashes []common.Hash) []core.TxStatus -} - -type ProtocolManager struct { - // Configs - chainConfig *params.ChainConfig - iConfig *light.IndexerConfig - - client bool // The indicator whether the node is light client - maxPeers int // The maximum number peers allowed to connect. - networkId uint64 // The identity of network. - - txpool txPool - txrelay *lesTxRelay - blockchain BlockChain - chainDb ethdb.Database - odr *LesOdr - server *LesServer - serverPool *serverPool - lesTopic discv5.Topic - reqDist *requestDistributor - retriever *retrieveManager - servingQueue *servingQueue - downloader *downloader.Downloader - fetcher *lightFetcher - ulc *ulc - peers *peerSet - checkpoint *params.TrustedCheckpoint - reg *checkpointOracle // If reg == nil, it means the checkpoint registrar is not activated - - // channels for fetcher, syncer, txsyncLoop - newPeerCh chan *peer - quitSync chan struct{} - noMorePeers chan struct{} - - wg *sync.WaitGroup - eventMux *event.TypeMux - - // Callbacks - synced func() bool - - // Testing fields - addTxsSync bool -} - -// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable -// with the ethereum network. -func NewProtocolManager(chainConfig *params.ChainConfig, checkpoint *params.TrustedCheckpoint, indexerConfig *light.IndexerConfig, ulcServers []string, ulcFraction int, client bool, networkId uint64, mux *event.TypeMux, peers *peerSet, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, serverPool *serverPool, registrar *checkpointOracle, quitSync chan struct{}, wg *sync.WaitGroup, synced func() bool) (*ProtocolManager, error) { - // Create the protocol manager with the base fields - manager := &ProtocolManager{ - client: client, - eventMux: mux, - blockchain: blockchain, - chainConfig: chainConfig, - iConfig: indexerConfig, - chainDb: chainDb, - odr: odr, - networkId: networkId, - txpool: txpool, - serverPool: serverPool, - reg: registrar, - peers: peers, - newPeerCh: make(chan *peer), - quitSync: quitSync, - wg: wg, - noMorePeers: make(chan struct{}), - checkpoint: checkpoint, - synced: synced, - } - if odr != nil { - manager.retriever = odr.retriever - manager.reqDist = odr.retriever.dist - } - - if ulcServers != nil { - ulc, err := newULC(ulcServers, ulcFraction) - if err != nil { - log.Warn("Failed to initialize ultra light client", "err", err) - } else { - manager.ulc = ulc - } - } - removePeer := manager.removePeer - if disableClientRemovePeer { - removePeer = func(id string) {} - } - if client { - var checkpointNumber uint64 - if checkpoint != nil { - checkpointNumber = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 - } - manager.downloader = downloader.New(checkpointNumber, chainDb, nil, manager.eventMux, nil, blockchain, removePeer) - manager.peers.notify((*downloaderPeerNotify)(manager)) - manager.fetcher = newLightFetcher(manager) - } - return manager, nil -} - -// removePeer initiates disconnection from a peer by removing it from the peer set -func (pm *ProtocolManager) removePeer(id string) { - pm.peers.Unregister(id) -} - -func (pm *ProtocolManager) Start(maxPeers int) { - pm.maxPeers = maxPeers - if pm.client { - go pm.syncer() - } else { - go func() { - for range pm.newPeerCh { - } - }() - } -} - -func (pm *ProtocolManager) Stop() { - // Showing a log message. During download / process this could actually - // take between 5 to 10 seconds and therefor feedback is required. - log.Info("Stopping light Ethereum protocol") - - // Quit the sync loop. - // After this send has completed, no new peers will be accepted. - pm.noMorePeers <- struct{}{} - - close(pm.quitSync) // quits syncer, fetcher - - if pm.servingQueue != nil { - pm.servingQueue.stop() - } - - // Disconnect existing sessions. - // This also closes the gate for any new registrations on the peer set. - // sessions which are already established but not added to pm.peers yet - // will exit when they try to register. - pm.peers.Close() - - // Wait for any process action - pm.wg.Wait() - - log.Info("Light Ethereum protocol stopped") -} - -// runPeer is the p2p protocol run function for the given version. -func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { - var entry *poolEntry - peer := pm.newPeer(int(version), pm.networkId, p, rw) - if pm.serverPool != nil { - entry = pm.serverPool.connect(peer, peer.Node()) - } - peer.poolEntry = entry - select { - case pm.newPeerCh <- peer: - pm.wg.Add(1) - defer pm.wg.Done() - err := pm.handle(peer) - if entry != nil { - pm.serverPool.disconnect(entry) - } - return err - case <-pm.quitSync: - if entry != nil { - pm.serverPool.disconnect(entry) - } - return p2p.DiscQuitting - } -} - -func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { - var trusted bool - if pm.ulc != nil { - trusted = pm.ulc.trusted(p.ID()) - } - return newPeer(pv, nv, trusted, p, newMeteredMsgWriter(rw)) -} - -// handle is the callback invoked to manage the life cycle of a les peer. When -// this function terminates, the peer is disconnected. -func (pm *ProtocolManager) handle(p *peer) error { - // Ignore maxPeers if this is a trusted peer - // In server mode we try to check into the client pool after handshake - if pm.client && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { - clientRejectedMeter.Mark(1) - return p2p.DiscTooManyPeers - } - // Reject light clients if server is not synced. - if !pm.client && !pm.synced() { - clientRejectedMeter.Mark(1) - return p2p.DiscRequested - } - p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) - - // Execute the LES handshake - var ( - genesis = pm.blockchain.Genesis() - head = pm.blockchain.CurrentHeader() - hash = head.Hash() - number = head.Number.Uint64() - td = pm.blockchain.GetTd(hash, number) - ) - if err := p.Handshake(td, hash, number, genesis.Hash(), pm.server); err != nil { - p.Log().Debug("Light Ethereum handshake failed", "err", err) - clientErrorMeter.Mark(1) - return err - } - if p.fcClient != nil { - defer p.fcClient.Disconnect() - } - - if rw, ok := p.rw.(*meteredMsgReadWriter); ok { - rw.Init(p.version) - } - - // Register the peer locally - if err := pm.peers.Register(p); err != nil { - clientErrorMeter.Mark(1) - p.Log().Error("Light Ethereum peer registration failed", "err", err) - return err - } - if !pm.client && p.balanceTracker == nil { - // add dummy balance tracker for tests - p.balanceTracker = &balanceTracker{} - p.balanceTracker.init(&mclock.System{}, 1) - } - connectedAt := time.Now() - defer func() { - p.balanceTracker = nil - pm.removePeer(p.id) - connectionTimer.UpdateSince(connectedAt) - }() - - // Register the peer in the downloader. If the downloader considers it banned, we disconnect - if pm.client { - p.lock.Lock() - head := p.headInfo - p.lock.Unlock() - if pm.fetcher != nil { - pm.fetcher.announce(p, head) - } - - if p.poolEntry != nil { - pm.serverPool.registered(p.poolEntry) - } - } - // main loop. handle incoming messages. - for { - if err := pm.handleMsg(p); err != nil { - p.Log().Debug("Light Ethereum message handling failed", "err", err) - if p.fcServer != nil { - p.fcServer.DumpLogs() - } - return err - } - } -} - -// handleMsg is invoked whenever an inbound message is received from a remote -// peer. The remote connection is torn down upon returning any error. -func (pm *ProtocolManager) handleMsg(p *peer) error { - select { - case err := <-p.errCh: - return err - default: - } - // Read the next message from the remote peer, and ensure it's fully consumed - msg, err := p.rw.ReadMsg() - if err != nil { - return err - } - p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) - - p.responseCount++ - responseCount := p.responseCount - var ( - maxCost uint64 - task *servingTask - ) - - accept := func(reqID, reqCnt, maxCnt uint64) bool { - inSizeCost := func() uint64 { - if pm.server.costTracker != nil { - return pm.server.costTracker.realCost(0, msg.Size, 0) - } - return 0 - } - if p.isFrozen() || reqCnt == 0 || p.fcClient == nil || reqCnt > maxCnt { - p.fcClient.OneTimeCost(inSizeCost()) - return false - } - maxCost = p.fcCosts.getMaxCost(msg.Code, reqCnt) - gf := float64(1) - if pm.server.costTracker != nil { - gf = pm.server.costTracker.globalFactor() - if gf < 0.001 { - p.Log().Error("Invalid global cost factor", "globalFactor", gf) - gf = 1 - } - } - maxTime := uint64(float64(maxCost) / gf) - - if accepted, bufShort, servingPriority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost); !accepted { - p.freezeClient() - p.Log().Warn("Request came too early", "remaining", common.PrettyDuration(time.Duration(bufShort*1000000/p.fcParams.MinRecharge))) - p.fcClient.OneTimeCost(inSizeCost()) - return false - } else { - task = pm.servingQueue.newTask(p, maxTime, servingPriority) - } - if task.start() { - return true - } - p.fcClient.RequestProcessed(reqID, responseCount, maxCost, inSizeCost()) - return false - } - - if msg.Size > ProtocolMaxMsgSize { - return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) - } - defer msg.Discard() - - var deliverMsg *Msg - balanceTracker := p.balanceTracker - - sendResponse := func(reqID, amount uint64, reply *reply, servingTime uint64) { - p.responseLock.Lock() - defer p.responseLock.Unlock() - - if p.isFrozen() { - amount = 0 - reply = nil - } - var replySize uint32 - if reply != nil { - replySize = reply.size() - } - var realCost uint64 - if pm.server.costTracker != nil { - realCost = pm.server.costTracker.realCost(servingTime, msg.Size, replySize) - if amount != 0 { - pm.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) - balanceTracker.requestCost(realCost) - } - } else { - realCost = maxCost - } - bv := p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) - if reply != nil { - p.queueSend(func() { - if err := reply.send(bv); err != nil { - select { - case p.errCh <- err: - default: - } - } - }) - } - } - - // Handle the message depending on its contents - switch msg.Code { - case StatusMsg: - p.Log().Trace("Received status message") - // Status messages should never arrive after the handshake - return errResp(ErrExtraStatusMsg, "uncontrolled status message") - - // Block header query, collect the requested headers and reply - case AnnounceMsg: - p.Log().Trace("Received announce message") - var req announceData - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "%v: %v", msg, err) - } - if err := req.sanityCheck(); err != nil { - return err - } - update, size := req.Update.decode() - if p.rejectUpdate(size) { - return errResp(ErrRequestRejected, "") - } - p.updateFlowControl(update) - - if req.Hash != (common.Hash{}) { - if p.announceType == announceTypeNone { - return errResp(ErrUnexpectedResponse, "") - } - if p.announceType == announceTypeSigned { - if err := req.checkSignature(p.ID(), update); err != nil { - p.Log().Trace("Invalid announcement signature", "err", err) - return err - } - p.Log().Trace("Valid announcement signature") - } - - p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) - if pm.fetcher != nil { - pm.fetcher.announce(p, &req) - } - } - - case GetBlockHeadersMsg: - p.Log().Trace("Received block header request") - // Decode the complex header query - var req struct { - ReqID uint64 - Query getBlockHeadersData - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "%v: %v", msg, err) - } - - query := req.Query - if accept(req.ReqID, query.Amount, MaxHeaderFetch) { - go func() { - hashMode := query.Origin.Hash != (common.Hash{}) - first := true - maxNonCanonical := uint64(100) - - // Gather headers until the fetch or network limits is reached - var ( - bytes common.StorageSize - headers []*types.Header - unknown bool - ) - for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { - if !first && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - // Retrieve the next header satisfying the query - var origin *types.Header - if hashMode { - if first { - origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) - if origin != nil { - query.Origin.Number = origin.Number.Uint64() - } - } else { - origin = pm.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) - } - } else { - origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) - } - if origin == nil { - atomic.AddUint32(&p.invalidCount, 1) - break - } - headers = append(headers, origin) - bytes += estHeaderRlpSize - - // Advance to the next header of the query - switch { - case hashMode && query.Reverse: - // Hash based traversal towards the genesis block - ancestor := query.Skip + 1 - if ancestor == 0 { - unknown = true - } else { - query.Origin.Hash, query.Origin.Number = pm.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) - unknown = (query.Origin.Hash == common.Hash{}) - } - case hashMode && !query.Reverse: - // Hash based traversal towards the leaf block - var ( - current = origin.Number.Uint64() - next = current + query.Skip + 1 - ) - if next <= current { - infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") - p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) - unknown = true - } else { - if header := pm.blockchain.GetHeaderByNumber(next); header != nil { - nextHash := header.Hash() - expOldHash, _ := pm.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) - if expOldHash == query.Origin.Hash { - query.Origin.Hash, query.Origin.Number = nextHash, next - } else { - unknown = true - } - } else { - unknown = true - } - } - case query.Reverse: - // Number based traversal towards the genesis block - if query.Origin.Number >= query.Skip+1 { - query.Origin.Number -= query.Skip + 1 - } else { - unknown = true - } - case !query.Reverse: - // Number based traversal towards the leaf block - query.Origin.Number += query.Skip + 1 - } - first = false - } - sendResponse(req.ReqID, query.Amount, p.ReplyBlockHeaders(req.ReqID, headers), task.done()) - }() - } - - case BlockHeadersMsg: - if pm.downloader == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received block header response message") - // A batch of headers arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Headers []*types.Header - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) { - pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) - } else { - err := pm.downloader.DeliverHeaders(p.id, resp.Headers) - if err != nil { - log.Debug(fmt.Sprint(err)) - } - } - - case GetBlockBodiesMsg: - p.Log().Trace("Received block bodies request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather blocks until the fetch or network limits is reached - var ( - bytes int - bodies []rlp.RawValue - ) - reqCnt := len(req.Hashes) - if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { - go func() { - for i, hash := range req.Hashes { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - // Retrieve the requested block body, stopping if enough was found - if bytes >= softResponseLimit { - break - } - number := rawdb.ReadHeaderNumber(pm.chainDb, hash) - if number == nil { - atomic.AddUint32(&p.invalidCount, 1) - continue - } - if data := rawdb.ReadBodyRLP(pm.chainDb, hash, *number); len(data) != 0 { - bodies = append(bodies, data) - bytes += len(data) - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyBlockBodiesRLP(req.ReqID, bodies), task.done()) - }() - } - - case BlockBodiesMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received block bodies response") - // A batch of block bodies arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data []*types.Body - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgBlockBodies, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetCodeMsg: - p.Log().Trace("Received code request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []CodeReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - data [][]byte - ) - reqCnt := len(req.Reqs) - if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { - go func() { - for i, request := range req.Reqs { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - // Look up the root hash belonging to the request - number := rawdb.ReadHeaderNumber(pm.chainDb, request.BHash) - if number == nil { - p.Log().Warn("Failed to retrieve block num for code", "hash", request.BHash) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - header := rawdb.ReadHeader(pm.chainDb, request.BHash, *number) - if header == nil { - p.Log().Warn("Failed to retrieve header for code", "block", *number, "hash", request.BHash) - continue - } - // Refuse to search stale state data in the database since looking for - // a non-exist key is kind of expensive. - local := pm.blockchain.CurrentHeader().Number.Uint64() - if !pm.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { - p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - triedb := pm.blockchain.StateCache().TrieDB() - - account, err := pm.getAccount(triedb, header.Root, common.BytesToHash(request.AccKey)) - if err != nil { - p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - code, err := triedb.Node(common.BytesToHash(account.CodeHash)) - if err != nil { - p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err) - continue - } - // Accumulate the code and abort if enough data was retrieved - data = append(data, code) - if bytes += len(code); bytes >= softResponseLimit { - break - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyCode(req.ReqID, data), task.done()) - }() - } - - case CodeMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received code response") - // A batch of node state data arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data [][]byte - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgCode, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetReceiptsMsg: - p.Log().Trace("Received receipts request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - receipts []rlp.RawValue - ) - reqCnt := len(req.Hashes) - if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { - go func() { - for i, hash := range req.Hashes { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - if bytes >= softResponseLimit { - break - } - // Retrieve the requested block's receipts, skipping if unknown to us - var results types.Receipts - number := rawdb.ReadHeaderNumber(pm.chainDb, hash) - if number == nil { - atomic.AddUint32(&p.invalidCount, 1) - continue - } - results = rawdb.ReadRawReceipts(pm.chainDb, hash, *number) - if results == nil { - if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { - continue - } - } - // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(results); err != nil { - log.Error("Failed to encode receipt", "err", err) - } else { - receipts = append(receipts, encoded) - bytes += len(encoded) - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyReceiptsRLP(req.ReqID, receipts), task.done()) - }() - } - - case ReceiptsMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received receipts response") - // A batch of receipts arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Receipts []types.Receipts - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgReceipts, - ReqID: resp.ReqID, - Obj: resp.Receipts, - } - - case GetProofsV2Msg: - p.Log().Trace("Received les/2 proofs request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []ProofReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - lastBHash common.Hash - root common.Hash - ) - reqCnt := len(req.Reqs) - if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { - go func() { - nodes := light.NewNodeSet() - - for i, request := range req.Reqs { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - // Look up the root hash belonging to the request - var ( - number *uint64 - header *types.Header - trie state.Trie - ) - if request.BHash != lastBHash { - root, lastBHash = common.Hash{}, request.BHash - - if number = rawdb.ReadHeaderNumber(pm.chainDb, request.BHash); number == nil { - p.Log().Warn("Failed to retrieve block num for proof", "hash", request.BHash) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - if header = rawdb.ReadHeader(pm.chainDb, request.BHash, *number); header == nil { - p.Log().Warn("Failed to retrieve header for proof", "block", *number, "hash", request.BHash) - continue - } - // Refuse to search stale state data in the database since looking for - // a non-exist key is kind of expensive. - local := pm.blockchain.CurrentHeader().Number.Uint64() - if !pm.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { - p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - root = header.Root - } - // If a header lookup failed (non existent), ignore subsequent requests for the same header - if root == (common.Hash{}) { - atomic.AddUint32(&p.invalidCount, 1) - continue - } - // Open the account or storage trie for the request - statedb := pm.blockchain.StateCache() - - switch len(request.AccKey) { - case 0: - // No account key specified, open an account trie - trie, err = statedb.OpenTrie(root) - if trie == nil || err != nil { - p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err) - continue - } - default: - // Account key specified, open a storage trie - account, err := pm.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.AccKey)) - if err != nil { - p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) - atomic.AddUint32(&p.invalidCount, 1) - continue - } - trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.AccKey), account.Root) - if trie == nil || err != nil { - p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "root", account.Root, "err", err) - continue - } - } - // Prove the user's request from the account or stroage trie - if err := trie.Prove(request.Key, request.FromLevel, nodes); err != nil { - p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err) - continue - } - if nodes.DataSize() >= softResponseLimit { - break - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyProofsV2(req.ReqID, nodes.NodeList()), task.done()) - }() - } - - case ProofsV2Msg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received les/2 proofs response") - // A batch of merkle proofs arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data light.NodeList - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgProofsV2, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetHelperTrieProofsMsg: - p.Log().Trace("Received helper trie proof request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []HelperTrieReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - auxBytes int - auxData [][]byte - ) - reqCnt := len(req.Reqs) - if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { - go func() { - - var ( - lastIdx uint64 - lastType uint - root common.Hash - auxTrie *trie.Trie - ) - nodes := light.NewNodeSet() - for i, request := range req.Reqs { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - if auxTrie == nil || request.Type != lastType || request.TrieIdx != lastIdx { - auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIdx - - var prefix string - if root, prefix = pm.getHelperTrie(request.Type, request.TrieIdx); root != (common.Hash{}) { - auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(pm.chainDb, prefix))) - } - } - if request.AuxReq == auxRoot { - var data []byte - if root != (common.Hash{}) { - data = root[:] - } - auxData = append(auxData, data) - auxBytes += len(data) - } else { - if auxTrie != nil { - auxTrie.Prove(request.Key, request.FromLevel, nodes) - } - if request.AuxReq != 0 { - data := pm.getHelperTrieAuxData(request) - auxData = append(auxData, data) - auxBytes += len(data) - } - } - if nodes.DataSize()+auxBytes >= softResponseLimit { - break - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyHelperTrieProofs(req.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}), task.done()) - }() - } - - case HelperTrieProofsMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received helper trie proof response") - var resp struct { - ReqID, BV uint64 - Data HelperTrieResps - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgHelperTrieProofs, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case SendTxV2Msg: - if pm.txpool == nil { - return errResp(ErrRequestRejected, "") - } - // Transactions arrived, parse all of them and deliver to the pool - var req struct { - ReqID uint64 - Txs []*types.Transaction - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - reqCnt := len(req.Txs) - if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { - go func() { - stats := make([]light.TxStatus, len(req.Txs)) - for i, tx := range req.Txs { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - hash := tx.Hash() - stats[i] = pm.txStatus(hash) - if stats[i].Status == core.TxStatusUnknown { - addFn := pm.txpool.AddRemotes - // Add txs synchronously for testing purpose - if pm.addTxsSync { - addFn = pm.txpool.AddRemotesSync - } - if errs := addFn([]*types.Transaction{tx}); errs[0] != nil { - stats[i].Error = errs[0].Error() - continue - } - stats[i] = pm.txStatus(hash) - } - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyTxStatus(req.ReqID, stats), task.done()) - }() - } - - case GetTxStatusMsg: - if pm.txpool == nil { - return errResp(ErrUnexpectedResponse, "") - } - // Transactions arrived, parse all of them and deliver to the pool - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - reqCnt := len(req.Hashes) - if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { - go func() { - stats := make([]light.TxStatus, len(req.Hashes)) - for i, hash := range req.Hashes { - if i != 0 && !task.waitOrStop() { - sendResponse(req.ReqID, 0, nil, task.servingTime) - return - } - stats[i] = pm.txStatus(hash) - } - sendResponse(req.ReqID, uint64(reqCnt), p.ReplyTxStatus(req.ReqID, stats), task.done()) - }() - } - - case TxStatusMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received tx status response") - var resp struct { - ReqID, BV uint64 - Status []light.TxStatus - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - - p.fcServer.ReceivedReply(resp.ReqID, resp.BV) - - p.Log().Trace("Received helper trie proof response") - deliverMsg = &Msg{ - MsgType: MsgTxStatus, - ReqID: resp.ReqID, - Obj: resp.Status, - } - - case StopMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - p.freezeServer(true) - pm.retriever.frozen(p) - p.Log().Debug("Service stopped") - - case ResumeMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - var bv uint64 - if err := msg.Decode(&bv); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.ResumeFreeze(bv) - p.freezeServer(false) - p.Log().Debug("Service resumed") - - default: - p.Log().Trace("Received unknown message", "code", msg.Code) - return errResp(ErrInvalidMsgCode, "%v", msg.Code) - } - - if deliverMsg != nil { - err := pm.retriever.deliver(p, deliverMsg) - if err != nil { - p.responseErrors++ - if p.responseErrors > maxResponseErrors { - return err - } - } - } - // If the client has made too much invalid request(e.g. request a non-exist data), - // reject them to prevent SPAM attack. - if atomic.LoadUint32(&p.invalidCount) > maxRequestErrors { - return errTooManyInvalidRequest - } - return nil -} - -// getAccount retrieves an account from the state based at root. -func (pm *ProtocolManager) getAccount(triedb *trie.Database, root, hash common.Hash) (state.Account, error) { - trie, err := trie.New(root, triedb) - if err != nil { - return state.Account{}, err - } - blob, err := trie.TryGet(hash[:]) - if err != nil { - return state.Account{}, err - } - var account state.Account - if err = rlp.DecodeBytes(blob, &account); err != nil { - return state.Account{}, err - } - return account, nil -} - -// getHelperTrie returns the post-processed trie root for the given trie ID and section index -func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) { - switch id { - case htCanonical: - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.ChtSize-1) - return light.GetChtRoot(pm.chainDb, idx, sectionHead), light.ChtTablePrefix - case htBloomBits: - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.BloomTrieSize-1) - return light.GetBloomTrieRoot(pm.chainDb, idx, sectionHead), light.BloomTrieTablePrefix - } - return common.Hash{}, "" -} - -// getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request -func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte { - if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { - blockNum := binary.BigEndian.Uint64(req.Key) - hash := rawdb.ReadCanonicalHash(pm.chainDb, blockNum) - return rawdb.ReadHeaderRLP(pm.chainDb, hash, blockNum) - } - return nil -} - -func (pm *ProtocolManager) txStatus(hash common.Hash) light.TxStatus { - var stat light.TxStatus - stat.Status = pm.txpool.Status([]common.Hash{hash})[0] - // If the transaction is unknown to the pool, try looking it up locally - if stat.Status == core.TxStatusUnknown { - if tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(pm.chainDb, hash); tx != nil { - stat.Status = core.TxStatusIncluded - stat.Lookup = &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} - } - } - return stat -} - -// downloaderPeerNotify implements peerSetNotify -type downloaderPeerNotify ProtocolManager - -type peerConnection struct { - manager *ProtocolManager - peer *peer -} - -func (pc *peerConnection) Head() (common.Hash, *big.Int) { - return pc.peer.HeadAndTd() -} - -func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { - reqID := genReqID() - rq := &distReq{ - getCost: func(dp distPeer) uint64 { - peer := dp.(*peer) - return peer.GetRequestCost(GetBlockHeadersMsg, amount) - }, - canSend: func(dp distPeer) bool { - return dp.(*peer) == pc.peer - }, - request: func(dp distPeer) func() { - peer := dp.(*peer) - cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) - peer.fcServer.QueuedRequest(reqID, cost) - return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } - }, - } - _, ok := <-pc.manager.reqDist.queue(rq) - if !ok { - return light.ErrNoPeers - } - return nil -} - -func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { - reqID := genReqID() - rq := &distReq{ - getCost: func(dp distPeer) uint64 { - peer := dp.(*peer) - return peer.GetRequestCost(GetBlockHeadersMsg, amount) - }, - canSend: func(dp distPeer) bool { - return dp.(*peer) == pc.peer - }, - request: func(dp distPeer) func() { - peer := dp.(*peer) - cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) - peer.fcServer.QueuedRequest(reqID, cost) - return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } - }, - } - _, ok := <-pc.manager.reqDist.queue(rq) - if !ok { - return light.ErrNoPeers - } - return nil -} - -func (d *downloaderPeerNotify) registerPeer(p *peer) { - pm := (*ProtocolManager)(d) - pc := &peerConnection{ - manager: pm, - peer: p, - } - pm.downloader.RegisterLightPeer(p.id, ethVersion, pc) -} - -func (d *downloaderPeerNotify) unregisterPeer(p *peer) { - pm := (*ProtocolManager)(d) - pm.downloader.UnregisterPeer(p.id) -} diff --git a/vendor/github.com/ethereum/go-ethereum/les/metrics.go b/vendor/github.com/ethereum/go-ethereum/les/metrics.go index 4fe7031163..9ef8c36518 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/les/metrics.go @@ -22,31 +22,91 @@ import ( ) var ( - miscInPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets", nil) - miscInTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic", nil) - miscOutPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets", nil) - miscOutTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic", nil) - - connectionTimer = metrics.NewRegisteredTimer("les/connectionTime", nil) - - totalConnectedGauge = metrics.NewRegisteredGauge("les/server/totalConnected", nil) - totalCapacityGauge = metrics.NewRegisteredGauge("les/server/totalCapacity", nil) - totalRechargeGauge = metrics.NewRegisteredGauge("les/server/totalRecharge", nil) - blockProcessingTimer = metrics.NewRegisteredTimer("les/server/blockProcessingTime", nil) - requestServedTimer = metrics.NewRegisteredTimer("les/server/requestServed", nil) - requestServedMeter = metrics.NewRegisteredMeter("les/server/totalRequestServed", nil) - requestEstimatedMeter = metrics.NewRegisteredMeter("les/server/totalRequestEstimated", nil) - relativeCostHistogram = metrics.NewRegisteredHistogram("les/server/relativeCost", nil, metrics.NewExpDecaySample(1028, 0.015)) - recentServedGauge = metrics.NewRegisteredGauge("les/server/recentRequestServed", nil) - recentEstimatedGauge = metrics.NewRegisteredGauge("les/server/recentRequestEstimated", nil) - sqServedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/served", nil) - sqQueuedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/queued", nil) + miscInPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/total", nil) + miscInTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/total", nil) + miscInHeaderPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/header", nil) + miscInHeaderTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/header", nil) + miscInBodyPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/body", nil) + miscInBodyTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/body", nil) + miscInCodePacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/code", nil) + miscInCodeTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/code", nil) + miscInReceiptPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/receipt", nil) + miscInReceiptTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/receipt", nil) + miscInTrieProofPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/proof", nil) + miscInTrieProofTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/proof", nil) + miscInHelperTriePacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/helperTrie", nil) + miscInHelperTrieTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/helperTrie", nil) + miscInTxsPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/txs", nil) + miscInTxsTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/txs", nil) + miscInTxStatusPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/txStatus", nil) + miscInTxStatusTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/txStatus", nil) + + miscOutPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/total", nil) + miscOutTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/total", nil) + miscOutHeaderPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/header", nil) + miscOutHeaderTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/header", nil) + miscOutBodyPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/body", nil) + miscOutBodyTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/body", nil) + miscOutCodePacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/code", nil) + miscOutCodeTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/code", nil) + miscOutReceiptPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/receipt", nil) + miscOutReceiptTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/receipt", nil) + miscOutTrieProofPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/proof", nil) + miscOutTrieProofTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/proof", nil) + miscOutHelperTriePacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/helperTrie", nil) + miscOutHelperTrieTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/helperTrie", nil) + miscOutTxsPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/txs", nil) + miscOutTxsTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/txs", nil) + miscOutTxStatusPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/txStatus", nil) + miscOutTxStatusTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/txStatus", nil) + + miscServingTimeHeaderTimer = metrics.NewRegisteredTimer("les/misc/serve/header", nil) + miscServingTimeBodyTimer = metrics.NewRegisteredTimer("les/misc/serve/body", nil) + miscServingTimeCodeTimer = metrics.NewRegisteredTimer("les/misc/serve/code", nil) + miscServingTimeReceiptTimer = metrics.NewRegisteredTimer("les/misc/serve/receipt", nil) + miscServingTimeTrieProofTimer = metrics.NewRegisteredTimer("les/misc/serve/proof", nil) + miscServingTimeHelperTrieTimer = metrics.NewRegisteredTimer("les/misc/serve/helperTrie", nil) + miscServingTimeTxTimer = metrics.NewRegisteredTimer("les/misc/serve/txs", nil) + miscServingTimeTxStatusTimer = metrics.NewRegisteredTimer("les/misc/serve/txStatus", nil) + + connectionTimer = metrics.NewRegisteredTimer("les/connection/duration", nil) + serverConnectionGauge = metrics.NewRegisteredGauge("les/connection/server", nil) + clientConnectionGauge = metrics.NewRegisteredGauge("les/connection/client", nil) + + totalCapacityGauge = metrics.NewRegisteredGauge("les/server/totalCapacity", nil) + totalRechargeGauge = metrics.NewRegisteredGauge("les/server/totalRecharge", nil) + totalConnectedGauge = metrics.NewRegisteredGauge("les/server/totalConnected", nil) + blockProcessingTimer = metrics.NewRegisteredTimer("les/server/blockProcessingTime", nil) + + requestServedMeter = metrics.NewRegisteredMeter("les/server/req/avgServedTime", nil) + requestServedTimer = metrics.NewRegisteredTimer("les/server/req/servedTime", nil) + requestEstimatedMeter = metrics.NewRegisteredMeter("les/server/req/avgEstimatedTime", nil) + requestEstimatedTimer = metrics.NewRegisteredTimer("les/server/req/estimatedTime", nil) + relativeCostHistogram = metrics.NewRegisteredHistogram("les/server/req/relative", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostHeaderHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/header", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostBodyHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/body", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostReceiptHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/receipt", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostCodeHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/code", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostProofHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/proof", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostHelperProofHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/helperTrie", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostSendTxHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/txs", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostTxStatusHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/txStatus", nil, metrics.NewExpDecaySample(1028, 0.015)) + + globalFactorGauge = metrics.NewRegisteredGauge("les/server/globalFactor", nil) + recentServedGauge = metrics.NewRegisteredGauge("les/server/recentRequestServed", nil) + recentEstimatedGauge = metrics.NewRegisteredGauge("les/server/recentRequestEstimated", nil) + sqServedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/served", nil) + sqQueuedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/queued", nil) + clientConnectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/connected", nil) clientRejectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/rejected", nil) clientKickedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/kicked", nil) clientDisconnectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/disconnected", nil) clientFreezeMeter = metrics.NewRegisteredMeter("les/server/clientEvent/freeze", nil) clientErrorMeter = metrics.NewRegisteredMeter("les/server/clientEvent/error", nil) + + requestRTT = metrics.NewRegisteredTimer("les/client/req/rtt", nil) + requestSendDelay = metrics.NewRegisteredTimer("les/client/req/sendDelay", nil) ) // meteredMsgReadWriter is a wrapper around a p2p.MsgReadWriter, capable of @@ -58,17 +118,11 @@ type meteredMsgReadWriter struct { // newMeteredMsgWriter wraps a p2p MsgReadWriter with metering support. If the // metrics system is disabled, this function returns the original object. -func newMeteredMsgWriter(rw p2p.MsgReadWriter) p2p.MsgReadWriter { +func newMeteredMsgWriter(rw p2p.MsgReadWriter, version int) p2p.MsgReadWriter { if !metrics.Enabled { return rw } - return &meteredMsgReadWriter{MsgReadWriter: rw} -} - -// Init sets the protocol version used by the stream to know which meters to -// increment in case of overlapping message ids between protocol versions. -func (rw *meteredMsgReadWriter) Init(version int) { - rw.version = version + return &meteredMsgReadWriter{MsgReadWriter: rw, version: version} } func (rw *meteredMsgReadWriter) ReadMsg() (p2p.Msg, error) { diff --git a/vendor/github.com/ethereum/go-ethereum/les/odr.go b/vendor/github.com/ethereum/go-ethereum/les/odr.go index a26c06680b..136ecf4df4 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/odr.go +++ b/vendor/github.com/ethereum/go-ethereum/les/odr.go @@ -18,7 +18,9 @@ package les import ( "context" + "time" + "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/light" @@ -120,10 +122,11 @@ func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err erro return func() { lreq.Request(reqID, p) } }, } - + sent := mclock.Now() if err = odr.retriever.retrieve(ctx, reqID, rq, func(p distPeer, msg *Msg) error { return lreq.Validate(odr.db, msg) }, odr.stop); err == nil { // retrieved from network, store in db req.StoreResult(odr.db) + requestRTT.Update(time.Duration(mclock.Now() - sent)) } else { log.Debug("Failed to retrieve data from network", "err", err) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/peer.go b/vendor/github.com/ethereum/go-ethereum/les/peer.go index bcd91cd835..ab5b30a657 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/les/peer.go @@ -94,6 +94,7 @@ type peer struct { sendQueue *execQueue errCh chan error + // responseLock ensures that responses are queued in the same order as // RequestProcessed is called responseLock sync.Mutex @@ -107,11 +108,10 @@ type peer struct { updateTime mclock.AbsTime frozen uint32 // 1 if client is in frozen state - fcClient *flowcontrol.ClientNode // nil if the peer is server only - fcServer *flowcontrol.ServerNode // nil if the peer is client only - fcParams flowcontrol.ServerParams - fcCosts requestCostTable - balanceTracker *balanceTracker // set by clientPool.connect, used and removed by ProtocolManager.handle + fcClient *flowcontrol.ClientNode // nil if the peer is server only + fcServer *flowcontrol.ServerNode // nil if the peer is client only + fcParams flowcontrol.ServerParams + fcCosts requestCostTable trusted bool onlyAnnounce bool @@ -291,6 +291,11 @@ func (p *peer) updateCapacity(cap uint64) { p.queueSend(func() { p.SendAnnounce(announceData{Update: kvList}) }) } +func (p *peer) responseID() uint64 { + p.responseCount += 1 + return p.responseCount +} + func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) error { type req struct { ReqID uint64 @@ -373,6 +378,7 @@ func (p *peer) HasBlock(hash common.Hash, number uint64, hasState bool) bool { } hasBlock := p.hasBlock p.lock.RUnlock() + return head >= number && number >= since && (recent == 0 || number+recent+4 > head) && hasBlock != nil && hasBlock(hash, number, hasState) } @@ -571,6 +577,8 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis defer p.lock.Unlock() var send keyValueList + + // Add some basic handshake fields send = send.add("protocolVersion", uint64(p.version)) send = send.add("networkId", p.network) send = send.add("headTd", td) @@ -578,7 +586,8 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis send = send.add("headNum", headNum) send = send.add("genesisHash", genesis) if server != nil { - if !server.onlyAnnounce { + // Add some information which services server can offer. + if !server.config.UltraLightOnlyAnnounce { send = send.add("serveHeaders", nil) send = send.add("serveChainSince", uint64(0)) send = send.add("serveStateSince", uint64(0)) @@ -594,25 +603,28 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis } send = send.add("flowControl/BL", server.defParams.BufLimit) send = send.add("flowControl/MRR", server.defParams.MinRecharge) + var costList RequestCostList - if server.costTracker != nil { - costList = server.costTracker.makeCostList(server.costTracker.globalFactor()) + if server.costTracker.testCostList != nil { + costList = server.costTracker.testCostList } else { - costList = testCostList(server.testCost) + costList = server.costTracker.makeCostList(server.costTracker.globalFactor()) } send = send.add("flowControl/MRC", costList) p.fcCosts = costList.decode(ProtocolLengths[uint(p.version)]) p.fcParams = server.defParams - if server.protocolManager != nil && server.protocolManager.reg != nil && server.protocolManager.reg.isRunning() { - cp, height := server.protocolManager.reg.stableCheckpoint() + // Add advertised checkpoint and register block height which + // client can verify the checkpoint validity. + if server.oracle != nil && server.oracle.isRunning() { + cp, height := server.oracle.stableCheckpoint() if cp != nil { send = send.add("checkpoint/value", cp) send = send.add("checkpoint/registerHeight", height) } } } else { - //on client node + // Add some client-specific handshake fields p.announceType = announceTypeSimple if p.trusted { p.announceType = announceTypeSigned @@ -663,17 +675,12 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis } if server != nil { - // until we have a proper peer connectivity API, allow LES connection to other servers - /*if recv.get("serveStateSince", nil) == nil { - return errResp(ErrUselessPeer, "wanted client, got server") - }*/ if recv.get("announceType", &p.announceType) != nil { - //set default announceType on server side + // set default announceType on server side p.announceType = announceTypeSimple } p.fcClient = flowcontrol.NewClientNode(server.fcManager, server.defParams) } else { - //mark OnlyAnnounce server if "serveHeaders", "serveChainSince", "serveStateSince" or "txRelay" fields don't exist if recv.get("serveChainSince", &p.chainSince) != nil { p.onlyAnnounce = true } @@ -730,15 +737,10 @@ func (p *peer) updateFlowControl(update keyValueMap) { if p.fcServer == nil { return } - params := p.fcParams - updateParams := false - if update.get("flowControl/BL", ¶ms.BufLimit) == nil { - updateParams = true - } - if update.get("flowControl/MRR", ¶ms.MinRecharge) == nil { - updateParams = true - } - if updateParams { + // If any of the flow control params is nil, refuse to update. + var params flowcontrol.ServerParams + if update.get("flowControl/BL", ¶ms.BufLimit) == nil && update.get("flowControl/MRR", ¶ms.MinRecharge) == nil { + // todo can light client set a minimal acceptable flow control params? p.fcParams = params p.fcServer.UpdateParams(params) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/server.go b/vendor/github.com/ethereum/go-ethereum/les/server.go index 97e82a42b2..997a24191b 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/server.go +++ b/vendor/github.com/ethereum/go-ethereum/les/server.go @@ -18,15 +18,11 @@ package les import ( "crypto/ecdsa" - "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/light" @@ -34,84 +30,98 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) -const bufLimitRatio = 6000 // fixed bufLimit/MRR ratio - type LesServer struct { lesCommons archiveMode bool // Flag whether the ethereum node runs in archive mode. + handler *serverHandler + lesTopics []discv5.Topic + privateKey *ecdsa.PrivateKey - fcManager *flowcontrol.ClientManager // nil if our node is client only + // Flow control and capacity management + fcManager *flowcontrol.ClientManager costTracker *costTracker - testCost uint64 defParams flowcontrol.ServerParams - lesTopics []discv5.Topic - privateKey *ecdsa.PrivateKey - quitSync chan struct{} - onlyAnnounce bool - - thcNormal, thcBlockProcessing int // serving thread count for normal operation and block processing mode + servingQueue *servingQueue + clientPool *clientPool - maxPeers int - minCapacity, maxCapacity, freeClientCap uint64 - clientPool *clientPool + freeCapacity uint64 // The minimal client capacity used for free client. + threadsIdle int // Request serving threads count when system is idle. + threadsBusy int // Request serving threads count when system is busy(block insertion). } func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) { + // Collect les protocol version information supported by local node. lesTopics := make([]discv5.Topic, len(AdvertiseProtocolVersions)) for i, pv := range AdvertiseProtocolVersions { lesTopics[i] = lesTopic(e.BlockChain().Genesis().Hash(), pv) } - quitSync := make(chan struct{}) + // Calculate the number of threads used to service the light client + // requests based on the user-specified value. + threads := config.LightServ * 4 / 100 + if threads < 4 { + threads = 4 + } srv := &LesServer{ lesCommons: lesCommons{ + genesis: e.BlockChain().Genesis().Hash(), config: config, + chainConfig: e.BlockChain().Config(), iConfig: light.DefaultServerIndexerConfig, chainDb: e.ChainDb(), + peers: newPeerSet(), + chainReader: e.BlockChain(), chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations), bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency), + closeCh: make(chan struct{}), }, archiveMode: e.ArchiveMode(), - quitSync: quitSync, lesTopics: lesTopics, - onlyAnnounce: config.UltraLightOnlyAnnounce, + fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}), + servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100), + threadsBusy: config.LightServ/100 + 1, + threadsIdle: threads, + } + srv.handler = newServerHandler(srv, e.BlockChain(), e.ChainDb(), e.TxPool(), e.Synced) + srv.costTracker, srv.freeCapacity = newCostTracker(e.ChainDb(), config) + + // Set up checkpoint oracle. + oracle := config.CheckpointOracle + if oracle == nil { + oracle = params.CheckpointOracles[e.BlockChain().Genesis().Hash()] } - srv.costTracker, srv.minCapacity = newCostTracker(e.ChainDb(), config) + srv.oracle = newCheckpointOracle(oracle, srv.localCheckpoint) - logger := log.New() - srv.thcNormal = config.LightServ * 4 / 100 - if srv.thcNormal < 4 { - srv.thcNormal = 4 + // Initialize server capacity management fields. + srv.defParams = flowcontrol.ServerParams{ + BufLimit: srv.freeCapacity * bufLimitRatio, + MinRecharge: srv.freeCapacity, } - srv.thcBlockProcessing = config.LightServ/100 + 1 - srv.fcManager = flowcontrol.NewClientManager(nil, &mclock.System{}) + // LES flow control tries to more or less guarantee the possibility for the + // clients to send a certain amount of requests at any time and get a quick + // response. Most of the clients want this guarantee but don't actually need + // to send requests most of the time. Our goal is to serve as many clients as + // possible while the actually used server capacity does not exceed the limits + totalRecharge := srv.costTracker.totalRecharge() + maxCapacity := srv.freeCapacity * uint64(srv.config.LightPeers) + if totalRecharge > maxCapacity { + maxCapacity = totalRecharge + } + srv.fcManager.SetCapacityLimits(srv.freeCapacity, maxCapacity, srv.freeCapacity*2) + srv.clientPool = newClientPool(srv.chainDb, srv.freeCapacity, mclock.System{}, func(id enode.ID) { go srv.peers.Unregister(peerIdToString(id)) }) + srv.clientPool.setPriceFactors(priceFactors{0, 1, 1}, priceFactors{0, 1, 1}) checkpoint := srv.latestLocalCheckpoint() if !checkpoint.Empty() { - logger.Info("Loaded latest checkpoint", "section", checkpoint.SectionIndex, "head", checkpoint.SectionHead, + log.Info("Loaded latest checkpoint", "section", checkpoint.SectionIndex, "head", checkpoint.SectionHead, "chtroot", checkpoint.CHTRoot, "bloomroot", checkpoint.BloomRoot) } - srv.chtIndexer.Start(e.BlockChain()) - - oracle := config.CheckpointOracle - if oracle == nil { - oracle = params.CheckpointOracles[e.BlockChain().Genesis().Hash()] - } - registrar := newCheckpointOracle(oracle, srv.getLocalCheckpoint) - // TODO(rjl493456442) Checkpoint is useless for les server, separate handler for client and server. - pm, err := NewProtocolManager(e.BlockChain().Config(), nil, light.DefaultServerIndexerConfig, config.UltraLightServers, config.UltraLightFraction, false, config.NetworkId, e.EventMux(), newPeerSet(), e.BlockChain(), e.TxPool(), e.ChainDb(), nil, nil, registrar, quitSync, new(sync.WaitGroup), e.Synced) - if err != nil { - return nil, err - } - srv.protocolManager = pm - pm.servingQueue = newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100) - pm.server = srv - return srv, nil } @@ -120,102 +130,34 @@ func (s *LesServer) APIs() []rpc.API { { Namespace: "les", Version: "1.0", - Service: NewPrivateLightAPI(&s.lesCommons, s.protocolManager.reg), + Service: NewPrivateLightAPI(&s.lesCommons), Public: false, }, } } -// startEventLoop starts an event handler loop that updates the recharge curve of -// the client manager and adjusts the client pool's size according to the total -// capacity updates coming from the client manager -func (s *LesServer) startEventLoop() { - s.protocolManager.wg.Add(1) - - var ( - processing, procLast bool - procStarted time.Time - ) - blockProcFeed := make(chan bool, 100) - s.protocolManager.blockchain.(*core.BlockChain).SubscribeBlockProcessingEvent(blockProcFeed) - totalRechargeCh := make(chan uint64, 100) - totalRecharge := s.costTracker.subscribeTotalRecharge(totalRechargeCh) - totalCapacityCh := make(chan uint64, 100) - updateRecharge := func() { - if processing { - if !procLast { - procStarted = time.Now() - } - s.protocolManager.servingQueue.setThreads(s.thcBlockProcessing) - s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge, totalRecharge}}) - } else { - if procLast { - blockProcessingTimer.UpdateSince(procStarted) - } - s.protocolManager.servingQueue.setThreads(s.thcNormal) - s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge / 16, totalRecharge / 2}, {totalRecharge / 2, totalRecharge / 2}, {totalRecharge, totalRecharge}}) +func (s *LesServer) Protocols() []p2p.Protocol { + ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { + if p := s.peers.Peer(peerIdToString(id)); p != nil { + return p.Info() } - procLast = processing + return nil + }) + // Add "les" ENR entries. + for i := range ps { + ps[i].Attributes = []enr.Entry{&lesEntry{}} } - updateRecharge() - totalCapacity := s.fcManager.SubscribeTotalCapacity(totalCapacityCh) - s.clientPool.setLimits(s.maxPeers, totalCapacity) - - var maxFreePeers uint64 - go func() { - for { - select { - case processing = <-blockProcFeed: - updateRecharge() - case totalRecharge = <-totalRechargeCh: - updateRecharge() - case totalCapacity = <-totalCapacityCh: - totalCapacityGauge.Update(int64(totalCapacity)) - newFreePeers := totalCapacity / s.freeClientCap - if newFreePeers < maxFreePeers && newFreePeers < uint64(s.maxPeers) { - log.Warn("Reduced total capacity", "maxFreePeers", newFreePeers) - } - maxFreePeers = newFreePeers - s.clientPool.setLimits(s.maxPeers, totalCapacity) - case <-s.protocolManager.quitSync: - s.protocolManager.wg.Done() - return - } - } - }() -} - -func (s *LesServer) Protocols() []p2p.Protocol { - return s.makeProtocols(ServerProtocolVersions) + return ps } // Start starts the LES server func (s *LesServer) Start(srvr *p2p.Server) { - s.maxPeers = s.config.LightPeers - totalRecharge := s.costTracker.totalRecharge() - if s.maxPeers > 0 { - s.freeClientCap = s.minCapacity //totalRecharge / uint64(s.maxPeers) - if s.freeClientCap < s.minCapacity { - s.freeClientCap = s.minCapacity - } - if s.freeClientCap > 0 { - s.defParams = flowcontrol.ServerParams{ - BufLimit: s.freeClientCap * bufLimitRatio, - MinRecharge: s.freeClientCap, - } - } - } + s.privateKey = srvr.PrivateKey + s.handler.start() + + s.wg.Add(1) + go s.capacityManagement() - s.maxCapacity = s.freeClientCap * uint64(s.maxPeers) - if totalRecharge > s.maxCapacity { - s.maxCapacity = totalRecharge - } - s.fcManager.SetCapacityLimits(s.freeClientCap, s.maxCapacity, s.freeClientCap*2) - s.clientPool = newClientPool(s.chainDb, s.freeClientCap, 10000, mclock.System{}, func(id enode.ID) { go s.protocolManager.removePeer(peerIdToString(id)) }) - s.clientPool.setPriceFactors(priceFactors{0, 1, 1}, priceFactors{0, 1, 1}) - s.protocolManager.peers.notify(s.clientPool) - s.startEventLoop() - s.protocolManager.Start(s.config.LightPeers) if srvr.DiscV5 != nil { for _, topic := range s.lesTopics { topic := topic @@ -224,12 +166,32 @@ func (s *LesServer) Start(srvr *p2p.Server) { logger.Info("Starting topic registration") defer logger.Info("Terminated topic registration") - srvr.DiscV5.RegisterTopic(topic, s.quitSync) + srvr.DiscV5.RegisterTopic(topic, s.closeCh) }() } } - s.privateKey = srvr.PrivateKey - s.protocolManager.blockLoop() +} + +// Stop stops the LES service +func (s *LesServer) Stop() { + close(s.closeCh) + + // Disconnect existing sessions. + // This also closes the gate for any new registrations on the peer set. + // sessions which are already established but not added to pm.peers yet + // will exit when they try to register. + s.peers.Close() + + s.fcManager.Stop() + s.costTracker.stop() + s.handler.stop() + s.clientPool.stop() // client pool should be closed after handler. + s.servingQueue.stop() + + // Note, bloom trie indexer is closed by parent bloombits indexer. + s.chtIndexer.Close() + s.wg.Wait() + log.Info("Les server stopped") } func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) { @@ -238,78 +200,67 @@ func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) { // SetClient sets the rpc client and starts running checkpoint contract if it is not yet watched. func (s *LesServer) SetContractBackend(backend bind.ContractBackend) { - if s.protocolManager.reg != nil { - s.protocolManager.reg.start(backend) + if s.oracle == nil { + return } + s.oracle.start(backend) } -// Stop stops the LES service -func (s *LesServer) Stop() { - s.fcManager.Stop() - s.chtIndexer.Close() - // bloom trie indexer is closed by parent bloombits indexer - go func() { - <-s.protocolManager.noMorePeers - }() - s.clientPool.stop() - s.costTracker.stop() - s.protocolManager.Stop() -} +// capacityManagement starts an event handler loop that updates the recharge curve of +// the client manager and adjusts the client pool's size according to the total +// capacity updates coming from the client manager +func (s *LesServer) capacityManagement() { + defer s.wg.Done() -// todo(rjl493456442) separate client and server implementation. -func (pm *ProtocolManager) blockLoop() { - pm.wg.Add(1) - headCh := make(chan core.ChainHeadEvent, 10) - headSub := pm.blockchain.SubscribeChainHeadEvent(headCh) - go func() { - var lastHead *types.Header - lastBroadcastTd := common.Big0 - for { - select { - case ev := <-headCh: - peers := pm.peers.AllPeers() - if len(peers) > 0 { - header := ev.Block.Header() - hash := header.Hash() - number := header.Number.Uint64() - td := rawdb.ReadTd(pm.chainDb, hash, number) - if td != nil && td.Cmp(lastBroadcastTd) > 0 { - var reorg uint64 - if lastHead != nil { - reorg = lastHead.Number.Uint64() - rawdb.FindCommonAncestor(pm.chainDb, header, lastHead).Number.Uint64() - } - lastHead = header - lastBroadcastTd = td + processCh := make(chan bool, 100) + sub := s.handler.blockchain.SubscribeBlockProcessingEvent(processCh) + defer sub.Unsubscribe() - log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg) + totalRechargeCh := make(chan uint64, 100) + totalRecharge := s.costTracker.subscribeTotalRecharge(totalRechargeCh) + + totalCapacityCh := make(chan uint64, 100) + totalCapacity := s.fcManager.SubscribeTotalCapacity(totalCapacityCh) + s.clientPool.setLimits(s.config.LightPeers, totalCapacity) - announce := announceData{Hash: hash, Number: number, Td: td, ReorgDepth: reorg} - var ( - signed bool - signedAnnounce announceData - ) + var ( + busy bool + freePeers uint64 + blockProcess mclock.AbsTime + ) + updateRecharge := func() { + if busy { + s.servingQueue.setThreads(s.threadsBusy) + s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge, totalRecharge}}) + } else { + s.servingQueue.setThreads(s.threadsIdle) + s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge / 10, totalRecharge}, {totalRecharge, totalRecharge}}) + } + } + updateRecharge() - for _, p := range peers { - p := p - switch p.announceType { - case announceTypeSimple: - p.queueSend(func() { p.SendAnnounce(announce) }) - case announceTypeSigned: - if !signed { - signedAnnounce = announce - signedAnnounce.sign(pm.server.privateKey) - signed = true - } - p.queueSend(func() { p.SendAnnounce(signedAnnounce) }) - } - } - } - } - case <-pm.quitSync: - headSub.Unsubscribe() - pm.wg.Done() - return + for { + select { + case busy = <-processCh: + if busy { + blockProcess = mclock.Now() + } else { + blockProcessingTimer.Update(time.Duration(mclock.Now() - blockProcess)) } + updateRecharge() + case totalRecharge = <-totalRechargeCh: + totalRechargeGauge.Update(int64(totalRecharge)) + updateRecharge() + case totalCapacity = <-totalCapacityCh: + totalCapacityGauge.Update(int64(totalCapacity)) + newFreePeers := totalCapacity / s.freeCapacity + if newFreePeers < freePeers && newFreePeers < uint64(s.config.LightPeers) { + log.Warn("Reduced free peer connections", "from", freePeers, "to", newFreePeers) + } + freePeers = newFreePeers + s.clientPool.setLimits(s.config.LightPeers, totalCapacity) + case <-s.closeCh: + return } - }() + } } diff --git a/vendor/github.com/ethereum/go-ethereum/les/server_handler.go b/vendor/github.com/ethereum/go-ethereum/les/server_handler.go new file mode 100644 index 0000000000..16249ef1ba --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/server_handler.go @@ -0,0 +1,950 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package les + +import ( + "encoding/binary" + "encoding/json" + "errors" + "sync" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +const ( + softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. + estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header + ethVersion = 63 // equivalent eth version for the downloader + + MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request + MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request + MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request + MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request + MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request + MaxHelperTrieProofsFetch = 64 // Amount of helper tries to be fetched per retrieval request + MaxTxSend = 64 // Amount of transactions to be send per request + MaxTxStatus = 256 // Amount of transactions to queried per request +) + +var ( + errTooManyInvalidRequest = errors.New("too many invalid requests made") + errFullClientPool = errors.New("client pool is full") +) + +// serverHandler is responsible for serving light client and process +// all incoming light requests. +type serverHandler struct { + blockchain *core.BlockChain + chainDb ethdb.Database + txpool *core.TxPool + server *LesServer + + closeCh chan struct{} // Channel used to exit all background routines of handler. + wg sync.WaitGroup // WaitGroup used to track all background routines of handler. + synced func() bool // Callback function used to determine whether local node is synced. + + // Testing fields + addTxsSync bool +} + +func newServerHandler(server *LesServer, blockchain *core.BlockChain, chainDb ethdb.Database, txpool *core.TxPool, synced func() bool) *serverHandler { + handler := &serverHandler{ + server: server, + blockchain: blockchain, + chainDb: chainDb, + txpool: txpool, + closeCh: make(chan struct{}), + synced: synced, + } + return handler +} + +// start starts the server handler. +func (h *serverHandler) start() { + h.wg.Add(1) + go h.broadcastHeaders() +} + +// stop stops the server handler. +func (h *serverHandler) stop() { + close(h.closeCh) + h.wg.Wait() +} + +// runPeer is the p2p protocol run function for the given version. +func (h *serverHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { + peer := newPeer(int(version), h.server.config.NetworkId, false, p, newMeteredMsgWriter(rw, int(version))) + h.wg.Add(1) + defer h.wg.Done() + return h.handle(peer) +} + +func (h *serverHandler) handle(p *peer) error { + // Reject light clients if server is not synced. + if !h.synced() { + return p2p.DiscRequested + } + p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) + + // Execute the LES handshake + var ( + head = h.blockchain.CurrentHeader() + hash = head.Hash() + number = head.Number.Uint64() + td = h.blockchain.GetTd(hash, number) + ) + if err := p.Handshake(td, hash, number, h.blockchain.Genesis().Hash(), h.server); err != nil { + p.Log().Debug("Light Ethereum handshake failed", "err", err) + return err + } + defer p.fcClient.Disconnect() + + // Disconnect the inbound peer if it's rejected by clientPool + if !h.server.clientPool.connect(p, 0) { + p.Log().Debug("Light Ethereum peer registration failed", "err", errFullClientPool) + return errFullClientPool + } + // Register the peer locally + if err := h.server.peers.Register(p); err != nil { + h.server.clientPool.disconnect(p) + p.Log().Error("Light Ethereum peer registration failed", "err", err) + return err + } + clientConnectionGauge.Update(int64(h.server.peers.Len())) + + var wg sync.WaitGroup // Wait group used to track all in-flight task routines. + + connectedAt := mclock.Now() + defer func() { + wg.Wait() // Ensure all background task routines have exited. + h.server.peers.Unregister(p.id) + h.server.clientPool.disconnect(p) + clientConnectionGauge.Update(int64(h.server.peers.Len())) + connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) + }() + + // Spawn a main loop to handle all incoming messages. + for { + select { + case err := <-p.errCh: + p.Log().Debug("Failed to send light ethereum response", "err", err) + return err + default: + } + if err := h.handleMsg(p, &wg); err != nil { + p.Log().Debug("Light Ethereum message handling failed", "err", err) + return err + } + } +} + +// handleMsg is invoked whenever an inbound message is received from a remote +// peer. The remote connection is torn down upon returning any error. +func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error { + // Read the next message from the remote peer, and ensure it's fully consumed + msg, err := p.rw.ReadMsg() + if err != nil { + return err + } + p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) + + // Discard large message which exceeds the limitation. + if msg.Size > ProtocolMaxMsgSize { + clientErrorMeter.Mark(1) + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + } + defer msg.Discard() + + var ( + maxCost uint64 + task *servingTask + ) + p.responseCount++ + responseCount := p.responseCount + // accept returns an indicator whether the request can be served. + // If so, deduct the max cost from the flow control buffer. + accept := func(reqID, reqCnt, maxCnt uint64) bool { + // Short circuit if the peer is already frozen or the request is invalid. + inSizeCost := h.server.costTracker.realCost(0, msg.Size, 0) + if p.isFrozen() || reqCnt == 0 || reqCnt > maxCnt { + p.fcClient.OneTimeCost(inSizeCost) + return false + } + // Prepaid max cost units before request been serving. + maxCost = p.fcCosts.getMaxCost(msg.Code, reqCnt) + accepted, bufShort, priority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost) + if !accepted { + p.freezeClient() + p.Log().Error("Request came too early", "remaining", common.PrettyDuration(time.Duration(bufShort*1000000/p.fcParams.MinRecharge))) + p.fcClient.OneTimeCost(inSizeCost) + return false + } + // Create a multi-stage task, estimate the time it takes for the task to + // execute, and cache it in the request service queue. + factor := h.server.costTracker.globalFactor() + if factor < 0.001 { + factor = 1 + p.Log().Error("Invalid global cost factor", "factor", factor) + } + maxTime := uint64(float64(maxCost) / factor) + task = h.server.servingQueue.newTask(p, maxTime, priority) + if task.start() { + return true + } + p.fcClient.RequestProcessed(reqID, responseCount, maxCost, inSizeCost) + return false + } + // sendResponse sends back the response and updates the flow control statistic. + sendResponse := func(reqID, amount uint64, reply *reply, servingTime uint64) { + p.responseLock.Lock() + defer p.responseLock.Unlock() + + // Short circuit if the client is already frozen. + if p.isFrozen() { + realCost := h.server.costTracker.realCost(servingTime, msg.Size, 0) + p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) + return + } + // Positive correction buffer value with real cost. + var replySize uint32 + if reply != nil { + replySize = reply.size() + } + var realCost uint64 + if h.server.costTracker.testing { + realCost = maxCost // Assign a fake cost for testing purpose + } else { + realCost = h.server.costTracker.realCost(servingTime, msg.Size, replySize) + } + bv := p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) + if amount != 0 { + // Feed cost tracker request serving statistic. + h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) + // Reduce priority "balance" for the specific peer. + h.server.clientPool.requestCost(p, realCost) + } + if reply != nil { + p.queueSend(func() { + if err := reply.send(bv); err != nil { + select { + case p.errCh <- err: + default: + } + } + }) + } + } + switch msg.Code { + case GetBlockHeadersMsg: + p.Log().Trace("Received block header request") + if metrics.EnabledExpensive { + miscInHeaderPacketsMeter.Mark(1) + miscInHeaderTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeHeaderTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Query getBlockHeadersData + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "%v: %v", msg, err) + } + query := req.Query + if accept(req.ReqID, query.Amount, MaxHeaderFetch) { + wg.Add(1) + go func() { + defer wg.Done() + hashMode := query.Origin.Hash != (common.Hash{}) + first := true + maxNonCanonical := uint64(100) + + // Gather headers until the fetch or network limits is reached + var ( + bytes common.StorageSize + headers []*types.Header + unknown bool + ) + for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { + if !first && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Retrieve the next header satisfying the query + var origin *types.Header + if hashMode { + if first { + origin = h.blockchain.GetHeaderByHash(query.Origin.Hash) + if origin != nil { + query.Origin.Number = origin.Number.Uint64() + } + } else { + origin = h.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) + } + } else { + origin = h.blockchain.GetHeaderByNumber(query.Origin.Number) + } + if origin == nil { + atomic.AddUint32(&p.invalidCount, 1) + break + } + headers = append(headers, origin) + bytes += estHeaderRlpSize + + // Advance to the next header of the query + switch { + case hashMode && query.Reverse: + // Hash based traversal towards the genesis block + ancestor := query.Skip + 1 + if ancestor == 0 { + unknown = true + } else { + query.Origin.Hash, query.Origin.Number = h.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) + unknown = query.Origin.Hash == common.Hash{} + } + case hashMode && !query.Reverse: + // Hash based traversal towards the leaf block + var ( + current = origin.Number.Uint64() + next = current + query.Skip + 1 + ) + if next <= current { + infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") + p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) + unknown = true + } else { + if header := h.blockchain.GetHeaderByNumber(next); header != nil { + nextHash := header.Hash() + expOldHash, _ := h.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) + if expOldHash == query.Origin.Hash { + query.Origin.Hash, query.Origin.Number = nextHash, next + } else { + unknown = true + } + } else { + unknown = true + } + } + case query.Reverse: + // Number based traversal towards the genesis block + if query.Origin.Number >= query.Skip+1 { + query.Origin.Number -= query.Skip + 1 + } else { + unknown = true + } + + case !query.Reverse: + // Number based traversal towards the leaf block + query.Origin.Number += query.Skip + 1 + } + first = false + } + reply := p.ReplyBlockHeaders(req.ReqID, headers) + sendResponse(req.ReqID, query.Amount, p.ReplyBlockHeaders(req.ReqID, headers), task.done()) + if metrics.EnabledExpensive { + miscOutHeaderPacketsMeter.Mark(1) + miscOutHeaderTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetBlockBodiesMsg: + p.Log().Trace("Received block bodies request") + if metrics.EnabledExpensive { + miscInBodyPacketsMeter.Mark(1) + miscInBodyTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeBodyTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + bodies []rlp.RawValue + ) + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if bytes >= softResponseLimit { + break + } + body := h.blockchain.GetBodyRLP(hash) + if body == nil { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + bodies = append(bodies, body) + bytes += len(body) + } + reply := p.ReplyBlockBodiesRLP(req.ReqID, bodies) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutBodyPacketsMeter.Mark(1) + miscOutBodyTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetCodeMsg: + p.Log().Trace("Received code request") + if metrics.EnabledExpensive { + miscInCodePacketsMeter.Mark(1) + miscInCodeTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeCodeTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []CodeReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + data [][]byte + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Look up the root hash belonging to the request + header := h.blockchain.GetHeaderByHash(request.BHash) + if header == nil { + p.Log().Warn("Failed to retrieve associate header for code", "hash", request.BHash) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Refuse to search stale state data in the database since looking for + // a non-exist key is kind of expensive. + local := h.blockchain.CurrentHeader().Number.Uint64() + if !h.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { + p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + triedb := h.blockchain.StateCache().TrieDB() + + account, err := h.getAccount(triedb, header.Root, common.BytesToHash(request.AccKey)) + if err != nil { + p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + code, err := triedb.Node(common.BytesToHash(account.CodeHash)) + if err != nil { + p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err) + continue + } + // Accumulate the code and abort if enough data was retrieved + data = append(data, code) + if bytes += len(code); bytes >= softResponseLimit { + break + } + } + reply := p.ReplyCode(req.ReqID, data) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutCodePacketsMeter.Mark(1) + miscOutCodeTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetReceiptsMsg: + p.Log().Trace("Received receipts request") + if metrics.EnabledExpensive { + miscInReceiptPacketsMeter.Mark(1) + miscInReceiptTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeReceiptTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + receipts []rlp.RawValue + ) + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if bytes >= softResponseLimit { + break + } + // Retrieve the requested block's receipts, skipping if unknown to us + results := h.blockchain.GetReceiptsByHash(hash) + if results == nil { + if header := h.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + } + // If known, encode and queue for response packet + if encoded, err := rlp.EncodeToBytes(results); err != nil { + log.Error("Failed to encode receipt", "err", err) + } else { + receipts = append(receipts, encoded) + bytes += len(encoded) + } + } + reply := p.ReplyReceiptsRLP(req.ReqID, receipts) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutReceiptPacketsMeter.Mark(1) + miscOutReceiptTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetProofsV2Msg: + p.Log().Trace("Received les/2 proofs request") + if metrics.EnabledExpensive { + miscInTrieProofPacketsMeter.Mark(1) + miscInTrieProofTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTrieProofTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []ProofReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + // Gather state data until the fetch or network limits is reached + var ( + lastBHash common.Hash + root common.Hash + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { + wg.Add(1) + go func() { + defer wg.Done() + nodes := light.NewNodeSet() + + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Look up the root hash belonging to the request + var ( + header *types.Header + trie state.Trie + ) + if request.BHash != lastBHash { + root, lastBHash = common.Hash{}, request.BHash + + if header = h.blockchain.GetHeaderByHash(request.BHash); header == nil { + p.Log().Warn("Failed to retrieve header for proof", "hash", request.BHash) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Refuse to search stale state data in the database since looking for + // a non-exist key is kind of expensive. + local := h.blockchain.CurrentHeader().Number.Uint64() + if !h.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { + p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + root = header.Root + } + // If a header lookup failed (non existent), ignore subsequent requests for the same header + if root == (common.Hash{}) { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Open the account or storage trie for the request + statedb := h.blockchain.StateCache() + + switch len(request.AccKey) { + case 0: + // No account key specified, open an account trie + trie, err = statedb.OpenTrie(root) + if trie == nil || err != nil { + p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err) + continue + } + default: + // Account key specified, open a storage trie + account, err := h.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.AccKey)) + if err != nil { + p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.AccKey), account.Root) + if trie == nil || err != nil { + p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "root", account.Root, "err", err) + continue + } + } + // Prove the user's request from the account or stroage trie + if err := trie.Prove(request.Key, request.FromLevel, nodes); err != nil { + p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err) + continue + } + if nodes.DataSize() >= softResponseLimit { + break + } + } + reply := p.ReplyProofsV2(req.ReqID, nodes.NodeList()) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTrieProofPacketsMeter.Mark(1) + miscOutTrieProofTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetHelperTrieProofsMsg: + p.Log().Trace("Received helper trie proof request") + if metrics.EnabledExpensive { + miscInHelperTriePacketsMeter.Mark(1) + miscInHelperTrieTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeHelperTrieTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []HelperTrieReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + // Gather state data until the fetch or network limits is reached + var ( + auxBytes int + auxData [][]byte + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { + wg.Add(1) + go func() { + defer wg.Done() + var ( + lastIdx uint64 + lastType uint + root common.Hash + auxTrie *trie.Trie + ) + nodes := light.NewNodeSet() + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if auxTrie == nil || request.Type != lastType || request.TrieIdx != lastIdx { + auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIdx + + var prefix string + if root, prefix = h.getHelperTrie(request.Type, request.TrieIdx); root != (common.Hash{}) { + auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix))) + } + } + if request.AuxReq == auxRoot { + var data []byte + if root != (common.Hash{}) { + data = root[:] + } + auxData = append(auxData, data) + auxBytes += len(data) + } else { + if auxTrie != nil { + auxTrie.Prove(request.Key, request.FromLevel, nodes) + } + if request.AuxReq != 0 { + data := h.getAuxiliaryHeaders(request) + auxData = append(auxData, data) + auxBytes += len(data) + } + } + if nodes.DataSize()+auxBytes >= softResponseLimit { + break + } + } + reply := p.ReplyHelperTrieProofs(req.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutHelperTriePacketsMeter.Mark(1) + miscOutHelperTrieTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case SendTxV2Msg: + p.Log().Trace("Received new transactions") + if metrics.EnabledExpensive { + miscInTxsPacketsMeter.Mark(1) + miscInTxsTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTxTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Txs []*types.Transaction + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + reqCnt := len(req.Txs) + if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { + wg.Add(1) + go func() { + defer wg.Done() + stats := make([]light.TxStatus, len(req.Txs)) + for i, tx := range req.Txs { + if i != 0 && !task.waitOrStop() { + return + } + hash := tx.Hash() + stats[i] = h.txStatus(hash) + if stats[i].Status == core.TxStatusUnknown { + addFn := h.txpool.AddRemotes + // Add txs synchronously for testing purpose + if h.addTxsSync { + addFn = h.txpool.AddRemotesSync + } + if errs := addFn([]*types.Transaction{tx}); errs[0] != nil { + stats[i].Error = errs[0].Error() + continue + } + stats[i] = h.txStatus(hash) + } + } + reply := p.ReplyTxStatus(req.ReqID, stats) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTxsPacketsMeter.Mark(1) + miscOutTxsTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetTxStatusMsg: + p.Log().Trace("Received transaction status query request") + if metrics.EnabledExpensive { + miscInTxStatusPacketsMeter.Mark(1) + miscInTxStatusTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTxStatusTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { + wg.Add(1) + go func() { + defer wg.Done() + stats := make([]light.TxStatus, len(req.Hashes)) + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + stats[i] = h.txStatus(hash) + } + reply := p.ReplyTxStatus(req.ReqID, stats) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTxStatusPacketsMeter.Mark(1) + miscOutTxStatusTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + default: + p.Log().Trace("Received invalid message", "code", msg.Code) + clientErrorMeter.Mark(1) + return errResp(ErrInvalidMsgCode, "%v", msg.Code) + } + // If the client has made too much invalid request(e.g. request a non-exist data), + // reject them to prevent SPAM attack. + if atomic.LoadUint32(&p.invalidCount) > maxRequestErrors { + clientErrorMeter.Mark(1) + return errTooManyInvalidRequest + } + return nil +} + +// getAccount retrieves an account from the state based on root. +func (h *serverHandler) getAccount(triedb *trie.Database, root, hash common.Hash) (state.Account, error) { + trie, err := trie.New(root, triedb) + if err != nil { + return state.Account{}, err + } + blob, err := trie.TryGet(hash[:]) + if err != nil { + return state.Account{}, err + } + var account state.Account + if err = rlp.DecodeBytes(blob, &account); err != nil { + return state.Account{}, err + } + return account, nil +} + +// getHelperTrie returns the post-processed trie root for the given trie ID and section index +func (h *serverHandler) getHelperTrie(typ uint, index uint64) (common.Hash, string) { + switch typ { + case htCanonical: + sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.ChtSize-1) + return light.GetChtRoot(h.chainDb, index, sectionHead), light.ChtTablePrefix + case htBloomBits: + sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.BloomTrieSize-1) + return light.GetBloomTrieRoot(h.chainDb, index, sectionHead), light.BloomTrieTablePrefix + } + return common.Hash{}, "" +} + +// getAuxiliaryHeaders returns requested auxiliary headers for the CHT request. +func (h *serverHandler) getAuxiliaryHeaders(req HelperTrieReq) []byte { + if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { + blockNum := binary.BigEndian.Uint64(req.Key) + hash := rawdb.ReadCanonicalHash(h.chainDb, blockNum) + return rawdb.ReadHeaderRLP(h.chainDb, hash, blockNum) + } + return nil +} + +// txStatus returns the status of a specified transaction. +func (h *serverHandler) txStatus(hash common.Hash) light.TxStatus { + var stat light.TxStatus + // Looking the transaction in txpool first. + stat.Status = h.txpool.Status([]common.Hash{hash})[0] + + // If the transaction is unknown to the pool, try looking it up locally. + if stat.Status == core.TxStatusUnknown { + lookup := h.blockchain.GetTransactionLookup(hash) + if lookup != nil { + stat.Status = core.TxStatusIncluded + stat.Lookup = lookup + } + } + return stat +} + +// broadcastHeaders broadcasts new block information to all connected light +// clients. According to the agreement between client and server, server should +// only broadcast new announcement if the total difficulty is higher than the +// last one. Besides server will add the signature if client requires. +func (h *serverHandler) broadcastHeaders() { + defer h.wg.Done() + + headCh := make(chan core.ChainHeadEvent, 10) + headSub := h.blockchain.SubscribeChainHeadEvent(headCh) + defer headSub.Unsubscribe() + + var ( + lastHead *types.Header + lastTd = common.Big0 + ) + for { + select { + case ev := <-headCh: + peers := h.server.peers.AllPeers() + if len(peers) == 0 { + continue + } + header := ev.Block.Header() + hash, number := header.Hash(), header.Number.Uint64() + td := h.blockchain.GetTd(hash, number) + if td == nil || td.Cmp(lastTd) <= 0 { + continue + } + var reorg uint64 + if lastHead != nil { + reorg = lastHead.Number.Uint64() - rawdb.FindCommonAncestor(h.chainDb, header, lastHead).Number.Uint64() + } + lastHead, lastTd = header, td + + log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg) + var ( + signed bool + signedAnnounce announceData + ) + announce := announceData{Hash: hash, Number: number, Td: td, ReorgDepth: reorg} + for _, p := range peers { + p := p + switch p.announceType { + case announceTypeSimple: + p.queueSend(func() { p.SendAnnounce(announce) }) + case announceTypeSigned: + if !signed { + signedAnnounce = announce + signedAnnounce.sign(h.server.privateKey) + signed = true + } + p.queueSend(func() { p.SendAnnounce(signedAnnounce) }) + } + } + case <-h.closeCh: + return + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/serverpool.go b/vendor/github.com/ethereum/go-ethereum/les/serverpool.go index 3e8cdee410..37621dc634 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/serverpool.go +++ b/vendor/github.com/ethereum/go-ethereum/les/serverpool.go @@ -115,8 +115,6 @@ type serverPool struct { db ethdb.Database dbKey []byte server *p2p.Server - quit chan struct{} - wg *sync.WaitGroup connWg sync.WaitGroup topic discv5.Topic @@ -137,14 +135,15 @@ type serverPool struct { connCh chan *connReq disconnCh chan *disconnReq registerCh chan *registerReq + + closeCh chan struct{} + wg sync.WaitGroup } // newServerPool creates a new serverPool instance -func newServerPool(db ethdb.Database, quit chan struct{}, wg *sync.WaitGroup, trustedNodes []string) *serverPool { +func newServerPool(db ethdb.Database, ulcServers []string) *serverPool { pool := &serverPool{ db: db, - quit: quit, - wg: wg, entries: make(map[enode.ID]*poolEntry), timeout: make(chan *poolEntry, 1), adjustStats: make(chan poolStatAdjust, 100), @@ -152,10 +151,11 @@ func newServerPool(db ethdb.Database, quit chan struct{}, wg *sync.WaitGroup, tr connCh: make(chan *connReq), disconnCh: make(chan *disconnReq), registerCh: make(chan *registerReq), + closeCh: make(chan struct{}), knownSelect: newWeightedRandomSelect(), newSelect: newWeightedRandomSelect(), fastDiscover: true, - trustedNodes: parseTrustedNodes(trustedNodes), + trustedNodes: parseTrustedNodes(ulcServers), } pool.knownQueue = newPoolEntryQueue(maxKnownEntries, pool.removeEntry) @@ -167,7 +167,6 @@ func (pool *serverPool) start(server *p2p.Server, topic discv5.Topic) { pool.server = server pool.topic = topic pool.dbKey = append([]byte("serverPool/"), []byte(topic)...) - pool.wg.Add(1) pool.loadNodes() pool.connectToTrustedNodes() @@ -178,9 +177,15 @@ func (pool *serverPool) start(server *p2p.Server, topic discv5.Topic) { go pool.discoverNodes() } pool.checkDial() + pool.wg.Add(1) go pool.eventLoop() } +func (pool *serverPool) stop() { + close(pool.closeCh) + pool.wg.Wait() +} + // discoverNodes wraps SearchTopic, converting result nodes to enode.Node. func (pool *serverPool) discoverNodes() { ch := make(chan *discv5.Node) @@ -207,7 +212,7 @@ func (pool *serverPool) connect(p *peer, node *enode.Node) *poolEntry { req := &connReq{p: p, node: node, result: make(chan *poolEntry, 1)} select { case pool.connCh <- req: - case <-pool.quit: + case <-pool.closeCh: return nil } return <-req.result @@ -219,7 +224,7 @@ func (pool *serverPool) registered(entry *poolEntry) { req := ®isterReq{entry: entry, done: make(chan struct{})} select { case pool.registerCh <- req: - case <-pool.quit: + case <-pool.closeCh: return } <-req.done @@ -231,7 +236,7 @@ func (pool *serverPool) registered(entry *poolEntry) { func (pool *serverPool) disconnect(entry *poolEntry) { stopped := false select { - case <-pool.quit: + case <-pool.closeCh: stopped = true default: } @@ -278,6 +283,7 @@ func (pool *serverPool) adjustResponseTime(entry *poolEntry, time time.Duration, // eventLoop handles pool events and mutex locking for all internal functions func (pool *serverPool) eventLoop() { + defer pool.wg.Done() lookupCnt := 0 var convTime mclock.AbsTime if pool.discSetPeriod != nil { @@ -361,7 +367,7 @@ func (pool *serverPool) eventLoop() { case req := <-pool.connCh: if pool.trustedNodes[req.p.ID()] != nil { // ignore trusted nodes - req.result <- nil + req.result <- &poolEntry{trusted: true} } else { // Handle peer connection requests. entry := pool.entries[req.p.ID()] @@ -389,6 +395,9 @@ func (pool *serverPool) eventLoop() { } case req := <-pool.registerCh: + if req.entry.trusted { + continue + } // Handle peer registration requests. entry := req.entry entry.state = psRegistered @@ -402,10 +411,13 @@ func (pool *serverPool) eventLoop() { close(req.done) case req := <-pool.disconnCh: + if req.entry.trusted { + continue + } // Handle peer disconnection requests. disconnect(req, req.stopped) - case <-pool.quit: + case <-pool.closeCh: if pool.discSetPeriod != nil { close(pool.discSetPeriod) } @@ -421,7 +433,6 @@ func (pool *serverPool) eventLoop() { disconnect(req, true) } pool.saveNodes() - pool.wg.Done() return } } @@ -549,10 +560,10 @@ func (pool *serverPool) setRetryDial(entry *poolEntry) { entry.delayedRetry = true go func() { select { - case <-pool.quit: + case <-pool.closeCh: case <-time.After(delay): select { - case <-pool.quit: + case <-pool.closeCh: case pool.enableRetry <- entry: } } @@ -618,10 +629,10 @@ func (pool *serverPool) dial(entry *poolEntry, knownSelected bool) { go func() { pool.server.AddPeer(entry.node) select { - case <-pool.quit: + case <-pool.closeCh: case <-time.After(dialTimeout): select { - case <-pool.quit: + case <-pool.closeCh: case pool.timeout <- entry: } } @@ -662,14 +673,14 @@ type poolEntry struct { lastConnected, dialed *poolEntryAddress addrSelect weightedRandomSelect - lastDiscovered mclock.AbsTime - known, knownSelected bool - connectStats, delayStats poolStats - responseStats, timeoutStats poolStats - state int - regTime mclock.AbsTime - queueIdx int - removed bool + lastDiscovered mclock.AbsTime + known, knownSelected, trusted bool + connectStats, delayStats poolStats + responseStats, timeoutStats poolStats + state int + regTime mclock.AbsTime + queueIdx int + removed bool delayedRetry bool shortRetry int diff --git a/vendor/github.com/ethereum/go-ethereum/les/sync.go b/vendor/github.com/ethereum/go-ethereum/les/sync.go index 54fd81c2c2..1214fefcaf 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/les/sync.go @@ -43,35 +43,6 @@ const ( checkpointSync ) -// syncer is responsible for periodically synchronising with the network, both -// downloading hashes and blocks as well as handling the announcement handler. -func (pm *ProtocolManager) syncer() { - // Start and ensure cleanup of sync mechanisms - //pm.fetcher.Start() - //defer pm.fetcher.Stop() - defer pm.downloader.Terminate() - - // Wait for different events to fire synchronisation operations - //forceSync := time.Tick(forceSyncCycle) - for { - select { - case <-pm.newPeerCh: - /* // Make sure we have peers to select from, then sync - if pm.peers.Len() < minDesiredPeerCount { - break - } - go pm.synchronise(pm.peers.BestPeer()) - */ - /*case <-forceSync: - // Force a sync even if not enough peers are present - go pm.synchronise(pm.peers.BestPeer()) - */ - case <-pm.noMorePeers: - return - } - } -} - // validateCheckpoint verifies the advertised checkpoint by peer is valid or not. // // Each network has several hard-coded checkpoint signer addresses. Only the @@ -80,22 +51,22 @@ func (pm *ProtocolManager) syncer() { // In addition to the checkpoint registered in the registrar contract, there are // several legacy hardcoded checkpoints in our codebase. These checkpoints are // also considered as valid. -func (pm *ProtocolManager) validateCheckpoint(peer *peer) error { +func (h *clientHandler) validateCheckpoint(peer *peer) error { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() // Fetch the block header corresponding to the checkpoint registration. cp := peer.checkpoint - header, err := light.GetUntrustedHeaderByNumber(ctx, pm.odr, peer.checkpointNumber, peer.id) + header, err := light.GetUntrustedHeaderByNumber(ctx, h.backend.odr, peer.checkpointNumber, peer.id) if err != nil { return err } // Fetch block logs associated with the block header. - logs, err := light.GetUntrustedBlockLogs(ctx, pm.odr, header) + logs, err := light.GetUntrustedBlockLogs(ctx, h.backend.odr, header) if err != nil { return err } - events := pm.reg.contract.LookupCheckpointEvents(logs, cp.SectionIndex, cp.Hash()) + events := h.backend.oracle.contract.LookupCheckpointEvents(logs, cp.SectionIndex, cp.Hash()) if len(events) == 0 { return errInvalidCheckpoint } @@ -107,7 +78,7 @@ func (pm *ProtocolManager) validateCheckpoint(peer *peer) error { for _, event := range events { signatures = append(signatures, append(event.R[:], append(event.S[:], event.V)...)) } - valid, signers := pm.reg.verifySigners(index, hash, signatures) + valid, signers := h.backend.oracle.verifySigners(index, hash, signatures) if !valid { return errInvalidCheckpoint } @@ -116,14 +87,14 @@ func (pm *ProtocolManager) validateCheckpoint(peer *peer) error { } // synchronise tries to sync up our local chain with a remote peer. -func (pm *ProtocolManager) synchronise(peer *peer) { +func (h *clientHandler) synchronise(peer *peer) { // Short circuit if the peer is nil. if peer == nil { return } // Make sure the peer's TD is higher than our own. - latest := pm.blockchain.CurrentHeader() - currentTd := rawdb.ReadTd(pm.chainDb, latest.Hash(), latest.Number.Uint64()) + latest := h.backend.blockchain.CurrentHeader() + currentTd := rawdb.ReadTd(h.backend.chainDb, latest.Hash(), latest.Number.Uint64()) if currentTd != nil && peer.headBlockInfo().Td.Cmp(currentTd) < 0 { return } @@ -140,8 +111,8 @@ func (pm *ProtocolManager) synchronise(peer *peer) { // => Use provided checkpoint var checkpoint = &peer.checkpoint var hardcoded bool - if pm.checkpoint != nil && pm.checkpoint.SectionIndex >= peer.checkpoint.SectionIndex { - checkpoint = pm.checkpoint // Use the hardcoded one. + if h.checkpoint != nil && h.checkpoint.SectionIndex >= peer.checkpoint.SectionIndex { + checkpoint = h.checkpoint // Use the hardcoded one. hardcoded = true } // Determine whether we should run checkpoint syncing or normal light syncing. @@ -157,34 +128,37 @@ func (pm *ProtocolManager) synchronise(peer *peer) { case checkpoint.Empty(): mode = lightSync log.Debug("Disable checkpoint syncing", "reason", "empty checkpoint") - case latest.Number.Uint64() >= (checkpoint.SectionIndex+1)*pm.iConfig.ChtSize-1: + case latest.Number.Uint64() >= (checkpoint.SectionIndex+1)*h.backend.iConfig.ChtSize-1: mode = lightSync log.Debug("Disable checkpoint syncing", "reason", "local chain beyond the checkpoint") case hardcoded: mode = legacyCheckpointSync log.Debug("Disable checkpoint syncing", "reason", "checkpoint is hardcoded") - case pm.reg == nil || !pm.reg.isRunning(): - mode = legacyCheckpointSync + case h.backend.oracle == nil || !h.backend.oracle.isRunning(): + if h.checkpoint == nil { + mode = lightSync // Downgrade to light sync unfortunately. + } else { + checkpoint = h.checkpoint + mode = legacyCheckpointSync + } log.Debug("Disable checkpoint syncing", "reason", "checkpoint syncing is not activated") } // Notify testing framework if syncing has completed(for testing purpose). defer func() { - if pm.reg != nil && pm.reg.syncDoneHook != nil { - pm.reg.syncDoneHook() + if h.syncDone != nil { + h.syncDone() } }() start := time.Now() if mode == checkpointSync || mode == legacyCheckpointSync { // Validate the advertised checkpoint - if mode == legacyCheckpointSync { - checkpoint = pm.checkpoint - } else if mode == checkpointSync { - if err := pm.validateCheckpoint(peer); err != nil { + if mode == checkpointSync { + if err := h.validateCheckpoint(peer); err != nil { log.Debug("Failed to validate checkpoint", "reason", err) - pm.removePeer(peer.id) + h.removePeer(peer.id) return } - pm.blockchain.(*light.LightChain).AddTrustedCheckpoint(checkpoint) + h.backend.blockchain.AddTrustedCheckpoint(checkpoint) } log.Debug("Checkpoint syncing start", "peer", peer.id, "checkpoint", checkpoint.SectionIndex) @@ -197,14 +171,14 @@ func (pm *ProtocolManager) synchronise(peer *peer) { // of the latest epoch covered by checkpoint. ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - if !checkpoint.Empty() && !pm.blockchain.(*light.LightChain).SyncCheckpoint(ctx, checkpoint) { + if !checkpoint.Empty() && !h.backend.blockchain.SyncCheckpoint(ctx, checkpoint) { log.Debug("Sync checkpoint failed") - pm.removePeer(peer.id) + h.removePeer(peer.id) return } } // Fetch the remaining block headers based on the current chain header. - if err := pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync); err != nil { + if err := h.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync); err != nil { log.Debug("Synchronise failed", "reason", err) return } diff --git a/vendor/github.com/ethereum/go-ethereum/les/test_helper.go b/vendor/github.com/ethereum/go-ethereum/les/test_helper.go new file mode 100644 index 0000000000..ee3d7a32e1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/test_helper.go @@ -0,0 +1,558 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains some shares testing functionality, common to multiple +// different files and modules being tested. + +package les + +import ( + "context" + "crypto/rand" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/les/flowcontrol" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/params" +) + +var ( + bankKey, _ = crypto.GenerateKey() + bankAddr = crypto.PubkeyToAddress(bankKey.PublicKey) + bankFunds = big.NewInt(1000000000000000000) + + userKey1, _ = crypto.GenerateKey() + userKey2, _ = crypto.GenerateKey() + userAddr1 = crypto.PubkeyToAddress(userKey1.PublicKey) + userAddr2 = crypto.PubkeyToAddress(userKey2.PublicKey) + + testContractAddr common.Address + testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") + testContractCodeDeployed = testContractCode[16:] + testContractDeployed = uint64(2) + + testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029") + + // Checkpoint registrar relative + registrarAddr common.Address + signerKey, _ = crypto.GenerateKey() + signerAddr = crypto.PubkeyToAddress(signerKey.PublicKey) +) + +var ( + // The block frequency for creating checkpoint(only used in test) + sectionSize = big.NewInt(128) + + // The number of confirmations needed to generate a checkpoint(only used in test). + processConfirms = big.NewInt(1) + + // The token bucket buffer limit for testing purpose. + testBufLimit = uint64(1000000) + + // The buffer recharging speed for testing purpose. + testBufRecharge = uint64(1000) +) + +/* +contract test { + + uint256[100] data; + + function Put(uint256 addr, uint256 value) { + data[addr] = value; + } + + function Get(uint256 addr) constant returns (uint256 value) { + return data[addr]; + } +} +*/ + +// prepare pre-commits specified number customized blocks into chain. +func prepare(n int, backend *backends.SimulatedBackend) { + var ( + ctx = context.Background() + signer = types.HomesteadSigner{} + ) + for i := 0; i < n; i++ { + switch i { + case 0: + // deploy checkpoint contract + registrarAddr, _, _, _ = contract.DeployCheckpointOracle(bind.NewKeyedTransactor(bankKey), backend, []common.Address{signerAddr}, sectionSize, processConfirms, big.NewInt(1)) + // bankUser transfers some ether to user1 + nonce, _ := backend.PendingNonceAt(ctx, bankAddr) + tx, _ := types.SignTx(types.NewTransaction(nonce, userAddr1, big.NewInt(10000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx) + case 1: + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + userNonce1, _ := backend.PendingNonceAt(ctx, userAddr1) + + // bankUser transfers more ether to user1 + tx1, _ := types.SignTx(types.NewTransaction(bankNonce, userAddr1, big.NewInt(1000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx1) + + // user1 relays ether to user2 + tx2, _ := types.SignTx(types.NewTransaction(userNonce1, userAddr2, big.NewInt(1000), params.TxGas, nil, nil), signer, userKey1) + backend.SendTransaction(ctx, tx2) + + // user1 deploys a test contract + tx3, _ := types.SignTx(types.NewContractCreation(userNonce1+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, userKey1) + backend.SendTransaction(ctx, tx3) + testContractAddr = crypto.CreateAddress(userAddr1, userNonce1+1) + + // user1 deploys a event contract + tx4, _ := types.SignTx(types.NewContractCreation(userNonce1+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, userKey1) + backend.SendTransaction(ctx, tx4) + case 2: + // bankUser transfer some ether to signer + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + tx1, _ := types.SignTx(types.NewTransaction(bankNonce, signerAddr, big.NewInt(1000000000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx1) + + // invoke test contract + data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") + tx2, _ := types.SignTx(types.NewTransaction(bankNonce+1, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) + backend.SendTransaction(ctx, tx2) + case 3: + // invoke test contract + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") + tx, _ := types.SignTx(types.NewTransaction(bankNonce, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) + backend.SendTransaction(ctx, tx) + } + backend.Commit() + } +} + +// testIndexers creates a set of indexers with specified params for testing purpose. +func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.IndexerConfig) []*core.ChainIndexer { + var indexers [3]*core.ChainIndexer + indexers[0] = light.NewChtIndexer(db, odr, config.ChtSize, config.ChtConfirms) + indexers[1] = eth.NewBloomIndexer(db, config.BloomSize, config.BloomConfirms) + indexers[2] = light.NewBloomTrieIndexer(db, odr, config.BloomSize, config.BloomTrieSize) + // make bloomTrieIndexer as a child indexer of bloom indexer. + indexers[1].AddChildIndexer(indexers[2]) + return indexers[:] +} + +func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, ulcServers []string, ulcFraction int) *clientHandler { + var ( + evmux = new(event.TypeMux) + engine = ethash.NewFaker() + gspec = core.Genesis{ + Config: params.AllEthashProtocolChanges, + Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, + GasLimit: 100000000, + } + oracle *checkpointOracle + ) + genesis := gspec.MustCommit(db) + chain, _ := light.NewLightChain(odr, gspec.Config, engine, nil) + if indexers != nil { + checkpointConfig := ¶ms.CheckpointOracleConfig{ + Address: crypto.CreateAddress(bankAddr, 0), + Signers: []common.Address{signerAddr}, + Threshold: 1, + } + getLocal := func(index uint64) params.TrustedCheckpoint { + chtIndexer := indexers[0] + sectionHead := chtIndexer.SectionHead(index) + return params.TrustedCheckpoint{ + SectionIndex: index, + SectionHead: sectionHead, + CHTRoot: light.GetChtRoot(db, index, sectionHead), + BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), + } + } + oracle = newCheckpointOracle(checkpointConfig, getLocal) + } + client := &LightEthereum{ + lesCommons: lesCommons{ + genesis: genesis.Hash(), + config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, + chainConfig: params.AllEthashProtocolChanges, + iConfig: light.TestClientIndexerConfig, + chainDb: db, + oracle: oracle, + chainReader: chain, + peers: peers, + closeCh: make(chan struct{}), + }, + reqDist: odr.retriever.dist, + retriever: odr.retriever, + odr: odr, + engine: engine, + blockchain: chain, + eventMux: evmux, + } + client.handler = newClientHandler(ulcServers, ulcFraction, nil, client) + + if client.oracle != nil { + client.oracle.start(backend) + } + return client.handler +} + +func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) { + var ( + gspec = core.Genesis{ + Config: params.AllEthashProtocolChanges, + Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, + GasLimit: 100000000, + } + oracle *checkpointOracle + ) + genesis := gspec.MustCommit(db) + + // create a simulation backend and pre-commit several customized block to the database. + simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000) + prepare(blocks, simulation) + + txpoolConfig := core.DefaultTxPoolConfig + txpoolConfig.Journal = "" + txpool := core.NewTxPool(txpoolConfig, gspec.Config, simulation.Blockchain()) + if indexers != nil { + checkpointConfig := ¶ms.CheckpointOracleConfig{ + Address: crypto.CreateAddress(bankAddr, 0), + Signers: []common.Address{signerAddr}, + Threshold: 1, + } + getLocal := func(index uint64) params.TrustedCheckpoint { + chtIndexer := indexers[0] + sectionHead := chtIndexer.SectionHead(index) + return params.TrustedCheckpoint{ + SectionIndex: index, + SectionHead: sectionHead, + CHTRoot: light.GetChtRoot(db, index, sectionHead), + BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), + } + } + oracle = newCheckpointOracle(checkpointConfig, getLocal) + } + server := &LesServer{ + lesCommons: lesCommons{ + genesis: genesis.Hash(), + config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, + chainConfig: params.AllEthashProtocolChanges, + iConfig: light.TestServerIndexerConfig, + chainDb: db, + chainReader: simulation.Blockchain(), + oracle: oracle, + peers: peers, + closeCh: make(chan struct{}), + }, + servingQueue: newServingQueue(int64(time.Millisecond*10), 1), + defParams: flowcontrol.ServerParams{ + BufLimit: testBufLimit, + MinRecharge: testBufRecharge, + }, + fcManager: flowcontrol.NewClientManager(nil, clock), + } + server.costTracker, server.freeCapacity = newCostTracker(db, server.config) + server.costTracker.testCostList = testCostList(0) // Disable flow control mechanism. + server.clientPool = newClientPool(db, 1, clock, nil) + server.clientPool.setLimits(10000, 10000) // Assign enough capacity for clientpool + server.handler = newServerHandler(server, simulation.Blockchain(), db, txpool, func() bool { return true }) + if server.oracle != nil { + server.oracle.start(simulation) + } + server.servingQueue.setThreads(4) + server.handler.start() + return server.handler, simulation +} + +// testPeer is a simulated peer to allow testing direct network calls. +type testPeer struct { + peer *peer + + net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging + app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side +} + +// newTestPeer creates a new peer registered at the given protocol manager. +func newTestPeer(t *testing.T, name string, version int, handler *serverHandler, shake bool, testCost uint64) (*testPeer, <-chan error) { + // Create a message pipe to communicate through + app, net := p2p.MsgPipe() + + // Generate a random id and create the peer + var id enode.ID + rand.Read(id[:]) + peer := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net) + + // Start the peer on a new thread + errCh := make(chan error, 1) + go func() { + select { + case <-handler.closeCh: + errCh <- p2p.DiscQuitting + case errCh <- handler.handle(peer): + } + }() + tp := &testPeer{ + app: app, + net: net, + peer: peer, + } + // Execute any implicitly requested handshakes and return + if shake { + // Customize the cost table if required. + if testCost != 0 { + handler.server.costTracker.testCostList = testCostList(testCost) + } + var ( + genesis = handler.blockchain.Genesis() + head = handler.blockchain.CurrentHeader() + td = handler.blockchain.GetTd(head.Hash(), head.Number.Uint64()) + ) + tp.handshake(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash(), testCostList(testCost)) + } + return tp, errCh +} + +// close terminates the local side of the peer, notifying the remote protocol +// manager of termination. +func (p *testPeer) close() { + p.app.Close() +} + +func newTestPeerPair(name string, version int, server *serverHandler, client *clientHandler) (*testPeer, <-chan error, *testPeer, <-chan error) { + // Create a message pipe to communicate through + app, net := p2p.MsgPipe() + + // Generate a random id and create the peer + var id enode.ID + rand.Read(id[:]) + + peer1 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net) + peer2 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), app) + + // Start the peer on a new thread + errc1 := make(chan error, 1) + errc2 := make(chan error, 1) + go func() { + select { + case <-server.closeCh: + errc1 <- p2p.DiscQuitting + case errc1 <- server.handle(peer1): + } + }() + go func() { + select { + case <-client.closeCh: + errc1 <- p2p.DiscQuitting + case errc1 <- client.handle(peer2): + } + }() + return &testPeer{peer: peer1, net: net, app: app}, errc1, &testPeer{peer: peer2, net: app, app: net}, errc2 +} + +// handshake simulates a trivial handshake that expects the same state from the +// remote side as we are simulating locally. +func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, costList RequestCostList) { + var expList keyValueList + expList = expList.add("protocolVersion", uint64(p.peer.version)) + expList = expList.add("networkId", uint64(NetworkId)) + expList = expList.add("headTd", td) + expList = expList.add("headHash", head) + expList = expList.add("headNum", headNum) + expList = expList.add("genesisHash", genesis) + sendList := make(keyValueList, len(expList)) + copy(sendList, expList) + expList = expList.add("serveHeaders", nil) + expList = expList.add("serveChainSince", uint64(0)) + expList = expList.add("serveStateSince", uint64(0)) + expList = expList.add("serveRecentState", uint64(core.TriesInMemory-4)) + expList = expList.add("txRelay", nil) + expList = expList.add("flowControl/BL", testBufLimit) + expList = expList.add("flowControl/MRR", testBufRecharge) + expList = expList.add("flowControl/MRC", costList) + + if err := p2p.ExpectMsg(p.app, StatusMsg, expList); err != nil { + t.Fatalf("status recv: %v", err) + } + if err := p2p.Send(p.app, StatusMsg, sendList); err != nil { + t.Fatalf("status send: %v", err) + } + p.peer.fcParams = flowcontrol.ServerParams{ + BufLimit: testBufLimit, + MinRecharge: testBufRecharge, + } +} + +type indexerCallback func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer) + +// testClient represents a client for testing with necessary auxiliary fields. +type testClient struct { + clock mclock.Clock + db ethdb.Database + peer *testPeer + handler *clientHandler + + chtIndexer *core.ChainIndexer + bloomIndexer *core.ChainIndexer + bloomTrieIndexer *core.ChainIndexer +} + +// testServer represents a server for testing with necessary auxiliary fields. +type testServer struct { + clock mclock.Clock + backend *backends.SimulatedBackend + db ethdb.Database + peer *testPeer + handler *serverHandler + + chtIndexer *core.ChainIndexer + bloomIndexer *core.ChainIndexer + bloomTrieIndexer *core.ChainIndexer +} + +func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, simClock bool, newPeer bool, testCost uint64) (*testServer, func()) { + db := rawdb.NewMemoryDatabase() + indexers := testIndexers(db, nil, light.TestServerIndexerConfig) + + var clock mclock.Clock = &mclock.System{} + if simClock { + clock = &mclock.Simulated{} + } + handler, b := newTestServerHandler(blocks, indexers, db, newPeerSet(), clock) + + var peer *testPeer + if newPeer { + peer, _ = newTestPeer(t, "peer", protocol, handler, true, testCost) + } + + cIndexer, bIndexer, btIndexer := indexers[0], indexers[1], indexers[2] + cIndexer.Start(handler.blockchain) + bIndexer.Start(handler.blockchain) + + // Wait until indexers generate enough index data. + if callback != nil { + callback(cIndexer, bIndexer, btIndexer) + } + server := &testServer{ + clock: clock, + backend: b, + db: db, + peer: peer, + handler: handler, + chtIndexer: cIndexer, + bloomIndexer: bIndexer, + bloomTrieIndexer: btIndexer, + } + teardown := func() { + if newPeer { + peer.close() + b.Close() + } + cIndexer.Close() + bIndexer.Close() + } + return server, teardown +} + +func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) { + sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase() + speers, cPeers := newPeerSet(), newPeerSet() + + var clock mclock.Clock = &mclock.System{} + if simClock { + clock = &mclock.Simulated{} + } + dist := newRequestDistributor(cPeers, clock) + rm := newRetrieveManager(cPeers, dist, nil) + odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm) + + sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig) + cIndexers := testIndexers(cdb, odr, light.TestClientIndexerConfig) + + scIndexer, sbIndexer, sbtIndexer := sindexers[0], sindexers[1], sindexers[2] + ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2] + odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer) + + server, b := newTestServerHandler(blocks, sindexers, sdb, speers, clock) + client := newTestClientHandler(b, odr, cIndexers, cdb, cPeers, ulcServers, ulcFraction) + + scIndexer.Start(server.blockchain) + sbIndexer.Start(server.blockchain) + ccIndexer.Start(client.backend.blockchain) + cbIndexer.Start(client.backend.blockchain) + + if callback != nil { + callback(scIndexer, sbIndexer, sbtIndexer) + } + var ( + speer, cpeer *testPeer + err1, err2 <-chan error + ) + if connect { + cpeer, err1, speer, err2 = newTestPeerPair("peer", protocol, server, client) + select { + case <-time.After(time.Millisecond * 300): + case err := <-err1: + t.Fatalf("peer 1 handshake error: %v", err) + case err := <-err2: + t.Fatalf("peer 2 handshake error: %v", err) + } + } + s := &testServer{ + clock: clock, + backend: b, + db: sdb, + peer: cpeer, + handler: server, + chtIndexer: scIndexer, + bloomIndexer: sbIndexer, + bloomTrieIndexer: sbtIndexer, + } + c := &testClient{ + clock: clock, + db: cdb, + peer: speer, + handler: client, + chtIndexer: ccIndexer, + bloomIndexer: cbIndexer, + bloomTrieIndexer: cbtIndexer, + } + teardown := func() { + if connect { + speer.close() + cpeer.close() + } + ccIndexer.Close() + cbIndexer.Close() + scIndexer.Close() + sbIndexer.Close() + b.Close() + } + return s, c, teardown +} diff --git a/vendor/github.com/ethereum/go-ethereum/light/lightchain.go b/vendor/github.com/ethereum/go-ethereum/light/lightchain.go index 7f64d1c28b..02b90138a2 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/lightchain.go +++ b/vendor/github.com/ethereum/go-ethereum/light/lightchain.go @@ -426,6 +426,11 @@ func (lc *LightChain) HasHeader(hash common.Hash, number uint64) bool { return lc.hc.HasHeader(hash, number) } +// GetCanonicalHash returns the canonical hash for a given block number +func (bc *LightChain) GetCanonicalHash(number uint64) common.Hash { + return bc.hc.GetCanonicalHash(number) +} + // GetBlockHashesFromHash retrieves a number of block hashes starting at a given // hash, fetching towards the genesis block. func (lc *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { @@ -438,9 +443,6 @@ func (lc *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com // // Note: ancestor == 0 returns the same block, 1 returns its parent and so on. func (lc *LightChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - lc.chainmu.RLock() - defer lc.chainmu.RUnlock() - return lc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) } diff --git a/vendor/github.com/ethereum/go-ethereum/light/odr_util.go b/vendor/github.com/ethereum/go-ethereum/light/odr_util.go index 82e33bb78f..2c820d40c7 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/odr_util.go +++ b/vendor/github.com/ethereum/go-ethereum/light/odr_util.go @@ -60,7 +60,7 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ } } if number >= chtCount*odr.IndexerConfig().ChtSize { - return nil, ErrNoTrustedCht + return nil, errNoTrustedCht } r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number, Config: odr.IndexerConfig()} if err := odr.Retrieve(ctx, r); err != nil { @@ -124,7 +124,7 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint // Retrieve the block header and body contents header := rawdb.ReadHeader(odr.Database(), hash, number) if header == nil { - return nil, ErrNoHeader + return nil, errNoHeader } body, err := GetBody(ctx, odr, hash, number) if err != nil { @@ -241,7 +241,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi } else { // TODO(rjl493456442) Convert sectionIndex to BloomTrie relative index if sectionIdx >= bloomTrieCount { - return nil, ErrNoTrustedBloomTrie + return nil, errNoTrustedBloomTrie } reqList = append(reqList, sectionIdx) reqIdx = append(reqIdx, i) diff --git a/vendor/github.com/ethereum/go-ethereum/light/postprocess.go b/vendor/github.com/ethereum/go-ethereum/light/postprocess.go index bf632a4496..af3b257923 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/postprocess.go +++ b/vendor/github.com/ethereum/go-ethereum/light/postprocess.go @@ -79,28 +79,28 @@ var ( } // TestServerIndexerConfig wraps a set of configs as a test indexer config for server side. TestServerIndexerConfig = &IndexerConfig{ - ChtSize: 512, - ChtConfirms: 4, - BloomSize: 64, - BloomConfirms: 4, - BloomTrieSize: 512, - BloomTrieConfirms: 4, + ChtSize: 128, + ChtConfirms: 1, + BloomSize: 16, + BloomConfirms: 1, + BloomTrieSize: 128, + BloomTrieConfirms: 1, } // TestClientIndexerConfig wraps a set of configs as a test indexer config for client side. TestClientIndexerConfig = &IndexerConfig{ - ChtSize: 512, - ChtConfirms: 32, - BloomSize: 512, - BloomConfirms: 32, - BloomTrieSize: 512, - BloomTrieConfirms: 32, + ChtSize: 128, + ChtConfirms: 8, + BloomSize: 128, + BloomConfirms: 8, + BloomTrieSize: 128, + BloomTrieConfirms: 8, } ) var ( - ErrNoTrustedCht = errors.New("no trusted canonical hash trie") - ErrNoTrustedBloomTrie = errors.New("no trusted bloom trie") - ErrNoHeader = errors.New("header not found") + errNoTrustedCht = errors.New("no trusted canonical hash trie") + errNoTrustedBloomTrie = errors.New("no trusted bloom trie") + errNoHeader = errors.New("header not found") chtPrefix = []byte("chtRootV2-") // chtPrefix + chtNum (uint64 big endian) -> trie root hash ChtTablePrefix = "cht-" ) diff --git a/vendor/github.com/ethereum/go-ethereum/light/txpool.go b/vendor/github.com/ethereum/go-ethereum/light/txpool.go index e945ef2ec1..11a0e76ae0 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/txpool.go +++ b/vendor/github.com/ethereum/go-ethereum/light/txpool.go @@ -19,6 +19,7 @@ package light import ( "context" "fmt" + "math/big" "sync" "time" @@ -67,7 +68,7 @@ type TxPool struct { mined map[common.Hash][]*types.Transaction // mined transactions by block hash clearIdx uint64 // earliest block nr that can contain mined tx info - homestead bool + istanbul bool // Fork indicator whether we are in the istanbul stage. } // TxRelayBackend provides an interface to the mechanism that forwards transacions @@ -309,8 +310,10 @@ func (pool *TxPool) setNewHead(head *types.Header) { txc, _ := pool.reorgOnNewHead(ctx, head) m, r := txc.getLists() pool.relay.NewHead(pool.head, m, r) - pool.homestead = pool.config.IsHomestead(head.Number) - pool.signer = types.MakeSigner(pool.config, head.Number) + + // Update fork indicator by next pending block number + next := new(big.Int).Add(head.Number, big.NewInt(1)) + pool.istanbul = pool.config.IsIstanbul(next) } // Stop stops the light transaction pool @@ -378,7 +381,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error } // Should supply enough intrinsic gas - gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) + gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, true, pool.istanbul) if err != nil { return err } diff --git a/vendor/github.com/ethereum/go-ethereum/log/README.md b/vendor/github.com/ethereum/go-ethereum/log/README.md index b4476577b6..47426806dd 100644 --- a/vendor/github.com/ethereum/go-ethereum/log/README.md +++ b/vendor/github.com/ethereum/go-ethereum/log/README.md @@ -1,8 +1,8 @@ -![obligatory xkcd](http://imgs.xkcd.com/comics/standards.png) +![obligatory xkcd](https://imgs.xkcd.com/comics/standards.png) # log15 [![godoc reference](https://godoc.org/github.com/inconshreveable/log15?status.png)](https://godoc.org/github.com/inconshreveable/log15) [![Build Status](https://travis-ci.org/inconshreveable/log15.svg?branch=master)](https://travis-ci.org/inconshreveable/log15) -Package log15 provides an opinionated, simple toolkit for best-practice logging in Go (golang) that is both human and machine readable. It is modeled after the Go standard library's [`io`](http://golang.org/pkg/io/) and [`net/http`](http://golang.org/pkg/net/http/) packages and is an alternative to the standard library's [`log`](http://golang.org/pkg/log/) package. +Package log15 provides an opinionated, simple toolkit for best-practice logging in Go (golang) that is both human and machine readable. It is modeled after the Go standard library's [`io`](https://golang.org/pkg/io/) and [`net/http`](https://golang.org/pkg/net/http/) packages and is an alternative to the standard library's [`log`](https://golang.org/pkg/log/) package. ## Features - A simple, easy-to-understand API diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/README.md b/vendor/github.com/ethereum/go-ethereum/metrics/README.md index bc2a45a838..e2d7945008 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/README.md +++ b/vendor/github.com/ethereum/go-ethereum/metrics/README.md @@ -5,7 +5,7 @@ go-metrics Go port of Coda Hale's Metrics library: . -Documentation: . +Documentation: . Usage ----- @@ -128,7 +128,7 @@ go stathat.Stathat(metrics.DefaultRegistry, 10e9, "example@example.com") Maintain all metrics along with expvars at `/debug/metrics`: -This uses the same mechanism as [the official expvar](http://golang.org/pkg/expvar/) +This uses the same mechanism as [the official expvar](https://golang.org/pkg/expvar/) but exposed under `/debug/metrics`, which shows a json representation of all your usual expvars as well as all your go-metrics. diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go b/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go index 0fbfdb8603..b6b2758b0d 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go @@ -6,6 +6,8 @@ import "sync/atomic" type Gauge interface { Snapshot() Gauge Update(int64) + Dec(int64) + Inc(int64) Value() int64 } @@ -65,6 +67,16 @@ func (GaugeSnapshot) Update(int64) { panic("Update called on a GaugeSnapshot") } +// Dec panics. +func (GaugeSnapshot) Dec(int64) { + panic("Dec called on a GaugeSnapshot") +} + +// Inc panics. +func (GaugeSnapshot) Inc(int64) { + panic("Inc called on a GaugeSnapshot") +} + // Value returns the value at the time the snapshot was taken. func (g GaugeSnapshot) Value() int64 { return int64(g) } @@ -77,6 +89,12 @@ func (NilGauge) Snapshot() Gauge { return NilGauge{} } // Update is a no-op. func (NilGauge) Update(v int64) {} +// Dec is a no-op. +func (NilGauge) Dec(i int64) {} + +// Inc is a no-op. +func (NilGauge) Inc(i int64) {} + // Value is a no-op. func (NilGauge) Value() int64 { return 0 } @@ -101,6 +119,16 @@ func (g *StandardGauge) Value() int64 { return atomic.LoadInt64(&g.value) } +// Dec decrements the gauge's current value by the given amount. +func (g *StandardGauge) Dec(i int64) { + atomic.AddInt64(&g.value, -i) +} + +// Inc increments the gauge's current value by the given amount. +func (g *StandardGauge) Inc(i int64) { + atomic.AddInt64(&g.value, i) +} + // FunctionalGauge returns value from given function type FunctionalGauge struct { value func() int64 @@ -118,3 +146,13 @@ func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } func (FunctionalGauge) Update(int64) { panic("Update called on a FunctionalGauge") } + +// Dec panics. +func (FunctionalGauge) Dec(int64) { + panic("Dec called on a FunctionalGauge") +} + +// Inc panics. +func (FunctionalGauge) Inc(int64) { + panic("Inc called on a FunctionalGauge") +} diff --git a/vendor/github.com/ethereum/go-ethereum/miner/worker.go b/vendor/github.com/ethereum/go-ethereum/miner/worker.go index 4a9528c395..183499ec30 100644 --- a/vendor/github.com/ethereum/go-ethereum/miner/worker.go +++ b/vendor/github.com/ethereum/go-ethereum/miner/worker.go @@ -704,7 +704,7 @@ func (w *worker) updateSnapshot() { func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() - receipt, _, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) if err != nil { w.current.state.RevertToSnapshot(snap) return nil, err diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go index 8dee5063f1..68e06cce58 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go @@ -33,12 +33,7 @@ const ( // private networks. dialHistoryExpiration = inboundThrottleTime + 5*time.Second - // Discovery lookups are throttled and can only run - // once every few seconds. - lookupInterval = 4 * time.Second - - // If no peers are found for this amount of time, the initial bootnodes are - // attempted to be connected. + // If no peers are found for this amount of time, the initial bootnodes are dialed. fallbackInterval = 20 * time.Second // Endpoint resolution is throttled with bounded backoff. @@ -52,6 +47,10 @@ type NodeDialer interface { Dial(*enode.Node) (net.Conn, error) } +type nodeResolver interface { + Resolve(*enode.Node) *enode.Node +} + // TCPDialer implements the NodeDialer interface by using a net.Dialer to // create TCP connections to nodes in the network type TCPDialer struct { @@ -69,7 +68,6 @@ func (t TCPDialer) Dial(dest *enode.Node) (net.Conn, error) { // of the main loop in Server.run. type dialstate struct { maxDynDials int - ntab discoverTable netrestrict *netutil.Netlist self enode.ID bootnodes []*enode.Node // default dials when there are no peers @@ -79,55 +77,23 @@ type dialstate struct { lookupRunning bool dialing map[enode.ID]connFlag lookupBuf []*enode.Node // current discovery lookup results - randomNodes []*enode.Node // filled from Table static map[enode.ID]*dialTask hist expHeap } -type discoverTable interface { - Close() - Resolve(*enode.Node) *enode.Node - LookupRandom() []*enode.Node - ReadRandomNodes([]*enode.Node) int -} - type task interface { Do(*Server) } -// A dialTask is generated for each node that is dialed. Its -// fields cannot be accessed while the task is running. -type dialTask struct { - flags connFlag - dest *enode.Node - lastResolved time.Time - resolveDelay time.Duration -} - -// discoverTask runs discovery table operations. -// Only one discoverTask is active at any time. -// discoverTask.Do performs a random lookup. -type discoverTask struct { - results []*enode.Node -} - -// A waitExpireTask is generated if there are no other tasks -// to keep the loop in Server.run ticking. -type waitExpireTask struct { - time.Duration -} - -func newDialState(self enode.ID, ntab discoverTable, maxdyn int, cfg *Config) *dialstate { +func newDialState(self enode.ID, maxdyn int, cfg *Config) *dialstate { s := &dialstate{ maxDynDials: maxdyn, - ntab: ntab, self: self, netrestrict: cfg.NetRestrict, log: cfg.Logger, static: make(map[enode.ID]*dialTask), dialing: make(map[enode.ID]connFlag), bootnodes: make([]*enode.Node, len(cfg.BootstrapNodes)), - randomNodes: make([]*enode.Node, maxdyn/2), } copy(s.bootnodes, cfg.BootstrapNodes) if s.log == nil { @@ -151,10 +117,6 @@ func (s *dialstate) removeStatic(n *enode.Node) { } func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Time) []task { - if s.start.IsZero() { - s.start = now - } - var newtasks []task addDial := func(flag connFlag, n *enode.Node) bool { if err := s.checkDial(n, peers); err != nil { @@ -166,20 +128,9 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti return true } - // Compute number of dynamic dials necessary at this point. - needDynDials := s.maxDynDials - for _, p := range peers { - if p.rw.is(dynDialedConn) { - needDynDials-- - } - } - for _, flag := range s.dialing { - if flag&dynDialedConn != 0 { - needDynDials-- - } + if s.start.IsZero() { + s.start = now } - - // Expire the dial history on every invocation. s.hist.expire(now) // Create dials for static nodes if they are not connected. @@ -194,6 +145,20 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti newtasks = append(newtasks, t) } } + + // Compute number of dynamic dials needed. + needDynDials := s.maxDynDials + for _, p := range peers { + if p.rw.is(dynDialedConn) { + needDynDials-- + } + } + for _, flag := range s.dialing { + if flag&dynDialedConn != 0 { + needDynDials-- + } + } + // If we don't have any peers whatsoever, try to dial a random bootnode. This // scenario is useful for the testnet (and private networks) where the discovery // table might be full of mostly bad peers, making it hard to find good ones. @@ -201,24 +166,12 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti bootnode := s.bootnodes[0] s.bootnodes = append(s.bootnodes[:0], s.bootnodes[1:]...) s.bootnodes = append(s.bootnodes, bootnode) - if addDial(dynDialedConn, bootnode) { needDynDials-- } } - // Use random nodes from the table for half of the necessary - // dynamic dials. - randomCandidates := needDynDials / 2 - if randomCandidates > 0 { - n := s.ntab.ReadRandomNodes(s.randomNodes) - for i := 0; i < randomCandidates && i < n; i++ { - if addDial(dynDialedConn, s.randomNodes[i]) { - needDynDials-- - } - } - } - // Create dynamic dials from random lookup results, removing tried - // items from the result buffer. + + // Create dynamic dials from discovery results. i := 0 for ; i < len(s.lookupBuf) && needDynDials > 0; i++ { if addDial(dynDialedConn, s.lookupBuf[i]) { @@ -226,10 +179,11 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti } } s.lookupBuf = s.lookupBuf[:copy(s.lookupBuf, s.lookupBuf[i:])] + // Launch a discovery lookup if more candidates are needed. if len(s.lookupBuf) < needDynDials && !s.lookupRunning { s.lookupRunning = true - newtasks = append(newtasks, &discoverTask{}) + newtasks = append(newtasks, &discoverTask{want: needDynDials - len(s.lookupBuf)}) } // Launch a timer to wait for the next node to expire if all @@ -279,6 +233,15 @@ func (s *dialstate) taskDone(t task, now time.Time) { } } +// A dialTask is generated for each node that is dialed. Its +// fields cannot be accessed while the task is running. +type dialTask struct { + flags connFlag + dest *enode.Node + lastResolved time.Time + resolveDelay time.Duration +} + func (t *dialTask) Do(srv *Server) { if t.dest.Incomplete() { if !t.resolve(srv) { @@ -304,8 +267,8 @@ func (t *dialTask) Do(srv *Server) { // discovery network with useless queries for nodes that don't exist. // The backoff delay resets when the node is found. func (t *dialTask) resolve(srv *Server) bool { - if srv.ntab == nil { - srv.log.Debug("Can't resolve node", "id", t.dest.ID, "err", "discovery is disabled") + if srv.staticNodeResolver == nil { + srv.log.Debug("Can't resolve node", "id", t.dest.ID(), "err", "discovery is disabled") return false } if t.resolveDelay == 0 { @@ -314,20 +277,20 @@ func (t *dialTask) resolve(srv *Server) bool { if time.Since(t.lastResolved) < t.resolveDelay { return false } - resolved := srv.ntab.Resolve(t.dest) + resolved := srv.staticNodeResolver.Resolve(t.dest) t.lastResolved = time.Now() if resolved == nil { t.resolveDelay *= 2 if t.resolveDelay > maxResolveDelay { t.resolveDelay = maxResolveDelay } - srv.log.Debug("Resolving node failed", "id", t.dest.ID, "newdelay", t.resolveDelay) + srv.log.Debug("Resolving node failed", "id", t.dest.ID(), "newdelay", t.resolveDelay) return false } // The node was found. t.resolveDelay = initialResolveDelay t.dest = resolved - srv.log.Debug("Resolved node", "id", t.dest.ID, "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) + srv.log.Debug("Resolved node", "id", t.dest.ID(), "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) return true } @@ -350,26 +313,34 @@ func (t *dialTask) String() string { return fmt.Sprintf("%v %x %v:%d", t.flags, id[:8], t.dest.IP(), t.dest.TCP()) } +// discoverTask runs discovery table operations. +// Only one discoverTask is active at any time. +// discoverTask.Do performs a random lookup. +type discoverTask struct { + want int + results []*enode.Node +} + func (t *discoverTask) Do(srv *Server) { - // newTasks generates a lookup task whenever dynamic dials are - // necessary. Lookups need to take some time, otherwise the - // event loop spins too fast. - next := srv.lastLookup.Add(lookupInterval) - if now := time.Now(); now.Before(next) { - time.Sleep(next.Sub(now)) - } - srv.lastLookup = time.Now() - t.results = srv.ntab.LookupRandom() + t.results = enode.ReadNodes(srv.discmix, t.want) } func (t *discoverTask) String() string { - s := "discovery lookup" + s := "discovery query" if len(t.results) > 0 { s += fmt.Sprintf(" (%d results)", len(t.results)) + } else { + s += fmt.Sprintf(" (want %d)", t.want) } return s } +// A waitExpireTask is generated if there are no other tasks +// to keep the loop in Server.run ticking. +type waitExpireTask struct { + time.Duration +} + func (t waitExpireTask) Do(*Server) { time.Sleep(t.Duration) } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go index 3c080359fd..cef6a9fc4f 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/netutil" ) +// UDPConn is a network connection on which discovery can operate. type UDPConn interface { ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) @@ -32,7 +33,7 @@ type UDPConn interface { LocalAddr() net.Addr } -// Config holds Table-related settings. +// Config holds settings for the discovery listener. type Config struct { // These settings are required and configure the UDP listener: PrivateKey *ecdsa.PrivateKey @@ -50,7 +51,7 @@ func ListenUDP(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { } // ReadPacket is a packet that couldn't be handled. Those packets are sent to the unhandled -// channel if configured. +// channel if configured. This is exported for internal use, do not use this type. type ReadPacket struct { Data []byte Addr *net.UDPAddr diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/lookup.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/lookup.go new file mode 100644 index 0000000000..f988e06838 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/lookup.go @@ -0,0 +1,209 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package discover + +import ( + "context" + + "github.com/ethereum/go-ethereum/p2p/enode" +) + +// lookup performs a network search for nodes close to the given target. It approaches the +// target by querying nodes that are closer to it on each iteration. The given target does +// not need to be an actual node identifier. +type lookup struct { + tab *Table + queryfunc func(*node) ([]*node, error) + replyCh chan []*node + cancelCh <-chan struct{} + asked, seen map[enode.ID]bool + result nodesByDistance + replyBuffer []*node + queries int +} + +type queryFunc func(*node) ([]*node, error) + +func newLookup(ctx context.Context, tab *Table, target enode.ID, q queryFunc) *lookup { + it := &lookup{ + tab: tab, + queryfunc: q, + asked: make(map[enode.ID]bool), + seen: make(map[enode.ID]bool), + result: nodesByDistance{target: target}, + replyCh: make(chan []*node, alpha), + cancelCh: ctx.Done(), + queries: -1, + } + // Don't query further if we hit ourself. + // Unlikely to happen often in practice. + it.asked[tab.self().ID()] = true + return it +} + +// run runs the lookup to completion and returns the closest nodes found. +func (it *lookup) run() []*enode.Node { + for it.advance() { + } + return unwrapNodes(it.result.entries) +} + +// advance advances the lookup until any new nodes have been found. +// It returns false when the lookup has ended. +func (it *lookup) advance() bool { + for it.startQueries() { + select { + case nodes := <-it.replyCh: + it.replyBuffer = it.replyBuffer[:0] + for _, n := range nodes { + if n != nil && !it.seen[n.ID()] { + it.seen[n.ID()] = true + it.result.push(n, bucketSize) + it.replyBuffer = append(it.replyBuffer, n) + } + } + it.queries-- + if len(it.replyBuffer) > 0 { + return true + } + case <-it.cancelCh: + it.shutdown() + } + } + return false +} + +func (it *lookup) shutdown() { + for it.queries > 0 { + <-it.replyCh + it.queries-- + } + it.queryfunc = nil + it.replyBuffer = nil +} + +func (it *lookup) startQueries() bool { + if it.queryfunc == nil { + return false + } + + // The first query returns nodes from the local table. + if it.queries == -1 { + it.tab.mutex.Lock() + closest := it.tab.closest(it.result.target, bucketSize, false) + it.tab.mutex.Unlock() + it.queries = 1 + it.replyCh <- closest.entries + return true + } + + // Ask the closest nodes that we haven't asked yet. + for i := 0; i < len(it.result.entries) && it.queries < alpha; i++ { + n := it.result.entries[i] + if !it.asked[n.ID()] { + it.asked[n.ID()] = true + it.queries++ + go it.query(n, it.replyCh) + } + } + // The lookup ends when no more nodes can be asked. + return it.queries > 0 +} + +func (it *lookup) query(n *node, reply chan<- []*node) { + fails := it.tab.db.FindFails(n.ID(), n.IP()) + r, err := it.queryfunc(n) + if err == errClosed { + // Avoid recording failures on shutdown. + reply <- nil + return + } else if len(r) == 0 { + fails++ + it.tab.db.UpdateFindFails(n.ID(), n.IP(), fails) + it.tab.log.Trace("Findnode failed", "id", n.ID(), "failcount", fails, "err", err) + if fails >= maxFindnodeFailures { + it.tab.log.Trace("Too many findnode failures, dropping", "id", n.ID(), "failcount", fails) + it.tab.delete(n) + } + } else if fails > 0 { + // Reset failure counter because it counts _consecutive_ failures. + it.tab.db.UpdateFindFails(n.ID(), n.IP(), 0) + } + + // Grab as many nodes as possible. Some of them might not be alive anymore, but we'll + // just remove those again during revalidation. + for _, n := range r { + it.tab.addSeenNode(n) + } + reply <- r +} + +// lookupIterator performs lookup operations and iterates over all seen nodes. +// When a lookup finishes, a new one is created through nextLookup. +type lookupIterator struct { + buffer []*node + nextLookup lookupFunc + ctx context.Context + cancel func() + lookup *lookup +} + +type lookupFunc func(ctx context.Context) *lookup + +func newLookupIterator(ctx context.Context, next lookupFunc) *lookupIterator { + ctx, cancel := context.WithCancel(ctx) + return &lookupIterator{ctx: ctx, cancel: cancel, nextLookup: next} +} + +// Node returns the current node. +func (it *lookupIterator) Node() *enode.Node { + if len(it.buffer) == 0 { + return nil + } + return unwrapNode(it.buffer[0]) +} + +// Next moves to the next node. +func (it *lookupIterator) Next() bool { + // Consume next node in buffer. + if len(it.buffer) > 0 { + it.buffer = it.buffer[1:] + } + // Advance the lookup to refill the buffer. + for len(it.buffer) == 0 { + if it.ctx.Err() != nil { + it.lookup = nil + it.buffer = nil + return false + } + if it.lookup == nil { + it.lookup = it.nextLookup(it.ctx) + continue + } + if !it.lookup.advance() { + it.lookup = nil + continue + } + it.buffer = it.lookup.replyBuffer + } + return true +} + +// Close ends the iterator. +func (it *lookupIterator) Close() { + it.cancel() +} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go index a8f7101b05..bfb66fcb19 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go @@ -19,6 +19,7 @@ package discover import ( "bytes" "container/list" + "context" "crypto/ecdsa" crand "crypto/rand" "errors" @@ -207,7 +208,8 @@ type UDPv4 struct { addReplyMatcher chan *replyMatcher gotreply chan reply - closing chan struct{} + closeCtx context.Context + cancelCloseCtx func() } // replyMatcher represents a pending reply. @@ -256,20 +258,23 @@ type reply struct { } func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { + closeCtx, cancel := context.WithCancel(context.Background()) t := &UDPv4{ conn: c, priv: cfg.PrivateKey, netrestrict: cfg.NetRestrict, localNode: ln, db: ln.Database(), - closing: make(chan struct{}), gotreply: make(chan reply), addReplyMatcher: make(chan *replyMatcher), + closeCtx: closeCtx, + cancelCloseCtx: cancel, log: cfg.Log, } if t.log == nil { t.log = log.Root() } + tab, err := newTable(t, ln.Database(), cfg.Bootnodes, t.log) if err != nil { return nil, err @@ -291,126 +296,13 @@ func (t *UDPv4) Self() *enode.Node { // Close shuts down the socket and aborts any running queries. func (t *UDPv4) Close() { t.closeOnce.Do(func() { - close(t.closing) + t.cancelCloseCtx() t.conn.Close() t.wg.Wait() t.tab.close() }) } -// ReadRandomNodes reads random nodes from the local table. -func (t *UDPv4) ReadRandomNodes(buf []*enode.Node) int { - return t.tab.ReadRandomNodes(buf) -} - -// LookupRandom finds random nodes in the network. -func (t *UDPv4) LookupRandom() []*enode.Node { - if t.tab.len() == 0 { - // All nodes were dropped, refresh. The very first query will hit this - // case and run the bootstrapping logic. - <-t.tab.refresh() - } - return t.lookupRandom() -} - -func (t *UDPv4) LookupPubkey(key *ecdsa.PublicKey) []*enode.Node { - if t.tab.len() == 0 { - // All nodes were dropped, refresh. The very first query will hit this - // case and run the bootstrapping logic. - <-t.tab.refresh() - } - return unwrapNodes(t.lookup(encodePubkey(key))) -} - -func (t *UDPv4) lookupRandom() []*enode.Node { - var target encPubkey - crand.Read(target[:]) - return unwrapNodes(t.lookup(target)) -} - -func (t *UDPv4) lookupSelf() []*enode.Node { - return unwrapNodes(t.lookup(encodePubkey(&t.priv.PublicKey))) -} - -// lookup performs a network search for nodes close to the given target. It approaches the -// target by querying nodes that are closer to it on each iteration. The given target does -// not need to be an actual node identifier. -func (t *UDPv4) lookup(targetKey encPubkey) []*node { - var ( - target = enode.ID(crypto.Keccak256Hash(targetKey[:])) - asked = make(map[enode.ID]bool) - seen = make(map[enode.ID]bool) - reply = make(chan []*node, alpha) - pendingQueries = 0 - result *nodesByDistance - ) - // Don't query further if we hit ourself. - // Unlikely to happen often in practice. - asked[t.Self().ID()] = true - - // Generate the initial result set. - t.tab.mutex.Lock() - result = t.tab.closest(target, bucketSize, false) - t.tab.mutex.Unlock() - - for { - // ask the alpha closest nodes that we haven't asked yet - for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ { - n := result.entries[i] - if !asked[n.ID()] { - asked[n.ID()] = true - pendingQueries++ - go t.lookupWorker(n, targetKey, reply) - } - } - if pendingQueries == 0 { - // we have asked all closest nodes, stop the search - break - } - select { - case nodes := <-reply: - for _, n := range nodes { - if n != nil && !seen[n.ID()] { - seen[n.ID()] = true - result.push(n, bucketSize) - } - } - case <-t.tab.closeReq: - return nil // shutdown, no need to continue. - } - pendingQueries-- - } - return result.entries -} - -func (t *UDPv4) lookupWorker(n *node, targetKey encPubkey, reply chan<- []*node) { - fails := t.db.FindFails(n.ID(), n.IP()) - r, err := t.findnode(n.ID(), n.addr(), targetKey) - if err == errClosed { - // Avoid recording failures on shutdown. - reply <- nil - return - } else if len(r) == 0 { - fails++ - t.db.UpdateFindFails(n.ID(), n.IP(), fails) - t.log.Trace("Findnode failed", "id", n.ID(), "failcount", fails, "err", err) - if fails >= maxFindnodeFailures { - t.log.Trace("Too many findnode failures, dropping", "id", n.ID(), "failcount", fails) - t.tab.delete(n) - } - } else if fails > 0 { - // Reset failure counter because it counts _consecutive_ failures. - t.db.UpdateFindFails(n.ID(), n.IP(), 0) - } - - // Grab as many nodes as possible. Some of them might not be alive anymore, but we'll - // just remove those again during revalidation. - for _, n := range r { - t.tab.addSeenNode(n) - } - reply <- r -} - // Resolve searches for a specific node with the given ID and tries to get the most recent // version of the node record for it. It returns n if the node could not be resolved. func (t *UDPv4) Resolve(n *enode.Node) *enode.Node { @@ -498,6 +390,45 @@ func (t *UDPv4) makePing(toaddr *net.UDPAddr) *pingV4 { } } +// LookupPubkey finds the closest nodes to the given public key. +func (t *UDPv4) LookupPubkey(key *ecdsa.PublicKey) []*enode.Node { + if t.tab.len() == 0 { + // All nodes were dropped, refresh. The very first query will hit this + // case and run the bootstrapping logic. + <-t.tab.refresh() + } + return t.newLookup(t.closeCtx, encodePubkey(key)).run() +} + +// RandomNodes is an iterator yielding nodes from a random walk of the DHT. +func (t *UDPv4) RandomNodes() enode.Iterator { + return newLookupIterator(t.closeCtx, t.newRandomLookup) +} + +// lookupRandom implements transport. +func (t *UDPv4) lookupRandom() []*enode.Node { + return t.newRandomLookup(t.closeCtx).run() +} + +// lookupSelf implements transport. +func (t *UDPv4) lookupSelf() []*enode.Node { + return t.newLookup(t.closeCtx, encodePubkey(&t.priv.PublicKey)).run() +} + +func (t *UDPv4) newRandomLookup(ctx context.Context) *lookup { + var target encPubkey + crand.Read(target[:]) + return t.newLookup(ctx, target) +} + +func (t *UDPv4) newLookup(ctx context.Context, targetKey encPubkey) *lookup { + target := enode.ID(crypto.Keccak256Hash(targetKey[:])) + it := newLookup(ctx, t.tab, target, func(n *node) ([]*node, error) { + return t.findnode(n.ID(), n.addr(), targetKey) + }) + return it +} + // findnode sends a findnode request to the given node and waits until // the node has sent up to k neighbors. func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { @@ -575,7 +506,7 @@ func (t *UDPv4) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchF select { case t.addReplyMatcher <- p: // loop will handle it - case <-t.closing: + case <-t.closeCtx.Done(): ch <- errClosed } return p @@ -589,7 +520,7 @@ func (t *UDPv4) handleReply(from enode.ID, fromIP net.IP, req packetV4) bool { case t.gotreply <- reply{from, fromIP, req, matched}: // loop will handle it return <-matched - case <-t.closing: + case <-t.closeCtx.Done(): return false } } @@ -635,7 +566,7 @@ func (t *UDPv4) loop() { resetTimeout() select { - case <-t.closing: + case <-t.closeCtx.Done(): for el := plist.Front(); el != nil; el = el.Next() { el.Value.(*replyMatcher).errc <- errClosed } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/iter.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/iter.go new file mode 100644 index 0000000000..112b76d06a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/iter.go @@ -0,0 +1,286 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package enode + +import ( + "sync" + "time" +) + +// Iterator represents a sequence of nodes. The Next method moves to the next node in the +// sequence. It returns false when the sequence has ended or the iterator is closed. Close +// may be called concurrently with Next and Node, and interrupts Next if it is blocked. +type Iterator interface { + Next() bool // moves to next node + Node() *Node // returns current node + Close() // ends the iterator +} + +// ReadNodes reads at most n nodes from the given iterator. The return value contains no +// duplicates and no nil values. To prevent looping indefinitely for small repeating node +// sequences, this function calls Next at most n times. +func ReadNodes(it Iterator, n int) []*Node { + seen := make(map[ID]*Node, n) + for i := 0; i < n && it.Next(); i++ { + // Remove duplicates, keeping the node with higher seq. + node := it.Node() + prevNode, ok := seen[node.ID()] + if ok && prevNode.Seq() > node.Seq() { + continue + } + seen[node.ID()] = node + } + result := make([]*Node, 0, len(seen)) + for _, node := range seen { + result = append(result, node) + } + return result +} + +// IterNodes makes an iterator which runs through the given nodes once. +func IterNodes(nodes []*Node) Iterator { + return &sliceIter{nodes: nodes, index: -1} +} + +// CycleNodes makes an iterator which cycles through the given nodes indefinitely. +func CycleNodes(nodes []*Node) Iterator { + return &sliceIter{nodes: nodes, index: -1, cycle: true} +} + +type sliceIter struct { + mu sync.Mutex + nodes []*Node + index int + cycle bool +} + +func (it *sliceIter) Next() bool { + it.mu.Lock() + defer it.mu.Unlock() + + if len(it.nodes) == 0 { + return false + } + it.index++ + if it.index == len(it.nodes) { + if it.cycle { + it.index = 0 + } else { + it.nodes = nil + return false + } + } + return true +} + +func (it *sliceIter) Node() *Node { + if len(it.nodes) == 0 { + return nil + } + return it.nodes[it.index] +} + +func (it *sliceIter) Close() { + it.mu.Lock() + defer it.mu.Unlock() + + it.nodes = nil +} + +// Filter wraps an iterator such that Next only returns nodes for which +// the 'check' function returns true. +func Filter(it Iterator, check func(*Node) bool) Iterator { + return &filterIter{it, check} +} + +type filterIter struct { + Iterator + check func(*Node) bool +} + +func (f *filterIter) Next() bool { + for f.Iterator.Next() { + if f.check(f.Node()) { + return true + } + } + return false +} + +// FairMix aggregates multiple node iterators. The mixer itself is an iterator which ends +// only when Close is called. Source iterators added via AddSource are removed from the +// mix when they end. +// +// The distribution of nodes returned by Next is approximately fair, i.e. FairMix +// attempts to draw from all sources equally often. However, if a certain source is slow +// and doesn't return a node within the configured timeout, a node from any other source +// will be returned. +// +// It's safe to call AddSource and Close concurrently with Next. +type FairMix struct { + wg sync.WaitGroup + fromAny chan *Node + timeout time.Duration + cur *Node + + mu sync.Mutex + closed chan struct{} + sources []*mixSource + last int +} + +type mixSource struct { + it Iterator + next chan *Node + timeout time.Duration +} + +// NewFairMix creates a mixer. +// +// The timeout specifies how long the mixer will wait for the next fairly-chosen source +// before giving up and taking a node from any other source. A good way to set the timeout +// is deciding how long you'd want to wait for a node on average. Passing a negative +// timeout makes the mixer completely fair. +func NewFairMix(timeout time.Duration) *FairMix { + m := &FairMix{ + fromAny: make(chan *Node), + closed: make(chan struct{}), + timeout: timeout, + } + return m +} + +// AddSource adds a source of nodes. +func (m *FairMix) AddSource(it Iterator) { + m.mu.Lock() + defer m.mu.Unlock() + + if m.closed == nil { + return + } + m.wg.Add(1) + source := &mixSource{it, make(chan *Node), m.timeout} + m.sources = append(m.sources, source) + go m.runSource(m.closed, source) +} + +// Close shuts down the mixer and all current sources. +// Calling this is required to release resources associated with the mixer. +func (m *FairMix) Close() { + m.mu.Lock() + defer m.mu.Unlock() + + if m.closed == nil { + return + } + for _, s := range m.sources { + s.it.Close() + } + close(m.closed) + m.wg.Wait() + close(m.fromAny) + m.sources = nil + m.closed = nil +} + +// Next returns a node from a random source. +func (m *FairMix) Next() bool { + m.cur = nil + + var timeout <-chan time.Time + if m.timeout >= 0 { + timer := time.NewTimer(m.timeout) + timeout = timer.C + defer timer.Stop() + } + for { + source := m.pickSource() + if source == nil { + return m.nextFromAny() + } + select { + case n, ok := <-source.next: + if ok { + m.cur = n + source.timeout = m.timeout + return true + } + // This source has ended. + m.deleteSource(source) + case <-timeout: + source.timeout /= 2 + return m.nextFromAny() + } + } +} + +// Node returns the current node. +func (m *FairMix) Node() *Node { + return m.cur +} + +// nextFromAny is used when there are no sources or when the 'fair' choice +// doesn't turn up a node quickly enough. +func (m *FairMix) nextFromAny() bool { + n, ok := <-m.fromAny + if ok { + m.cur = n + } + return ok +} + +// pickSource chooses the next source to read from, cycling through them in order. +func (m *FairMix) pickSource() *mixSource { + m.mu.Lock() + defer m.mu.Unlock() + + if len(m.sources) == 0 { + return nil + } + m.last = (m.last + 1) % len(m.sources) + return m.sources[m.last] +} + +// deleteSource deletes a source. +func (m *FairMix) deleteSource(s *mixSource) { + m.mu.Lock() + defer m.mu.Unlock() + + for i := range m.sources { + if m.sources[i] == s { + copy(m.sources[i:], m.sources[i+1:]) + m.sources[len(m.sources)-1] = nil + m.sources = m.sources[:len(m.sources)-1] + break + } + } +} + +// runSource reads a single source in a loop. +func (m *FairMix) runSource(closed chan struct{}, s *mixSource) { + defer m.wg.Done() + defer close(s.next) + for s.it.Next() { + n := s.it.Node() + select { + case s.next <- n: + case m.fromAny <- n: + case <-closed: + return + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go index 2372d4820b..a9a3d1374e 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go @@ -125,15 +125,17 @@ func parseComplete(rawurl string) (*Node, error) { return nil, fmt.Errorf("invalid public key (%v)", err) } // Parse the IP address. - host, port, err := net.SplitHostPort(u.Host) + ips, err := net.LookupIP(u.Hostname()) if err != nil { - return nil, fmt.Errorf("invalid host: %v", err) + return nil, err } - if ip = net.ParseIP(host); ip == nil { - return nil, errors.New("invalid IP address") + ip = ips[0] + // Ensure the IP is 4 bytes long for IPv4 addresses. + if ipv4 := ip.To4(); ipv4 != nil { + ip = ipv4 } // Parse the port numbers. - if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil { + if tcpPort, err = strconv.ParseUint(u.Port(), 10, 16); err != nil { return nil, errors.New("invalid port") } udpPort = tcpPort diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/message.go b/vendor/github.com/ethereum/go-ethereum/p2p/message.go index b987732225..10b55a939c 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/message.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/message.go @@ -39,9 +39,13 @@ import ( // separate Msg with a bytes.Reader as Payload for each send. type Msg struct { Code uint64 - Size uint32 // size of the paylod + Size uint32 // Size of the raw payload Payload io.Reader ReceivedAt time.Time + + meterCap Cap // Protocol name and version for egress metering + meterCode uint64 // Message within protocol for egress metering + meterSize uint32 // Compressed message size for ingress metering } // Decode parses the RLP content of a message into diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go b/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go index c04e5ab4c3..8b29efdcdb 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go @@ -45,7 +45,7 @@ var ( ingressTrafficMeter = metrics.NewRegisteredMeter(MetricsInboundTraffic, nil) // Meter metering the cumulative ingress traffic egressConnectMeter = metrics.NewRegisteredMeter(MetricsOutboundConnects, nil) // Meter counting the egress connections egressTrafficMeter = metrics.NewRegisteredMeter(MetricsOutboundTraffic, nil) // Meter metering the cumulative egress traffic - activePeerCounter = metrics.NewRegisteredCounter("p2p/peers", nil) // Gauge tracking the current peer count + activePeerGauge = metrics.NewRegisteredGauge("p2p/peers", nil) // Gauge tracking the current peer count PeerIngressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsInboundTraffic+"/") // Registry containing the peer ingress PeerEgressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsOutboundTraffic+"/") // Registry containing the peer egress @@ -124,7 +124,7 @@ func newMeteredConn(conn net.Conn, ingress bool, ip net.IP) net.Conn { } else { egressConnectMeter.Mark(1) } - activePeerCounter.Inc(1) + activePeerGauge.Inc(1) return &meteredConn{ Conn: conn, @@ -200,7 +200,7 @@ func (c *meteredConn) Close() error { IP: c.ip, Elapsed: time.Since(c.connected), }) - activePeerCounter.Dec(1) + activePeerGauge.Dec(1) return err } id := c.id @@ -212,7 +212,7 @@ func (c *meteredConn) Close() error { IP: c.ip, ID: id, }) - activePeerCounter.Dec(1) + activePeerGauge.Dec(1) return err } ingress, egress := uint64(c.ingressMeter.Count()), uint64(c.egressMeter.Count()) @@ -233,6 +233,6 @@ func (c *meteredConn) Close() error { Ingress: ingress, Egress: egress, }) - activePeerCounter.Dec(1) + activePeerGauge.Dec(1) return err } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/peer.go b/vendor/github.com/ethereum/go-ethereum/p2p/peer.go index 372ba8d027..9a9788bc17 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/peer.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/rlp" @@ -300,6 +301,9 @@ func (p *Peer) handle(msg Msg) error { if err != nil { return fmt.Errorf("msg code out of range: %v", msg.Code) } + if metrics.Enabled { + metrics.GetOrRegisterMeter(fmt.Sprintf("%s/%s/%d/%#02x", MetricsInboundTraffic, proto.Name, proto.Version, msg.Code-proto.offset), nil).Mark(int64(msg.meterSize)) + } select { case proto.in <- msg: return nil @@ -398,7 +402,11 @@ func (rw *protoRW) WriteMsg(msg Msg) (err error) { if msg.Code >= rw.Length { return newPeerError(errInvalidMsgCode, "not handled") } + msg.meterCap = rw.cap() + msg.meterCode = msg.Code + msg.Code += rw.offset + select { case <-rw.wstart: err = rw.w.WriteMsg(msg) diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go b/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go index 9ce4c20203..fa23a087c2 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go @@ -54,6 +54,11 @@ type Protocol struct { // but returns nil, it is assumed that the protocol handshake is still running. PeerInfo func(id enode.ID) interface{} + // DialCandidates, if non-nil, is a way to tell Server about protocol-specific nodes + // that should be dialed. The server continuously reads nodes from the iterator and + // attempts to create connections to them. + DialCandidates enode.Iterator + // Attributes contains protocol specific information for the node record. Attributes []enr.Entry } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go b/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go index 0636431f53..115021fa94 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go @@ -38,6 +38,7 @@ import ( "github.com/ethereum/go-ethereum/common/bitutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "github.com/golang/snappy" "golang.org/x/crypto/sha3" @@ -46,10 +47,10 @@ import ( const ( maxUint24 = ^uint32(0) >> 8 - sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 - sigLen = 65 // elliptic S256 - pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte - shaLen = 32 // hash length (for nonce etc) + sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 + sigLen = crypto.SignatureLength // elliptic S256 + pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte + shaLen = 32 // hash length (for nonce etc) authMsgLen = sigLen + shaLen + pubLen + shaLen + 1 authRespLen = pubLen + shaLen + 1 @@ -602,6 +603,10 @@ func (rw *rlpxFrameRW) WriteMsg(msg Msg) error { msg.Payload = bytes.NewReader(payload) msg.Size = uint32(len(payload)) } + msg.meterSize = msg.Size + if metrics.Enabled && msg.meterCap.Name != "" { // don't meter non-subprotocol messages + metrics.GetOrRegisterMeter(fmt.Sprintf("%s/%s/%d/%#02x", MetricsOutboundTraffic, msg.meterCap.Name, msg.meterCap.Version, msg.meterCode), nil).Mark(int64(msg.meterSize)) + } // write header headbuf := make([]byte, 32) fsize := uint32(len(ptype)) + msg.Size @@ -686,6 +691,7 @@ func (rw *rlpxFrameRW) ReadMsg() (msg Msg, err error) { return msg, err } msg.Size = uint32(content.Len()) + msg.meterSize = msg.Size msg.Payload = content // if snappy is enabled, verify and decompress message diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/server.go b/vendor/github.com/ethereum/go-ethereum/p2p/server.go index 692c9eb7d9..246148741f 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/server.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/server.go @@ -45,6 +45,11 @@ import ( const ( defaultDialTimeout = 15 * time.Second + // This is the fairness knob for the discovery mixer. When looking for peers, we'll + // wait this long for a single source of candidates before moving on and trying other + // sources. + discmixTimeout = 5 * time.Second + // Connectivity defaults. maxActiveDialTasks = 16 defaultMaxPendingPeers = 50 @@ -167,16 +172,20 @@ type Server struct { lock sync.Mutex // protects running running bool - nodedb *enode.DB - localnode *enode.LocalNode - ntab discoverTable listener net.Listener ourHandshake *protoHandshake - DiscV5 *discv5.Network loopWG sync.WaitGroup // loop, listenLoop peerFeed event.Feed log log.Logger + nodedb *enode.DB + localnode *enode.LocalNode + ntab *discover.UDPv4 + DiscV5 *discv5.Network + discmix *enode.FairMix + + staticNodeResolver nodeResolver + // Channels into the run loop. quit chan struct{} addstatic chan *enode.Node @@ -470,7 +479,7 @@ func (srv *Server) Start() (err error) { } dynPeers := srv.maxDialedConns() - dialer := newDialState(srv.localnode.ID(), srv.ntab, dynPeers, &srv.Config) + dialer := newDialState(srv.localnode.ID(), dynPeers, &srv.Config) srv.loopWG.Add(1) go srv.run(dialer) return nil @@ -521,6 +530,18 @@ func (srv *Server) setupLocalNode() error { } func (srv *Server) setupDiscovery() error { + srv.discmix = enode.NewFairMix(discmixTimeout) + + // Add protocol-specific discovery sources. + added := make(map[string]bool) + for _, proto := range srv.Protocols { + if proto.DialCandidates != nil && !added[proto.Name] { + srv.discmix.AddSource(proto.DialCandidates) + added[proto.Name] = true + } + } + + // Don't listen on UDP endpoint if DHT is disabled. if srv.NoDiscovery && !srv.DiscoveryV5 { return nil } @@ -562,7 +583,10 @@ func (srv *Server) setupDiscovery() error { return err } srv.ntab = ntab + srv.discmix.AddSource(ntab.RandomNodes()) + srv.staticNodeResolver = ntab } + // Discovery V5 if srv.DiscoveryV5 { var ntab *discv5.Network @@ -620,6 +644,7 @@ func (srv *Server) run(dialstate dialer) { srv.log.Info("Started P2P networking", "self", srv.localnode.Node().URLv4()) defer srv.loopWG.Done() defer srv.nodedb.Close() + defer srv.discmix.Close() var ( peers = make(map[enode.ID]*Peer) diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/simulations/adapters/types.go b/vendor/github.com/ethereum/go-ethereum/p2p/simulations/adapters/types.go index f65ce7b605..850de96a15 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/simulations/adapters/types.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/simulations/adapters/types.go @@ -101,6 +101,11 @@ type NodeConfig struct { // services registered by calling the RegisterService function) Services []string + // Properties are the names of the properties this node should hold + // within running services (e.g. "bootnode", "lightnode" or any custom values) + // These values need to be checked and acted upon by node Services + Properties []string + // Enode node *enode.Node @@ -120,6 +125,7 @@ type nodeConfigJSON struct { PrivateKey string `json:"private_key"` Name string `json:"name"` Services []string `json:"services"` + Properties []string `json:"properties"` EnableMsgEvents bool `json:"enable_msg_events"` Port uint16 `json:"port"` } @@ -131,6 +137,7 @@ func (n *NodeConfig) MarshalJSON() ([]byte, error) { ID: n.ID.String(), Name: n.Name, Services: n.Services, + Properties: n.Properties, Port: n.Port, EnableMsgEvents: n.EnableMsgEvents, } @@ -168,6 +175,7 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error { n.Name = confJSON.Name n.Services = confJSON.Services + n.Properties = confJSON.Properties n.Port = confJSON.Port n.EnableMsgEvents = confJSON.EnableMsgEvents diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/simulations/network.go b/vendor/github.com/ethereum/go-ethereum/p2p/simulations/network.go index f03c953e89..58fd9a28b0 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/simulations/network.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/simulations/network.go @@ -56,6 +56,9 @@ type Network struct { Nodes []*Node `json:"nodes"` nodeMap map[enode.ID]int + // Maps a node property string to node indexes of all nodes that hold this property + propertyMap map[string][]int + Conns []*Conn `json:"conns"` connMap map[string]int @@ -71,6 +74,7 @@ func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network NetworkConfig: *conf, nodeAdapter: nodeAdapter, nodeMap: make(map[enode.ID]int), + propertyMap: make(map[string][]int), connMap: make(map[string]int), quitc: make(chan struct{}), } @@ -120,9 +124,16 @@ func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) Config: conf, } log.Trace("Node created", "id", conf.ID) - net.nodeMap[conf.ID] = len(net.Nodes) + + nodeIndex := len(net.Nodes) + net.nodeMap[conf.ID] = nodeIndex net.Nodes = append(net.Nodes, node) + // Register any node properties with the network-level propertyMap + for _, property := range conf.Properties { + net.propertyMap[property] = append(net.propertyMap[property], nodeIndex) + } + // emit a "control" event net.events.Send(ControlEvent(node)) @@ -410,7 +421,7 @@ func (net *Network) getNode(id enode.ID) *Node { return net.Nodes[i] } -// GetNode gets the node with the given name, returning nil if the node does +// GetNodeByName gets the node with the given name, returning nil if the node does // not exist func (net *Network) GetNodeByName(name string) *Node { net.lock.RLock() @@ -427,19 +438,104 @@ func (net *Network) getNodeByName(name string) *Node { return nil } -// GetNodes returns the existing nodes -func (net *Network) GetNodes() (nodes []*Node) { +// GetNodeIDs returns the IDs of all existing nodes +// Nodes can optionally be excluded by specifying their enode.ID. +func (net *Network) GetNodeIDs(excludeIDs ...enode.ID) []enode.ID { + net.lock.RLock() + defer net.lock.RUnlock() + + return net.getNodeIDs(excludeIDs) +} + +func (net *Network) getNodeIDs(excludeIDs []enode.ID) []enode.ID { + // Get all curent nodeIDs + nodeIDs := make([]enode.ID, 0, len(net.nodeMap)) + for id := range net.nodeMap { + nodeIDs = append(nodeIDs, id) + } + + if len(excludeIDs) > 0 { + // Return the difference of nodeIDs and excludeIDs + return filterIDs(nodeIDs, excludeIDs) + } else { + return nodeIDs + } +} + +// GetNodes returns the existing nodes. +// Nodes can optionally be excluded by specifying their enode.ID. +func (net *Network) GetNodes(excludeIDs ...enode.ID) []*Node { + net.lock.RLock() + defer net.lock.RUnlock() + + return net.getNodes(excludeIDs) +} + +func (net *Network) getNodes(excludeIDs []enode.ID) []*Node { + if len(excludeIDs) > 0 { + nodeIDs := net.getNodeIDs(excludeIDs) + return net.getNodesByID(nodeIDs) + } else { + return net.Nodes + } +} + +// GetNodesByID returns existing nodes with the given enode.IDs. +// If a node doesn't exist with a given enode.ID, it is ignored. +func (net *Network) GetNodesByID(nodeIDs []enode.ID) []*Node { + net.lock.RLock() + defer net.lock.RUnlock() + + return net.getNodesByID(nodeIDs) +} + +func (net *Network) getNodesByID(nodeIDs []enode.ID) []*Node { + nodes := make([]*Node, 0, len(nodeIDs)) + for _, id := range nodeIDs { + node := net.getNode(id) + if node != nil { + nodes = append(nodes, node) + } + } + + return nodes +} + +// GetNodesByProperty returns existing nodes that have the given property string registered in their NodeConfig +func (net *Network) GetNodesByProperty(property string) []*Node { net.lock.RLock() defer net.lock.RUnlock() - return net.getNodes() + return net.getNodesByProperty(property) } -func (net *Network) getNodes() (nodes []*Node) { - nodes = append(nodes, net.Nodes...) +func (net *Network) getNodesByProperty(property string) []*Node { + nodes := make([]*Node, 0, len(net.propertyMap[property])) + for _, nodeIndex := range net.propertyMap[property] { + nodes = append(nodes, net.Nodes[nodeIndex]) + } + return nodes } +// GetNodeIDsByProperty returns existing node's enode IDs that have the given property string registered in the NodeConfig +func (net *Network) GetNodeIDsByProperty(property string) []enode.ID { + net.lock.RLock() + defer net.lock.RUnlock() + + return net.getNodeIDsByProperty(property) +} + +func (net *Network) getNodeIDsByProperty(property string) []enode.ID { + nodeIDs := make([]enode.ID, 0, len(net.propertyMap[property])) + for _, nodeIndex := range net.propertyMap[property] { + node := net.Nodes[nodeIndex] + nodeIDs = append(nodeIDs, node.ID()) + } + + return nodeIDs +} + // GetRandomUpNode returns a random node on the network, which is running. func (net *Network) GetRandomUpNode(excludeIDs ...enode.ID) *Node { net.lock.RLock() @@ -469,7 +565,7 @@ func (net *Network) GetRandomDownNode(excludeIDs ...enode.ID) *Node { } func (net *Network) getDownNodeIDs() (ids []enode.ID) { - for _, node := range net.getNodes() { + for _, node := range net.Nodes { if !node.Up() { ids = append(ids, node.ID()) } @@ -477,6 +573,13 @@ func (net *Network) getDownNodeIDs() (ids []enode.ID) { return ids } +// GetRandomNode returns a random node on the network, regardless of whether it is running or not +func (net *Network) GetRandomNode(excludeIDs ...enode.ID) *Node { + net.lock.RLock() + defer net.lock.RUnlock() + return net.getRandomNode(net.getNodeIDs(nil), excludeIDs) // no need to exclude twice +} + func (net *Network) getRandomNode(ids []enode.ID, excludeIDs []enode.ID) *Node { filtered := filterIDs(ids, excludeIDs) @@ -616,6 +719,7 @@ func (net *Network) Reset() { //re-initialize the maps net.connMap = make(map[string]int) net.nodeMap = make(map[enode.ID]int) + net.propertyMap = make(map[string][]int) net.Nodes = nil net.Conns = nil @@ -634,12 +738,14 @@ type Node struct { upMu sync.RWMutex } +// Up returns whether the node is currently up (online) func (n *Node) Up() bool { n.upMu.RLock() defer n.upMu.RUnlock() return n.up } +// SetUp sets the up (online) status of the nodes with the given value func (n *Node) SetUp(up bool) { n.upMu.Lock() defer n.upMu.Unlock() diff --git a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go index 36f13d1787..967cba5bc4 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go +++ b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go @@ -29,13 +29,6 @@ var MainnetBootnodes = []string{ "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", // bootnode-azure-koreasouth-001 "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", // bootnode-azure-westus-001 - // Ethereum Foundation Go Bootnodes (legacy) - "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", // IE - "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", // US-WEST - "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", // BR - "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", // AU - "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", // SG - // Ethereum Foundation C++ Bootnodes "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", // DE } diff --git a/vendor/github.com/ethereum/go-ethereum/params/config.go b/vendor/github.com/ethereum/go-ethereum/params/config.go index 200add01b5..c90de56dc3 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/config.go +++ b/vendor/github.com/ethereum/go-ethereum/params/config.go @@ -65,16 +65,16 @@ var ( ByzantiumBlock: big.NewInt(4370000), ConstantinopleBlock: big.NewInt(7280000), PetersburgBlock: big.NewInt(7280000), - IstanbulBlock: nil, + IstanbulBlock: big.NewInt(9069000), Ethash: new(EthashConfig), } // MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network. MainnetTrustedCheckpoint = &TrustedCheckpoint{ - SectionIndex: 253, - SectionHead: common.HexToHash("0xf35fabd036e2030196183bb70ae194f6ce1ea7b58559e3825c168f1df9c0a258"), - CHTRoot: common.HexToHash("0x8992849e2be3390696eaf66312626e484045501cd3ec207922c27a6a80a7bb07"), - BloomRoot: common.HexToHash("0xcc510b51ca4d73fb3fdf43208d73286f8f23817cdc31b8ea9f4de8d645f07df4"), + SectionIndex: 270, + SectionHead: common.HexToHash("0xb67c33d838a60c282c2fb49b188fbbac1ef8565ffb4a1c4909b0a05885e72e40"), + CHTRoot: common.HexToHash("0x781daa4607782300da85d440df3813ba38a1262585231e35e9480726de81dbfc"), + BloomRoot: common.HexToHash("0xfd8951fa6d779cbc981df40dc31056ed1a549db529349d7dfae016f9d96cae72"), } // MainnetCheckpointOracle contains a set of configs for the main network oracle. @@ -103,16 +103,16 @@ var ( ByzantiumBlock: big.NewInt(1700000), ConstantinopleBlock: big.NewInt(4230000), PetersburgBlock: big.NewInt(4939394), - IstanbulBlock: nil, + IstanbulBlock: big.NewInt(6485846), Ethash: new(EthashConfig), } // TestnetTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network. TestnetTrustedCheckpoint = &TrustedCheckpoint{ - SectionIndex: 187, - SectionHead: common.HexToHash("0x7d6db64d8ec43303e4392fb726d2346f7231b246decca3d8140dd7e2c0d0b07d"), - CHTRoot: common.HexToHash("0xa5095e1a004a8642fb93ca682eb91e8f20ef5bce151e47404fbb68772d17705b"), - BloomRoot: common.HexToHash("0x90b28050f948ec6fb35b23a91d9aed38ce0c92d3cdd6e1d383c1bddf8b4071cf"), + SectionIndex: 204, + SectionHead: common.HexToHash("0xa39168b51c3205456f30ce6a91f3590a43295b15a1c8c2ab86bb8c06b8ad1808"), + CHTRoot: common.HexToHash("0x9a3654147b79882bfc4e16fbd3421512aa7e4dfadc6c511923980e0877bdf3b4"), + BloomRoot: common.HexToHash("0xe72b979522d94fa45c1331639316da234a9bb85062d64d72e13afe1d3f5c17d5"), } // TestnetCheckpointOracle contains a set of configs for the Ropsten test network oracle. @@ -141,7 +141,7 @@ var ( ByzantiumBlock: big.NewInt(1035301), ConstantinopleBlock: big.NewInt(3660663), PetersburgBlock: big.NewInt(4321234), - IstanbulBlock: nil, + IstanbulBlock: big.NewInt(5435345), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -150,10 +150,10 @@ var ( // RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network. RinkebyTrustedCheckpoint = &TrustedCheckpoint{ - SectionIndex: 148, - SectionHead: common.HexToHash("0x45918f4686732c2a3e80827e1bc39cdb6a27fa362ddfe1fdfb61c69a7f1df1a9"), - CHTRoot: common.HexToHash("0x8ac7046391fec14834a2a0183513937c0b5f696666545991477d24b067008961"), - BloomRoot: common.HexToHash("0xfe4b852517612d7da54bf7e9fc18861a83171a93c72583bb6a61893b74422168"), + SectionIndex: 163, + SectionHead: common.HexToHash("0x36e5deaa46f258bece94b05d8e10f1ef68f422fb62ed47a2b6e616aa26e84997"), + CHTRoot: common.HexToHash("0x829b9feca1c2cdf5a4cf3efac554889e438ee4df8718c2ce3e02555a02d9e9e5"), + BloomRoot: common.HexToHash("0x58c01de24fdae7c082ebbe7665f189d0aa4d90ee10e72086bf56651c63269e54"), } // RinkebyCheckpointOracle contains a set of configs for the Rinkeby test network oracle. @@ -180,7 +180,7 @@ var ( ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), - IstanbulBlock: nil, + IstanbulBlock: big.NewInt(1561651), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -189,10 +189,10 @@ var ( // GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network. GoerliTrustedCheckpoint = &TrustedCheckpoint{ - SectionIndex: 32, - SectionHead: common.HexToHash("0x50eaedd8361fa9edd0ac2dec410310b9bdf67b963b60f3b1dce47f84b30670f9"), - CHTRoot: common.HexToHash("0x6504db73139f75ffa9102ae980e41b361cf3d5b66cea06c79cde9f457368820c"), - BloomRoot: common.HexToHash("0x7551ae027bb776252a20ded51ee2ff0cbfbd1d8d57261b9161cc1f2f80237001"), + SectionIndex: 47, + SectionHead: common.HexToHash("0x00c5b54c6c9a73660501fd9273ccdb4c5bbdbe5d7b8b650e28f881ec9d2337f6"), + CHTRoot: common.HexToHash("0xef35caa155fd659f57167e7d507de2f8132cbb31f771526481211d8a977d704c"), + BloomRoot: common.HexToHash("0xbda330402f66008d52e7adc748da28535b1212a7912a21244acd2ba77ff0ff06"), } // GoerliCheckpointOracle contains a set of configs for the Goerli test network oracle. @@ -213,16 +213,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -415,6 +415,42 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *Confi return lasterr } +// CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough +// to guarantee that forks +func (c *ChainConfig) CheckConfigForkOrder() error { + type fork struct { + name string + block *big.Int + } + var lastFork fork + for _, cur := range []fork{ + {"homesteadBlock", c.HomesteadBlock}, + {"eip150Block", c.EIP150Block}, + {"eip155Block", c.EIP155Block}, + {"eip158Block", c.EIP158Block}, + {"byzantiumBlock", c.ByzantiumBlock}, + {"constantinopleBlock", c.ConstantinopleBlock}, + {"petersburgBlock", c.PetersburgBlock}, + {"istanbulBlock", c.IstanbulBlock}, + } { + if lastFork.name != "" { + // Next one must be higher number + if lastFork.block == nil && cur.block != nil { + return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v", + lastFork.name, cur.name, cur.block) + } + if lastFork.block != nil && cur.block != nil { + if lastFork.block.Cmp(cur.block) > 0 { + return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v", + lastFork.name, lastFork.block, cur.name, cur.block) + } + } + } + lastFork = cur + } + return nil +} + func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError { if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) { return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) diff --git a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go index 943788be8c..11b858a61c 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go +++ b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go @@ -52,22 +52,32 @@ const ( NetSstoreResetRefund uint64 = 4800 // Once per SSTORE operation for resetting to the original non-zero value NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value + SstoreSentryGasEIP2200 uint64 = 2300 // Minimum gas required to be present for an SSTORE call, not consumed + SstoreNoopGasEIP2200 uint64 = 800 // Once per SSTORE operation if the value doesn't change. + SstoreDirtyGasEIP2200 uint64 = 800 // Once per SSTORE operation if a dirty value is changed. + SstoreInitGasEIP2200 uint64 = 20000 // Once per SSTORE operation from clean zero to non-zero + SstoreInitRefundEIP2200 uint64 = 19200 // Once per SSTORE operation for resetting to the original zero value + SstoreCleanGasEIP2200 uint64 = 5000 // Once per SSTORE operation from clean non-zero to something else + SstoreCleanRefundEIP2200 uint64 = 4200 // Once per SSTORE operation for resetting to the original non-zero value + SstoreClearRefundEIP2200 uint64 = 15000 // Once per SSTORE operation for clearing an originally existing storage slot + JumpdestGas uint64 = 1 // Once per JUMPDEST operation. EpochDuration uint64 = 30000 // Duration between proof-of-work epochs. - CreateDataGas uint64 = 200 // - CallCreateDepth uint64 = 1024 // Maximum depth of call/create stack. - ExpGas uint64 = 10 // Once per EXP instruction - LogGas uint64 = 375 // Per LOG* operation. - CopyGas uint64 = 3 // - StackLimit uint64 = 1024 // Maximum size of VM stack allowed. - TierStepGas uint64 = 0 // Once per operation, for a selection of them. - LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. - CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction. - Create2Gas uint64 = 32000 // Once per CREATE2 operation - SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation. - MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. - TxDataNonZeroGas uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + CreateDataGas uint64 = 200 // + CallCreateDepth uint64 = 1024 // Maximum depth of call/create stack. + ExpGas uint64 = 10 // Once per EXP instruction + LogGas uint64 = 375 // Per LOG* operation. + CopyGas uint64 = 3 // + StackLimit uint64 = 1024 // Maximum size of VM stack allowed. + TierStepGas uint64 = 0 // Once per operation, for a selection of them. + LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. + CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction. + Create2Gas uint64 = 32000 // Once per CREATE2 operation + SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation. + MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul) // These have been changed during the course of the chain CallGasFrontier uint64 = 40 // Once per CALL operation & message call transaction. diff --git a/vendor/github.com/ethereum/go-ethereum/params/version.go b/vendor/github.com/ethereum/go-ethereum/params/version.go index 87934df80d..efb92abb28 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/version.go +++ b/vendor/github.com/ethereum/go-ethereum/params/version.go @@ -23,7 +23,7 @@ import ( const ( VersionMajor = 1 // Major version component of the current release VersionMinor = 9 // Minor version component of the current release - VersionPatch = 2 // Patch version component of the current release + VersionPatch = 7 // Patch version component of the current release VersionMeta = "stable" // Version metadata to append to the version string ) diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go index 4f29f2fb03..524395915d 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go @@ -55,81 +55,23 @@ var ( } ) -// Decoder is implemented by types that require custom RLP -// decoding rules or need to decode into private fields. +// Decoder is implemented by types that require custom RLP decoding rules or need to decode +// into private fields. // -// The DecodeRLP method should read one value from the given -// Stream. It is not forbidden to read less or more, but it might -// be confusing. +// The DecodeRLP method should read one value from the given Stream. It is not forbidden to +// read less or more, but it might be confusing. type Decoder interface { DecodeRLP(*Stream) error } -// Decode parses RLP-encoded data from r and stores the result in the -// value pointed to by val. Val must be a non-nil pointer. If r does -// not implement ByteReader, Decode will do its own buffering. +// Decode parses RLP-encoded data from r and stores the result in the value pointed to by +// val. Please see package-level documentation for the decoding rules. Val must be a +// non-nil pointer. // -// Decode uses the following type-dependent decoding rules: +// If r does not implement ByteReader, Decode will do its own buffering. // -// If the type implements the Decoder interface, decode calls -// DecodeRLP. -// -// To decode into a pointer, Decode will decode into the value pointed -// to. If the pointer is nil, a new value of the pointer's element -// type is allocated. If the pointer is non-nil, the existing value -// will be reused. -// -// To decode into a struct, Decode expects the input to be an RLP -// list. The decoded elements of the list are assigned to each public -// field in the order given by the struct's definition. The input list -// must contain an element for each decoded field. Decode returns an -// error if there are too few or too many elements. -// -// The decoding of struct fields honours certain struct tags, "tail", -// "nil" and "-". -// -// The "-" tag ignores fields. -// -// For an explanation of "tail", see the example. -// -// The "nil" tag applies to pointer-typed fields and changes the decoding -// rules for the field such that input values of size zero decode as a nil -// pointer. This tag can be useful when decoding recursive types. -// -// type StructWithEmptyOK struct { -// Foo *[20]byte `rlp:"nil"` -// } -// -// To decode into a slice, the input must be a list and the resulting -// slice will contain the input elements in order. For byte slices, -// the input must be an RLP string. Array types decode similarly, with -// the additional restriction that the number of input elements (or -// bytes) must match the array's length. -// -// To decode into a Go string, the input must be an RLP string. The -// input bytes are taken as-is and will not necessarily be valid UTF-8. -// -// To decode into an unsigned integer type, the input must also be an RLP -// string. The bytes are interpreted as a big endian representation of -// the integer. If the RLP string is larger than the bit size of the -// type, Decode will return an error. Decode also supports *big.Int. -// There is no size limit for big integers. -// -// To decode into a boolean, the input must contain an unsigned integer -// of value zero (false) or one (true). -// -// To decode into an interface value, Decode stores one of these -// in the value: -// -// []interface{}, for RLP lists -// []byte, for RLP strings -// -// Non-empty interface types are not supported, nor are signed integers, -// floating point numbers, maps, channels and functions. -// -// Note that Decode does not set an input limit for all readers -// and may be vulnerable to panics cause by huge value sizes. If -// you need an input limit, use +// Note that Decode does not set an input limit for all readers and may be vulnerable to +// panics cause by huge value sizes. If you need an input limit, use // // NewStream(r, limit).Decode(val) func Decode(r io.Reader, val interface{}) error { @@ -140,9 +82,8 @@ func Decode(r io.Reader, val interface{}) error { return stream.Decode(val) } -// DecodeBytes parses RLP data from b into val. -// Please see the documentation of Decode for the decoding rules. -// The input must contain exactly one value and no trailing data. +// DecodeBytes parses RLP data from b into val. Please see package-level documentation for +// the decoding rules. The input must contain exactly one value and no trailing data. func DecodeBytes(b []byte, val interface{}) error { r := bytes.NewReader(b) @@ -211,14 +152,15 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { switch { case typ == rawValueType: return decodeRawValue, nil - case typ.Implements(decoderInterface): return decodeDecoder, nil - case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface): - return decodeDecoderNoPtr, nil case typ.AssignableTo(reflect.PtrTo(bigInt)): return decodeBigInt, nil case typ.AssignableTo(bigInt): return decodeBigIntNoPtr, nil + case kind == reflect.Ptr: + return makePtrDecoder(typ, tags) + case reflect.PtrTo(typ).Implements(decoderInterface): + return decodeDecoder, nil case isUint(kind): return decodeUint, nil case kind == reflect.Bool: @@ -229,11 +171,6 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { return makeListDecoder(typ, tags) case kind == reflect.Struct: return makeStructDecoder(typ) - case kind == reflect.Ptr: - if tags.nilOK { - return makeOptionalPtrDecoder(typ) - } - return makePtrDecoder(typ) case kind == reflect.Interface: return decodeInterface, nil default: @@ -448,6 +385,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { if err != nil { return nil, err } + for _, f := range fields { + if f.info.decoderErr != nil { + return nil, structFieldError{typ, f.index, f.info.decoderErr} + } + } dec := func(s *Stream, val reflect.Value) (err error) { if _, err := s.List(); err != nil { return wrapStreamError(err, typ) @@ -465,15 +407,22 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { return dec, nil } -// makePtrDecoder creates a decoder that decodes into -// the pointer's element type. -func makePtrDecoder(typ reflect.Type) (decoder, error) { +// makePtrDecoder creates a decoder that decodes into the pointer's element type. +func makePtrDecoder(typ reflect.Type, tag tags) (decoder, error) { etype := typ.Elem() etypeinfo := cachedTypeInfo1(etype, tags{}) - if etypeinfo.decoderErr != nil { + switch { + case etypeinfo.decoderErr != nil: return nil, etypeinfo.decoderErr + case !tag.nilOK: + return makeSimplePtrDecoder(etype, etypeinfo), nil + default: + return makeNilPtrDecoder(etype, etypeinfo, tag.nilKind), nil } - dec := func(s *Stream, val reflect.Value) (err error) { +} + +func makeSimplePtrDecoder(etype reflect.Type, etypeinfo *typeinfo) decoder { + return func(s *Stream, val reflect.Value) (err error) { newval := val if val.IsNil() { newval = reflect.New(etype) @@ -483,30 +432,35 @@ func makePtrDecoder(typ reflect.Type) (decoder, error) { } return err } - return dec, nil } -// makeOptionalPtrDecoder creates a decoder that decodes empty values -// as nil. Non-empty values are decoded into a value of the element type, -// just like makePtrDecoder does. +// makeNilPtrDecoder creates a decoder that decodes empty values as nil. Non-empty +// values are decoded into a value of the element type, just like makePtrDecoder does. // // This decoder is used for pointer-typed struct fields with struct tag "nil". -func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { - etype := typ.Elem() - etypeinfo := cachedTypeInfo1(etype, tags{}) - if etypeinfo.decoderErr != nil { - return nil, etypeinfo.decoderErr - } - dec := func(s *Stream, val reflect.Value) (err error) { +func makeNilPtrDecoder(etype reflect.Type, etypeinfo *typeinfo, nilKind Kind) decoder { + typ := reflect.PtrTo(etype) + nilPtr := reflect.Zero(typ) + return func(s *Stream, val reflect.Value) (err error) { kind, size, err := s.Kind() - if err != nil || size == 0 && kind != Byte { + if err != nil { + val.Set(nilPtr) + return wrapStreamError(err, typ) + } + // Handle empty values as a nil pointer. + if kind != Byte && size == 0 { + if kind != nilKind { + return &decodeError{ + msg: fmt.Sprintf("wrong kind of empty value (got %v, want %v)", kind, nilKind), + typ: typ, + } + } // rearm s.Kind. This is important because the input // position must advance to the next value even though // we don't read anything. s.kind = -1 - // set the pointer to nil. - val.Set(reflect.Zero(typ)) - return err + val.Set(nilPtr) + return nil } newval := val if val.IsNil() { @@ -517,7 +471,6 @@ func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { } return err } - return dec, nil } var ifsliceType = reflect.TypeOf([]interface{}{}) @@ -546,21 +499,8 @@ func decodeInterface(s *Stream, val reflect.Value) error { return nil } -// This decoder is used for non-pointer values of types -// that implement the Decoder interface using a pointer receiver. -func decodeDecoderNoPtr(s *Stream, val reflect.Value) error { - return val.Addr().Interface().(Decoder).DecodeRLP(s) -} - func decodeDecoder(s *Stream, val reflect.Value) error { - // Decoder instances are not handled using the pointer rule if the type - // implements Decoder with pointer receiver (i.e. always) - // because it might handle empty values specially. - // We need to allocate one here in this case, like makePtrDecoder does. - if val.Kind() == reflect.Ptr && val.IsNil() { - val.Set(reflect.New(val.Type().Elem())) - } - return val.Interface().(Decoder).DecodeRLP(s) + return val.Addr().Interface().(Decoder).DecodeRLP(s) } // Kind represents the kind of value contained in an RLP stream. diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/doc.go b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go index b3a81fe232..7e6ee85200 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/doc.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go @@ -17,17 +17,114 @@ /* Package rlp implements the RLP serialization format. -The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily -nested arrays of binary data, and RLP is the main encoding method used -to serialize objects in Ethereum. The only purpose of RLP is to encode -structure; encoding specific atomic data types (eg. strings, ints, -floats) is left up to higher-order protocols; in Ethereum integers -must be represented in big endian binary form with no leading zeroes -(thus making the integer value zero equivalent to the empty byte -array). - -RLP values are distinguished by a type tag. The type tag precedes the -value in the input stream and defines the size and kind of the bytes -that follow. +The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily nested arrays of +binary data, and RLP is the main encoding method used to serialize objects in Ethereum. +The only purpose of RLP is to encode structure; encoding specific atomic data types (eg. +strings, ints, floats) is left up to higher-order protocols. In Ethereum integers must be +represented in big endian binary form with no leading zeroes (thus making the integer +value zero equivalent to the empty string). + +RLP values are distinguished by a type tag. The type tag precedes the value in the input +stream and defines the size and kind of the bytes that follow. + + +Encoding Rules + +Package rlp uses reflection and encodes RLP based on the Go type of the value. + +If the type implements the Encoder interface, Encode calls EncodeRLP. It does not +call EncodeRLP on nil pointer values. + +To encode a pointer, the value being pointed to is encoded. A nil pointer to a struct +type, slice or array always encodes as an empty RLP list unless the slice or array has +elememt type byte. A nil pointer to any other value encodes as the empty string. + +Struct values are encoded as an RLP list of all their encoded public fields. Recursive +struct types are supported. + +To encode slices and arrays, the elements are encoded as an RLP list of the value's +elements. Note that arrays and slices with element type uint8 or byte are always encoded +as an RLP string. + +A Go string is encoded as an RLP string. + +An unsigned integer value is encoded as an RLP string. Zero always encodes as an empty RLP +string. big.Int values are treated as integers. Signed integers (int, int8, int16, ...) +are not supported and will return an error when encoding. + +Boolean values are encoded as the unsigned integers zero (false) and one (true). + +An interface value encodes as the value contained in the interface. + +Floating point numbers, maps, channels and functions are not supported. + + +Decoding Rules + +Decoding uses the following type-dependent rules: + +If the type implements the Decoder interface, DecodeRLP is called. + +To decode into a pointer, the value will be decoded as the element type of the pointer. If +the pointer is nil, a new value of the pointer's element type is allocated. If the pointer +is non-nil, the existing value will be reused. Note that package rlp never leaves a +pointer-type struct field as nil unless one of the "nil" struct tags is present. + +To decode into a struct, decoding expects the input to be an RLP list. The decoded +elements of the list are assigned to each public field in the order given by the struct's +definition. The input list must contain an element for each decoded field. Decoding +returns an error if there are too few or too many elements for the struct. + +To decode into a slice, the input must be a list and the resulting slice will contain the +input elements in order. For byte slices, the input must be an RLP string. Array types +decode similarly, with the additional restriction that the number of input elements (or +bytes) must match the array's defined length. + +To decode into a Go string, the input must be an RLP string. The input bytes are taken +as-is and will not necessarily be valid UTF-8. + +To decode into an unsigned integer type, the input must also be an RLP string. The bytes +are interpreted as a big endian representation of the integer. If the RLP string is larger +than the bit size of the type, decoding will return an error. Decode also supports +*big.Int. There is no size limit for big integers. + +To decode into a boolean, the input must contain an unsigned integer of value zero (false) +or one (true). + +To decode into an interface value, one of these types is stored in the value: + + []interface{}, for RLP lists + []byte, for RLP strings + +Non-empty interface types are not supported when decoding. +Signed integers, floating point numbers, maps, channels and functions cannot be decoded into. + + +Struct Tags + +Package rlp honours certain struct tags: "-", "tail", "nil", "nilList" and "nilString". + +The "-" tag ignores fields. + +The "tail" tag, which may only be used on the last exported struct field, allows slurping +up any excess list elements into a slice. See examples for more details. + +The "nil" tag applies to pointer-typed fields and changes the decoding rules for the field +such that input values of size zero decode as a nil pointer. This tag can be useful when +decoding recursive types. + + type StructWithOptionalFoo struct { + Foo *[20]byte `rlp:"nil"` + } + +RLP supports two kinds of empty values: empty lists and empty strings. When using the +"nil" tag, the kind of empty value allowed for a type is chosen automatically. A struct +field whose Go type is a pointer to an unsigned integer, string, boolean or byte +array/slice expects an empty RLP string. Any other pointer field type encodes/decodes as +an empty RLP list. + +The choice of null value can be made explicit with the "nilList" and "nilString" struct +tags. Using these tags encodes/decodes a Go nil pointer value as the kind of empty +RLP value defined by the tag. */ package rlp diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go index f255c38a9c..9c9e8d706d 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go @@ -49,36 +49,7 @@ type Encoder interface { // perform many small writes in some cases. Consider making w // buffered. // -// Encode uses the following type-dependent encoding rules: -// -// If the type implements the Encoder interface, Encode calls -// EncodeRLP. This is true even for nil pointers, please see the -// documentation for Encoder. -// -// To encode a pointer, the value being pointed to is encoded. For nil -// pointers, Encode will encode the zero value of the type. A nil -// pointer to a struct type always encodes as an empty RLP list. -// A nil pointer to an array encodes as an empty list (or empty string -// if the array has element type byte). -// -// Struct values are encoded as an RLP list of all their encoded -// public fields. Recursive struct types are supported. -// -// To encode slices and arrays, the elements are encoded as an RLP -// list of the value's elements. Note that arrays and slices with -// element type uint8 or byte are always encoded as an RLP string. -// -// A Go string is encoded as an RLP string. -// -// An unsigned integer value is encoded as an RLP string. Zero always -// encodes as an empty RLP string. Encode also supports *big.Int. -// -// Boolean values are encoded as unsigned integers zero (false) and one (true). -// -// An interface value encodes as the value contained in the interface. -// -// Signed integers are not supported, nor are floating point numbers, maps, -// channels and functions. +// Please see package-level documentation of encoding rules. func Encode(w io.Writer, val interface{}) error { if outer, ok := w.(*encbuf); ok { // Encode was called by some type's EncodeRLP. @@ -95,7 +66,7 @@ func Encode(w io.Writer, val interface{}) error { } // EncodeToBytes returns the RLP encoding of val. -// Please see the documentation of Encode for the encoding rules. +// Please see package-level documentation for the encoding rules. func EncodeToBytes(val interface{}) ([]byte, error) { eb := encbufPool.Get().(*encbuf) defer encbufPool.Put(eb) @@ -349,16 +320,14 @@ func makeWriter(typ reflect.Type, ts tags) (writer, error) { switch { case typ == rawValueType: return writeRawValue, nil - case typ.Implements(encoderInterface): - return writeEncoder, nil - case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface): - return writeEncoderNoPtr, nil - case kind == reflect.Interface: - return writeInterface, nil case typ.AssignableTo(reflect.PtrTo(bigInt)): return writeBigIntPtr, nil case typ.AssignableTo(bigInt): return writeBigIntNoPtr, nil + case kind == reflect.Ptr: + return makePtrWriter(typ, ts) + case reflect.PtrTo(typ).Implements(encoderInterface): + return makeEncoderWriter(typ), nil case isUint(kind): return writeUint, nil case kind == reflect.Bool: @@ -373,8 +342,8 @@ func makeWriter(typ reflect.Type, ts tags) (writer, error) { return makeSliceWriter(typ, ts) case kind == reflect.Struct: return makeStructWriter(typ) - case kind == reflect.Ptr: - return makePtrWriter(typ) + case kind == reflect.Interface: + return writeInterface, nil default: return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) } @@ -470,26 +439,6 @@ func writeString(val reflect.Value, w *encbuf) error { return nil } -func writeEncoder(val reflect.Value, w *encbuf) error { - return val.Interface().(Encoder).EncodeRLP(w) -} - -// writeEncoderNoPtr handles non-pointer values that implement Encoder -// with a pointer receiver. -func writeEncoderNoPtr(val reflect.Value, w *encbuf) error { - if !val.CanAddr() { - // We can't get the address. It would be possible to make the - // value addressable by creating a shallow copy, but this - // creates other problems so we're not doing it (yet). - // - // package json simply doesn't call MarshalJSON for cases like - // this, but encodes the value as if it didn't implement the - // interface. We don't want to handle it that way. - return fmt.Errorf("rlp: game over: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) - } - return val.Addr().Interface().(Encoder).EncodeRLP(w) -} - func writeInterface(val reflect.Value, w *encbuf) error { if val.IsNil() { // Write empty list. This is consistent with the previous RLP @@ -531,6 +480,11 @@ func makeStructWriter(typ reflect.Type) (writer, error) { if err != nil { return nil, err } + for _, f := range fields { + if f.info.writerErr != nil { + return nil, structFieldError{typ, f.index, f.info.writerErr} + } + } writer := func(val reflect.Value, w *encbuf) error { lh := w.list() for _, f := range fields { @@ -544,44 +498,51 @@ func makeStructWriter(typ reflect.Type) (writer, error) { return writer, nil } -func makePtrWriter(typ reflect.Type) (writer, error) { +func makePtrWriter(typ reflect.Type, ts tags) (writer, error) { etypeinfo := cachedTypeInfo1(typ.Elem(), tags{}) if etypeinfo.writerErr != nil { return nil, etypeinfo.writerErr } - - // determine nil pointer handler - var nilfunc func(*encbuf) error - kind := typ.Elem().Kind() - switch { - case kind == reflect.Array && isByte(typ.Elem().Elem()): - nilfunc = func(w *encbuf) error { - w.str = append(w.str, 0x80) - return nil - } - case kind == reflect.Struct || kind == reflect.Array: - nilfunc = func(w *encbuf) error { - // encoding the zero value of a struct/array could trigger - // infinite recursion, avoid that. - w.listEnd(w.list()) - return nil - } - default: - zero := reflect.Zero(typ.Elem()) - nilfunc = func(w *encbuf) error { - return etypeinfo.writer(zero, w) - } + // Determine how to encode nil pointers. + var nilKind Kind + if ts.nilOK { + nilKind = ts.nilKind // use struct tag if provided + } else { + nilKind = defaultNilKind(typ.Elem()) } writer := func(val reflect.Value, w *encbuf) error { if val.IsNil() { - return nilfunc(w) + if nilKind == String { + w.str = append(w.str, 0x80) + } else { + w.listEnd(w.list()) + } + return nil } return etypeinfo.writer(val.Elem(), w) } return writer, nil } +func makeEncoderWriter(typ reflect.Type) writer { + if typ.Implements(encoderInterface) { + return func(val reflect.Value, w *encbuf) error { + return val.Interface().(Encoder).EncodeRLP(w) + } + } + w := func(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // package json simply doesn't call MarshalJSON for this case, but encodes the + // value as if it didn't implement the interface. We don't want to handle it that + // way. + return fmt.Errorf("rlp: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) + } + return val.Addr().Interface().(Encoder).EncodeRLP(w) + } + return w +} + // putint writes i to the beginning of b in big endian byte // order, using the least number of bytes needed to represent i. func putint(b []byte, i uint64) (size int) { diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go index ab5ee3da76..e9a1e3f9e2 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go @@ -35,22 +35,28 @@ type typeinfo struct { writerErr error // error from makeWriter } -// represents struct tags +// tags represents struct tags. type tags struct { // rlp:"nil" controls whether empty input results in a nil pointer. nilOK bool + + // This controls whether nil pointers are encoded/decoded as empty strings + // or empty lists. + nilKind Kind + // rlp:"tail" controls whether this field swallows additional list // elements. It can only be set for the last field, which must be // of slice type. tail bool + // rlp:"-" ignores fields. ignored bool } +// typekey is the key of a type in typeCache. It includes the struct tags because +// they might generate a different decoder. type typekey struct { reflect.Type - // the key must include the struct tags because they - // might generate a different decoder. tags } @@ -120,6 +126,25 @@ func structFields(typ reflect.Type) (fields []field, err error) { return fields, nil } +type structFieldError struct { + typ reflect.Type + field int + err error +} + +func (e structFieldError) Error() string { + return fmt.Sprintf("%v (struct field %v.%s)", e.err, e.typ, e.typ.Field(e.field).Name) +} + +type structTagError struct { + typ reflect.Type + field, tag, err string +} + +func (e structTagError) Error() string { + return fmt.Sprintf("rlp: invalid struct tag %q for %v.%s (%s)", e.tag, e.typ, e.field, e.err) +} + func parseStructTag(typ reflect.Type, fi, lastPublic int) (tags, error) { f := typ.Field(fi) var ts tags @@ -128,15 +153,26 @@ func parseStructTag(typ reflect.Type, fi, lastPublic int) (tags, error) { case "": case "-": ts.ignored = true - case "nil": + case "nil", "nilString", "nilList": ts.nilOK = true + if f.Type.Kind() != reflect.Ptr { + return ts, structTagError{typ, f.Name, t, "field is not a pointer"} + } + switch t { + case "nil": + ts.nilKind = defaultNilKind(f.Type.Elem()) + case "nilString": + ts.nilKind = String + case "nilList": + ts.nilKind = List + } case "tail": ts.tail = true if fi != lastPublic { - return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) + return ts, structTagError{typ, f.Name, t, "must be on last field"} } if f.Type.Kind() != reflect.Slice { - return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) + return ts, structTagError{typ, f.Name, t, "field type is not slice"} } default: return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) @@ -160,6 +196,20 @@ func (i *typeinfo) generate(typ reflect.Type, tags tags) { i.writer, i.writerErr = makeWriter(typ, tags) } +// defaultNilKind determines whether a nil pointer to typ encodes/decodes +// as an empty string or empty list. +func defaultNilKind(typ reflect.Type) Kind { + k := typ.Kind() + if isUint(k) || k == reflect.String || k == reflect.Bool || isByteArray(typ) { + return String + } + return List +} + func isUint(k reflect.Kind) bool { return k >= reflect.Uint && k <= reflect.Uintptr } + +func isByteArray(typ reflect.Type) bool { + return (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Array) && isByte(typ.Elem()) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go b/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go new file mode 100644 index 0000000000..a14fd09d54 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go @@ -0,0 +1,66 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rpc + +import ( + "compress/gzip" + "io" + "io/ioutil" + "net/http" + "strings" + "sync" +) + +var gzPool = sync.Pool{ + New: func() interface{} { + w := gzip.NewWriter(ioutil.Discard) + return w + }, +} + +type gzipResponseWriter struct { + io.Writer + http.ResponseWriter +} + +func (w *gzipResponseWriter) WriteHeader(status int) { + w.Header().Del("Content-Length") + w.ResponseWriter.WriteHeader(status) +} + +func (w *gzipResponseWriter) Write(b []byte) (int, error) { + return w.Writer.Write(b) +} + +func newGzipHandler(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + next.ServeHTTP(w, r) + return + } + + w.Header().Set("Content-Encoding", "gzip") + + gz := gzPool.Get().(*gzip.Writer) + defer gzPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r) + }) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/http.go b/vendor/github.com/ethereum/go-ethereum/rpc/http.go index e8f2cfda77..2c0cb5edbe 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/http.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/http.go @@ -216,6 +216,7 @@ func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv ht // Wrap the CORS-handler within a host-handler handler := newCorsHandler(srv, cors) handler = newVHostHandler(vhosts, handler) + handler = newGzipHandler(handler) // Make sure timeout values are meaningful if timeouts.ReadTimeout < time.Second { diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/types.go b/vendor/github.com/ethereum/go-ethereum/rpc/types.go index f31f09a774..e6b9f2a300 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/types.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/types.go @@ -18,10 +18,12 @@ package rpc import ( "context" + "encoding/json" "fmt" "math" "strings" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -105,3 +107,94 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { func (bn BlockNumber) Int64() int64 { return (int64)(bn) } + +type BlockNumberOrHash struct { + BlockNumber *BlockNumber `json:"blockNumber,omitempty"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + RequireCanonical bool `json:"requireCanonical,omitempty"` +} + +func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error { + type erased BlockNumberOrHash + e := erased{} + err := json.Unmarshal(data, &e) + if err == nil { + if e.BlockNumber != nil && e.BlockHash != nil { + return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other") + } + bnh.BlockNumber = e.BlockNumber + bnh.BlockHash = e.BlockHash + bnh.RequireCanonical = e.RequireCanonical + return nil + } + var input string + err = json.Unmarshal(data, &input) + if err != nil { + return err + } + switch input { + case "earliest": + bn := EarliestBlockNumber + bnh.BlockNumber = &bn + return nil + case "latest": + bn := LatestBlockNumber + bnh.BlockNumber = &bn + return nil + case "pending": + bn := PendingBlockNumber + bnh.BlockNumber = &bn + return nil + default: + if len(input) == 66 { + hash := common.Hash{} + err := hash.UnmarshalText([]byte(input)) + if err != nil { + return err + } + bnh.BlockHash = &hash + return nil + } else { + blckNum, err := hexutil.DecodeUint64(input) + if err != nil { + return err + } + if blckNum > math.MaxInt64 { + return fmt.Errorf("blocknumber too high") + } + bn := BlockNumber(blckNum) + bnh.BlockNumber = &bn + return nil + } + } +} + +func (bnh *BlockNumberOrHash) Number() (BlockNumber, bool) { + if bnh.BlockNumber != nil { + return *bnh.BlockNumber, true + } + return BlockNumber(0), false +} + +func (bnh *BlockNumberOrHash) Hash() (common.Hash, bool) { + if bnh.BlockHash != nil { + return *bnh.BlockHash, true + } + return common.Hash{}, false +} + +func BlockNumberOrHashWithNumber(blockNr BlockNumber) BlockNumberOrHash { + return BlockNumberOrHash{ + BlockNumber: &blockNr, + BlockHash: nil, + RequireCanonical: false, + } +} + +func BlockNumberOrHashWithHash(hash common.Hash, canonical bool) BlockNumberOrHash { + return BlockNumberOrHash{ + BlockNumber: nil, + BlockHash: &hash, + RequireCanonical: canonical, + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/sync.go b/vendor/github.com/ethereum/go-ethereum/trie/sync.go index 6f40b45a1e..e5a0c17493 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/sync.go @@ -57,14 +57,12 @@ type SyncResult struct { // persisted data items. type syncMemBatch struct { batch map[common.Hash][]byte // In-memory membatch of recently completed items - order []common.Hash // Order of completion to prevent out-of-order data loss } // newSyncMemBatch allocates a new memory-buffer for not-yet persisted trie nodes. func newSyncMemBatch() *syncMemBatch { return &syncMemBatch{ batch: make(map[common.Hash][]byte), - order: make([]common.Hash, 0, 256), } } @@ -223,20 +221,18 @@ func (s *Sync) Process(results []SyncResult) (bool, int, error) { } // Commit flushes the data stored in the internal membatch out to persistent -// storage, returning the number of items written and any occurred error. -func (s *Sync) Commit(dbw ethdb.KeyValueWriter) (int, error) { +// storage, returning any occurred error. +func (s *Sync) Commit(dbw ethdb.Batch) error { // Dump the membatch into a database dbw - for i, key := range s.membatch.order { - if err := dbw.Put(key[:], s.membatch.batch[key]); err != nil { - return i, err + for key, value := range s.membatch.batch { + if err := dbw.Put(key[:], value); err != nil { + return err } s.bloom.Add(key[:]) } - written := len(s.membatch.order) // TODO(karalabe): could an order change improve write performance? - // Drop the membatch data and return s.membatch = newSyncMemBatch() - return written, nil + return nil } // Pending returns the number of state entries currently pending for download. @@ -330,7 +326,6 @@ func (s *Sync) children(req *request, object node) ([]*request, error) { func (s *Sync) commit(req *request) (err error) { // Write the node content to the membatch s.membatch.batch[req.hash] = req.data - s.membatch.order = append(s.membatch.order, req.hash) delete(s.requests, req.hash) diff --git a/vendor/github.com/ethereum/go-ethereum/whisper/whisperv6/doc.go b/vendor/github.com/ethereum/go-ethereum/whisper/whisperv6/doc.go index 529bf3d2de..44c0c3271c 100644 --- a/vendor/github.com/ethereum/go-ethereum/whisper/whisperv6/doc.go +++ b/vendor/github.com/ethereum/go-ethereum/whisper/whisperv6/doc.go @@ -34,6 +34,8 @@ package whisperv6 import ( "time" + + "github.com/ethereum/go-ethereum/crypto" ) // Whisper protocol parameters @@ -54,12 +56,12 @@ const ( SizeMask = byte(3) // mask used to extract the size of payload size field from the flags signatureFlag = byte(4) - TopicLength = 4 // in bytes - signatureLength = 65 // in bytes - aesKeyLength = 32 // in bytes - aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize() - keyIDSize = 32 // in bytes - BloomFilterSize = 64 // in bytes + TopicLength = 4 // in bytes + signatureLength = crypto.SignatureLength // in bytes + aesKeyLength = 32 // in bytes + aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize() + keyIDSize = 32 // in bytes + BloomFilterSize = 64 // in bytes flagsLength = 1 EnvelopeHeaderLength = 20 diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go b/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go index ddec46c670..672c672e4f 100644 --- a/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go +++ b/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go @@ -28,8 +28,8 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build dragonfly darwin freebsd netbsd openbsd solaris +// +build dragonfly freebsd netbsd openbsd solaris package pcsc -const PCSCDSockName string = "/var/run/pcscd/pcscd.comm" \ No newline at end of file +const PCSCDSockName string = "/var/run/pcscd/pcscd.comm" diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go b/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go new file mode 100644 index 0000000000..3dec7c79b4 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go @@ -0,0 +1,35 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build darwin + +package pcsc + +const PCSCDSockName string = "" diff --git a/vendor/github.com/gballet/go-libpcsclite/error.go b/vendor/github.com/gballet/go-libpcsclite/error.go index 4710de5e60..87cfee3d0f 100644 --- a/vendor/github.com/gballet/go-libpcsclite/error.go +++ b/vendor/github.com/gballet/go-libpcsclite/error.go @@ -36,66 +36,66 @@ type ErrorCode uint32 const ( SCardSuccess ErrorCode = 0x00000000 /* No error was encountered. */ - ErrSCardInternal = 0x80100001 /* An internal consistency check failed. */ - ErrSCardCancelled = 0x80100002 /* The action was cancelled by an SCardCancel request. */ - ErrSCardInvalidHandle = 0x80100003 /* The supplied handle was invalid. */ - ErrSCardInvalidParameter = 0x80100004 /* One or more of the supplied parameters could not be properly interpreted. */ - ErrSCardInvalidTarget = 0x80100005 /* Registry startup information is missing or invalid. */ - ErrSCardNoMemory = 0x80100006 /* Not enough memory available to complete this command. */ - ErrSCardWaitedTooLong = 0x80100007 /* An internal consistency timer has expired. */ - ErrSCardInsufficientBuffer = 0x80100008 /* The data buffer to receive returned data is too small for the returned data. */ - ErrScardUnknownReader = 0x80100009 /* The specified reader name is not recognized. */ - ErrSCardTimeout = 0x8010000A /* The user-specified timeout value has expired. */ - ErrSCardSharingViolation = 0x8010000B /* The smart card cannot be accessed because of other connections outstanding. */ - ErrSCardNoSmartCard = 0x8010000C /* The operation requires a Smart Card, but no Smart Card is currently in the device. */ - ErrSCardUnknownCard = 0x8010000D /* The specified smart card name is not recognized. */ - ErrSCardCannotDispose = 0x8010000E /* The system could not dispose of the media in the requested manner. */ - ErrSCardProtoMismatch = 0x8010000F /* The requested protocols are incompatible with the protocol currently in use with the smart card. */ - ErrSCardNotReady = 0x80100010 /* The reader or smart card is not ready to accept commands. */ - ErrSCardInvalidValue = 0x80100011 /* One or more of the supplied parameters values could not be properly interpreted. */ - ErrSCardSystemCancelled = 0x80100012 /* The action was cancelled by the system, presumably to log off or shut down. */ - ErrSCardCommError = 0x80100013 /* An internal communications error has been detected. */ - ErrScardUnknownError = 0x80100014 /* An internal error has been detected, but the source is unknown. */ - ErrSCardInvalidATR = 0x80100015 /* An ATR obtained from the registry is not a valid ATR string. */ - ErrSCardNotTransacted = 0x80100016 /* An attempt was made to end a non-existent transaction. */ - ErrSCardReaderUnavailable = 0x80100017 /* The specified reader is not currently available for use. */ - ErrSCardShutdown = 0x80100018 /* The operation has been aborted to allow the server application to exit. */ - ErrSCardPCITooSmall = 0x80100019 /* The PCI Receive buffer was too small. */ - ErrSCardReaderUnsupported = 0x8010001A /* The reader driver does not meet minimal requirements for support. */ - ErrSCardDuplicateReader = 0x8010001B /* The reader driver did not produce a unique reader name. */ - ErrSCardCardUnsupported = 0x8010001C /* The smart card does not meet minimal requirements for support. */ - ErrScardNoService = 0x8010001D /* The Smart card resource manager is not running. */ - ErrSCardServiceStopped = 0x8010001E /* The Smart card resource manager has shut down. */ - ErrSCardUnexpected = 0x8010001F /* An unexpected card error has occurred. */ - ErrSCardUnsupportedFeature = 0x8010001F /* This smart card does not support the requested feature. */ - ErrSCardICCInstallation = 0x80100020 /* No primary provider can be found for the smart card. */ - ErrSCardICCCreateOrder = 0x80100021 /* The requested order of object creation is not supported. */ - ErrSCardDirNotFound = 0x80100023 /* The identified directory does not exist in the smart card. */ - ErrSCardFileNotFound = 0x80100024 /* The identified file does not exist in the smart card. */ - ErrSCardNoDir = 0x80100025 /* The supplied path does not represent a smart card directory. */ - ErrSCardNoFile = 0x80100026 /* The supplied path does not represent a smart card file. */ - ErrScardNoAccess = 0x80100027 /* Access is denied to this file. */ - ErrSCardWriteTooMany = 0x80100028 /* The smart card does not have enough memory to store the information. */ - ErrSCardBadSeek = 0x80100029 /* There was an error trying to set the smart card file object pointer. */ - ErrSCardInvalidCHV = 0x8010002A /* The supplied PIN is incorrect. */ - ErrSCardUnknownResMNG = 0x8010002B /* An unrecognized error code was returned from a layered component. */ - ErrSCardNoSuchCertificate = 0x8010002C /* The requested certificate does not exist. */ - ErrSCardCertificateUnavailable = 0x8010002D /* The requested certificate could not be obtained. */ - ErrSCardNoReadersAvailable = 0x8010002E /* Cannot find a smart card reader. */ - ErrSCardCommDataLost = 0x8010002F /* A communications error with the smart card has been detected. Retry the operation. */ - ErrScardNoKeyContainer = 0x80100030 /* The requested key container does not exist on the smart card. */ - ErrSCardServerTooBusy = 0x80100031 /* The Smart Card Resource Manager is too busy to complete this operation. */ - ErrSCardUnsupportedCard = 0x80100065 /* The reader cannot communicate with the card, due to ATR string configuration conflicts. */ - ErrSCardUnresponsiveCard = 0x80100066 /* The smart card is not responding to a reset. */ - ErrSCardUnpoweredCard = 0x80100067 /* Power has been removed from the smart card, so that further communication is not possible. */ - ErrSCardResetCard = 0x80100068 /* The smart card has been reset, so any shared state information is invalid. */ - ErrSCardRemovedCard = 0x80100069 /* The smart card has been removed, so further communication is not possible. */ - ErrSCardSecurityViolation = 0x8010006A /* Access was denied because of a security violation. */ - ErrSCardWrongCHV = 0x8010006B /* The card cannot be accessed because the wrong PIN was presented. */ - ErrSCardCHVBlocked = 0x8010006C /* The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */ - ErrSCardEOF = 0x8010006D /* The end of the smart card file has been reached. */ - ErrSCardCancelledByUser = 0x8010006E /* The user pressed "Cancel" on a Smart Card Selection Dialog. */ - ErrSCardCardNotAuthenticated = 0x8010006F /* No PIN was presented to the smart card. */ + ErrSCardInternal ErrorCode = 0x80100001 /* An internal consistency check failed. */ + ErrSCardCancelled ErrorCode = 0x80100002 /* The action was cancelled by an SCardCancel request. */ + ErrSCardInvalidHandle ErrorCode = 0x80100003 /* The supplied handle was invalid. */ + ErrSCardInvalidParameter ErrorCode = 0x80100004 /* One or more of the supplied parameters could not be properly interpreted. */ + ErrSCardInvalidTarget ErrorCode = 0x80100005 /* Registry startup information is missing or invalid. */ + ErrSCardNoMemory ErrorCode = 0x80100006 /* Not enough memory available to complete this command. */ + ErrSCardWaitedTooLong ErrorCode = 0x80100007 /* An internal consistency timer has expired. */ + ErrSCardInsufficientBuffer ErrorCode = 0x80100008 /* The data buffer to receive returned data is too small for the returned data. */ + ErrScardUnknownReader ErrorCode = 0x80100009 /* The specified reader name is not recognized. */ + ErrSCardTimeout ErrorCode = 0x8010000A /* The user-specified timeout value has expired. */ + ErrSCardSharingViolation ErrorCode = 0x8010000B /* The smart card cannot be accessed because of other connections outstanding. */ + ErrSCardNoSmartCard ErrorCode = 0x8010000C /* The operation requires a Smart Card, but no Smart Card is currently in the device. */ + ErrSCardUnknownCard ErrorCode = 0x8010000D /* The specified smart card name is not recognized. */ + ErrSCardCannotDispose ErrorCode = 0x8010000E /* The system could not dispose of the media in the requested manner. */ + ErrSCardProtoMismatch ErrorCode = 0x8010000F /* The requested protocols are incompatible with the protocol currently in use with the smart card. */ + ErrSCardNotReady ErrorCode = 0x80100010 /* The reader or smart card is not ready to accept commands. */ + ErrSCardInvalidValue ErrorCode = 0x80100011 /* One or more of the supplied parameters values could not be properly interpreted. */ + ErrSCardSystemCancelled ErrorCode = 0x80100012 /* The action was cancelled by the system, presumably to log off or shut down. */ + ErrSCardCommError ErrorCode = 0x80100013 /* An internal communications error has been detected. */ + ErrScardUnknownError ErrorCode = 0x80100014 /* An internal error has been detected, but the source is unknown. */ + ErrSCardInvalidATR ErrorCode = 0x80100015 /* An ATR obtained from the registry is not a valid ATR string. */ + ErrSCardNotTransacted ErrorCode = 0x80100016 /* An attempt was made to end a non-existent transaction. */ + ErrSCardReaderUnavailable ErrorCode = 0x80100017 /* The specified reader is not currently available for use. */ + ErrSCardShutdown ErrorCode = 0x80100018 /* The operation has been aborted to allow the server application to exit. */ + ErrSCardPCITooSmall ErrorCode = 0x80100019 /* The PCI Receive buffer was too small. */ + ErrSCardReaderUnsupported ErrorCode = 0x8010001A /* The reader driver does not meet minimal requirements for support. */ + ErrSCardDuplicateReader ErrorCode = 0x8010001B /* The reader driver did not produce a unique reader name. */ + ErrSCardCardUnsupported ErrorCode = 0x8010001C /* The smart card does not meet minimal requirements for support. */ + ErrScardNoService ErrorCode = 0x8010001D /* The Smart card resource manager is not running. */ + ErrSCardServiceStopped ErrorCode = 0x8010001E /* The Smart card resource manager has shut down. */ + ErrSCardUnexpected ErrorCode = 0x8010001F /* An unexpected card error has occurred. */ + ErrSCardUnsupportedFeature ErrorCode = 0x8010001F /* This smart card does not support the requested feature. */ + ErrSCardICCInstallation ErrorCode = 0x80100020 /* No primary provider can be found for the smart card. */ + ErrSCardICCCreateOrder ErrorCode = 0x80100021 /* The requested order of object creation is not supported. */ + ErrSCardDirNotFound ErrorCode = 0x80100023 /* The identified directory does not exist in the smart card. */ + ErrSCardFileNotFound ErrorCode = 0x80100024 /* The identified file does not exist in the smart card. */ + ErrSCardNoDir ErrorCode = 0x80100025 /* The supplied path does not represent a smart card directory. */ + ErrSCardNoFile ErrorCode = 0x80100026 /* The supplied path does not represent a smart card file. */ + ErrScardNoAccess ErrorCode = 0x80100027 /* Access is denied to this file. */ + ErrSCardWriteTooMany ErrorCode = 0x80100028 /* The smart card does not have enough memory to store the information. */ + ErrSCardBadSeek ErrorCode = 0x80100029 /* There was an error trying to set the smart card file object pointer. */ + ErrSCardInvalidCHV ErrorCode = 0x8010002A /* The supplied PIN is incorrect. */ + ErrSCardUnknownResMNG ErrorCode = 0x8010002B /* An unrecognized error code was returned from a layered component. */ + ErrSCardNoSuchCertificate ErrorCode = 0x8010002C /* The requested certificate does not exist. */ + ErrSCardCertificateUnavailable ErrorCode = 0x8010002D /* The requested certificate could not be obtained. */ + ErrSCardNoReadersAvailable ErrorCode = 0x8010002E /* Cannot find a smart card reader. */ + ErrSCardCommDataLost ErrorCode = 0x8010002F /* A communications error with the smart card has been detected. Retry the operation. */ + ErrScardNoKeyContainer ErrorCode = 0x80100030 /* The requested key container does not exist on the smart card. */ + ErrSCardServerTooBusy ErrorCode = 0x80100031 /* The Smart Card Resource Manager is too busy to complete this operation. */ + ErrSCardUnsupportedCard ErrorCode = 0x80100065 /* The reader cannot communicate with the card, due to ATR string configuration conflicts. */ + ErrSCardUnresponsiveCard ErrorCode = 0x80100066 /* The smart card is not responding to a reset. */ + ErrSCardUnpoweredCard ErrorCode = 0x80100067 /* Power has been removed from the smart card, so that further communication is not possible. */ + ErrSCardResetCard ErrorCode = 0x80100068 /* The smart card has been reset, so any shared state information is invalid. */ + ErrSCardRemovedCard ErrorCode = 0x80100069 /* The smart card has been removed, so further communication is not possible. */ + ErrSCardSecurityViolation ErrorCode = 0x8010006A /* Access was denied because of a security violation. */ + ErrSCardWrongCHV ErrorCode = 0x8010006B /* The card cannot be accessed because the wrong PIN was presented. */ + ErrSCardCHVBlocked ErrorCode = 0x8010006C /* The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */ + ErrSCardEOF ErrorCode = 0x8010006D /* The end of the smart card file has been reached. */ + ErrSCardCancelledByUser ErrorCode = 0x8010006E /* The user pressed "Cancel" on a Smart Card Selection Dialog. */ + ErrSCardCardNotAuthenticated ErrorCode = 0x8010006F /* No PIN was presented to the smart card. */ ) // Code returns the error code, with an uint32 type to be used in PutUInt32 @@ -106,95 +106,95 @@ func (code ErrorCode) Code() uint32 { func (code ErrorCode) Error() error { switch code { case SCardSuccess: - return fmt.Errorf("Command successful") + return fmt.Errorf("command successful") case ErrSCardInternal: - return fmt.Errorf("Internal error") + return fmt.Errorf("internal error") case ErrSCardCancelled: - return fmt.Errorf("Command cancelled") + return fmt.Errorf("command cancelled") case ErrSCardInvalidHandle: - return fmt.Errorf("Invalid handle") + return fmt.Errorf("invalid handle") case ErrSCardInvalidParameter: - return fmt.Errorf("Invalid parameter given") + return fmt.Errorf("invalid parameter given") case ErrSCardInvalidTarget: - return fmt.Errorf("Invalid target given") + return fmt.Errorf("invalid target given") case ErrSCardNoMemory: - return fmt.Errorf("Not enough memory") + return fmt.Errorf("not enough memory") case ErrSCardWaitedTooLong: - return fmt.Errorf("Waited too long") + return fmt.Errorf("waited too long") case ErrSCardInsufficientBuffer: - return fmt.Errorf("Insufficient buffer") + return fmt.Errorf("insufficient buffer") case ErrScardUnknownReader: - return fmt.Errorf("Unknown reader specified") + return fmt.Errorf("unknown reader specified") case ErrSCardTimeout: - return fmt.Errorf("Command timeout") + return fmt.Errorf("command timeout") case ErrSCardSharingViolation: - return fmt.Errorf("Sharing violation") + return fmt.Errorf("sharing violation") case ErrSCardNoSmartCard: - return fmt.Errorf("No smart card inserted") + return fmt.Errorf("no smart card inserted") case ErrSCardUnknownCard: - return fmt.Errorf("Unknown card") + return fmt.Errorf("unknown card") case ErrSCardCannotDispose: - return fmt.Errorf("Cannot dispose handle") + return fmt.Errorf("cannot dispose handle") case ErrSCardProtoMismatch: - return fmt.Errorf("Card protocol mismatch") + return fmt.Errorf("card protocol mismatch") case ErrSCardNotReady: - return fmt.Errorf("Subsystem not ready") + return fmt.Errorf("subsystem not ready") case ErrSCardInvalidValue: - return fmt.Errorf("Invalid value given") + return fmt.Errorf("invalid value given") case ErrSCardSystemCancelled: - return fmt.Errorf("System cancelled") + return fmt.Errorf("system cancelled") case ErrSCardCommError: - return fmt.Errorf("RPC transport error") + return fmt.Errorf("rpc transport error") case ErrScardUnknownError: - return fmt.Errorf("Unknown error") + return fmt.Errorf("unknown error") case ErrSCardInvalidATR: - return fmt.Errorf("Invalid ATR") + return fmt.Errorf("invalid ATR") case ErrSCardNotTransacted: - return fmt.Errorf("Transaction failed") + return fmt.Errorf("transaction failed") case ErrSCardReaderUnavailable: - return fmt.Errorf("Reader is unavailable") + return fmt.Errorf("reader is unavailable") /* case SCARD_P_SHUTDOWN: */ case ErrSCardPCITooSmall: return fmt.Errorf("PCI struct too small") case ErrSCardReaderUnsupported: - return fmt.Errorf("Reader is unsupported") + return fmt.Errorf("reader is unsupported") case ErrSCardDuplicateReader: - return fmt.Errorf("Reader already exists") + return fmt.Errorf("reader already exists") case ErrSCardCardUnsupported: - return fmt.Errorf("Card is unsupported") + return fmt.Errorf("card is unsupported") case ErrScardNoService: - return fmt.Errorf("Service not available") + return fmt.Errorf("service not available") case ErrSCardServiceStopped: - return fmt.Errorf("Service was stopped") + return fmt.Errorf("service was stopped") /* case SCARD_E_UNEXPECTED: */ /* case SCARD_E_ICC_CREATEORDER: */ @@ -210,7 +210,7 @@ func (code ErrorCode) Error() error { /* case SCARD_E_NO_SUCH_CERTIFICATE: */ /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */ case ErrSCardNoReadersAvailable: - return fmt.Errorf("Cannot find a smart card reader") + return fmt.Errorf("cannot find a smart card reader") /* case SCARD_E_COMM_DATA_LOST: */ /* case SCARD_E_NO_KEY_CONTAINER: */ @@ -238,7 +238,7 @@ func (code ErrorCode) Error() error { /* case SCARD_W_CARD_NOT_AUTHENTICATED: */ case ErrSCardUnsupportedFeature: - return fmt.Errorf("Feature not supported") + return fmt.Errorf("feature not supported") default: return fmt.Errorf("unknown error: %08x", code) diff --git a/vendor/github.com/gballet/go-libpcsclite/winscard.go b/vendor/github.com/gballet/go-libpcsclite/winscard.go index b916db1621..791c974f15 100644 --- a/vendor/github.com/gballet/go-libpcsclite/winscard.go +++ b/vendor/github.com/gballet/go-libpcsclite/winscard.go @@ -291,16 +291,16 @@ func (client *Client) Connect(name string, shareMode uint32, preferredProtocol u * * These data are passed throw the field \c sharedSegmentMsg.data. */ -type transmit struct { - hCard uint32 - ioSendPciProtocol uint32 - ioSendPciLength uint32 - cbSendLength uint32 - ioRecvPciProtocol uint32 - ioRecvPciLength uint32 - pcbRecvLength uint32 - rv uint32 -} +//type transmit struct { +//hCard uint32 +//ioSendPciProtocol uint32 +//ioSendPciLength uint32 +//cbSendLength uint32 +//ioRecvPciProtocol uint32 +//ioRecvPciLength uint32 +//pcbRecvLength uint32 +//rv uint32 +//} // SCardIoRequest contains the info needed for performing an IO request type SCardIoRequest struct { @@ -336,7 +336,7 @@ func (card *Card) Transmit(adpu []byte) ([]byte, *SCardIoRequest, error) { return nil, nil, err } if n != len(adpu) { - return nil, nil, fmt.Errorf("Invalid number of bytes written: expected %d, got %d", len(adpu), n) + return nil, nil, fmt.Errorf("invalid number of bytes written: expected %d, got %d", len(adpu), n) } response := [TransmitRequestLength]byte{} total := 0 diff --git a/vendor/github.com/go-ole/go-ole/.travis.yml b/vendor/github.com/go-ole/go-ole/.travis.yml deleted file mode 100644 index 28f740cd5d..0000000000 --- a/vendor/github.com/go-ole/go-ole/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -sudo: false - -go: - - 1.9.x - - 1.10.x - - 1.11.x - - tip diff --git a/vendor/github.com/go-ole/go-ole/ChangeLog.md b/vendor/github.com/go-ole/go-ole/ChangeLog.md deleted file mode 100644 index 4ba6a8c64d..0000000000 --- a/vendor/github.com/go-ole/go-ole/ChangeLog.md +++ /dev/null @@ -1,49 +0,0 @@ -# Version 1.x.x - -* **Add more test cases and reference new test COM server project.** (Placeholder for future additions) - -# Version 1.2.0-alphaX - -**Minimum supported version is now Go 1.4. Go 1.1 support is deprecated, but should still build.** - - * Added CI configuration for Travis-CI and AppVeyor. - * Added test InterfaceID and ClassID for the COM Test Server project. - * Added more inline documentation (#83). - * Added IEnumVARIANT implementation (#88). - * Added IEnumVARIANT test cases (#99, #100, #101). - * Added support for retrieving `time.Time` from VARIANT (#92). - * Added test case for IUnknown (#64). - * Added test case for IDispatch (#64). - * Added test cases for scalar variants (#64, #76). - -# Version 1.1.1 - - * Fixes for Linux build. - * Fixes for Windows build. - -# Version 1.1.0 - -The change to provide building on all platforms is a new feature. The increase in minor version reflects that and allows those who wish to stay on 1.0.x to continue to do so. Support for 1.0.x will be limited to bug fixes. - - * Move GUID out of variables.go into its own file to make new documentation available. - * Move OleError out of ole.go into its own file to make new documentation available. - * Add documentation to utility functions. - * Add documentation to variant receiver functions. - * Add documentation to ole structures. - * Make variant available to other systems outside of Windows. - * Make OLE structures available to other systems outside of Windows. - -## New Features - - * Library should now be built on all platforms supported by Go. Library will NOOP on any platform that is not Windows. - * More functions are now documented and available on godoc.org. - -# Version 1.0.1 - - 1. Fix package references from repository location change. - -# Version 1.0.0 - -This version is stable enough for use. The COM API is still incomplete, but provides enough functionality for accessing COM servers using IDispatch interface. - -There is no changelog for this version. Check commits for history. diff --git a/vendor/github.com/go-ole/go-ole/LICENSE b/vendor/github.com/go-ole/go-ole/LICENSE deleted file mode 100644 index 623ec06f91..0000000000 --- a/vendor/github.com/go-ole/go-ole/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright © 2013-2017 Yasuhiro Matsumoto, - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the “Software”), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/go-ole/go-ole/README.md b/vendor/github.com/go-ole/go-ole/README.md deleted file mode 100644 index 7b577558d1..0000000000 --- a/vendor/github.com/go-ole/go-ole/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Go OLE - -[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28) -[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole) -[![GoDoc](https://godoc.org/github.com/go-ole/go-ole?status.svg)](https://godoc.org/github.com/go-ole/go-ole) - -Go bindings for Windows COM using shared libraries instead of cgo. - -By Yasuhiro Matsumoto. - -## Install - -To experiment with go-ole, you can just compile and run the example program: - -``` -go get github.com/go-ole/go-ole -cd /path/to/go-ole/ -go test - -cd /path/to/go-ole/example/excel -go run excel.go -``` - -## Continuous Integration - -Continuous integration configuration has been added for both Travis-CI and AppVeyor. You will have to add these to your own account for your fork in order for it to run. - -**Travis-CI** - -Travis-CI was added to check builds on Linux to ensure that `go get` works when cross building. Currently, Travis-CI is not used to test cross-building, but this may be changed in the future. It is also not currently possible to test the library on Linux, since COM API is specific to Windows and it is not currently possible to run a COM server on Linux or even connect to a remote COM server. - -**AppVeyor** - -AppVeyor is used to build on Windows using the (in-development) test COM server. It is currently only used to test the build and ensure that the code works on Windows. It will be used to register a COM server and then run the test cases based on the test COM server. - -The tests currently do run and do pass and this should be maintained with commits. - -## Versioning - -Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch. - -This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed. - -## LICENSE - -Under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml deleted file mode 100644 index 0d557ac2ff..0000000000 --- a/vendor/github.com/go-ole/go-ole/appveyor.yml +++ /dev/null @@ -1,54 +0,0 @@ -# Notes: -# - Minimal appveyor.yml file is an empty file. All sections are optional. -# - Indent each level of configuration with 2 spaces. Do not use tabs! -# - All section names are case-sensitive. -# - Section names should be unique on each level. - -version: "1.3.0.{build}-alpha-{branch}" - -os: Windows Server 2012 R2 - -branches: - only: - - master - - v1.2 - - v1.1 - - v1.0 - -skip_tags: true - -clone_folder: c:\gopath\src\github.com\go-ole\go-ole - -environment: - GOPATH: c:\gopath - matrix: - - GOARCH: amd64 - GOVERSION: 1.5 - GOROOT: c:\go - DOWNLOADPLATFORM: "x64" - -install: - - choco install mingw - - SET PATH=c:\tools\mingw64\bin;%PATH% - # - Download COM Server - - ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip" - - 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL - - c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat - # - set - - go version - - go env - - go get -u golang.org/x/tools/cmd/cover - - go get -u golang.org/x/tools/cmd/godoc - - go get -u golang.org/x/tools/cmd/stringer - -build_script: - - cd c:\gopath\src\github.com\go-ole\go-ole - - go get -v -t ./... - - go build - - go test -v -cover ./... - -# disable automatic tests -test: off - -# disable deployment -deploy: off diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go deleted file mode 100644 index 6f986b1894..0000000000 --- a/vendor/github.com/go-ole/go-ole/com.go +++ /dev/null @@ -1,344 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unicode/utf16" - "unsafe" -) - -var ( - procCoInitialize, _ = modole32.FindProc("CoInitialize") - procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx") - procCoUninitialize, _ = modole32.FindProc("CoUninitialize") - procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance") - procCoTaskMemFree, _ = modole32.FindProc("CoTaskMemFree") - procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID") - procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString") - procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID") - procStringFromIID, _ = modole32.FindProc("StringFromIID") - procIIDFromString, _ = modole32.FindProc("IIDFromString") - procCoGetObject, _ = modole32.FindProc("CoGetObject") - procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID") - procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory") - procVariantInit, _ = modoleaut32.FindProc("VariantInit") - procVariantClear, _ = modoleaut32.FindProc("VariantClear") - procVariantTimeToSystemTime, _ = modoleaut32.FindProc("VariantTimeToSystemTime") - procSysAllocString, _ = modoleaut32.FindProc("SysAllocString") - procSysAllocStringLen, _ = modoleaut32.FindProc("SysAllocStringLen") - procSysFreeString, _ = modoleaut32.FindProc("SysFreeString") - procSysStringLen, _ = modoleaut32.FindProc("SysStringLen") - procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo") - procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch") - procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject") - - procGetMessageW, _ = moduser32.FindProc("GetMessageW") - procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW") -) - -// coInitialize initializes COM library on current thread. -// -// MSDN documentation suggests that this function should not be called. Call -// CoInitializeEx() instead. The reason has to do with threading and this -// function is only for single-threaded apartments. -// -// That said, most users of the library have gotten away with just this -// function. If you are experiencing threading issues, then use -// CoInitializeEx(). -func coInitialize() (err error) { - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx - // Suggests that no value should be passed to CoInitialized. - // Could just be Call() since the parameter is optional. <-- Needs testing to be sure. - hr, _, _ := procCoInitialize.Call(uintptr(0)) - if hr != 0 { - err = NewError(hr) - } - return -} - -// coInitializeEx initializes COM library with concurrency model. -func coInitializeEx(coinit uint32) (err error) { - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx - // Suggests that the first parameter is not only optional but should always be NULL. - hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit)) - if hr != 0 { - err = NewError(hr) - } - return -} - -// CoInitialize initializes COM library on current thread. -// -// MSDN documentation suggests that this function should not be called. Call -// CoInitializeEx() instead. The reason has to do with threading and this -// function is only for single-threaded apartments. -// -// That said, most users of the library have gotten away with just this -// function. If you are experiencing threading issues, then use -// CoInitializeEx(). -func CoInitialize(p uintptr) (err error) { - // p is ignored and won't be used. - // Avoid any variable not used errors. - p = uintptr(0) - return coInitialize() -} - -// CoInitializeEx initializes COM library with concurrency model. -func CoInitializeEx(p uintptr, coinit uint32) (err error) { - // Avoid any variable not used errors. - p = uintptr(0) - return coInitializeEx(coinit) -} - -// CoUninitialize uninitializes COM Library. -func CoUninitialize() { - procCoUninitialize.Call() -} - -// CoTaskMemFree frees memory pointer. -func CoTaskMemFree(memptr uintptr) { - procCoTaskMemFree.Call(memptr) -} - -// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. -// -// The Programmatic Identifier must be registered, because it will be looked up -// in the Windows Registry. The registry entry has the following keys: CLSID, -// Insertable, Protocol and Shell -// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). -// -// programID identifies the class id with less precision and is not guaranteed -// to be unique. These are usually found in the registry under -// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of -// "Program.Component.Version" with version being optional. -// -// CLSIDFromProgID in Windows API. -func CLSIDFromProgID(progId string) (clsid *GUID, err error) { - var guid GUID - lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) - hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid))) - if hr != 0 { - err = NewError(hr) - } - clsid = &guid - return -} - -// CLSIDFromString retrieves Class ID from string representation. -// -// This is technically the string version of the GUID and will convert the -// string to object. -// -// CLSIDFromString in Windows API. -func CLSIDFromString(str string) (clsid *GUID, err error) { - var guid GUID - lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) - hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) - if hr != 0 { - err = NewError(hr) - } - clsid = &guid - return -} - -// StringFromCLSID returns GUID formated string from GUID object. -func StringFromCLSID(clsid *GUID) (str string, err error) { - var p *uint16 - hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p))) - if hr != 0 { - err = NewError(hr) - } - str = LpOleStrToString(p) - return -} - -// IIDFromString returns GUID from program ID. -func IIDFromString(progId string) (clsid *GUID, err error) { - var guid GUID - lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) - hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) - if hr != 0 { - err = NewError(hr) - } - clsid = &guid - return -} - -// StringFromIID returns GUID formatted string from GUID object. -func StringFromIID(iid *GUID) (str string, err error) { - var p *uint16 - hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p))) - if hr != 0 { - err = NewError(hr) - } - str = LpOleStrToString(p) - return -} - -// CreateInstance of single uninitialized object with GUID. -func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { - if iid == nil { - iid = IID_IUnknown - } - hr, _, _ := procCoCreateInstance.Call( - uintptr(unsafe.Pointer(clsid)), - 0, - CLSCTX_SERVER, - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(&unk))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// GetActiveObject retrieves pointer to active object. -func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { - if iid == nil { - iid = IID_IUnknown - } - hr, _, _ := procGetActiveObject.Call( - uintptr(unsafe.Pointer(clsid)), - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(&unk))) - if hr != 0 { - err = NewError(hr) - } - return -} - -type BindOpts struct { - CbStruct uint32 - GrfFlags uint32 - GrfMode uint32 - TickCountDeadline uint32 -} - -// GetObject retrieves pointer to active object. -func GetObject(programID string, bindOpts *BindOpts, iid *GUID) (unk *IUnknown, err error) { - if bindOpts != nil { - bindOpts.CbStruct = uint32(unsafe.Sizeof(BindOpts{})) - } - if iid == nil { - iid = IID_IUnknown - } - hr, _, _ := procCoGetObject.Call( - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(programID))), - uintptr(unsafe.Pointer(bindOpts)), - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(&unk))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// VariantInit initializes variant. -func VariantInit(v *VARIANT) (err error) { - hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// VariantClear clears value in Variant settings to VT_EMPTY. -func VariantClear(v *VARIANT) (err error) { - hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// SysAllocString allocates memory for string and copies string into memory. -func SysAllocString(v string) (ss *int16) { - pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) - ss = (*int16)(unsafe.Pointer(pss)) - return -} - -// SysAllocStringLen copies up to length of given string returning pointer. -func SysAllocStringLen(v string) (ss *int16) { - utf16 := utf16.Encode([]rune(v + "\x00")) - ptr := &utf16[0] - - pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1)) - ss = (*int16)(unsafe.Pointer(pss)) - return -} - -// SysFreeString frees string system memory. This must be called with SysAllocString. -func SysFreeString(v *int16) (err error) { - hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// SysStringLen is the length of the system allocated string. -func SysStringLen(v *int16) uint32 { - l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) - return uint32(l) -} - -// CreateStdDispatch provides default IDispatch implementation for IUnknown. -// -// This handles default IDispatch implementation for objects. It haves a few -// limitations with only supporting one language. It will also only return -// default exception codes. -func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) { - hr, _, _ := procCreateStdDispatch.Call( - uintptr(unsafe.Pointer(unk)), - v, - uintptr(unsafe.Pointer(ptinfo)), - uintptr(unsafe.Pointer(&disp))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. -// -// This will not handle the full implementation of the interface. -func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) { - hr, _, _ := procCreateDispTypeInfo.Call( - uintptr(unsafe.Pointer(idata)), - uintptr(GetUserDefaultLCID()), - uintptr(unsafe.Pointer(&pptinfo))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// copyMemory moves location of a block of memory. -func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) { - procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length)) -} - -// GetUserDefaultLCID retrieves current user default locale. -func GetUserDefaultLCID() (lcid uint32) { - ret, _, _ := procGetUserDefaultLCID.Call() - lcid = uint32(ret) - return -} - -// GetMessage in message queue from runtime. -// -// This function appears to block. PeekMessage does not block. -func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) { - r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax)) - ret = int32(r0) - return -} - -// DispatchMessage to window procedure. -func DispatchMessage(msg *Msg) (ret int32) { - r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg))) - ret = int32(r0) - return -} diff --git a/vendor/github.com/go-ole/go-ole/com_func.go b/vendor/github.com/go-ole/go-ole/com_func.go deleted file mode 100644 index cef539d9dd..0000000000 --- a/vendor/github.com/go-ole/go-ole/com_func.go +++ /dev/null @@ -1,174 +0,0 @@ -// +build !windows - -package ole - -import ( - "time" - "unsafe" -) - -// coInitialize initializes COM library on current thread. -// -// MSDN documentation suggests that this function should not be called. Call -// CoInitializeEx() instead. The reason has to do with threading and this -// function is only for single-threaded apartments. -// -// That said, most users of the library have gotten away with just this -// function. If you are experiencing threading issues, then use -// CoInitializeEx(). -func coInitialize() error { - return NewError(E_NOTIMPL) -} - -// coInitializeEx initializes COM library with concurrency model. -func coInitializeEx(coinit uint32) error { - return NewError(E_NOTIMPL) -} - -// CoInitialize initializes COM library on current thread. -// -// MSDN documentation suggests that this function should not be called. Call -// CoInitializeEx() instead. The reason has to do with threading and this -// function is only for single-threaded apartments. -// -// That said, most users of the library have gotten away with just this -// function. If you are experiencing threading issues, then use -// CoInitializeEx(). -func CoInitialize(p uintptr) error { - return NewError(E_NOTIMPL) -} - -// CoInitializeEx initializes COM library with concurrency model. -func CoInitializeEx(p uintptr, coinit uint32) error { - return NewError(E_NOTIMPL) -} - -// CoUninitialize uninitializes COM Library. -func CoUninitialize() {} - -// CoTaskMemFree frees memory pointer. -func CoTaskMemFree(memptr uintptr) {} - -// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. -// -// The Programmatic Identifier must be registered, because it will be looked up -// in the Windows Registry. The registry entry has the following keys: CLSID, -// Insertable, Protocol and Shell -// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). -// -// programID identifies the class id with less precision and is not guaranteed -// to be unique. These are usually found in the registry under -// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of -// "Program.Component.Version" with version being optional. -// -// CLSIDFromProgID in Windows API. -func CLSIDFromProgID(progId string) (*GUID, error) { - return nil, NewError(E_NOTIMPL) -} - -// CLSIDFromString retrieves Class ID from string representation. -// -// This is technically the string version of the GUID and will convert the -// string to object. -// -// CLSIDFromString in Windows API. -func CLSIDFromString(str string) (*GUID, error) { - return nil, NewError(E_NOTIMPL) -} - -// StringFromCLSID returns GUID formated string from GUID object. -func StringFromCLSID(clsid *GUID) (string, error) { - return "", NewError(E_NOTIMPL) -} - -// IIDFromString returns GUID from program ID. -func IIDFromString(progId string) (*GUID, error) { - return nil, NewError(E_NOTIMPL) -} - -// StringFromIID returns GUID formatted string from GUID object. -func StringFromIID(iid *GUID) (string, error) { - return "", NewError(E_NOTIMPL) -} - -// CreateInstance of single uninitialized object with GUID. -func CreateInstance(clsid *GUID, iid *GUID) (*IUnknown, error) { - return nil, NewError(E_NOTIMPL) -} - -// GetActiveObject retrieves pointer to active object. -func GetActiveObject(clsid *GUID, iid *GUID) (*IUnknown, error) { - return nil, NewError(E_NOTIMPL) -} - -// VariantInit initializes variant. -func VariantInit(v *VARIANT) error { - return NewError(E_NOTIMPL) -} - -// VariantClear clears value in Variant settings to VT_EMPTY. -func VariantClear(v *VARIANT) error { - return NewError(E_NOTIMPL) -} - -// SysAllocString allocates memory for string and copies string into memory. -func SysAllocString(v string) *int16 { - u := int16(0) - return &u -} - -// SysAllocStringLen copies up to length of given string returning pointer. -func SysAllocStringLen(v string) *int16 { - u := int16(0) - return &u -} - -// SysFreeString frees string system memory. This must be called with SysAllocString. -func SysFreeString(v *int16) error { - return NewError(E_NOTIMPL) -} - -// SysStringLen is the length of the system allocated string. -func SysStringLen(v *int16) uint32 { - return uint32(0) -} - -// CreateStdDispatch provides default IDispatch implementation for IUnknown. -// -// This handles default IDispatch implementation for objects. It haves a few -// limitations with only supporting one language. It will also only return -// default exception codes. -func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (*IDispatch, error) { - return nil, NewError(E_NOTIMPL) -} - -// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. -// -// This will not handle the full implementation of the interface. -func CreateDispTypeInfo(idata *INTERFACEDATA) (*IUnknown, error) { - return nil, NewError(E_NOTIMPL) -} - -// copyMemory moves location of a block of memory. -func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {} - -// GetUserDefaultLCID retrieves current user default locale. -func GetUserDefaultLCID() uint32 { - return uint32(0) -} - -// GetMessage in message queue from runtime. -// -// This function appears to block. PeekMessage does not block. -func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (int32, error) { - return int32(0), NewError(E_NOTIMPL) -} - -// DispatchMessage to window procedure. -func DispatchMessage(msg *Msg) int32 { - return int32(0) -} - -func GetVariantDate(value uint64) (time.Time, error) { - return time.Now(), NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/connect.go b/vendor/github.com/go-ole/go-ole/connect.go deleted file mode 100644 index b2ac2ec67a..0000000000 --- a/vendor/github.com/go-ole/go-ole/connect.go +++ /dev/null @@ -1,192 +0,0 @@ -package ole - -// Connection contains IUnknown for fluent interface interaction. -// -// Deprecated. Use oleutil package instead. -type Connection struct { - Object *IUnknown // Access COM -} - -// Initialize COM. -func (*Connection) Initialize() (err error) { - return coInitialize() -} - -// Uninitialize COM. -func (*Connection) Uninitialize() { - CoUninitialize() -} - -// Create IUnknown object based first on ProgId and then from String. -func (c *Connection) Create(progId string) (err error) { - var clsid *GUID - clsid, err = CLSIDFromProgID(progId) - if err != nil { - clsid, err = CLSIDFromString(progId) - if err != nil { - return - } - } - - unknown, err := CreateInstance(clsid, IID_IUnknown) - if err != nil { - return - } - c.Object = unknown - - return -} - -// Release IUnknown object. -func (c *Connection) Release() { - c.Object.Release() -} - -// Load COM object from list of programIDs or strings. -func (c *Connection) Load(names ...string) (errors []error) { - var tempErrors []error = make([]error, len(names)) - var numErrors int = 0 - for _, name := range names { - err := c.Create(name) - if err != nil { - tempErrors = append(tempErrors, err) - numErrors += 1 - continue - } - break - } - - copy(errors, tempErrors[0:numErrors]) - return -} - -// Dispatch returns Dispatch object. -func (c *Connection) Dispatch() (object *Dispatch, err error) { - dispatch, err := c.Object.QueryInterface(IID_IDispatch) - if err != nil { - return - } - object = &Dispatch{dispatch} - return -} - -// Dispatch stores IDispatch object. -type Dispatch struct { - Object *IDispatch // Dispatch object. -} - -// Call method on IDispatch with parameters. -func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) { - id, err := d.GetId(method) - if err != nil { - return - } - - result, err = d.Invoke(id, DISPATCH_METHOD, params) - return -} - -// MustCall method on IDispatch with parameters. -func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) { - id, err := d.GetId(method) - if err != nil { - panic(err) - } - - result, err = d.Invoke(id, DISPATCH_METHOD, params) - if err != nil { - panic(err) - } - - return -} - -// Get property on IDispatch with parameters. -func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) { - id, err := d.GetId(name) - if err != nil { - return - } - result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) - return -} - -// MustGet property on IDispatch with parameters. -func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) { - id, err := d.GetId(name) - if err != nil { - panic(err) - } - - result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) - if err != nil { - panic(err) - } - return -} - -// Set property on IDispatch with parameters. -func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) { - id, err := d.GetId(name) - if err != nil { - return - } - result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) - return -} - -// MustSet property on IDispatch with parameters. -func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) { - id, err := d.GetId(name) - if err != nil { - panic(err) - } - - result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) - if err != nil { - panic(err) - } - return -} - -// GetId retrieves ID of name on IDispatch. -func (d *Dispatch) GetId(name string) (id int32, err error) { - var dispid []int32 - dispid, err = d.Object.GetIDsOfName([]string{name}) - if err != nil { - return - } - id = dispid[0] - return -} - -// GetIds retrieves all IDs of names on IDispatch. -func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) { - dispid, err = d.Object.GetIDsOfName(names) - return -} - -// Invoke IDispatch on DisplayID of dispatch type with parameters. -// -// There have been problems where if send cascading params..., it would error -// out because the parameters would be empty. -func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) { - if len(params) < 1 { - result, err = d.Object.Invoke(id, dispatch) - } else { - result, err = d.Object.Invoke(id, dispatch, params...) - } - return -} - -// Release IDispatch object. -func (d *Dispatch) Release() { - d.Object.Release() -} - -// Connect initializes COM and attempts to load IUnknown based on given names. -func Connect(names ...string) (connection *Connection) { - connection.Initialize() - connection.Load(names...) - return -} diff --git a/vendor/github.com/go-ole/go-ole/constants.go b/vendor/github.com/go-ole/go-ole/constants.go deleted file mode 100644 index fd0c6d74b0..0000000000 --- a/vendor/github.com/go-ole/go-ole/constants.go +++ /dev/null @@ -1,153 +0,0 @@ -package ole - -const ( - CLSCTX_INPROC_SERVER = 1 - CLSCTX_INPROC_HANDLER = 2 - CLSCTX_LOCAL_SERVER = 4 - CLSCTX_INPROC_SERVER16 = 8 - CLSCTX_REMOTE_SERVER = 16 - CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER - CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER - CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER -) - -const ( - COINIT_APARTMENTTHREADED = 0x2 - COINIT_MULTITHREADED = 0x0 - COINIT_DISABLE_OLE1DDE = 0x4 - COINIT_SPEED_OVER_MEMORY = 0x8 -) - -const ( - DISPATCH_METHOD = 1 - DISPATCH_PROPERTYGET = 2 - DISPATCH_PROPERTYPUT = 4 - DISPATCH_PROPERTYPUTREF = 8 -) - -const ( - S_OK = 0x00000000 - E_UNEXPECTED = 0x8000FFFF - E_NOTIMPL = 0x80004001 - E_OUTOFMEMORY = 0x8007000E - E_INVALIDARG = 0x80070057 - E_NOINTERFACE = 0x80004002 - E_POINTER = 0x80004003 - E_HANDLE = 0x80070006 - E_ABORT = 0x80004004 - E_FAIL = 0x80004005 - E_ACCESSDENIED = 0x80070005 - E_PENDING = 0x8000000A - - CO_E_CLASSSTRING = 0x800401F3 -) - -const ( - CC_FASTCALL = iota - CC_CDECL - CC_MSCPASCAL - CC_PASCAL = CC_MSCPASCAL - CC_MACPASCAL - CC_STDCALL - CC_FPFASTCALL - CC_SYSCALL - CC_MPWCDECL - CC_MPWPASCAL - CC_MAX = CC_MPWPASCAL -) - -type VT uint16 - -const ( - VT_EMPTY VT = 0x0 - VT_NULL VT = 0x1 - VT_I2 VT = 0x2 - VT_I4 VT = 0x3 - VT_R4 VT = 0x4 - VT_R8 VT = 0x5 - VT_CY VT = 0x6 - VT_DATE VT = 0x7 - VT_BSTR VT = 0x8 - VT_DISPATCH VT = 0x9 - VT_ERROR VT = 0xa - VT_BOOL VT = 0xb - VT_VARIANT VT = 0xc - VT_UNKNOWN VT = 0xd - VT_DECIMAL VT = 0xe - VT_I1 VT = 0x10 - VT_UI1 VT = 0x11 - VT_UI2 VT = 0x12 - VT_UI4 VT = 0x13 - VT_I8 VT = 0x14 - VT_UI8 VT = 0x15 - VT_INT VT = 0x16 - VT_UINT VT = 0x17 - VT_VOID VT = 0x18 - VT_HRESULT VT = 0x19 - VT_PTR VT = 0x1a - VT_SAFEARRAY VT = 0x1b - VT_CARRAY VT = 0x1c - VT_USERDEFINED VT = 0x1d - VT_LPSTR VT = 0x1e - VT_LPWSTR VT = 0x1f - VT_RECORD VT = 0x24 - VT_INT_PTR VT = 0x25 - VT_UINT_PTR VT = 0x26 - VT_FILETIME VT = 0x40 - VT_BLOB VT = 0x41 - VT_STREAM VT = 0x42 - VT_STORAGE VT = 0x43 - VT_STREAMED_OBJECT VT = 0x44 - VT_STORED_OBJECT VT = 0x45 - VT_BLOB_OBJECT VT = 0x46 - VT_CF VT = 0x47 - VT_CLSID VT = 0x48 - VT_BSTR_BLOB VT = 0xfff - VT_VECTOR VT = 0x1000 - VT_ARRAY VT = 0x2000 - VT_BYREF VT = 0x4000 - VT_RESERVED VT = 0x8000 - VT_ILLEGAL VT = 0xffff - VT_ILLEGALMASKED VT = 0xfff - VT_TYPEMASK VT = 0xfff -) - -const ( - DISPID_UNKNOWN = -1 - DISPID_VALUE = 0 - DISPID_PROPERTYPUT = -3 - DISPID_NEWENUM = -4 - DISPID_EVALUATE = -5 - DISPID_CONSTRUCTOR = -6 - DISPID_DESTRUCTOR = -7 - DISPID_COLLECT = -8 -) - -const ( - TKIND_ENUM = 1 - TKIND_RECORD = 2 - TKIND_MODULE = 3 - TKIND_INTERFACE = 4 - TKIND_DISPATCH = 5 - TKIND_COCLASS = 6 - TKIND_ALIAS = 7 - TKIND_UNION = 8 - TKIND_MAX = 9 -) - -// Safe Array Feature Flags - -const ( - FADF_AUTO = 0x0001 - FADF_STATIC = 0x0002 - FADF_EMBEDDED = 0x0004 - FADF_FIXEDSIZE = 0x0010 - FADF_RECORD = 0x0020 - FADF_HAVEIID = 0x0040 - FADF_HAVEVARTYPE = 0x0080 - FADF_BSTR = 0x0100 - FADF_UNKNOWN = 0x0200 - FADF_DISPATCH = 0x0400 - FADF_VARIANT = 0x0800 - FADF_RESERVED = 0xF008 -) diff --git a/vendor/github.com/go-ole/go-ole/error.go b/vendor/github.com/go-ole/go-ole/error.go deleted file mode 100644 index 096b456d3a..0000000000 --- a/vendor/github.com/go-ole/go-ole/error.go +++ /dev/null @@ -1,51 +0,0 @@ -package ole - -// OleError stores COM errors. -type OleError struct { - hr uintptr - description string - subError error -} - -// NewError creates new error with HResult. -func NewError(hr uintptr) *OleError { - return &OleError{hr: hr} -} - -// NewErrorWithDescription creates new COM error with HResult and description. -func NewErrorWithDescription(hr uintptr, description string) *OleError { - return &OleError{hr: hr, description: description} -} - -// NewErrorWithSubError creates new COM error with parent error. -func NewErrorWithSubError(hr uintptr, description string, err error) *OleError { - return &OleError{hr: hr, description: description, subError: err} -} - -// Code is the HResult. -func (v *OleError) Code() uintptr { - return uintptr(v.hr) -} - -// String description, either manually set or format message with error code. -func (v *OleError) String() string { - if v.description != "" { - return errstr(int(v.hr)) + " (" + v.description + ")" - } - return errstr(int(v.hr)) -} - -// Error implements error interface. -func (v *OleError) Error() string { - return v.String() -} - -// Description retrieves error summary, if there is one. -func (v *OleError) Description() string { - return v.description -} - -// SubError returns parent error, if there is one. -func (v *OleError) SubError() error { - return v.subError -} diff --git a/vendor/github.com/go-ole/go-ole/error_func.go b/vendor/github.com/go-ole/go-ole/error_func.go deleted file mode 100644 index 8a2ffaa272..0000000000 --- a/vendor/github.com/go-ole/go-ole/error_func.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !windows - -package ole - -// errstr converts error code to string. -func errstr(errno int) string { - return "" -} diff --git a/vendor/github.com/go-ole/go-ole/error_windows.go b/vendor/github.com/go-ole/go-ole/error_windows.go deleted file mode 100644 index d0e8e68595..0000000000 --- a/vendor/github.com/go-ole/go-ole/error_windows.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build windows - -package ole - -import ( - "fmt" - "syscall" - "unicode/utf16" -) - -// errstr converts error code to string. -func errstr(errno int) string { - // ask windows for the remaining errors - var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS - b := make([]uint16, 300) - n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil) - if err != nil { - return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err) - } - // trim terminating \r and \n - for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { - } - return string(utf16.Decode(b[:n])) -} diff --git a/vendor/github.com/go-ole/go-ole/go.mod b/vendor/github.com/go-ole/go-ole/go.mod deleted file mode 100644 index df98533ea9..0000000000 --- a/vendor/github.com/go-ole/go-ole/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/go-ole/go-ole - -go 1.12 diff --git a/vendor/github.com/go-ole/go-ole/guid.go b/vendor/github.com/go-ole/go-ole/guid.go deleted file mode 100644 index 8d20f68fbf..0000000000 --- a/vendor/github.com/go-ole/go-ole/guid.go +++ /dev/null @@ -1,284 +0,0 @@ -package ole - -var ( - // IID_NULL is null Interface ID, used when no other Interface ID is known. - IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}") - - // IID_IUnknown is for IUnknown interfaces. - IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}") - - // IID_IDispatch is for IDispatch interfaces. - IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}") - - // IID_IEnumVariant is for IEnumVariant interfaces - IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}") - - // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces. - IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}") - - // IID_IConnectionPoint is for IConnectionPoint interfaces. - IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}") - - // IID_IInspectable is for IInspectable interfaces. - IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}") - - // IID_IProvideClassInfo is for IProvideClassInfo interfaces. - IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}") -) - -// These are for testing and not part of any library. -var ( - // IID_ICOMTestString is for ICOMTestString interfaces. - // - // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED} - IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}") - - // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces. - // - // {BEB06610-EB84-4155-AF58-E2BFF53680B4} - IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}") - - // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces. - // - // {DAA3F9FA-761E-4976-A860-8364CE55F6FC} - IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}") - - // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces. - // - // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0} - IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}") - - // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces. - // - // {8D437CBC-B3ED-485C-BC32-C336432A1623} - IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}") - - // IID_ICOMTestFloat is for ICOMTestFloat interfaces. - // - // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C} - IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}") - - // IID_ICOMTestDouble is for ICOMTestDouble interfaces. - // - // {BF908A81-8687-4E93-999F-D86FAB284BA0} - IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}") - - // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces. - // - // {D530E7A6-4EE8-40D1-8931-3D63B8605010} - IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}") - - // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces. - // - // {6485B1EF-D780-4834-A4FE-1EBB51746CA3} - IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}") - - // IID_ICOMTestTypes is for ICOMTestTypes interfaces. - // - // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0} - IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}") - - // CLSID_COMEchoTestObject is for COMEchoTestObject class. - // - // {3C24506A-AE9E-4D50-9157-EF317281F1B0} - CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}") - - // CLSID_COMTestScalarClass is for COMTestScalarClass class. - // - // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86} - CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}") -) - -const hextable = "0123456789ABCDEF" -const emptyGUID = "{00000000-0000-0000-0000-000000000000}" - -// GUID is Windows API specific GUID type. -// -// This exists to match Windows GUID type for direct passing for COM. -// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. -type GUID struct { - Data1 uint32 - Data2 uint16 - Data3 uint16 - Data4 [8]byte -} - -// NewGUID converts the given string into a globally unique identifier that is -// compliant with the Windows API. -// -// The supplied string may be in any of these formats: -// -// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} -// -// The conversion of the supplied string is not case-sensitive. -func NewGUID(guid string) *GUID { - d := []byte(guid) - var d1, d2, d3, d4a, d4b []byte - - switch len(d) { - case 38: - if d[0] != '{' || d[37] != '}' { - return nil - } - d = d[1:37] - fallthrough - case 36: - if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { - return nil - } - d1 = d[0:8] - d2 = d[9:13] - d3 = d[14:18] - d4a = d[19:23] - d4b = d[24:36] - case 32: - d1 = d[0:8] - d2 = d[8:12] - d3 = d[12:16] - d4a = d[16:20] - d4b = d[20:32] - default: - return nil - } - - var g GUID - var ok1, ok2, ok3, ok4 bool - g.Data1, ok1 = decodeHexUint32(d1) - g.Data2, ok2 = decodeHexUint16(d2) - g.Data3, ok3 = decodeHexUint16(d3) - g.Data4, ok4 = decodeHexByte64(d4a, d4b) - if ok1 && ok2 && ok3 && ok4 { - return &g - } - return nil -} - -func decodeHexUint32(src []byte) (value uint32, ok bool) { - var b1, b2, b3, b4 byte - var ok1, ok2, ok3, ok4 bool - b1, ok1 = decodeHexByte(src[0], src[1]) - b2, ok2 = decodeHexByte(src[2], src[3]) - b3, ok3 = decodeHexByte(src[4], src[5]) - b4, ok4 = decodeHexByte(src[6], src[7]) - value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) - ok = ok1 && ok2 && ok3 && ok4 - return -} - -func decodeHexUint16(src []byte) (value uint16, ok bool) { - var b1, b2 byte - var ok1, ok2 bool - b1, ok1 = decodeHexByte(src[0], src[1]) - b2, ok2 = decodeHexByte(src[2], src[3]) - value = (uint16(b1) << 8) | uint16(b2) - ok = ok1 && ok2 - return -} - -func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { - var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool - value[0], ok1 = decodeHexByte(s1[0], s1[1]) - value[1], ok2 = decodeHexByte(s1[2], s1[3]) - value[2], ok3 = decodeHexByte(s2[0], s2[1]) - value[3], ok4 = decodeHexByte(s2[2], s2[3]) - value[4], ok5 = decodeHexByte(s2[4], s2[5]) - value[5], ok6 = decodeHexByte(s2[6], s2[7]) - value[6], ok7 = decodeHexByte(s2[8], s2[9]) - value[7], ok8 = decodeHexByte(s2[10], s2[11]) - ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 - return -} - -func decodeHexByte(c1, c2 byte) (value byte, ok bool) { - var n1, n2 byte - var ok1, ok2 bool - n1, ok1 = decodeHexChar(c1) - n2, ok2 = decodeHexChar(c2) - value = (n1 << 4) | n2 - ok = ok1 && ok2 - return -} - -func decodeHexChar(c byte) (byte, bool) { - switch { - case '0' <= c && c <= '9': - return c - '0', true - case 'a' <= c && c <= 'f': - return c - 'a' + 10, true - case 'A' <= c && c <= 'F': - return c - 'A' + 10, true - } - - return 0, false -} - -// String converts the GUID to string form. It will adhere to this pattern: -// -// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} -// -// If the GUID is nil, the string representation of an empty GUID is returned: -// -// {00000000-0000-0000-0000-000000000000} -func (guid *GUID) String() string { - if guid == nil { - return emptyGUID - } - - var c [38]byte - c[0] = '{' - putUint32Hex(c[1:9], guid.Data1) - c[9] = '-' - putUint16Hex(c[10:14], guid.Data2) - c[14] = '-' - putUint16Hex(c[15:19], guid.Data3) - c[19] = '-' - putByteHex(c[20:24], guid.Data4[0:2]) - c[24] = '-' - putByteHex(c[25:37], guid.Data4[2:8]) - c[37] = '}' - return string(c[:]) -} - -func putUint32Hex(b []byte, v uint32) { - b[0] = hextable[byte(v>>24)>>4] - b[1] = hextable[byte(v>>24)&0x0f] - b[2] = hextable[byte(v>>16)>>4] - b[3] = hextable[byte(v>>16)&0x0f] - b[4] = hextable[byte(v>>8)>>4] - b[5] = hextable[byte(v>>8)&0x0f] - b[6] = hextable[byte(v)>>4] - b[7] = hextable[byte(v)&0x0f] -} - -func putUint16Hex(b []byte, v uint16) { - b[0] = hextable[byte(v>>8)>>4] - b[1] = hextable[byte(v>>8)&0x0f] - b[2] = hextable[byte(v)>>4] - b[3] = hextable[byte(v)&0x0f] -} - -func putByteHex(dst, src []byte) { - for i := 0; i < len(src); i++ { - dst[i*2] = hextable[src[i]>>4] - dst[i*2+1] = hextable[src[i]&0x0f] - } -} - -// IsEqualGUID compares two GUID. -// -// Not constant time comparison. -func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { - return guid1.Data1 == guid2.Data1 && - guid1.Data2 == guid2.Data2 && - guid1.Data3 == guid2.Data3 && - guid1.Data4[0] == guid2.Data4[0] && - guid1.Data4[1] == guid2.Data4[1] && - guid1.Data4[2] == guid2.Data4[2] && - guid1.Data4[3] == guid2.Data4[3] && - guid1.Data4[4] == guid2.Data4[4] && - guid1.Data4[5] == guid2.Data4[5] && - guid1.Data4[6] == guid2.Data4[6] && - guid1.Data4[7] == guid2.Data4[7] -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go deleted file mode 100644 index 9e6c49f41f..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go +++ /dev/null @@ -1,20 +0,0 @@ -package ole - -import "unsafe" - -type IConnectionPoint struct { - IUnknown -} - -type IConnectionPointVtbl struct { - IUnknownVtbl - GetConnectionInterface uintptr - GetConnectionPointContainer uintptr - Advise uintptr - Unadvise uintptr - EnumConnections uintptr -} - -func (v *IConnectionPoint) VTable() *IConnectionPointVtbl { - return (*IConnectionPointVtbl)(unsafe.Pointer(v.RawVTable)) -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go deleted file mode 100644 index 5414dc3cd3..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !windows - -package ole - -import "unsafe" - -func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { - return int32(0) -} - -func (v *IConnectionPoint) Advise(unknown *IUnknown) (uint32, error) { - return uint32(0), NewError(E_NOTIMPL) -} - -func (v *IConnectionPoint) Unadvise(cookie uint32) error { - return NewError(E_NOTIMPL) -} - -func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) { - return NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go deleted file mode 100644 index 32bc183248..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go +++ /dev/null @@ -1,43 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unsafe" -) - -func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { - // XXX: This doesn't look like it does what it's supposed to - return release((*IUnknown)(unsafe.Pointer(v))) -} - -func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) { - hr, _, _ := syscall.Syscall( - v.VTable().Advise, - 3, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(unknown)), - uintptr(unsafe.Pointer(&cookie))) - if hr != 0 { - err = NewError(hr) - } - return -} - -func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) { - hr, _, _ := syscall.Syscall( - v.VTable().Unadvise, - 2, - uintptr(unsafe.Pointer(v)), - uintptr(cookie), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} - -func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) error { - return NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go deleted file mode 100644 index 165860d199..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go +++ /dev/null @@ -1,17 +0,0 @@ -package ole - -import "unsafe" - -type IConnectionPointContainer struct { - IUnknown -} - -type IConnectionPointContainerVtbl struct { - IUnknownVtbl - EnumConnectionPoints uintptr - FindConnectionPoint uintptr -} - -func (v *IConnectionPointContainer) VTable() *IConnectionPointContainerVtbl { - return (*IConnectionPointContainerVtbl)(unsafe.Pointer(v.RawVTable)) -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go deleted file mode 100644 index 5dfa42aaeb..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !windows - -package ole - -func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { - return NewError(E_NOTIMPL) -} - -func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) error { - return NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go deleted file mode 100644 index ad30d79efc..0000000000 --- a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unsafe" -) - -func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { - return NewError(E_NOTIMPL) -} - -func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) { - hr, _, _ := syscall.Syscall( - v.VTable().FindConnectionPoint, - 3, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(point))) - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/idispatch.go b/vendor/github.com/go-ole/go-ole/idispatch.go deleted file mode 100644 index d4af124092..0000000000 --- a/vendor/github.com/go-ole/go-ole/idispatch.go +++ /dev/null @@ -1,94 +0,0 @@ -package ole - -import "unsafe" - -type IDispatch struct { - IUnknown -} - -type IDispatchVtbl struct { - IUnknownVtbl - GetTypeInfoCount uintptr - GetTypeInfo uintptr - GetIDsOfNames uintptr - Invoke uintptr -} - -func (v *IDispatch) VTable() *IDispatchVtbl { - return (*IDispatchVtbl)(unsafe.Pointer(v.RawVTable)) -} - -func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) { - dispid, err = getIDsOfName(v, names) - return -} - -func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { - result, err = invoke(v, dispid, dispatch, params...) - return -} - -func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) { - c, err = getTypeInfoCount(v) - return -} - -func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) { - tinfo, err = getTypeInfo(v) - return -} - -// GetSingleIDOfName is a helper that returns single display ID for IDispatch name. -// -// This replaces the common pattern of attempting to get a single name from the list of available -// IDs. It gives the first ID, if it is available. -func (v *IDispatch) GetSingleIDOfName(name string) (displayID int32, err error) { - var displayIDs []int32 - displayIDs, err = v.GetIDsOfName([]string{name}) - if err != nil { - return - } - displayID = displayIDs[0] - return -} - -// InvokeWithOptionalArgs accepts arguments as an array, works like Invoke. -// -// Accepts name and will attempt to retrieve Display ID to pass to Invoke. -// -// Passing params as an array is a workaround that could be fixed in later versions of Go that -// prevent passing empty params. During testing it was discovered that this is an acceptable way of -// getting around not being able to pass params normally. -func (v *IDispatch) InvokeWithOptionalArgs(name string, dispatch int16, params []interface{}) (result *VARIANT, err error) { - displayID, err := v.GetSingleIDOfName(name) - if err != nil { - return - } - - if len(params) < 1 { - result, err = v.Invoke(displayID, dispatch) - } else { - result, err = v.Invoke(displayID, dispatch, params...) - } - - return -} - -// CallMethod invokes named function with arguments on object. -func (v *IDispatch) CallMethod(name string, params ...interface{}) (*VARIANT, error) { - return v.InvokeWithOptionalArgs(name, DISPATCH_METHOD, params) -} - -// GetProperty retrieves the property with the name with the ability to pass arguments. -// -// Most of the time you will not need to pass arguments as most objects do not allow for this -// feature. Or at least, should not allow for this feature. Some servers don't follow best practices -// and this is provided for those edge cases. -func (v *IDispatch) GetProperty(name string, params ...interface{}) (*VARIANT, error) { - return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYGET, params) -} - -// PutProperty attempts to mutate a property in the object. -func (v *IDispatch) PutProperty(name string, params ...interface{}) (*VARIANT, error) { - return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYPUT, params) -} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_func.go b/vendor/github.com/go-ole/go-ole/idispatch_func.go deleted file mode 100644 index b8fbbe319f..0000000000 --- a/vendor/github.com/go-ole/go-ole/idispatch_func.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package ole - -func getIDsOfName(disp *IDispatch, names []string) ([]int32, error) { - return []int32{}, NewError(E_NOTIMPL) -} - -func getTypeInfoCount(disp *IDispatch) (uint32, error) { - return uint32(0), NewError(E_NOTIMPL) -} - -func getTypeInfo(disp *IDispatch) (*ITypeInfo, error) { - return nil, NewError(E_NOTIMPL) -} - -func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) { - return nil, NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go deleted file mode 100644 index 6ec180b55f..0000000000 --- a/vendor/github.com/go-ole/go-ole/idispatch_windows.go +++ /dev/null @@ -1,200 +0,0 @@ -// +build windows - -package ole - -import ( - "math/big" - "syscall" - "time" - "unsafe" -) - -func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) { - wnames := make([]*uint16, len(names)) - for i := 0; i < len(names); i++ { - wnames[i] = syscall.StringToUTF16Ptr(names[i]) - } - dispid = make([]int32, len(names)) - namelen := uint32(len(names)) - hr, _, _ := syscall.Syscall6( - disp.VTable().GetIDsOfNames, - 6, - uintptr(unsafe.Pointer(disp)), - uintptr(unsafe.Pointer(IID_NULL)), - uintptr(unsafe.Pointer(&wnames[0])), - uintptr(namelen), - uintptr(GetUserDefaultLCID()), - uintptr(unsafe.Pointer(&dispid[0]))) - if hr != 0 { - err = NewError(hr) - } - return -} - -func getTypeInfoCount(disp *IDispatch) (c uint32, err error) { - hr, _, _ := syscall.Syscall( - disp.VTable().GetTypeInfoCount, - 2, - uintptr(unsafe.Pointer(disp)), - uintptr(unsafe.Pointer(&c)), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} - -func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) { - hr, _, _ := syscall.Syscall( - disp.VTable().GetTypeInfo, - 3, - uintptr(unsafe.Pointer(disp)), - uintptr(GetUserDefaultLCID()), - uintptr(unsafe.Pointer(&tinfo))) - if hr != 0 { - err = NewError(hr) - } - return -} - -func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { - var dispparams DISPPARAMS - - if dispatch&DISPATCH_PROPERTYPUT != 0 { - dispnames := [1]int32{DISPID_PROPERTYPUT} - dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) - dispparams.cNamedArgs = 1 - } else if dispatch&DISPATCH_PROPERTYPUTREF != 0 { - dispnames := [1]int32{DISPID_PROPERTYPUT} - dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) - dispparams.cNamedArgs = 1 - } - var vargs []VARIANT - if len(params) > 0 { - vargs = make([]VARIANT, len(params)) - for i, v := range params { - //n := len(params)-i-1 - n := len(params) - i - 1 - VariantInit(&vargs[n]) - switch vv := v.(type) { - case bool: - if vv { - vargs[n] = NewVariant(VT_BOOL, 0xffff) - } else { - vargs[n] = NewVariant(VT_BOOL, 0) - } - case *bool: - vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool))))) - case uint8: - vargs[n] = NewVariant(VT_I1, int64(v.(uint8))) - case *uint8: - vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) - case int8: - vargs[n] = NewVariant(VT_I1, int64(v.(int8))) - case *int8: - vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) - case int16: - vargs[n] = NewVariant(VT_I2, int64(v.(int16))) - case *int16: - vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16))))) - case uint16: - vargs[n] = NewVariant(VT_UI2, int64(v.(uint16))) - case *uint16: - vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16))))) - case int32: - vargs[n] = NewVariant(VT_I4, int64(v.(int32))) - case *int32: - vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32))))) - case uint32: - vargs[n] = NewVariant(VT_UI4, int64(v.(uint32))) - case *uint32: - vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32))))) - case int64: - vargs[n] = NewVariant(VT_I8, int64(v.(int64))) - case *int64: - vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64))))) - case uint64: - vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64)))) - case *uint64: - vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64))))) - case int: - vargs[n] = NewVariant(VT_I4, int64(v.(int))) - case *int: - vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int))))) - case uint: - vargs[n] = NewVariant(VT_UI4, int64(v.(uint))) - case *uint: - vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint))))) - case float32: - vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv))) - case *float32: - vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32))))) - case float64: - vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv))) - case *float64: - vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64))))) - case *big.Int: - vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64()) - case string: - vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string)))))) - case *string: - vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string))))) - case time.Time: - s := vv.Format("2006-01-02 15:04:05") - vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s))))) - case *time.Time: - s := vv.Format("2006-01-02 15:04:05") - vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s)))) - case *IDispatch: - vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))) - case **IDispatch: - vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))) - case nil: - vargs[n] = NewVariant(VT_NULL, 0) - case *VARIANT: - vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))) - case []byte: - safeByteArray := safeArrayFromByteSlice(v.([]byte)) - vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray)))) - defer VariantClear(&vargs[n]) - case []string: - safeByteArray := safeArrayFromStringSlice(v.([]string)) - vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray)))) - defer VariantClear(&vargs[n]) - default: - panic("unknown type") - } - } - dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0])) - dispparams.cArgs = uint32(len(params)) - } - - result = new(VARIANT) - var excepInfo EXCEPINFO - VariantInit(result) - hr, _, _ := syscall.Syscall9( - disp.VTable().Invoke, - 9, - uintptr(unsafe.Pointer(disp)), - uintptr(dispid), - uintptr(unsafe.Pointer(IID_NULL)), - uintptr(GetUserDefaultLCID()), - uintptr(dispatch), - uintptr(unsafe.Pointer(&dispparams)), - uintptr(unsafe.Pointer(result)), - uintptr(unsafe.Pointer(&excepInfo)), - 0) - if hr != 0 { - err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo) - } - for i, varg := range vargs { - n := len(params) - i - 1 - if varg.VT == VT_BSTR && varg.Val != 0 { - SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) - } - if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 { - *(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val)))) - } - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant.go b/vendor/github.com/go-ole/go-ole/ienumvariant.go deleted file mode 100644 index 2433897544..0000000000 --- a/vendor/github.com/go-ole/go-ole/ienumvariant.go +++ /dev/null @@ -1,19 +0,0 @@ -package ole - -import "unsafe" - -type IEnumVARIANT struct { - IUnknown -} - -type IEnumVARIANTVtbl struct { - IUnknownVtbl - Next uintptr - Skip uintptr - Reset uintptr - Clone uintptr -} - -func (v *IEnumVARIANT) VTable() *IEnumVARIANTVtbl { - return (*IEnumVARIANTVtbl)(unsafe.Pointer(v.RawVTable)) -} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go deleted file mode 100644 index c14848199c..0000000000 --- a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package ole - -func (enum *IEnumVARIANT) Clone() (*IEnumVARIANT, error) { - return nil, NewError(E_NOTIMPL) -} - -func (enum *IEnumVARIANT) Reset() error { - return NewError(E_NOTIMPL) -} - -func (enum *IEnumVARIANT) Skip(celt uint) error { - return NewError(E_NOTIMPL) -} - -func (enum *IEnumVARIANT) Next(celt uint) (VARIANT, uint, error) { - return NewVariant(VT_NULL, int64(0)), 0, NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go deleted file mode 100644 index 4781f3b8b0..0000000000 --- a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go +++ /dev/null @@ -1,63 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unsafe" -) - -func (enum *IEnumVARIANT) Clone() (cloned *IEnumVARIANT, err error) { - hr, _, _ := syscall.Syscall( - enum.VTable().Clone, - 2, - uintptr(unsafe.Pointer(enum)), - uintptr(unsafe.Pointer(&cloned)), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} - -func (enum *IEnumVARIANT) Reset() (err error) { - hr, _, _ := syscall.Syscall( - enum.VTable().Reset, - 1, - uintptr(unsafe.Pointer(enum)), - 0, - 0) - if hr != 0 { - err = NewError(hr) - } - return -} - -func (enum *IEnumVARIANT) Skip(celt uint) (err error) { - hr, _, _ := syscall.Syscall( - enum.VTable().Skip, - 2, - uintptr(unsafe.Pointer(enum)), - uintptr(celt), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} - -func (enum *IEnumVARIANT) Next(celt uint) (array VARIANT, length uint, err error) { - hr, _, _ := syscall.Syscall6( - enum.VTable().Next, - 4, - uintptr(unsafe.Pointer(enum)), - uintptr(celt), - uintptr(unsafe.Pointer(&array)), - uintptr(unsafe.Pointer(&length)), - 0, - 0) - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable.go b/vendor/github.com/go-ole/go-ole/iinspectable.go deleted file mode 100644 index f4a19e253a..0000000000 --- a/vendor/github.com/go-ole/go-ole/iinspectable.go +++ /dev/null @@ -1,18 +0,0 @@ -package ole - -import "unsafe" - -type IInspectable struct { - IUnknown -} - -type IInspectableVtbl struct { - IUnknownVtbl - GetIIds uintptr - GetRuntimeClassName uintptr - GetTrustLevel uintptr -} - -func (v *IInspectable) VTable() *IInspectableVtbl { - return (*IInspectableVtbl)(unsafe.Pointer(v.RawVTable)) -} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_func.go b/vendor/github.com/go-ole/go-ole/iinspectable_func.go deleted file mode 100644 index 348829bf06..0000000000 --- a/vendor/github.com/go-ole/go-ole/iinspectable_func.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !windows - -package ole - -func (v *IInspectable) GetIids() ([]*GUID, error) { - return []*GUID{}, NewError(E_NOTIMPL) -} - -func (v *IInspectable) GetRuntimeClassName() (string, error) { - return "", NewError(E_NOTIMPL) -} - -func (v *IInspectable) GetTrustLevel() (uint32, error) { - return uint32(0), NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go deleted file mode 100644 index 4519a4aa44..0000000000 --- a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build windows - -package ole - -import ( - "bytes" - "encoding/binary" - "reflect" - "syscall" - "unsafe" -) - -func (v *IInspectable) GetIids() (iids []*GUID, err error) { - var count uint32 - var array uintptr - hr, _, _ := syscall.Syscall( - v.VTable().GetIIds, - 3, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(&count)), - uintptr(unsafe.Pointer(&array))) - if hr != 0 { - err = NewError(hr) - return - } - defer CoTaskMemFree(array) - - iids = make([]*GUID, count) - byteCount := count * uint32(unsafe.Sizeof(GUID{})) - slicehdr := reflect.SliceHeader{Data: array, Len: int(byteCount), Cap: int(byteCount)} - byteSlice := *(*[]byte)(unsafe.Pointer(&slicehdr)) - reader := bytes.NewReader(byteSlice) - for i := range iids { - guid := GUID{} - err = binary.Read(reader, binary.LittleEndian, &guid) - if err != nil { - return - } - iids[i] = &guid - } - return -} - -func (v *IInspectable) GetRuntimeClassName() (s string, err error) { - var hstring HString - hr, _, _ := syscall.Syscall( - v.VTable().GetRuntimeClassName, - 2, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(&hstring)), - 0) - if hr != 0 { - err = NewError(hr) - return - } - s = hstring.String() - DeleteHString(hstring) - return -} - -func (v *IInspectable) GetTrustLevel() (level uint32, err error) { - hr, _, _ := syscall.Syscall( - v.VTable().GetTrustLevel, - 2, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(&level)), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go deleted file mode 100644 index 25f3a6f24a..0000000000 --- a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go +++ /dev/null @@ -1,21 +0,0 @@ -package ole - -import "unsafe" - -type IProvideClassInfo struct { - IUnknown -} - -type IProvideClassInfoVtbl struct { - IUnknownVtbl - GetClassInfo uintptr -} - -func (v *IProvideClassInfo) VTable() *IProvideClassInfoVtbl { - return (*IProvideClassInfoVtbl)(unsafe.Pointer(v.RawVTable)) -} - -func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) { - cinfo, err = getClassInfo(v) - return -} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go deleted file mode 100644 index 7e3cb63ea7..0000000000 --- a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !windows - -package ole - -func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { - return nil, NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go deleted file mode 100644 index 2ad0163949..0000000000 --- a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unsafe" -) - -func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { - hr, _, _ := syscall.Syscall( - disp.VTable().GetClassInfo, - 2, - uintptr(unsafe.Pointer(disp)), - uintptr(unsafe.Pointer(&tinfo)), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo.go b/vendor/github.com/go-ole/go-ole/itypeinfo.go deleted file mode 100644 index dd3c5e21bb..0000000000 --- a/vendor/github.com/go-ole/go-ole/itypeinfo.go +++ /dev/null @@ -1,34 +0,0 @@ -package ole - -import "unsafe" - -type ITypeInfo struct { - IUnknown -} - -type ITypeInfoVtbl struct { - IUnknownVtbl - GetTypeAttr uintptr - GetTypeComp uintptr - GetFuncDesc uintptr - GetVarDesc uintptr - GetNames uintptr - GetRefTypeOfImplType uintptr - GetImplTypeFlags uintptr - GetIDsOfNames uintptr - Invoke uintptr - GetDocumentation uintptr - GetDllEntry uintptr - GetRefTypeInfo uintptr - AddressOfMember uintptr - CreateInstance uintptr - GetMops uintptr - GetContainingTypeLib uintptr - ReleaseTypeAttr uintptr - ReleaseFuncDesc uintptr - ReleaseVarDesc uintptr -} - -func (v *ITypeInfo) VTable() *ITypeInfoVtbl { - return (*ITypeInfoVtbl)(unsafe.Pointer(v.RawVTable)) -} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go deleted file mode 100644 index 8364a659ba..0000000000 --- a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !windows - -package ole - -func (v *ITypeInfo) GetTypeAttr() (*TYPEATTR, error) { - return nil, NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go deleted file mode 100644 index 54782b3da5..0000000000 --- a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" - "unsafe" -) - -func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) { - hr, _, _ := syscall.Syscall( - uintptr(v.VTable().GetTypeAttr), - 2, - uintptr(unsafe.Pointer(v)), - uintptr(unsafe.Pointer(&tattr)), - 0) - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/iunknown.go b/vendor/github.com/go-ole/go-ole/iunknown.go deleted file mode 100644 index 108f28ea61..0000000000 --- a/vendor/github.com/go-ole/go-ole/iunknown.go +++ /dev/null @@ -1,57 +0,0 @@ -package ole - -import "unsafe" - -type IUnknown struct { - RawVTable *interface{} -} - -type IUnknownVtbl struct { - QueryInterface uintptr - AddRef uintptr - Release uintptr -} - -type UnknownLike interface { - QueryInterface(iid *GUID) (disp *IDispatch, err error) - AddRef() int32 - Release() int32 -} - -func (v *IUnknown) VTable() *IUnknownVtbl { - return (*IUnknownVtbl)(unsafe.Pointer(v.RawVTable)) -} - -func (v *IUnknown) PutQueryInterface(interfaceID *GUID, obj interface{}) error { - return reflectQueryInterface(v, v.VTable().QueryInterface, interfaceID, obj) -} - -func (v *IUnknown) IDispatch(interfaceID *GUID) (dispatch *IDispatch, err error) { - err = v.PutQueryInterface(interfaceID, &dispatch) - return -} - -func (v *IUnknown) IEnumVARIANT(interfaceID *GUID) (enum *IEnumVARIANT, err error) { - err = v.PutQueryInterface(interfaceID, &enum) - return -} - -func (v *IUnknown) QueryInterface(iid *GUID) (*IDispatch, error) { - return queryInterface(v, iid) -} - -func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) { - unk, err := queryInterface(v, iid) - if err != nil { - panic(err) - } - return unk -} - -func (v *IUnknown) AddRef() int32 { - return addRef(v) -} - -func (v *IUnknown) Release() int32 { - return release(v) -} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_func.go b/vendor/github.com/go-ole/go-ole/iunknown_func.go deleted file mode 100644 index d0a62cfd73..0000000000 --- a/vendor/github.com/go-ole/go-ole/iunknown_func.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package ole - -func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { - return NewError(E_NOTIMPL) -} - -func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { - return nil, NewError(E_NOTIMPL) -} - -func addRef(unk *IUnknown) int32 { - return 0 -} - -func release(unk *IUnknown) int32 { - return 0 -} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_windows.go b/vendor/github.com/go-ole/go-ole/iunknown_windows.go deleted file mode 100644 index ede5bb8c17..0000000000 --- a/vendor/github.com/go-ole/go-ole/iunknown_windows.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build windows - -package ole - -import ( - "reflect" - "syscall" - "unsafe" -) - -func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { - selfValue := reflect.ValueOf(self).Elem() - objValue := reflect.ValueOf(obj).Elem() - - hr, _, _ := syscall.Syscall( - method, - 3, - selfValue.UnsafeAddr(), - uintptr(unsafe.Pointer(interfaceID)), - objValue.Addr().Pointer()) - if hr != 0 { - err = NewError(hr) - } - return -} - -func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { - hr, _, _ := syscall.Syscall( - unk.VTable().QueryInterface, - 3, - uintptr(unsafe.Pointer(unk)), - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(&disp))) - if hr != 0 { - err = NewError(hr) - } - return -} - -func addRef(unk *IUnknown) int32 { - ret, _, _ := syscall.Syscall( - unk.VTable().AddRef, - 1, - uintptr(unsafe.Pointer(unk)), - 0, - 0) - return int32(ret) -} - -func release(unk *IUnknown) int32 { - ret, _, _ := syscall.Syscall( - unk.VTable().Release, - 1, - uintptr(unsafe.Pointer(unk)), - 0, - 0) - return int32(ret) -} diff --git a/vendor/github.com/go-ole/go-ole/ole.go b/vendor/github.com/go-ole/go-ole/ole.go deleted file mode 100644 index e2ae4f4bbf..0000000000 --- a/vendor/github.com/go-ole/go-ole/ole.go +++ /dev/null @@ -1,157 +0,0 @@ -package ole - -import ( - "fmt" - "strings" -) - -// DISPPARAMS are the arguments that passed to methods or property. -type DISPPARAMS struct { - rgvarg uintptr - rgdispidNamedArgs uintptr - cArgs uint32 - cNamedArgs uint32 -} - -// EXCEPINFO defines exception info. -type EXCEPINFO struct { - wCode uint16 - wReserved uint16 - bstrSource *uint16 - bstrDescription *uint16 - bstrHelpFile *uint16 - dwHelpContext uint32 - pvReserved uintptr - pfnDeferredFillIn uintptr - scode uint32 -} - -// WCode return wCode in EXCEPINFO. -func (e EXCEPINFO) WCode() uint16 { - return e.wCode -} - -// SCODE return scode in EXCEPINFO. -func (e EXCEPINFO) SCODE() uint32 { - return e.scode -} - -// String convert EXCEPINFO to string. -func (e EXCEPINFO) String() string { - var src, desc, hlp string - if e.bstrSource == nil { - src = "" - } else { - src = BstrToString(e.bstrSource) - } - - if e.bstrDescription == nil { - desc = "" - } else { - desc = BstrToString(e.bstrDescription) - } - - if e.bstrHelpFile == nil { - hlp = "" - } else { - hlp = BstrToString(e.bstrHelpFile) - } - - return fmt.Sprintf( - "wCode: %#x, bstrSource: %v, bstrDescription: %v, bstrHelpFile: %v, dwHelpContext: %#x, scode: %#x", - e.wCode, src, desc, hlp, e.dwHelpContext, e.scode, - ) -} - -// Error implements error interface and returns error string. -func (e EXCEPINFO) Error() string { - if e.bstrDescription != nil { - return strings.TrimSpace(BstrToString(e.bstrDescription)) - } - - src := "Unknown" - if e.bstrSource != nil { - src = BstrToString(e.bstrSource) - } - - code := e.scode - if e.wCode != 0 { - code = uint32(e.wCode) - } - - return fmt.Sprintf("%v: %#x", src, code) -} - -// PARAMDATA defines parameter data type. -type PARAMDATA struct { - Name *int16 - Vt uint16 -} - -// METHODDATA defines method info. -type METHODDATA struct { - Name *uint16 - Data *PARAMDATA - Dispid int32 - Meth uint32 - CC int32 - CArgs uint32 - Flags uint16 - VtReturn uint32 -} - -// INTERFACEDATA defines interface info. -type INTERFACEDATA struct { - MethodData *METHODDATA - CMembers uint32 -} - -// Point is 2D vector type. -type Point struct { - X int32 - Y int32 -} - -// Msg is message between processes. -type Msg struct { - Hwnd uint32 - Message uint32 - Wparam int32 - Lparam int32 - Time uint32 - Pt Point -} - -// TYPEDESC defines data type. -type TYPEDESC struct { - Hreftype uint32 - VT uint16 -} - -// IDLDESC defines IDL info. -type IDLDESC struct { - DwReserved uint32 - WIDLFlags uint16 -} - -// TYPEATTR defines type info. -type TYPEATTR struct { - Guid GUID - Lcid uint32 - dwReserved uint32 - MemidConstructor int32 - MemidDestructor int32 - LpstrSchema *uint16 - CbSizeInstance uint32 - Typekind int32 - CFuncs uint16 - CVars uint16 - CImplTypes uint16 - CbSizeVft uint16 - CbAlignment uint16 - WTypeFlags uint16 - WMajorVerNum uint16 - WMinorVerNum uint16 - TdescAlias TYPEDESC - IdldescType IDLDESC -} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection.go b/vendor/github.com/go-ole/go-ole/oleutil/connection.go deleted file mode 100644 index 60df73cda0..0000000000 --- a/vendor/github.com/go-ole/go-ole/oleutil/connection.go +++ /dev/null @@ -1,100 +0,0 @@ -// +build windows - -package oleutil - -import ( - "reflect" - "unsafe" - - ole "github.com/go-ole/go-ole" -) - -type stdDispatch struct { - lpVtbl *stdDispatchVtbl - ref int32 - iid *ole.GUID - iface interface{} - funcMap map[string]int32 -} - -type stdDispatchVtbl struct { - pQueryInterface uintptr - pAddRef uintptr - pRelease uintptr - pGetTypeInfoCount uintptr - pGetTypeInfo uintptr - pGetIDsOfNames uintptr - pInvoke uintptr -} - -func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { - pthis := (*stdDispatch)(unsafe.Pointer(this)) - *punk = nil - if ole.IsEqualGUID(iid, ole.IID_IUnknown) || - ole.IsEqualGUID(iid, ole.IID_IDispatch) { - dispAddRef(this) - *punk = this - return ole.S_OK - } - if ole.IsEqualGUID(iid, pthis.iid) { - dispAddRef(this) - *punk = this - return ole.S_OK - } - return ole.E_NOINTERFACE -} - -func dispAddRef(this *ole.IUnknown) int32 { - pthis := (*stdDispatch)(unsafe.Pointer(this)) - pthis.ref++ - return pthis.ref -} - -func dispRelease(this *ole.IUnknown) int32 { - pthis := (*stdDispatch)(unsafe.Pointer(this)) - pthis.ref-- - return pthis.ref -} - -func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { - pthis := (*stdDispatch)(unsafe.Pointer(this)) - names := make([]string, len(wnames)) - for i := 0; i < len(names); i++ { - names[i] = ole.LpOleStrToString(wnames[i]) - } - for n := 0; n < namelen; n++ { - if id, ok := pthis.funcMap[names[n]]; ok { - pdisp[n] = id - } - } - return ole.S_OK -} - -func dispGetTypeInfoCount(pcount *int) uintptr { - if pcount != nil { - *pcount = 0 - } - return ole.S_OK -} - -func dispGetTypeInfo(ptypeif *uintptr) uintptr { - return ole.E_NOTIMPL -} - -func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { - pthis := (*stdDispatch)(unsafe.Pointer(this)) - found := "" - for name, id := range pthis.funcMap { - if id == dispid { - found = name - } - } - if found != "" { - rv := reflect.ValueOf(pthis.iface).Elem() - rm := rv.MethodByName(found) - rr := rm.Call([]reflect.Value{}) - println(len(rr)) - return ole.S_OK - } - return ole.E_NOTIMPL -} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go deleted file mode 100644 index 8818fb8275..0000000000 --- a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !windows - -package oleutil - -import ole "github.com/go-ole/go-ole" - -// ConnectObject creates a connection point between two services for communication. -func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (uint32, error) { - return 0, ole.NewError(ole.E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go deleted file mode 100644 index ab9c0d8dcb..0000000000 --- a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build windows - -package oleutil - -import ( - "reflect" - "syscall" - "unsafe" - - ole "github.com/go-ole/go-ole" -) - -// ConnectObject creates a connection point between two services for communication. -func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) { - unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer) - if err != nil { - return - } - - container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown)) - var point *ole.IConnectionPoint - err = container.FindConnectionPoint(iid, &point) - if err != nil { - return - } - if edisp, ok := idisp.(*ole.IUnknown); ok { - cookie, err = point.Advise(edisp) - container.Release() - if err != nil { - return - } - } - rv := reflect.ValueOf(disp).Elem() - if rv.Type().Kind() == reflect.Struct { - dest := &stdDispatch{} - dest.lpVtbl = &stdDispatchVtbl{} - dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface) - dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef) - dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease) - dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount) - dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo) - dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames) - dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke) - dest.iface = disp - dest.iid = iid - cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest))) - container.Release() - if err != nil { - point.Release() - return - } - return - } - - container.Release() - - return 0, ole.NewError(ole.E_INVALIDARG) -} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go deleted file mode 100644 index 58347628f2..0000000000 --- a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go +++ /dev/null @@ -1,6 +0,0 @@ -// This file is here so go get succeeds as without it errors with: -// no buildable Go source files in ... -// -// +build !windows - -package oleutil diff --git a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go deleted file mode 100644 index f7803c1e30..0000000000 --- a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go +++ /dev/null @@ -1,127 +0,0 @@ -package oleutil - -import ole "github.com/go-ole/go-ole" - -// ClassIDFrom retrieves class ID whether given is program ID or application string. -func ClassIDFrom(programID string) (classID *ole.GUID, err error) { - return ole.ClassIDFrom(programID) -} - -// CreateObject creates object from programID based on interface type. -// -// Only supports IUnknown. -// -// Program ID can be either program ID or application string. -func CreateObject(programID string) (unknown *ole.IUnknown, err error) { - classID, err := ole.ClassIDFrom(programID) - if err != nil { - return - } - - unknown, err = ole.CreateInstance(classID, ole.IID_IUnknown) - if err != nil { - return - } - - return -} - -// GetActiveObject retrieves active object for program ID and interface ID based -// on interface type. -// -// Only supports IUnknown. -// -// Program ID can be either program ID or application string. -func GetActiveObject(programID string) (unknown *ole.IUnknown, err error) { - classID, err := ole.ClassIDFrom(programID) - if err != nil { - return - } - - unknown, err = ole.GetActiveObject(classID, ole.IID_IUnknown) - if err != nil { - return - } - - return -} - -// CallMethod calls method on IDispatch with parameters. -func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { - return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_METHOD, params) -} - -// MustCallMethod calls method on IDispatch with parameters or panics. -func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { - r, err := CallMethod(disp, name, params...) - if err != nil { - panic(err.Error()) - } - return r -} - -// GetProperty retrieves property from IDispatch. -func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { - return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYGET, params) -} - -// MustGetProperty retrieves property from IDispatch or panics. -func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { - r, err := GetProperty(disp, name, params...) - if err != nil { - panic(err.Error()) - } - return r -} - -// PutProperty mutates property. -func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { - return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUT, params) -} - -// MustPutProperty mutates property or panics. -func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { - r, err := PutProperty(disp, name, params...) - if err != nil { - panic(err.Error()) - } - return r -} - -// PutPropertyRef mutates property reference. -func PutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { - return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUTREF, params) -} - -// MustPutPropertyRef mutates property reference or panics. -func MustPutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { - r, err := PutPropertyRef(disp, name, params...) - if err != nil { - panic(err.Error()) - } - return r -} - -func ForEach(disp *ole.IDispatch, f func(v *ole.VARIANT) error) error { - newEnum, err := disp.GetProperty("_NewEnum") - if err != nil { - return err - } - defer newEnum.Clear() - - enum, err := newEnum.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return err - } - defer enum.Release() - - for item, length, err := enum.Next(1); length > 0; item, length, err = enum.Next(1) { - if err != nil { - return err - } - if ferr := f(&item); ferr != nil { - return ferr - } - } - return nil -} diff --git a/vendor/github.com/go-ole/go-ole/safearray.go b/vendor/github.com/go-ole/go-ole/safearray.go deleted file mode 100644 index a5201b56c3..0000000000 --- a/vendor/github.com/go-ole/go-ole/safearray.go +++ /dev/null @@ -1,27 +0,0 @@ -// Package is meant to retrieve and process safe array data returned from COM. - -package ole - -// SafeArrayBound defines the SafeArray boundaries. -type SafeArrayBound struct { - Elements uint32 - LowerBound int32 -} - -// SafeArray is how COM handles arrays. -type SafeArray struct { - Dimensions uint16 - FeaturesFlag uint16 - ElementsSize uint32 - LocksAmount uint32 - Data uint32 - Bounds [16]byte -} - -// SAFEARRAY is obsolete, exists for backwards compatibility. -// Use SafeArray -type SAFEARRAY SafeArray - -// SAFEARRAYBOUND is obsolete, exists for backwards compatibility. -// Use SafeArrayBound -type SAFEARRAYBOUND SafeArrayBound diff --git a/vendor/github.com/go-ole/go-ole/safearray_func.go b/vendor/github.com/go-ole/go-ole/safearray_func.go deleted file mode 100644 index 0dee670ceb..0000000000 --- a/vendor/github.com/go-ole/go-ole/safearray_func.go +++ /dev/null @@ -1,211 +0,0 @@ -// +build !windows - -package ole - -import ( - "unsafe" -) - -// safeArrayAccessData returns raw array pointer. -// -// AKA: SafeArrayAccessData in Windows API. -func safeArrayAccessData(safearray *SafeArray) (uintptr, error) { - return uintptr(0), NewError(E_NOTIMPL) -} - -// safeArrayUnaccessData releases raw array. -// -// AKA: SafeArrayUnaccessData in Windows API. -func safeArrayUnaccessData(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayAllocData allocates SafeArray. -// -// AKA: SafeArrayAllocData in Windows API. -func safeArrayAllocData(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayAllocDescriptor allocates SafeArray. -// -// AKA: SafeArrayAllocDescriptor in Windows API. -func safeArrayAllocDescriptor(dimensions uint32) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayAllocDescriptorEx allocates SafeArray. -// -// AKA: SafeArrayAllocDescriptorEx in Windows API. -func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayCopy returns copy of SafeArray. -// -// AKA: SafeArrayCopy in Windows API. -func safeArrayCopy(original *SafeArray) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayCopyData duplicates SafeArray into another SafeArray object. -// -// AKA: SafeArrayCopyData in Windows API. -func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayCreate creates SafeArray. -// -// AKA: SafeArrayCreate in Windows API. -func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayCreateEx creates SafeArray. -// -// AKA: SafeArrayCreateEx in Windows API. -func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayCreateVector creates SafeArray. -// -// AKA: SafeArrayCreateVector in Windows API. -func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayCreateVectorEx creates SafeArray. -// -// AKA: SafeArrayCreateVectorEx in Windows API. -func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (*SafeArray, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayDestroy destroys SafeArray object. -// -// AKA: SafeArrayDestroy in Windows API. -func safeArrayDestroy(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayDestroyData destroys SafeArray object. -// -// AKA: SafeArrayDestroyData in Windows API. -func safeArrayDestroyData(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayDestroyDescriptor destroys SafeArray object. -// -// AKA: SafeArrayDestroyDescriptor in Windows API. -func safeArrayDestroyDescriptor(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayGetDim is the amount of dimensions in the SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetDim in Windows API. -func safeArrayGetDim(safearray *SafeArray) (*uint32, error) { - u := uint32(0) - return &u, NewError(E_NOTIMPL) -} - -// safeArrayGetElementSize is the element size in bytes. -// -// AKA: SafeArrayGetElemsize in Windows API. -func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) { - u := uint32(0) - return &u, NewError(E_NOTIMPL) -} - -// safeArrayGetElement retrieves element at given index. -func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error { - return NewError(E_NOTIMPL) -} - -// safeArrayGetElement retrieves element at given index and converts to string. -func safeArrayGetElementString(safearray *SafeArray, index int32) (string, error) { - return "", NewError(E_NOTIMPL) -} - -// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. -// -// AKA: SafeArrayGetIID in Windows API. -func safeArrayGetIID(safearray *SafeArray) (*GUID, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArrayGetLBound returns lower bounds of SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetLBound in Windows API. -func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int32, error) { - return int32(0), NewError(E_NOTIMPL) -} - -// safeArrayGetUBound returns upper bounds of SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetUBound in Windows API. -func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int32, error) { - return int32(0), NewError(E_NOTIMPL) -} - -// safeArrayGetVartype returns data type of SafeArray. -// -// AKA: SafeArrayGetVartype in Windows API. -func safeArrayGetVartype(safearray *SafeArray) (uint16, error) { - return uint16(0), NewError(E_NOTIMPL) -} - -// safeArrayLock locks SafeArray for reading to modify SafeArray. -// -// This must be called during some calls to ensure that another process does not -// read or write to the SafeArray during editing. -// -// AKA: SafeArrayLock in Windows API. -func safeArrayLock(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayUnlock unlocks SafeArray for reading. -// -// AKA: SafeArrayUnlock in Windows API. -func safeArrayUnlock(safearray *SafeArray) error { - return NewError(E_NOTIMPL) -} - -// safeArrayPutElement stores the data element at the specified location in the -// array. -// -// AKA: SafeArrayPutElement in Windows API. -func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) error { - return NewError(E_NOTIMPL) -} - -// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. -// -// AKA: SafeArrayGetRecordInfo in Windows API. -// -// XXX: Must implement IRecordInfo interface for this to return. -func safeArrayGetRecordInfo(safearray *SafeArray) (interface{}, error) { - return nil, NewError(E_NOTIMPL) -} - -// safeArraySetRecordInfo mutates IRecordInfo info for custom types. -// -// AKA: SafeArraySetRecordInfo in Windows API. -// -// XXX: Must implement IRecordInfo interface for this to return. -func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) error { - return NewError(E_NOTIMPL) -} diff --git a/vendor/github.com/go-ole/go-ole/safearray_windows.go b/vendor/github.com/go-ole/go-ole/safearray_windows.go deleted file mode 100644 index b48a2394d1..0000000000 --- a/vendor/github.com/go-ole/go-ole/safearray_windows.go +++ /dev/null @@ -1,337 +0,0 @@ -// +build windows - -package ole - -import ( - "unsafe" -) - -var ( - procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData") - procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData") - procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor") - procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx") - procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy") - procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData") - procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate") - procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx") - procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector") - procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx") - procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy") - procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData") - procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor") - procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim") - procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement") - procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize") - procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID") - procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound") - procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound") - procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype") - procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock") - procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex") - procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData") - procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock") - procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement") - //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO - //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO - procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo") - procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo") -) - -// safeArrayAccessData returns raw array pointer. -// -// AKA: SafeArrayAccessData in Windows API. -// Todo: Test -func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) { - err = convertHresultToError( - procSafeArrayAccessData.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&element)))) - return -} - -// safeArrayUnaccessData releases raw array. -// -// AKA: SafeArrayUnaccessData in Windows API. -func safeArrayUnaccessData(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayAllocData allocates SafeArray. -// -// AKA: SafeArrayAllocData in Windows API. -func safeArrayAllocData(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayAllocDescriptor allocates SafeArray. -// -// AKA: SafeArrayAllocDescriptor in Windows API. -func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) { - err = convertHresultToError( - procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray)))) - return -} - -// safeArrayAllocDescriptorEx allocates SafeArray. -// -// AKA: SafeArrayAllocDescriptorEx in Windows API. -func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (safearray *SafeArray, err error) { - err = convertHresultToError( - procSafeArrayAllocDescriptorEx.Call( - uintptr(variantType), - uintptr(dimensions), - uintptr(unsafe.Pointer(&safearray)))) - return -} - -// safeArrayCopy returns copy of SafeArray. -// -// AKA: SafeArrayCopy in Windows API. -func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) { - err = convertHresultToError( - procSafeArrayCopy.Call( - uintptr(unsafe.Pointer(original)), - uintptr(unsafe.Pointer(&safearray)))) - return -} - -// safeArrayCopyData duplicates SafeArray into another SafeArray object. -// -// AKA: SafeArrayCopyData in Windows API. -func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) { - err = convertHresultToError( - procSafeArrayCopyData.Call( - uintptr(unsafe.Pointer(original)), - uintptr(unsafe.Pointer(duplicate)))) - return -} - -// safeArrayCreate creates SafeArray. -// -// AKA: SafeArrayCreate in Windows API. -func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) { - sa, _, err := procSafeArrayCreate.Call( - uintptr(variantType), - uintptr(dimensions), - uintptr(unsafe.Pointer(bounds))) - safearray = (*SafeArray)(unsafe.Pointer(&sa)) - return -} - -// safeArrayCreateEx creates SafeArray. -// -// AKA: SafeArrayCreateEx in Windows API. -func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) { - sa, _, err := procSafeArrayCreateEx.Call( - uintptr(variantType), - uintptr(dimensions), - uintptr(unsafe.Pointer(bounds)), - extra) - safearray = (*SafeArray)(unsafe.Pointer(sa)) - return -} - -// safeArrayCreateVector creates SafeArray. -// -// AKA: SafeArrayCreateVector in Windows API. -func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (safearray *SafeArray, err error) { - sa, _, err := procSafeArrayCreateVector.Call( - uintptr(variantType), - uintptr(lowerBound), - uintptr(length)) - safearray = (*SafeArray)(unsafe.Pointer(sa)) - return -} - -// safeArrayCreateVectorEx creates SafeArray. -// -// AKA: SafeArrayCreateVectorEx in Windows API. -func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) { - sa, _, err := procSafeArrayCreateVectorEx.Call( - uintptr(variantType), - uintptr(lowerBound), - uintptr(length), - extra) - safearray = (*SafeArray)(unsafe.Pointer(sa)) - return -} - -// safeArrayDestroy destroys SafeArray object. -// -// AKA: SafeArrayDestroy in Windows API. -func safeArrayDestroy(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayDestroyData destroys SafeArray object. -// -// AKA: SafeArrayDestroyData in Windows API. -func safeArrayDestroyData(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayDestroyDescriptor destroys SafeArray object. -// -// AKA: SafeArrayDestroyDescriptor in Windows API. -func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayGetDim is the amount of dimensions in the SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetDim in Windows API. -func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) { - l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray))) - dimensions = (*uint32)(unsafe.Pointer(l)) - return -} - -// safeArrayGetElementSize is the element size in bytes. -// -// AKA: SafeArrayGetElemsize in Windows API. -func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) { - l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray))) - length = (*uint32)(unsafe.Pointer(l)) - return -} - -// safeArrayGetElement retrieves element at given index. -func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error { - return convertHresultToError( - procSafeArrayGetElement.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&index)), - uintptr(pv))) -} - -// safeArrayGetElementString retrieves element at given index and converts to string. -func safeArrayGetElementString(safearray *SafeArray, index int32) (str string, err error) { - var element *int16 - err = convertHresultToError( - procSafeArrayGetElement.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&index)), - uintptr(unsafe.Pointer(&element)))) - str = BstrToString(*(**uint16)(unsafe.Pointer(&element))) - SysFreeString(element) - return -} - -// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. -// -// AKA: SafeArrayGetIID in Windows API. -func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) { - err = convertHresultToError( - procSafeArrayGetIID.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&guid)))) - return -} - -// safeArrayGetLBound returns lower bounds of SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetLBound in Windows API. -func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int32, err error) { - err = convertHresultToError( - procSafeArrayGetLBound.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(dimension), - uintptr(unsafe.Pointer(&lowerBound)))) - return -} - -// safeArrayGetUBound returns upper bounds of SafeArray. -// -// SafeArrays may have multiple dimensions. Meaning, it could be -// multidimensional array. -// -// AKA: SafeArrayGetUBound in Windows API. -func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int32, err error) { - err = convertHresultToError( - procSafeArrayGetUBound.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(dimension), - uintptr(unsafe.Pointer(&upperBound)))) - return -} - -// safeArrayGetVartype returns data type of SafeArray. -// -// AKA: SafeArrayGetVartype in Windows API. -func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) { - err = convertHresultToError( - procSafeArrayGetVartype.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&varType)))) - return -} - -// safeArrayLock locks SafeArray for reading to modify SafeArray. -// -// This must be called during some calls to ensure that another process does not -// read or write to the SafeArray during editing. -// -// AKA: SafeArrayLock in Windows API. -func safeArrayLock(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayUnlock unlocks SafeArray for reading. -// -// AKA: SafeArrayUnlock in Windows API. -func safeArrayUnlock(safearray *SafeArray) (err error) { - err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray)))) - return -} - -// safeArrayPutElement stores the data element at the specified location in the -// array. -// -// AKA: SafeArrayPutElement in Windows API. -func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) (err error) { - err = convertHresultToError( - procSafeArrayPutElement.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&index)), - uintptr(unsafe.Pointer(element)))) - return -} - -// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. -// -// AKA: SafeArrayGetRecordInfo in Windows API. -// -// XXX: Must implement IRecordInfo interface for this to return. -func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) { - err = convertHresultToError( - procSafeArrayGetRecordInfo.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&recordInfo)))) - return -} - -// safeArraySetRecordInfo mutates IRecordInfo info for custom types. -// -// AKA: SafeArraySetRecordInfo in Windows API. -// -// XXX: Must implement IRecordInfo interface for this to return. -func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) { - err = convertHresultToError( - procSafeArraySetRecordInfo.Call( - uintptr(unsafe.Pointer(safearray)), - uintptr(unsafe.Pointer(&recordInfo)))) - return -} diff --git a/vendor/github.com/go-ole/go-ole/safearrayconversion.go b/vendor/github.com/go-ole/go-ole/safearrayconversion.go deleted file mode 100644 index 259f488ec7..0000000000 --- a/vendor/github.com/go-ole/go-ole/safearrayconversion.go +++ /dev/null @@ -1,140 +0,0 @@ -// Helper for converting SafeArray to array of objects. - -package ole - -import ( - "unsafe" -) - -type SafeArrayConversion struct { - Array *SafeArray -} - -func (sac *SafeArrayConversion) ToStringArray() (strings []string) { - totalElements, _ := sac.TotalElements(0) - strings = make([]string, totalElements) - - for i := int32(0); i < totalElements; i++ { - strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i) - } - - return -} - -func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) { - totalElements, _ := sac.TotalElements(0) - bytes = make([]byte, totalElements) - - for i := int32(0); i < totalElements; i++ { - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)])) - } - - return -} - -func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) { - totalElements, _ := sac.TotalElements(0) - values = make([]interface{}, totalElements) - vt, _ := safeArrayGetVartype(sac.Array) - - for i := int32(0); i < totalElements; i++ { - switch VT(vt) { - case VT_BOOL: - var v bool - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_I1: - var v int8 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_I2: - var v int16 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_I4: - var v int32 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_I8: - var v int64 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_UI1: - var v uint8 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_UI2: - var v uint16 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_UI4: - var v uint32 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_UI8: - var v uint64 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_R4: - var v float32 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_R8: - var v float64 - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_BSTR: - var v string - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v - case VT_VARIANT: - var v VARIANT - safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) - values[i] = v.Value() - default: - // TODO - } - } - - return -} - -func (sac *SafeArrayConversion) GetType() (varType uint16, err error) { - return safeArrayGetVartype(sac.Array) -} - -func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) { - return safeArrayGetDim(sac.Array) -} - -func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) { - return safeArrayGetElementSize(sac.Array) -} - -func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int32, err error) { - if index < 1 { - index = 1 - } - - // Get array bounds - var LowerBounds int32 - var UpperBounds int32 - - LowerBounds, err = safeArrayGetLBound(sac.Array, index) - if err != nil { - return - } - - UpperBounds, err = safeArrayGetUBound(sac.Array, index) - if err != nil { - return - } - - totalElements = UpperBounds - LowerBounds + 1 - return -} - -// Release Safe Array memory -func (sac *SafeArrayConversion) Release() { - safeArrayDestroy(sac.Array) -} diff --git a/vendor/github.com/go-ole/go-ole/safearrayslices.go b/vendor/github.com/go-ole/go-ole/safearrayslices.go deleted file mode 100644 index a9fa885f1d..0000000000 --- a/vendor/github.com/go-ole/go-ole/safearrayslices.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build windows - -package ole - -import ( - "unsafe" -) - -func safeArrayFromByteSlice(slice []byte) *SafeArray { - array, _ := safeArrayCreateVector(VT_UI1, 0, uint32(len(slice))) - - if array == nil { - panic("Could not convert []byte to SAFEARRAY") - } - - for i, v := range slice { - safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(&v))) - } - return array -} - -func safeArrayFromStringSlice(slice []string) *SafeArray { - array, _ := safeArrayCreateVector(VT_BSTR, 0, uint32(len(slice))) - - if array == nil { - panic("Could not convert []string to SAFEARRAY") - } - // SysAllocStringLen(s) - for i, v := range slice { - safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(SysAllocStringLen(v)))) - } - return array -} diff --git a/vendor/github.com/go-ole/go-ole/utility.go b/vendor/github.com/go-ole/go-ole/utility.go deleted file mode 100644 index 99ee82dc34..0000000000 --- a/vendor/github.com/go-ole/go-ole/utility.go +++ /dev/null @@ -1,101 +0,0 @@ -package ole - -import ( - "unicode/utf16" - "unsafe" -) - -// ClassIDFrom retrieves class ID whether given is program ID or application string. -// -// Helper that provides check against both Class ID from Program ID and Class ID from string. It is -// faster, if you know which you are using, to use the individual functions, but this will check -// against available functions for you. -func ClassIDFrom(programID string) (classID *GUID, err error) { - classID, err = CLSIDFromProgID(programID) - if err != nil { - classID, err = CLSIDFromString(programID) - if err != nil { - return - } - } - return -} - -// BytePtrToString converts byte pointer to a Go string. -func BytePtrToString(p *byte) string { - a := (*[10000]uint8)(unsafe.Pointer(p)) - i := 0 - for a[i] != 0 { - i++ - } - return string(a[:i]) -} - -// UTF16PtrToString is alias for LpOleStrToString. -// -// Kept for compatibility reasons. -func UTF16PtrToString(p *uint16) string { - return LpOleStrToString(p) -} - -// LpOleStrToString converts COM Unicode to Go string. -func LpOleStrToString(p *uint16) string { - if p == nil { - return "" - } - - length := lpOleStrLen(p) - a := make([]uint16, length) - - ptr := unsafe.Pointer(p) - - for i := 0; i < int(length); i++ { - a[i] = *(*uint16)(ptr) - ptr = unsafe.Pointer(uintptr(ptr) + 2) - } - - return string(utf16.Decode(a)) -} - -// BstrToString converts COM binary string to Go string. -func BstrToString(p *uint16) string { - if p == nil { - return "" - } - length := SysStringLen((*int16)(unsafe.Pointer(p))) - a := make([]uint16, length) - - ptr := unsafe.Pointer(p) - - for i := 0; i < int(length); i++ { - a[i] = *(*uint16)(ptr) - ptr = unsafe.Pointer(uintptr(ptr) + 2) - } - return string(utf16.Decode(a)) -} - -// lpOleStrLen returns the length of Unicode string. -func lpOleStrLen(p *uint16) (length int64) { - if p == nil { - return 0 - } - - ptr := unsafe.Pointer(p) - - for i := 0; ; i++ { - if 0 == *(*uint16)(ptr) { - length = int64(i) - break - } - ptr = unsafe.Pointer(uintptr(ptr) + 2) - } - return -} - -// convertHresultToError converts syscall to error, if call is unsuccessful. -func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) { - if hr != 0 { - err = NewError(hr) - } - return -} diff --git a/vendor/github.com/go-ole/go-ole/variables.go b/vendor/github.com/go-ole/go-ole/variables.go deleted file mode 100644 index ebe00f1cfc..0000000000 --- a/vendor/github.com/go-ole/go-ole/variables.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build windows - -package ole - -import ( - "syscall" -) - -var ( - modcombase = syscall.NewLazyDLL("combase.dll") - modkernel32, _ = syscall.LoadDLL("kernel32.dll") - modole32, _ = syscall.LoadDLL("ole32.dll") - modoleaut32, _ = syscall.LoadDLL("oleaut32.dll") - modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll") - moduser32, _ = syscall.LoadDLL("user32.dll") -) diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go deleted file mode 100644 index 967a23fea9..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant.go +++ /dev/null @@ -1,105 +0,0 @@ -package ole - -import "unsafe" - -// NewVariant returns new variant based on type and value. -func NewVariant(vt VT, val int64) VARIANT { - return VARIANT{VT: vt, Val: val} -} - -// ToIUnknown converts Variant to Unknown object. -func (v *VARIANT) ToIUnknown() *IUnknown { - if v.VT != VT_UNKNOWN { - return nil - } - return (*IUnknown)(unsafe.Pointer(uintptr(v.Val))) -} - -// ToIDispatch converts variant to dispatch object. -func (v *VARIANT) ToIDispatch() *IDispatch { - if v.VT != VT_DISPATCH { - return nil - } - return (*IDispatch)(unsafe.Pointer(uintptr(v.Val))) -} - -// ToArray converts variant to SafeArray helper. -func (v *VARIANT) ToArray() *SafeArrayConversion { - if v.VT != VT_SAFEARRAY { - if v.VT&VT_ARRAY == 0 { - return nil - } - } - var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val))) - return &SafeArrayConversion{safeArray} -} - -// ToString converts variant to Go string. -func (v *VARIANT) ToString() string { - if v.VT != VT_BSTR { - return "" - } - return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val))) -} - -// Clear the memory of variant object. -func (v *VARIANT) Clear() error { - return VariantClear(v) -} - -// Value returns variant value based on its type. -// -// Currently supported types: 2- and 4-byte integers, strings, bools. -// Note that 64-bit integers, datetimes, and other types are stored as strings -// and will be returned as strings. -// -// Needs to be further converted, because this returns an interface{}. -func (v *VARIANT) Value() interface{} { - switch v.VT { - case VT_I1: - return int8(v.Val) - case VT_UI1: - return uint8(v.Val) - case VT_I2: - return int16(v.Val) - case VT_UI2: - return uint16(v.Val) - case VT_I4: - return int32(v.Val) - case VT_UI4: - return uint32(v.Val) - case VT_I8: - return int64(v.Val) - case VT_UI8: - return uint64(v.Val) - case VT_INT: - return int(v.Val) - case VT_UINT: - return uint(v.Val) - case VT_INT_PTR: - return uintptr(v.Val) // TODO - case VT_UINT_PTR: - return uintptr(v.Val) - case VT_R4: - return *(*float32)(unsafe.Pointer(&v.Val)) - case VT_R8: - return *(*float64)(unsafe.Pointer(&v.Val)) - case VT_BSTR: - return v.ToString() - case VT_DATE: - // VT_DATE type will either return float64 or time.Time. - d := uint64(v.Val) - date, err := GetVariantDate(d) - if err != nil { - return float64(v.Val) - } - return date - case VT_UNKNOWN: - return v.ToIUnknown() - case VT_DISPATCH: - return v.ToIDispatch() - case VT_BOOL: - return v.Val != 0 - } - return nil -} diff --git a/vendor/github.com/go-ole/go-ole/variant_386.go b/vendor/github.com/go-ole/go-ole/variant_386.go deleted file mode 100644 index e73736bf39..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_386.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build 386 - -package ole - -type VARIANT struct { - VT VT // 2 - wReserved1 uint16 // 4 - wReserved2 uint16 // 6 - wReserved3 uint16 // 8 - Val int64 // 16 -} diff --git a/vendor/github.com/go-ole/go-ole/variant_amd64.go b/vendor/github.com/go-ole/go-ole/variant_amd64.go deleted file mode 100644 index dccdde1323..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_amd64.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build amd64 - -package ole - -type VARIANT struct { - VT VT // 2 - wReserved1 uint16 // 4 - wReserved2 uint16 // 6 - wReserved3 uint16 // 8 - Val int64 // 16 - _ [8]byte // 24 -} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_386.go b/vendor/github.com/go-ole/go-ole/variant_date_386.go deleted file mode 100644 index 1b970f63f5..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_date_386.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build windows,386 - -package ole - -import ( - "errors" - "syscall" - "time" - "unsafe" -) - -// GetVariantDate converts COM Variant Time value to Go time.Time. -func GetVariantDate(value uint64) (time.Time, error) { - var st syscall.Systemtime - v1 := uint32(value) - v2 := uint32(value >> 32) - r, _, _ := procVariantTimeToSystemTime.Call(uintptr(v1), uintptr(v2), uintptr(unsafe.Pointer(&st))) - if r != 0 { - return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil - } - return time.Now(), errors.New("Could not convert to time, passing current time.") -} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_amd64.go b/vendor/github.com/go-ole/go-ole/variant_date_amd64.go deleted file mode 100644 index 6952f1f0de..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_date_amd64.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build windows,amd64 - -package ole - -import ( - "errors" - "syscall" - "time" - "unsafe" -) - -// GetVariantDate converts COM Variant Time value to Go time.Time. -func GetVariantDate(value uint64) (time.Time, error) { - var st syscall.Systemtime - r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st))) - if r != 0 { - return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil - } - return time.Now(), errors.New("Could not convert to time, passing current time.") -} diff --git a/vendor/github.com/go-ole/go-ole/variant_ppc64le.go b/vendor/github.com/go-ole/go-ole/variant_ppc64le.go deleted file mode 100644 index 326427a7d1..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_ppc64le.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build ppc64le - -package ole - -type VARIANT struct { - VT VT // 2 - wReserved1 uint16 // 4 - wReserved2 uint16 // 6 - wReserved3 uint16 // 8 - Val int64 // 16 - _ [8]byte // 24 -} diff --git a/vendor/github.com/go-ole/go-ole/variant_s390x.go b/vendor/github.com/go-ole/go-ole/variant_s390x.go deleted file mode 100644 index 9874ca66b4..0000000000 --- a/vendor/github.com/go-ole/go-ole/variant_s390x.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build s390x - -package ole - -type VARIANT struct { - VT VT // 2 - wReserved1 uint16 // 4 - wReserved2 uint16 // 6 - wReserved3 uint16 // 8 - Val int64 // 16 - _ [8]byte // 24 -} diff --git a/vendor/github.com/go-ole/go-ole/vt_string.go b/vendor/github.com/go-ole/go-ole/vt_string.go deleted file mode 100644 index 729b4a04dd..0000000000 --- a/vendor/github.com/go-ole/go-ole/vt_string.go +++ /dev/null @@ -1,58 +0,0 @@ -// generated by stringer -output vt_string.go -type VT; DO NOT EDIT - -package ole - -import "fmt" - -const ( - _VT_name_0 = "VT_EMPTYVT_NULLVT_I2VT_I4VT_R4VT_R8VT_CYVT_DATEVT_BSTRVT_DISPATCHVT_ERRORVT_BOOLVT_VARIANTVT_UNKNOWNVT_DECIMAL" - _VT_name_1 = "VT_I1VT_UI1VT_UI2VT_UI4VT_I8VT_UI8VT_INTVT_UINTVT_VOIDVT_HRESULTVT_PTRVT_SAFEARRAYVT_CARRAYVT_USERDEFINEDVT_LPSTRVT_LPWSTR" - _VT_name_2 = "VT_RECORDVT_INT_PTRVT_UINT_PTR" - _VT_name_3 = "VT_FILETIMEVT_BLOBVT_STREAMVT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTVT_CFVT_CLSID" - _VT_name_4 = "VT_BSTR_BLOBVT_VECTOR" - _VT_name_5 = "VT_ARRAY" - _VT_name_6 = "VT_BYREF" - _VT_name_7 = "VT_RESERVED" - _VT_name_8 = "VT_ILLEGAL" -) - -var ( - _VT_index_0 = [...]uint8{0, 8, 15, 20, 25, 30, 35, 40, 47, 54, 65, 73, 80, 90, 100, 110} - _VT_index_1 = [...]uint8{0, 5, 11, 17, 23, 28, 34, 40, 47, 54, 64, 70, 82, 91, 105, 113, 122} - _VT_index_2 = [...]uint8{0, 9, 19, 30} - _VT_index_3 = [...]uint8{0, 11, 18, 27, 37, 55, 71, 85, 90, 98} - _VT_index_4 = [...]uint8{0, 12, 21} - _VT_index_5 = [...]uint8{0, 8} - _VT_index_6 = [...]uint8{0, 8} - _VT_index_7 = [...]uint8{0, 11} - _VT_index_8 = [...]uint8{0, 10} -) - -func (i VT) String() string { - switch { - case 0 <= i && i <= 14: - return _VT_name_0[_VT_index_0[i]:_VT_index_0[i+1]] - case 16 <= i && i <= 31: - i -= 16 - return _VT_name_1[_VT_index_1[i]:_VT_index_1[i+1]] - case 36 <= i && i <= 38: - i -= 36 - return _VT_name_2[_VT_index_2[i]:_VT_index_2[i+1]] - case 64 <= i && i <= 72: - i -= 64 - return _VT_name_3[_VT_index_3[i]:_VT_index_3[i+1]] - case 4095 <= i && i <= 4096: - i -= 4095 - return _VT_name_4[_VT_index_4[i]:_VT_index_4[i+1]] - case i == 8192: - return _VT_name_5 - case i == 16384: - return _VT_name_6 - case i == 32768: - return _VT_name_7 - case i == 65535: - return _VT_name_8 - default: - return fmt.Sprintf("VT(%d)", i) - } -} diff --git a/vendor/github.com/go-ole/go-ole/winrt.go b/vendor/github.com/go-ole/go-ole/winrt.go deleted file mode 100644 index 4e9eca7324..0000000000 --- a/vendor/github.com/go-ole/go-ole/winrt.go +++ /dev/null @@ -1,99 +0,0 @@ -// +build windows - -package ole - -import ( - "reflect" - "syscall" - "unicode/utf8" - "unsafe" -) - -var ( - procRoInitialize = modcombase.NewProc("RoInitialize") - procRoActivateInstance = modcombase.NewProc("RoActivateInstance") - procRoGetActivationFactory = modcombase.NewProc("RoGetActivationFactory") - procWindowsCreateString = modcombase.NewProc("WindowsCreateString") - procWindowsDeleteString = modcombase.NewProc("WindowsDeleteString") - procWindowsGetStringRawBuffer = modcombase.NewProc("WindowsGetStringRawBuffer") -) - -func RoInitialize(thread_type uint32) (err error) { - hr, _, _ := procRoInitialize.Call(uintptr(thread_type)) - if hr != 0 { - err = NewError(hr) - } - return -} - -func RoActivateInstance(clsid string) (ins *IInspectable, err error) { - hClsid, err := NewHString(clsid) - if err != nil { - return nil, err - } - defer DeleteHString(hClsid) - - hr, _, _ := procRoActivateInstance.Call( - uintptr(unsafe.Pointer(hClsid)), - uintptr(unsafe.Pointer(&ins))) - if hr != 0 { - err = NewError(hr) - } - return -} - -func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { - hClsid, err := NewHString(clsid) - if err != nil { - return nil, err - } - defer DeleteHString(hClsid) - - hr, _, _ := procRoGetActivationFactory.Call( - uintptr(unsafe.Pointer(hClsid)), - uintptr(unsafe.Pointer(iid)), - uintptr(unsafe.Pointer(&ins))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// HString is handle string for pointers. -type HString uintptr - -// NewHString returns a new HString for Go string. -func NewHString(s string) (hstring HString, err error) { - u16 := syscall.StringToUTF16Ptr(s) - len := uint32(utf8.RuneCountInString(s)) - hr, _, _ := procWindowsCreateString.Call( - uintptr(unsafe.Pointer(u16)), - uintptr(len), - uintptr(unsafe.Pointer(&hstring))) - if hr != 0 { - err = NewError(hr) - } - return -} - -// DeleteHString deletes HString. -func DeleteHString(hstring HString) (err error) { - hr, _, _ := procWindowsDeleteString.Call(uintptr(hstring)) - if hr != 0 { - err = NewError(hr) - } - return -} - -// String returns Go string value of HString. -func (h HString) String() string { - var u16buf uintptr - var u16len uint32 - u16buf, _, _ = procWindowsGetStringRawBuffer.Call( - uintptr(h), - uintptr(unsafe.Pointer(&u16len))) - - u16hdr := reflect.SliceHeader{Data: u16buf, Len: int(u16len), Cap: int(u16len)} - u16 := *(*[]uint16)(unsafe.Pointer(&u16hdr)) - return syscall.UTF16ToString(u16) -} diff --git a/vendor/github.com/go-ole/go-ole/winrt_doc.go b/vendor/github.com/go-ole/go-ole/winrt_doc.go deleted file mode 100644 index 52e6d74c9a..0000000000 --- a/vendor/github.com/go-ole/go-ole/winrt_doc.go +++ /dev/null @@ -1,36 +0,0 @@ -// +build !windows - -package ole - -// RoInitialize -func RoInitialize(thread_type uint32) (err error) { - return NewError(E_NOTIMPL) -} - -// RoActivateInstance -func RoActivateInstance(clsid string) (ins *IInspectable, err error) { - return nil, NewError(E_NOTIMPL) -} - -// RoGetActivationFactory -func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { - return nil, NewError(E_NOTIMPL) -} - -// HString is handle string for pointers. -type HString uintptr - -// NewHString returns a new HString for Go string. -func NewHString(s string) (hstring HString, err error) { - return HString(uintptr(0)), NewError(E_NOTIMPL) -} - -// DeleteHString deletes HString. -func DeleteHString(hstring HString) (err error) { - return NewError(E_NOTIMPL) -} - -// String returns Go string value of HString. -func (h HString) String() string { - return "" -} diff --git a/vendor/github.com/google/uuid/.travis.yml b/vendor/github.com/google/uuid/.travis.yml new file mode 100644 index 0000000000..d8156a60ba --- /dev/null +++ b/vendor/github.com/google/uuid/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4.3 + - 1.5.3 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md new file mode 100644 index 0000000000..04fdf09f13 --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# How to contribute + +We definitely welcome patches and contribution to this project! + +### Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +You may have already signed it for other Google projects. diff --git a/vendor/github.com/google/uuid/CONTRIBUTORS b/vendor/github.com/google/uuid/CONTRIBUTORS new file mode 100644 index 0000000000..b4bb97f6bc --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTORS @@ -0,0 +1,9 @@ +Paul Borman +bmatsuo +shawnps +theory +jboverfelt +dsymonds +cd1 +wallclockbuilder +dansouza diff --git a/vendor/github.com/google/uuid/LICENSE b/vendor/github.com/google/uuid/LICENSE new file mode 100644 index 0000000000..5dc68268d9 --- /dev/null +++ b/vendor/github.com/google/uuid/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md new file mode 100644 index 0000000000..9d92c11f16 --- /dev/null +++ b/vendor/github.com/google/uuid/README.md @@ -0,0 +1,19 @@ +# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) +The uuid package generates and inspects UUIDs based on +[RFC 4122](http://tools.ietf.org/html/rfc4122) +and DCE 1.1: Authentication and Security Services. + +This package is based on the github.com/pborman/uuid package (previously named +code.google.com/p/go-uuid). It differs from these earlier packages in that +a UUID is a 16 byte array rather than a byte slice. One loss due to this +change is the ability to represent an invalid UUID (vs a NIL UUID). + +###### Install +`go get github.com/google/uuid` + +###### Documentation +[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) + +Full `go doc` style documentation for the package can be viewed online without +installing this package by using the GoDoc site here: +http://godoc.org/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go new file mode 100644 index 0000000000..fa820b9d30 --- /dev/null +++ b/vendor/github.com/google/uuid/dce.go @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "fmt" + "os" +) + +// A Domain represents a Version 2 domain +type Domain byte + +// Domain constants for DCE Security (Version 2) UUIDs. +const ( + Person = Domain(0) + Group = Domain(1) + Org = Domain(2) +) + +// NewDCESecurity returns a DCE Security (Version 2) UUID. +// +// The domain should be one of Person, Group or Org. +// On a POSIX system the id should be the users UID for the Person +// domain and the users GID for the Group. The meaning of id for +// the domain Org or on non-POSIX systems is site defined. +// +// For a given domain/id pair the same token may be returned for up to +// 7 minutes and 10 seconds. +func NewDCESecurity(domain Domain, id uint32) (UUID, error) { + uuid, err := NewUUID() + if err == nil { + uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 + uuid[9] = byte(domain) + binary.BigEndian.PutUint32(uuid[0:], id) + } + return uuid, err +} + +// NewDCEPerson returns a DCE Security (Version 2) UUID in the person +// domain with the id returned by os.Getuid. +// +// NewDCESecurity(Person, uint32(os.Getuid())) +func NewDCEPerson() (UUID, error) { + return NewDCESecurity(Person, uint32(os.Getuid())) +} + +// NewDCEGroup returns a DCE Security (Version 2) UUID in the group +// domain with the id returned by os.Getgid. +// +// NewDCESecurity(Group, uint32(os.Getgid())) +func NewDCEGroup() (UUID, error) { + return NewDCESecurity(Group, uint32(os.Getgid())) +} + +// Domain returns the domain for a Version 2 UUID. Domains are only defined +// for Version 2 UUIDs. +func (uuid UUID) Domain() Domain { + return Domain(uuid[9]) +} + +// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2 +// UUIDs. +func (uuid UUID) ID() uint32 { + return binary.BigEndian.Uint32(uuid[0:4]) +} + +func (d Domain) String() string { + switch d { + case Person: + return "Person" + case Group: + return "Group" + case Org: + return "Org" + } + return fmt.Sprintf("Domain%d", int(d)) +} diff --git a/vendor/github.com/google/uuid/doc.go b/vendor/github.com/google/uuid/doc.go new file mode 100644 index 0000000000..5b8a4b9af8 --- /dev/null +++ b/vendor/github.com/google/uuid/doc.go @@ -0,0 +1,12 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package uuid generates and inspects UUIDs. +// +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to +// maps or compared directly. +package uuid diff --git a/vendor/github.com/google/uuid/go.mod b/vendor/github.com/google/uuid/go.mod new file mode 100644 index 0000000000..fc84cd79d4 --- /dev/null +++ b/vendor/github.com/google/uuid/go.mod @@ -0,0 +1 @@ +module github.com/google/uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go new file mode 100644 index 0000000000..b174616315 --- /dev/null +++ b/vendor/github.com/google/uuid/hash.go @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "crypto/md5" + "crypto/sha1" + "hash" +) + +// Well known namespace IDs and UUIDs +var ( + NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) + Nil UUID // empty UUID, all zeros +) + +// NewHash returns a new UUID derived from the hash of space concatenated with +// data generated by h. The hash should be at least 16 byte in length. The +// first 16 bytes of the hash are used to form the UUID. The version of the +// UUID will be the lower 4 bits of version. NewHash is used to implement +// NewMD5 and NewSHA1. +func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { + h.Reset() + h.Write(space[:]) + h.Write(data) + s := h.Sum(nil) + var uuid UUID + copy(uuid[:], s) + uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant + return uuid +} + +// NewMD5 returns a new MD5 (Version 3) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(md5.New(), space, data, 3) +func NewMD5(space UUID, data []byte) UUID { + return NewHash(md5.New(), space, data, 3) +} + +// NewSHA1 returns a new SHA1 (Version 5) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(sha1.New(), space, data, 5) +func NewSHA1(space UUID, data []byte) UUID { + return NewHash(sha1.New(), space, data, 5) +} diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go new file mode 100644 index 0000000000..7f9e0c6c0e --- /dev/null +++ b/vendor/github.com/google/uuid/marshal.go @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "fmt" + +// MarshalText implements encoding.TextMarshaler. +func (uuid UUID) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], uuid) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (uuid *UUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err == nil { + *uuid = id + } + return err +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (uuid UUID) MarshalBinary() ([]byte, error) { + return uuid[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (uuid *UUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(uuid[:], data) + return nil +} diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go new file mode 100644 index 0000000000..d651a2b061 --- /dev/null +++ b/vendor/github.com/google/uuid/node.go @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "sync" +) + +var ( + nodeMu sync.Mutex + ifname string // name of interface being used + nodeID [6]byte // hardware for version 1 UUIDs + zeroID [6]byte // nodeID with only 0's +) + +// NodeInterface returns the name of the interface from which the NodeID was +// derived. The interface "user" is returned if the NodeID was set by +// SetNodeID. +func NodeInterface() string { + defer nodeMu.Unlock() + nodeMu.Lock() + return ifname +} + +// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. +// If name is "" then the first usable interface found will be used or a random +// Node ID will be generated. If a named interface cannot be found then false +// is returned. +// +// SetNodeInterface never fails when name is "". +func SetNodeInterface(name string) bool { + defer nodeMu.Unlock() + nodeMu.Lock() + return setNodeInterface(name) +} + +func setNodeInterface(name string) bool { + iname, addr := getHardwareInterface(name) // null implementation for js + if iname != "" && addr != nil { + ifname = iname + copy(nodeID[:], addr) + return true + } + + // We found no interfaces with a valid hardware address. If name + // does not specify a specific interface generate a random Node ID + // (section 4.1.6) + if name == "" { + ifname = "random" + randomBits(nodeID[:]) + return true + } + return false +} + +// NodeID returns a slice of a copy of the current Node ID, setting the Node ID +// if not already set. +func NodeID() []byte { + defer nodeMu.Unlock() + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nid := nodeID + return nid[:] +} + +// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes +// of id are used. If id is less than 6 bytes then false is returned and the +// Node ID is not set. +func SetNodeID(id []byte) bool { + if len(id) < 6 { + return false + } + defer nodeMu.Unlock() + nodeMu.Lock() + copy(nodeID[:], id) + ifname = "user" + return true +} + +// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is +// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) NodeID() []byte { + var node [6]byte + copy(node[:], uuid[10:]) + return node[:] +} diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go new file mode 100644 index 0000000000..24b78edc90 --- /dev/null +++ b/vendor/github.com/google/uuid/node_js.go @@ -0,0 +1,12 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build js + +package uuid + +// getHardwareInterface returns nil values for the JS version of the code. +// This remvoves the "net" dependency, because it is not used in the browser. +// Using the "net" library inflates the size of the transpiled JS code by 673k bytes. +func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go new file mode 100644 index 0000000000..0cbbcddbd6 --- /dev/null +++ b/vendor/github.com/google/uuid/node_net.go @@ -0,0 +1,33 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js + +package uuid + +import "net" + +var interfaces []net.Interface // cached list of interfaces + +// getHardwareInterface returns the name and hardware address of interface name. +// If name is "" then the name and hardware address of one of the system's +// interfaces is returned. If no interfaces are found (name does not exist or +// there are no interfaces) then "", nil is returned. +// +// Only addresses of at least 6 bytes are returned. +func getHardwareInterface(name string) (string, []byte) { + if interfaces == nil { + var err error + interfaces, err = net.Interfaces() + if err != nil { + return "", nil + } + } + for _, ifs := range interfaces { + if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { + return ifs.Name, ifs.HardwareAddr + } + } + return "", nil +} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go new file mode 100644 index 0000000000..f326b54db3 --- /dev/null +++ b/vendor/github.com/google/uuid/sql.go @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements sql.Scanner so UUIDs can be read from databases transparently +// Currently, database types that map to string and []byte are supported. Please +// consult database-specific driver documentation for matching types. +func (uuid *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case nil: + return nil + + case string: + // if an empty UUID comes from a table, we return a null UUID + if src == "" { + return nil + } + + // see Parse for required string format + u, err := Parse(src) + if err != nil { + return fmt.Errorf("Scan: %v", err) + } + + *uuid = u + + case []byte: + // if an empty UUID comes from a table, we return a null UUID + if len(src) == 0 { + return nil + } + + // assumes a simple slice of bytes if 16 bytes + // otherwise attempts to parse + if len(src) != 16 { + return uuid.Scan(string(src)) + } + copy((*uuid)[:], src) + + default: + return fmt.Errorf("Scan: unable to scan type %T into UUID", src) + } + + return nil +} + +// Value implements sql.Valuer so that UUIDs can be written to databases +// transparently. Currently, UUIDs map to strings. Please consult +// database-specific driver documentation for matching types. +func (uuid UUID) Value() (driver.Value, error) { + return uuid.String(), nil +} diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go new file mode 100644 index 0000000000..e6ef06cdc8 --- /dev/null +++ b/vendor/github.com/google/uuid/time.go @@ -0,0 +1,123 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "sync" + "time" +) + +// A Time represents a time as the number of 100's of nanoseconds since 15 Oct +// 1582. +type Time int64 + +const ( + lillian = 2299160 // Julian day of 15 Oct 1582 + unix = 2440587 // Julian day of 1 Jan 1970 + epoch = unix - lillian // Days between epochs + g1582 = epoch * 86400 // seconds between epochs + g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs +) + +var ( + timeMu sync.Mutex + lasttime uint64 // last time we returned + clockSeq uint16 // clock sequence for this run + + timeNow = time.Now // for testing +) + +// UnixTime converts t the number of seconds and nanoseconds using the Unix +// epoch of 1 Jan 1970. +func (t Time) UnixTime() (sec, nsec int64) { + sec = int64(t - g1582ns100) + nsec = (sec % 10000000) * 100 + sec /= 10000000 + return sec, nsec +} + +// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and +// clock sequence as well as adjusting the clock sequence as needed. An error +// is returned if the current time cannot be determined. +func GetTime() (Time, uint16, error) { + defer timeMu.Unlock() + timeMu.Lock() + return getTime() +} + +func getTime() (Time, uint16, error) { + t := timeNow() + + // If we don't have a clock sequence already, set one. + if clockSeq == 0 { + setClockSequence(-1) + } + now := uint64(t.UnixNano()/100) + g1582ns100 + + // If time has gone backwards with this clock sequence then we + // increment the clock sequence + if now <= lasttime { + clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 + } + lasttime = now + return Time(now), clockSeq, nil +} + +// ClockSequence returns the current clock sequence, generating one if not +// already set. The clock sequence is only used for Version 1 UUIDs. +// +// The uuid package does not use global static storage for the clock sequence or +// the last time a UUID was generated. Unless SetClockSequence is used, a new +// random clock sequence is generated the first time a clock sequence is +// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) +func ClockSequence() int { + defer timeMu.Unlock() + timeMu.Lock() + return clockSequence() +} + +func clockSequence() int { + if clockSeq == 0 { + setClockSequence(-1) + } + return int(clockSeq & 0x3fff) +} + +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to +// -1 causes a new sequence to be generated. +func SetClockSequence(seq int) { + defer timeMu.Unlock() + timeMu.Lock() + setClockSequence(seq) +} + +func setClockSequence(seq int) { + if seq == -1 { + var b [2]byte + randomBits(b[:]) // clock sequence + seq = int(b[0])<<8 | int(b[1]) + } + oldSeq := clockSeq + clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant + if oldSeq != clockSeq { + lasttime = 0 + } +} + +// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in +// uuid. The time is only defined for version 1 and 2 UUIDs. +func (uuid UUID) Time() Time { + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + return Time(time) +} + +// ClockSequence returns the clock sequence encoded in uuid. +// The clock sequence is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) ClockSequence() int { + return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff +} diff --git a/vendor/github.com/google/uuid/util.go b/vendor/github.com/google/uuid/util.go new file mode 100644 index 0000000000..5ea6c73780 --- /dev/null +++ b/vendor/github.com/google/uuid/util.go @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// randomBits completely fills slice b with random data. +func randomBits(b []byte) { + if _, err := io.ReadFull(rander, b); err != nil { + panic(err.Error()) // rand should never fail + } +} + +// xvalues returns the value of a byte as a hexadecimal digit or 255. +var xvalues = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +} + +// xtob converts hex characters x1 and x2 into a byte. +func xtob(x1, x2 byte) (byte, bool) { + b1 := xvalues[x1] + b2 := xvalues[x2] + return (b1 << 4) | b2, b1 != 255 && b2 != 255 +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go new file mode 100644 index 0000000000..524404cc52 --- /dev/null +++ b/vendor/github.com/google/uuid/uuid.go @@ -0,0 +1,245 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "strings" +) + +// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC +// 4122. +type UUID [16]byte + +// A Version represents a UUID's version. +type Version byte + +// A Variant represents a UUID's variant. +type Variant byte + +// Constants returned by Variant. +const ( + Invalid = Variant(iota) // Invalid UUID + RFC4122 // The variant specified in RFC4122 + Reserved // Reserved, NCS backward compatibility. + Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future // Reserved for future definition. +) + +var rander = rand.Reader // random function + +// Parse decodes s into a UUID or returns an error. Both the standard UUID +// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the +// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex +// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. +func Parse(s string) (UUID, error) { + var uuid UUID + switch len(s) { + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36: + + // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: + if strings.ToLower(s[:9]) != "urn:uuid:" { + return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + case 36 + 2: + s = s[1:] + + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + case 32: + var ok bool + for i := range uuid { + uuid[i], ok = xtob(s[i*2], s[i*2+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + v, ok := xtob(s[x], s[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + var uuid UUID + switch len(b) { + case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { + return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) + } + b = b[9:] + case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + b = b[1:] + case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + var ok bool + for i := 0; i < 32; i += 2 { + uuid[i/2], ok = xtob(b[i], b[i+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + v, ok := xtob(b[x], b[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// MustParse is like Parse but panics if the string cannot be parsed. +// It simplifies safe initialization of global variables holding compiled UUIDs. +func MustParse(s string) UUID { + uuid, err := Parse(s) + if err != nil { + panic(`uuid: Parse(` + s + `): ` + err.Error()) + } + return uuid +} + +// FromBytes creates a new UUID from a byte slice. Returns an error if the slice +// does not have a length of 16. The bytes are copied from the slice. +func FromBytes(b []byte) (uuid UUID, err error) { + err = uuid.UnmarshalBinary(b) + return uuid, err +} + +// Must returns uuid if err is nil and panics otherwise. +func Must(uuid UUID, err error) UUID { + if err != nil { + panic(err) + } + return uuid +} + +// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// , or "" if uuid is invalid. +func (uuid UUID) String() string { + var buf [36]byte + encodeHex(buf[:], uuid) + return string(buf[:]) +} + +// URN returns the RFC 2141 URN form of uuid, +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. +func (uuid UUID) URN() string { + var buf [36 + 9]byte + copy(buf[:], "urn:uuid:") + encodeHex(buf[9:], uuid) + return string(buf[:]) +} + +func encodeHex(dst []byte, uuid UUID) { + hex.Encode(dst, uuid[:4]) + dst[8] = '-' + hex.Encode(dst[9:13], uuid[4:6]) + dst[13] = '-' + hex.Encode(dst[14:18], uuid[6:8]) + dst[18] = '-' + hex.Encode(dst[19:23], uuid[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], uuid[10:]) +} + +// Variant returns the variant encoded in uuid. +func (uuid UUID) Variant() Variant { + switch { + case (uuid[8] & 0xc0) == 0x80: + return RFC4122 + case (uuid[8] & 0xe0) == 0xc0: + return Microsoft + case (uuid[8] & 0xe0) == 0xe0: + return Future + default: + return Reserved + } +} + +// Version returns the version of uuid. +func (uuid UUID) Version() Version { + return Version(uuid[6] >> 4) +} + +func (v Version) String() string { + if v > 15 { + return fmt.Sprintf("BAD_VERSION_%d", v) + } + return fmt.Sprintf("VERSION_%d", v) +} + +func (v Variant) String() string { + switch v { + case RFC4122: + return "RFC4122" + case Reserved: + return "Reserved" + case Microsoft: + return "Microsoft" + case Future: + return "Future" + case Invalid: + return "Invalid" + } + return fmt.Sprintf("BadVariant%d", int(v)) +} + +// SetRand sets the random number generator to r, which implements io.Reader. +// If r.Read returns an error when the package requests random data then +// a panic will be issued. +// +// Calling SetRand with nil sets the random number generator to the default +// generator. +func SetRand(r io.Reader) { + if r == nil { + rander = rand.Reader + return + } + rander = r +} diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go new file mode 100644 index 0000000000..199a1ac654 --- /dev/null +++ b/vendor/github.com/google/uuid/version1.go @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" +) + +// NewUUID returns a Version 1 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewUUID returns nil. If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewUUID returns nil and an error. +// +// In most cases, New should be used. +func NewUUID() (UUID, error) { + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nodeMu.Unlock() + + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + timeLow := uint32(now & 0xffffffff) + timeMid := uint16((now >> 32) & 0xffff) + timeHi := uint16((now >> 48) & 0x0fff) + timeHi |= 0x1000 // Version 1 + + binary.BigEndian.PutUint32(uuid[0:], timeLow) + binary.BigEndian.PutUint16(uuid[4:], timeMid) + binary.BigEndian.PutUint16(uuid[6:], timeHi) + binary.BigEndian.PutUint16(uuid[8:], seq) + copy(uuid[10:], nodeID[:]) + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go new file mode 100644 index 0000000000..84af91c9f5 --- /dev/null +++ b/vendor/github.com/google/uuid/version4.go @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "io" + +// New creates a new random UUID or panics. New is equivalent to +// the expression +// +// uuid.Must(uuid.NewRandom()) +func New() UUID { + return Must(NewRandom()) +} + +// NewRandom returns a Random (Version 4) UUID. +// +// The strength of the UUIDs is based on the strength of the crypto/rand +// package. +// +// A note about uniqueness derived from the UUID Wikipedia entry: +// +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. +func NewRandom() (UUID, error) { + var uuid UUID + _, err := io.ReadFull(rander, uuid[:]) + if err != nil { + return Nil, err + } + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/gorilla/websocket/.travis.yml b/vendor/github.com/gorilla/websocket/.travis.yml deleted file mode 100644 index a49db51c43..0000000000 --- a/vendor/github.com/gorilla/websocket/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: 1.11.x - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md index 20e391f865..0827d059c1 100644 --- a/vendor/github.com/gorilla/websocket/README.md +++ b/vendor/github.com/gorilla/websocket/README.md @@ -1,11 +1,11 @@ # Gorilla WebSocket +[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) +[![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket) + Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. -[![Build Status](https://travis-ci.org/gorilla/websocket.svg?branch=master)](https://travis-ci.org/gorilla/websocket) -[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) - ### Documentation * [API Reference](http://godoc.org/github.com/gorilla/websocket) @@ -27,7 +27,7 @@ package API is stable. ### Protocol Compliance The Gorilla WebSocket package passes the server tests in the [Autobahn Test -Suite](http://autobahn.ws/testsuite) using the application in the [examples/autobahn +Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). ### Gorilla WebSocket compared with other packages @@ -40,7 +40,7 @@ subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn RFC 6455 Features -Passes Autobahn Test SuiteYesNo +Passes Autobahn Test SuiteYesNo Receive fragmented messageYesNo, see note 1 Send close messageYesNo Send pings and receive pongsYesNo diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go index 2e32fd506e..962c06a391 100644 --- a/vendor/github.com/gorilla/websocket/client.go +++ b/vendor/github.com/gorilla/websocket/client.go @@ -70,7 +70,7 @@ type Dialer struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration - // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer // size is zero, then a useful default size is used. The I/O buffer sizes // do not limit the size of the messages that can be sent or received. ReadBufferSize, WriteBufferSize int @@ -140,7 +140,7 @@ var nilDialer = *DefaultDialer // Use the response.Header to get the selected subprotocol // (Sec-WebSocket-Protocol) and cookies (Set-Cookie). // -// The context will be used in the request and in the Dialer +// The context will be used in the request and in the Dialer. // // If the WebSocket handshake fails, ErrBadHandshake is returned along with a // non-nil *http.Response so that callers can handle redirects, authentication, diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index d2a21c148b..6f17cd2998 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -260,10 +260,12 @@ type Conn struct { newCompressionWriter func(io.WriteCloser, int) io.WriteCloser // Read fields - reader io.ReadCloser // the current reader returned to the application - readErr error - br *bufio.Reader - readRemaining int64 // bytes remaining in current frame. + reader io.ReadCloser // the current reader returned to the application + readErr error + br *bufio.Reader + // bytes remaining in current frame. + // set setReadRemaining to safely update this value and prevent overflow + readRemaining int64 readFinal bool // true the current message has more frames. readLength int64 // Message size. readLimit int64 // Maximum message size. @@ -320,6 +322,17 @@ func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int, return c } +// setReadRemaining tracks the number of bytes remaining on the connection. If n +// overflows, an ErrReadLimit is returned. +func (c *Conn) setReadRemaining(n int64) error { + if n < 0 { + return ErrReadLimit + } + + c.readRemaining = n + return nil +} + // Subprotocol returns the negotiated protocol for the connection. func (c *Conn) Subprotocol() string { return c.subprotocol @@ -451,7 +464,8 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er return err } -func (c *Conn) prepWrite(messageType int) error { +// beginMessage prepares a connection and message writer for a new message. +func (c *Conn) beginMessage(mw *messageWriter, messageType int) error { // Close previous writer if not already closed by the application. It's // probably better to return an error in this situation, but we cannot // change this without breaking existing applications. @@ -471,6 +485,10 @@ func (c *Conn) prepWrite(messageType int) error { return err } + mw.c = c + mw.frameType = messageType + mw.pos = maxFrameHeaderSize + if c.writeBuf == nil { wpd, ok := c.writePool.Get().(writePoolData) if ok { @@ -491,16 +509,11 @@ func (c *Conn) prepWrite(messageType int) error { // All message types (TextMessage, BinaryMessage, CloseMessage, PingMessage and // PongMessage) are supported. func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { - if err := c.prepWrite(messageType); err != nil { + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { return nil, err } - - mw := &messageWriter{ - c: c, - frameType: messageType, - pos: maxFrameHeaderSize, - } - c.writer = mw + c.writer = &mw if c.newCompressionWriter != nil && c.enableWriteCompression && isData(messageType) { w := c.newCompressionWriter(c.writer, c.compressionLevel) mw.compress = true @@ -517,10 +530,16 @@ type messageWriter struct { err error } -func (w *messageWriter) fatal(err error) error { +func (w *messageWriter) endMessage(err error) error { if w.err != nil { - w.err = err - w.c.writer = nil + return err + } + c := w.c + w.err = err + c.writer = nil + if c.writePool != nil { + c.writePool.Put(writePoolData{buf: c.writeBuf}) + c.writeBuf = nil } return err } @@ -534,7 +553,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { // Check for invalid control frames. if isControl(w.frameType) && (!final || length > maxControlFramePayloadSize) { - return w.fatal(errInvalidControlFrame) + return w.endMessage(errInvalidControlFrame) } b0 := byte(w.frameType) @@ -579,7 +598,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { copy(c.writeBuf[maxFrameHeaderSize-4:], key[:]) maskBytes(key, 0, c.writeBuf[maxFrameHeaderSize:w.pos]) if len(extra) > 0 { - return c.writeFatal(errors.New("websocket: internal error, extra used in client mode")) + return w.endMessage(c.writeFatal(errors.New("websocket: internal error, extra used in client mode"))) } } @@ -600,15 +619,11 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { c.isWriting = false if err != nil { - return w.fatal(err) + return w.endMessage(err) } if final { - c.writer = nil - if c.writePool != nil { - c.writePool.Put(writePoolData{buf: c.writeBuf}) - c.writeBuf = nil - } + w.endMessage(errWriteClosed) return nil } @@ -706,11 +721,7 @@ func (w *messageWriter) Close() error { if w.err != nil { return w.err } - if err := w.flushFrame(true, nil); err != nil { - return err - } - w.err = errWriteClosed - return nil + return w.flushFrame(true, nil) } // WritePreparedMessage writes prepared message into connection. @@ -742,10 +753,10 @@ func (c *Conn) WriteMessage(messageType int, data []byte) error { if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) { // Fast path with no allocations and single frame. - if err := c.prepWrite(messageType); err != nil { + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { return err } - mw := messageWriter{c: c, frameType: messageType, pos: maxFrameHeaderSize} n := copy(c.writeBuf[mw.pos:], data) mw.pos += n data = data[n:] @@ -792,7 +803,7 @@ func (c *Conn) advanceFrame() (int, error) { final := p[0]&finalBit != 0 frameType := int(p[0] & 0xf) mask := p[1]&maskBit != 0 - c.readRemaining = int64(p[1] & 0x7f) + c.setReadRemaining(int64(p[1] & 0x7f)) c.readDecompress = false if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 { @@ -826,7 +837,17 @@ func (c *Conn) advanceFrame() (int, error) { return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType)) } - // 3. Read and parse frame length. + // 3. Read and parse frame length as per + // https://tools.ietf.org/html/rfc6455#section-5.2 + // + // The length of the "Payload data", in bytes: if 0-125, that is the payload + // length. + // - If 126, the following 2 bytes interpreted as a 16-bit unsigned + // integer are the payload length. + // - If 127, the following 8 bytes interpreted as + // a 64-bit unsigned integer (the most significant bit MUST be 0) are the + // payload length. Multibyte length quantities are expressed in network byte + // order. switch c.readRemaining { case 126: @@ -834,13 +855,19 @@ func (c *Conn) advanceFrame() (int, error) { if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint16(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint16(p))); err != nil { + return noFrame, err + } case 127: p, err := c.read(8) if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint64(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint64(p))); err != nil { + return noFrame, err + } } // 4. Handle frame masking. @@ -863,6 +890,12 @@ func (c *Conn) advanceFrame() (int, error) { if frameType == continuationFrame || frameType == TextMessage || frameType == BinaryMessage { c.readLength += c.readRemaining + // Don't allow readLength to overflow in the presence of a large readRemaining + // counter. + if c.readLength < 0 { + return noFrame, ErrReadLimit + } + if c.readLimit > 0 && c.readLength > c.readLimit { c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait)) return noFrame, ErrReadLimit @@ -876,7 +909,7 @@ func (c *Conn) advanceFrame() (int, error) { var payload []byte if c.readRemaining > 0 { payload, err = c.read(int(c.readRemaining)) - c.readRemaining = 0 + c.setReadRemaining(0) if err != nil { return noFrame, err } @@ -949,6 +982,7 @@ func (c *Conn) NextReader() (messageType int, r io.Reader, err error) { c.readErr = hideTempErr(err) break } + if frameType == TextMessage || frameType == BinaryMessage { c.messageReader = &messageReader{c} c.reader = c.messageReader @@ -989,7 +1023,9 @@ func (r *messageReader) Read(b []byte) (int, error) { if c.isServer { c.readMaskPos = maskBytes(c.readMaskKey, c.readMaskPos, b[:n]) } - c.readRemaining -= int64(n) + rem := c.readRemaining + rem -= int64(n) + c.setReadRemaining(rem) if c.readRemaining > 0 && c.readErr == io.EOF { c.readErr = errUnexpectedEOF } @@ -1041,7 +1077,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error { return c.conn.SetReadDeadline(t) } -// SetReadLimit sets the maximum size for a message read from the peer. If a +// SetReadLimit sets the maximum size in bytes for a message read from the peer. If a // message exceeds the limit, the connection sends a close message to the peer // and returns ErrReadLimit to the application. func (c *Conn) SetReadLimit(limit int64) { diff --git a/vendor/github.com/gorilla/websocket/doc.go b/vendor/github.com/gorilla/websocket/doc.go index dcce1a63c0..c6f4df8960 100644 --- a/vendor/github.com/gorilla/websocket/doc.go +++ b/vendor/github.com/gorilla/websocket/doc.go @@ -151,6 +151,53 @@ // checking. The application is responsible for checking the Origin header // before calling the Upgrade function. // +// Buffers +// +// Connections buffer network input and output to reduce the number +// of system calls when reading or writing messages. +// +// Write buffers are also used for constructing WebSocket frames. See RFC 6455, +// Section 5 for a discussion of message framing. A WebSocket frame header is +// written to the network each time a write buffer is flushed to the network. +// Decreasing the size of the write buffer can increase the amount of framing +// overhead on the connection. +// +// The buffer sizes in bytes are specified by the ReadBufferSize and +// WriteBufferSize fields in the Dialer and Upgrader. The Dialer uses a default +// size of 4096 when a buffer size field is set to zero. The Upgrader reuses +// buffers created by the HTTP server when a buffer size field is set to zero. +// The HTTP server buffers have a size of 4096 at the time of this writing. +// +// The buffer sizes do not limit the size of a message that can be read or +// written by a connection. +// +// Buffers are held for the lifetime of the connection by default. If the +// Dialer or Upgrader WriteBufferPool field is set, then a connection holds the +// write buffer only when writing a message. +// +// Applications should tune the buffer sizes to balance memory use and +// performance. Increasing the buffer size uses more memory, but can reduce the +// number of system calls to read or write the network. In the case of writing, +// increasing the buffer size can reduce the number of frame headers written to +// the network. +// +// Some guidelines for setting buffer parameters are: +// +// Limit the buffer sizes to the maximum expected message size. Buffers larger +// than the largest message do not provide any benefit. +// +// Depending on the distribution of message sizes, setting the buffer size to +// to a value less than the maximum expected message size can greatly reduce +// memory use with a small impact on performance. Here's an example: If 99% of +// the messages are smaller than 256 bytes and the maximum message size is 512 +// bytes, then a buffer size of 256 bytes will result in 1.01 more system calls +// than a buffer size of 512 bytes. The memory savings is 50%. +// +// A write buffer pool is useful when the application has a modest number +// writes over a large number of connections. when buffers are pooled, a larger +// buffer size has a reduced impact on total memory use and has the benefit of +// reducing system calls and frame overhead. +// // Compression EXPERIMENTAL // // Per message compression extensions (RFC 7692) are experimentally supported diff --git a/vendor/github.com/gorilla/websocket/go.mod b/vendor/github.com/gorilla/websocket/go.mod new file mode 100644 index 0000000000..1a7afd5028 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.mod @@ -0,0 +1,3 @@ +module github.com/gorilla/websocket + +go 1.12 diff --git a/vendor/github.com/gorilla/websocket/go.sum b/vendor/github.com/gorilla/websocket/go.sum new file mode 100644 index 0000000000..cf4fbbaa07 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= diff --git a/vendor/github.com/gorilla/websocket/join.go b/vendor/github.com/gorilla/websocket/join.go new file mode 100644 index 0000000000..c64f8c8290 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/join.go @@ -0,0 +1,42 @@ +// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "io" + "strings" +) + +// JoinMessages concatenates received messages to create a single io.Reader. +// The string term is appended to each message. The returned reader does not +// support concurrent calls to the Read method. +func JoinMessages(c *Conn, term string) io.Reader { + return &joinReader{c: c, term: term} +} + +type joinReader struct { + c *Conn + term string + r io.Reader +} + +func (r *joinReader) Read(p []byte) (int, error) { + if r.r == nil { + var err error + _, r.r, err = r.c.NextReader() + if err != nil { + return 0, err + } + if r.term != "" { + r.r = io.MultiReader(r.r, strings.NewReader(r.term)) + } + } + n, err := r.r.Read(p) + if err == io.EOF { + err = nil + r.r = nil + } + return n, err +} diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go index bf2478e430..e87a8c9f0c 100644 --- a/vendor/github.com/gorilla/websocket/proxy.go +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -22,18 +22,18 @@ func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { func init() { proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { - return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil + return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil }) } type httpProxyDialer struct { - proxyURL *url.URL - fowardDial func(network, addr string) (net.Conn, error) + proxyURL *url.URL + forwardDial func(network, addr string) (net.Conn, error) } func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { hostPort, _ := hostPortNoPort(hpd.proxyURL) - conn, err := hpd.fowardDial(network, hostPort) + conn, err := hpd.forwardDial(network, hostPort) if err != nil { return nil, err } diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go index a761824b33..887d558918 100644 --- a/vendor/github.com/gorilla/websocket/server.go +++ b/vendor/github.com/gorilla/websocket/server.go @@ -27,7 +27,7 @@ type Upgrader struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration - // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer // size is zero, then buffers allocated by the HTTP server are used. The // I/O buffer sizes do not limit the size of the messages that can be sent // or received. @@ -153,7 +153,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade challengeKey := r.Header.Get("Sec-Websocket-Key") if challengeKey == "" { - return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: `Sec-WebSocket-Key' header is missing or blank") + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") } subprotocol := u.selectSubprotocol(r, responseHeader) diff --git a/vendor/github.com/gorilla/websocket/util.go b/vendor/github.com/gorilla/websocket/util.go index 354001e1ed..7bf2f66c67 100644 --- a/vendor/github.com/gorilla/websocket/util.go +++ b/vendor/github.com/gorilla/websocket/util.go @@ -31,68 +31,113 @@ func generateChallengeKey() (string, error) { return base64.StdEncoding.EncodeToString(p), nil } -// Octet types from RFC 2616. -var octetTypes [256]byte - -const ( - isTokenOctet = 1 << iota - isSpaceOctet -) - -func init() { - // From RFC 2616 - // - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t byte - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { - t |= isSpaceOctet - } - if isChar && !isCtl && !isSeparator { - t |= isTokenOctet - } - octetTypes[c] = t - } +// Token octets per RFC 2616. +var isTokenOctet = [256]bool{ + '!': true, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '*': true, + '+': true, + '-': true, + '.': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'W': true, + 'V': true, + 'X': true, + 'Y': true, + 'Z': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '|': true, + '~': true, } +// skipSpace returns a slice of the string s with all leading RFC 2616 linear +// whitespace removed. func skipSpace(s string) (rest string) { i := 0 for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpaceOctet == 0 { + if b := s[i]; b != ' ' && b != '\t' { break } } return s[i:] } +// nextToken returns the leading RFC 2616 token of s and the string following +// the token. func nextToken(s string) (token, rest string) { i := 0 for ; i < len(s); i++ { - if octetTypes[s[i]]&isTokenOctet == 0 { + if !isTokenOctet[s[i]] { break } } return s[:i], s[i:] } +// nextTokenOrQuoted returns the leading token or quoted string per RFC 2616 +// and the string following the token or quoted string. func nextTokenOrQuoted(s string) (value string, rest string) { if !strings.HasPrefix(s, "\"") { return nextToken(s) @@ -128,7 +173,8 @@ func nextTokenOrQuoted(s string) (value string, rest string) { return "", "" } -// equalASCIIFold returns true if s is equal to t with ASCII case folding. +// equalASCIIFold returns true if s is equal to t with ASCII case folding as +// defined in RFC 4790. func equalASCIIFold(s, t string) bool { for s != "" && t != "" { sr, size := utf8.DecodeRuneInString(s) diff --git a/vendor/github.com/huin/goupnp/.gitignore b/vendor/github.com/huin/goupnp/.gitignore index 09ef375e89..7a6e0ebe39 100644 --- a/vendor/github.com/huin/goupnp/.gitignore +++ b/vendor/github.com/huin/goupnp/.gitignore @@ -1 +1,2 @@ -/gotasks/specs +*.zip +*.sublime-workspace \ No newline at end of file diff --git a/vendor/github.com/huin/goupnp/LICENSE b/vendor/github.com/huin/goupnp/LICENSE index 252e3d6397..c5a45bcbf6 100644 --- a/vendor/github.com/huin/goupnp/LICENSE +++ b/vendor/github.com/huin/goupnp/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013, John Beisley +Copyright (c) 2013, John Beisley All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/vendor/github.com/huin/goupnp/README.md b/vendor/github.com/huin/goupnp/README.md index 433ba5c682..7c63903aeb 100644 --- a/vendor/github.com/huin/goupnp/README.md +++ b/vendor/github.com/huin/goupnp/README.md @@ -25,15 +25,19 @@ Core components: Regenerating dcps generated source code: ---------------------------------------- -1. Install gotasks: `go get -u github.com/jingweno/gotask` -2. Change to the gotasks directory: `cd gotasks` -3. Run specgen task: `gotask specgen` +1. Build code generator: + + `go get -u github.com/huin/goupnp/cmd/goupnpdcpgen` + +2. Regenerate the code: + + `go generate ./...` Supporting additional UPnP devices and services: ------------------------------------------------ Supporting additional services is, in the trivial case, simply a matter of -adding the service to the `dcpMetadata` whitelist in `gotasks/specgen_task.go`, +adding the service to the `dcpMetadata` whitelist in `cmd/goupnpdcpgen/metadata.go`, regenerating the source code (see above), and committing that source code. However, it would be helpful if anyone needing such a service could test the diff --git a/vendor/github.com/huin/goupnp/dcps/internetgateway1/gen.go b/vendor/github.com/huin/goupnp/dcps/internetgateway1/gen.go new file mode 100644 index 0000000000..2b146a345d --- /dev/null +++ b/vendor/github.com/huin/goupnp/dcps/internetgateway1/gen.go @@ -0,0 +1,2 @@ +//go:generate goupnpdcpgen -dcp_name internetgateway1 +package internetgateway1 diff --git a/vendor/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go b/vendor/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go index 1e0802cd4e..e9335047c8 100644 --- a/vendor/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go +++ b/vendor/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go @@ -5,7 +5,9 @@ // Typically, use one of the New* functions to create clients for services. package internetgateway1 -// Generated file - do not edit by hand. See README.md +// *********************************************************** +// GENERATED FILE - DO NOT EDIT BY HAND. See README.md +// *********************************************************** import ( "net/url" @@ -388,7 +390,6 @@ func (client *LANHostConfigManagement1) SetAddressRange(NewMinAddress string, Ne // Request structure. request := &struct { NewMinAddress string - NewMaxAddress string }{} // BEGIN Marshal arguments into request. @@ -425,7 +426,6 @@ func (client *LANHostConfigManagement1) GetAddressRange() (NewMinAddress string, // Response structure. response := &struct { NewMinAddress string - NewMaxAddress string }{} @@ -790,8 +790,7 @@ func (client *WANCableLinkConfig1) GetCableLinkConfigInfo() (NewCableLinkConfigS // Response structure. response := &struct { NewCableLinkConfigState string - - NewLinkType string + NewLinkType string }{} // Perform the SOAP call. @@ -1180,13 +1179,10 @@ func (client *WANCommonInterfaceConfig1) GetCommonLinkProperties() (NewWANAccess // Response structure. response := &struct { - NewWANAccessType string - - NewLayer1UpstreamMaxBitRate string - + NewWANAccessType string + NewLayer1UpstreamMaxBitRate string NewLayer1DownstreamMaxBitRate string - - NewPhysicalLinkStatus string + NewPhysicalLinkStatus string }{} // Perform the SOAP call. @@ -1268,7 +1264,7 @@ func (client *WANCommonInterfaceConfig1) GetMaximumActiveConnections() (NewMaxim return } -func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent uint32, err error) { +func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent uint64, err error) { // Request structure. request := interface{}(nil) // BEGIN Marshal arguments into request. @@ -1287,14 +1283,14 @@ func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent // BEGIN Unmarshal arguments from response. - if NewTotalBytesSent, err = soap.UnmarshalUi4(response.NewTotalBytesSent); err != nil { + if NewTotalBytesSent, err = soap.UnmarshalUi8(response.NewTotalBytesSent); err != nil { return } // END Unmarshal arguments from response. return } -func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesReceived uint32, err error) { +func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesReceived uint64, err error) { // Request structure. request := interface{}(nil) // BEGIN Marshal arguments into request. @@ -1313,7 +1309,7 @@ func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesR // BEGIN Unmarshal arguments from response. - if NewTotalBytesReceived, err = soap.UnmarshalUi4(response.NewTotalBytesReceived); err != nil { + if NewTotalBytesReceived, err = soap.UnmarshalUi8(response.NewTotalBytesReceived); err != nil { return } // END Unmarshal arguments from response. @@ -1387,7 +1383,6 @@ func (client *WANCommonInterfaceConfig1) GetActiveConnection(NewActiveConnection // Response structure. response := &struct { NewActiveConnDeviceContainer string - NewActiveConnectionServiceID string }{} @@ -1507,8 +1502,7 @@ func (client *WANDSLLinkConfig1) GetDSLLinkInfo() (NewLinkType string, NewLinkSt // Response structure. response := &struct { - NewLinkType string - + NewLinkType string NewLinkStatus string }{} @@ -1926,8 +1920,7 @@ func (client *WANIPConnection1) GetConnectionTypeInfo() (NewConnectionType strin // Response structure. response := &struct { - NewConnectionType string - + NewConnectionType string NewPossibleConnectionTypes string }{} @@ -2104,11 +2097,9 @@ func (client *WANIPConnection1) GetStatusInfo() (NewConnectionStatus string, New // Response structure. response := &struct { - NewConnectionStatus string - + NewConnectionStatus string NewLastConnectionError string - - NewUptime string + NewUptime string }{} // Perform the SOAP call. @@ -2219,8 +2210,7 @@ func (client *WANIPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewNA // Response structure. response := &struct { NewRSIPAvailable string - - NewNATEnabled string + NewNATEnabled string }{} // Perform the SOAP call. @@ -2258,21 +2248,14 @@ func (client *WANIPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex u // Response structure. response := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -2318,11 +2301,9 @@ func (client *WANIPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex u func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -2339,15 +2320,11 @@ func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string // Response structure. response := &struct { - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -2384,21 +2361,14 @@ func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string func (client *WANIPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -2450,11 +2420,9 @@ func (client *WANIPConnection1) AddPortMapping(NewRemoteHost string, NewExternal func (client *WANIPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -2578,10 +2546,8 @@ func (client *WANPOTSLinkConfig1) SetISPInfo(NewISPPhoneNumber string, NewISPInf // Request structure. request := &struct { NewISPPhoneNumber string - - NewISPInfo string - - NewLinkType string + NewISPInfo string + NewLinkType string }{} // BEGIN Marshal arguments into request. @@ -2613,8 +2579,7 @@ func (client *WANPOTSLinkConfig1) SetISPInfo(NewISPPhoneNumber string, NewISPInf func (client *WANPOTSLinkConfig1) SetCallRetryInfo(NewNumberOfRetries uint32, NewDelayBetweenRetries uint32) (err error) { // Request structure. request := &struct { - NewNumberOfRetries string - + NewNumberOfRetries string NewDelayBetweenRetries string }{} // BEGIN Marshal arguments into request. @@ -2655,10 +2620,8 @@ func (client *WANPOTSLinkConfig1) GetISPInfo() (NewISPPhoneNumber string, NewISP // Response structure. response := &struct { NewISPPhoneNumber string - - NewISPInfo string - - NewLinkType string + NewISPInfo string + NewLinkType string }{} // Perform the SOAP call. @@ -2690,8 +2653,7 @@ func (client *WANPOTSLinkConfig1) GetCallRetryInfo() (NewNumberOfRetries uint32, // Response structure. response := &struct { - NewNumberOfRetries string - + NewNumberOfRetries string NewDelayBetweenRetries string }{} @@ -2941,8 +2903,7 @@ func (client *WANPPPConnection1) GetConnectionTypeInfo() (NewConnectionType stri // Response structure. response := &struct { - NewConnectionType string - + NewConnectionType string NewPossibleConnectionTypes string }{} @@ -2967,7 +2928,6 @@ func (client *WANPPPConnection1) ConfigureConnection(NewUserName string, NewPass // Request structure. request := &struct { NewUserName string - NewPassword string }{} // BEGIN Marshal arguments into request. @@ -3150,11 +3110,9 @@ func (client *WANPPPConnection1) GetStatusInfo() (NewConnectionStatus string, Ne // Response structure. response := &struct { - NewConnectionStatus string - + NewConnectionStatus string NewLastConnectionError string - - NewUptime string + NewUptime string }{} // Perform the SOAP call. @@ -3186,8 +3144,7 @@ func (client *WANPPPConnection1) GetLinkLayerMaxBitRates() (NewUpstreamMaxBitRat // Response structure. response := &struct { - NewUpstreamMaxBitRate string - + NewUpstreamMaxBitRate string NewDownstreamMaxBitRate string }{} @@ -3426,8 +3383,7 @@ func (client *WANPPPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewN // Response structure. response := &struct { NewRSIPAvailable string - - NewNATEnabled string + NewNATEnabled string }{} // Perform the SOAP call. @@ -3465,21 +3421,14 @@ func (client *WANPPPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex // Response structure. response := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -3525,11 +3474,9 @@ func (client *WANPPPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -3546,15 +3493,11 @@ func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost strin // Response structure. response := &struct { - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -3591,21 +3534,14 @@ func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost strin func (client *WANPPPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -3657,11 +3593,9 @@ func (client *WANPPPConnection1) AddPortMapping(NewRemoteHost string, NewExterna func (client *WANPPPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. diff --git a/vendor/github.com/huin/goupnp/dcps/internetgateway2/gen.go b/vendor/github.com/huin/goupnp/dcps/internetgateway2/gen.go new file mode 100644 index 0000000000..752058b412 --- /dev/null +++ b/vendor/github.com/huin/goupnp/dcps/internetgateway2/gen.go @@ -0,0 +1,2 @@ +//go:generate goupnpdcpgen -dcp_name internetgateway2 +package internetgateway2 diff --git a/vendor/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go b/vendor/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go index 2d67a4a2e2..4eb5f61052 100644 --- a/vendor/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go +++ b/vendor/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go @@ -5,7 +5,9 @@ // Typically, use one of the New* functions to create clients for services. package internetgateway2 -// Generated file - do not edit by hand. See README.md +// *********************************************************** +// GENERATED FILE - DO NOT EDIT BY HAND. See README.md +// *********************************************************** import ( "net/url" @@ -107,8 +109,7 @@ func (client *DeviceProtection1) SendSetupMessage(ProtocolType string, InMessage // Request structure. request := &struct { ProtocolType string - - InMessage string + InMessage string }{} // BEGIN Marshal arguments into request. @@ -194,10 +195,8 @@ func (client *DeviceProtection1) GetAssignedRoles() (RoleList string, err error) func (client *DeviceProtection1) GetRolesForAction(DeviceUDN string, ServiceId string, ActionName string) (RoleList string, RestrictedRoleList string, err error) { // Request structure. request := &struct { - DeviceUDN string - - ServiceId string - + DeviceUDN string + ServiceId string ActionName string }{} // BEGIN Marshal arguments into request. @@ -215,8 +214,7 @@ func (client *DeviceProtection1) GetRolesForAction(DeviceUDN string, ServiceId s // Response structure. response := &struct { - RoleList string - + RoleList string RestrictedRoleList string }{} @@ -241,8 +239,7 @@ func (client *DeviceProtection1) GetUserLoginChallenge(ProtocolType string, Name // Request structure. request := &struct { ProtocolType string - - Name string + Name string }{} // BEGIN Marshal arguments into request. @@ -256,8 +253,7 @@ func (client *DeviceProtection1) GetUserLoginChallenge(ProtocolType string, Name // Response structure. response := &struct { - Salt string - + Salt string Challenge string }{} @@ -281,10 +277,8 @@ func (client *DeviceProtection1) GetUserLoginChallenge(ProtocolType string, Name func (client *DeviceProtection1) UserLogin(ProtocolType string, Challenge []byte, Authenticator []byte) (err error) { // Request structure. request := &struct { - ProtocolType string - - Challenge string - + ProtocolType string + Challenge string Authenticator string }{} // BEGIN Marshal arguments into request. @@ -422,12 +416,9 @@ func (client *DeviceProtection1) SetUserLoginPassword(ProtocolType string, Name // Request structure. request := &struct { ProtocolType string - - Name string - - Stored string - - Salt string + Name string + Stored string + Salt string }{} // BEGIN Marshal arguments into request. @@ -463,7 +454,6 @@ func (client *DeviceProtection1) AddRolesForIdentity(Identity string, RoleList s // Request structure. request := &struct { Identity string - RoleList string }{} // BEGIN Marshal arguments into request. @@ -494,7 +484,6 @@ func (client *DeviceProtection1) RemoveRolesForIdentity(Identity string, RoleLis // Request structure. request := &struct { Identity string - RoleList string }{} // BEGIN Marshal arguments into request. @@ -871,7 +860,6 @@ func (client *LANHostConfigManagement1) SetAddressRange(NewMinAddress string, Ne // Request structure. request := &struct { NewMinAddress string - NewMaxAddress string }{} // BEGIN Marshal arguments into request. @@ -908,7 +896,6 @@ func (client *LANHostConfigManagement1) GetAddressRange() (NewMinAddress string, // Response structure. response := &struct { NewMinAddress string - NewMaxAddress string }{} @@ -1273,8 +1260,7 @@ func (client *WANCableLinkConfig1) GetCableLinkConfigInfo() (NewCableLinkConfigS // Response structure. response := &struct { NewCableLinkConfigState string - - NewLinkType string + NewLinkType string }{} // Perform the SOAP call. @@ -1663,13 +1649,10 @@ func (client *WANCommonInterfaceConfig1) GetCommonLinkProperties() (NewWANAccess // Response structure. response := &struct { - NewWANAccessType string - - NewLayer1UpstreamMaxBitRate string - + NewWANAccessType string + NewLayer1UpstreamMaxBitRate string NewLayer1DownstreamMaxBitRate string - - NewPhysicalLinkStatus string + NewPhysicalLinkStatus string }{} // Perform the SOAP call. @@ -1751,7 +1734,7 @@ func (client *WANCommonInterfaceConfig1) GetMaximumActiveConnections() (NewMaxim return } -func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent uint32, err error) { +func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent uint64, err error) { // Request structure. request := interface{}(nil) // BEGIN Marshal arguments into request. @@ -1770,14 +1753,14 @@ func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent // BEGIN Unmarshal arguments from response. - if NewTotalBytesSent, err = soap.UnmarshalUi4(response.NewTotalBytesSent); err != nil { + if NewTotalBytesSent, err = soap.UnmarshalUi8(response.NewTotalBytesSent); err != nil { return } // END Unmarshal arguments from response. return } -func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesReceived uint32, err error) { +func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesReceived uint64, err error) { // Request structure. request := interface{}(nil) // BEGIN Marshal arguments into request. @@ -1796,7 +1779,7 @@ func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesR // BEGIN Unmarshal arguments from response. - if NewTotalBytesReceived, err = soap.UnmarshalUi4(response.NewTotalBytesReceived); err != nil { + if NewTotalBytesReceived, err = soap.UnmarshalUi8(response.NewTotalBytesReceived); err != nil { return } // END Unmarshal arguments from response. @@ -1870,7 +1853,6 @@ func (client *WANCommonInterfaceConfig1) GetActiveConnection(NewActiveConnection // Response structure. response := &struct { NewActiveConnDeviceContainer string - NewActiveConnectionServiceID string }{} @@ -1990,8 +1972,7 @@ func (client *WANDSLLinkConfig1) GetDSLLinkInfo() (NewLinkType string, NewLinkSt // Response structure. response := &struct { - NewLinkType string - + NewLinkType string NewLinkStatus string }{} @@ -2409,8 +2390,7 @@ func (client *WANIPConnection1) GetConnectionTypeInfo() (NewConnectionType strin // Response structure. response := &struct { - NewConnectionType string - + NewConnectionType string NewPossibleConnectionTypes string }{} @@ -2587,11 +2567,9 @@ func (client *WANIPConnection1) GetStatusInfo() (NewConnectionStatus string, New // Response structure. response := &struct { - NewConnectionStatus string - + NewConnectionStatus string NewLastConnectionError string - - NewUptime string + NewUptime string }{} // Perform the SOAP call. @@ -2702,8 +2680,7 @@ func (client *WANIPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewNA // Response structure. response := &struct { NewRSIPAvailable string - - NewNATEnabled string + NewNATEnabled string }{} // Perform the SOAP call. @@ -2741,21 +2718,14 @@ func (client *WANIPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex u // Response structure. response := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -2801,11 +2771,9 @@ func (client *WANIPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex u func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -2822,15 +2790,11 @@ func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string // Response structure. response := &struct { - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -2867,21 +2831,14 @@ func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string func (client *WANIPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -2933,11 +2890,9 @@ func (client *WANIPConnection1) AddPortMapping(NewRemoteHost string, NewExternal func (client *WANIPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -3087,8 +3042,7 @@ func (client *WANIPConnection2) GetConnectionTypeInfo() (NewConnectionType strin // Response structure. response := &struct { - NewConnectionType string - + NewConnectionType string NewPossibleConnectionTypes string }{} @@ -3265,11 +3219,9 @@ func (client *WANIPConnection2) GetStatusInfo() (NewConnectionStatus string, New // Response structure. response := &struct { - NewConnectionStatus string - + NewConnectionStatus string NewLastConnectionError string - - NewUptime string + NewUptime string }{} // Perform the SOAP call. @@ -3380,8 +3332,7 @@ func (client *WANIPConnection2) GetNATRSIPStatus() (NewRSIPAvailable bool, NewNA // Response structure. response := &struct { NewRSIPAvailable string - - NewNATEnabled string + NewNATEnabled string }{} // Perform the SOAP call. @@ -3419,21 +3370,14 @@ func (client *WANIPConnection2) GetGenericPortMappingEntry(NewPortMappingIndex u // Response structure. response := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -3479,11 +3423,9 @@ func (client *WANIPConnection2) GetGenericPortMappingEntry(NewPortMappingIndex u func (client *WANIPConnection2) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -3500,15 +3442,11 @@ func (client *WANIPConnection2) GetSpecificPortMappingEntry(NewRemoteHost string // Response structure. response := &struct { - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -3545,21 +3483,14 @@ func (client *WANIPConnection2) GetSpecificPortMappingEntry(NewRemoteHost string func (client *WANIPConnection2) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -3611,11 +3542,9 @@ func (client *WANIPConnection2) AddPortMapping(NewRemoteHost string, NewExternal func (client *WANIPConnection2) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -3653,12 +3582,9 @@ func (client *WANIPConnection2) DeletePortMappingRange(NewStartPort uint16, NewE // Request structure. request := &struct { NewStartPort string - - NewEndPort string - - NewProtocol string - - NewManage string + NewEndPort string + NewProtocol string + NewManage string }{} // BEGIN Marshal arguments into request. @@ -3724,14 +3650,10 @@ func (client *WANIPConnection2) GetExternalIPAddress() (NewExternalIPAddress str func (client *WANIPConnection2) GetListOfPortMappings(NewStartPort uint16, NewEndPort uint16, NewProtocol string, NewManage bool, NewNumberOfPorts uint16) (NewPortListing string, err error) { // Request structure. request := &struct { - NewStartPort string - - NewEndPort string - - NewProtocol string - - NewManage string - + NewStartPort string + NewEndPort string + NewProtocol string + NewManage string NewNumberOfPorts string }{} // BEGIN Marshal arguments into request. @@ -3780,21 +3702,14 @@ func (client *WANIPConnection2) GetListOfPortMappings(NewStartPort uint16, NewEn func (client *WANIPConnection2) AddAnyPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (NewReservedPort uint16, err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -3912,8 +3827,7 @@ func (client *WANIPv6FirewallControl1) GetFirewallStatus() (FirewallEnabled bool // Response structure. response := &struct { - FirewallEnabled string - + FirewallEnabled string InboundPinholeAllowed string }{} @@ -3937,15 +3851,11 @@ func (client *WANIPv6FirewallControl1) GetFirewallStatus() (FirewallEnabled bool func (client *WANIPv6FirewallControl1) GetOutboundPinholeTimeout(RemoteHost string, RemotePort uint16, InternalClient string, InternalPort uint16, Protocol uint16) (OutboundPinholeTimeout uint32, err error) { // Request structure. request := &struct { - RemoteHost string - - RemotePort string - + RemoteHost string + RemotePort string InternalClient string - - InternalPort string - - Protocol string + InternalPort string + Protocol string }{} // BEGIN Marshal arguments into request. @@ -3993,17 +3903,12 @@ func (client *WANIPv6FirewallControl1) GetOutboundPinholeTimeout(RemoteHost stri func (client *WANIPv6FirewallControl1) AddPinhole(RemoteHost string, RemotePort uint16, InternalClient string, InternalPort uint16, Protocol uint16, LeaseTime uint32) (UniqueID uint16, err error) { // Request structure. request := &struct { - RemoteHost string - - RemotePort string - + RemoteHost string + RemotePort string InternalClient string - - InternalPort string - - Protocol string - - LeaseTime string + InternalPort string + Protocol string + LeaseTime string }{} // BEGIN Marshal arguments into request. @@ -4054,8 +3959,7 @@ func (client *WANIPv6FirewallControl1) AddPinhole(RemoteHost string, RemotePort func (client *WANIPv6FirewallControl1) UpdatePinhole(UniqueID uint16, NewLeaseTime uint32) (err error) { // Request structure. request := &struct { - UniqueID string - + UniqueID string NewLeaseTime string }{} // BEGIN Marshal arguments into request. @@ -4239,10 +4143,8 @@ func (client *WANPOTSLinkConfig1) SetISPInfo(NewISPPhoneNumber string, NewISPInf // Request structure. request := &struct { NewISPPhoneNumber string - - NewISPInfo string - - NewLinkType string + NewISPInfo string + NewLinkType string }{} // BEGIN Marshal arguments into request. @@ -4274,8 +4176,7 @@ func (client *WANPOTSLinkConfig1) SetISPInfo(NewISPPhoneNumber string, NewISPInf func (client *WANPOTSLinkConfig1) SetCallRetryInfo(NewNumberOfRetries uint32, NewDelayBetweenRetries uint32) (err error) { // Request structure. request := &struct { - NewNumberOfRetries string - + NewNumberOfRetries string NewDelayBetweenRetries string }{} // BEGIN Marshal arguments into request. @@ -4316,10 +4217,8 @@ func (client *WANPOTSLinkConfig1) GetISPInfo() (NewISPPhoneNumber string, NewISP // Response structure. response := &struct { NewISPPhoneNumber string - - NewISPInfo string - - NewLinkType string + NewISPInfo string + NewLinkType string }{} // Perform the SOAP call. @@ -4351,8 +4250,7 @@ func (client *WANPOTSLinkConfig1) GetCallRetryInfo() (NewNumberOfRetries uint32, // Response structure. response := &struct { - NewNumberOfRetries string - + NewNumberOfRetries string NewDelayBetweenRetries string }{} @@ -4602,8 +4500,7 @@ func (client *WANPPPConnection1) GetConnectionTypeInfo() (NewConnectionType stri // Response structure. response := &struct { - NewConnectionType string - + NewConnectionType string NewPossibleConnectionTypes string }{} @@ -4628,7 +4525,6 @@ func (client *WANPPPConnection1) ConfigureConnection(NewUserName string, NewPass // Request structure. request := &struct { NewUserName string - NewPassword string }{} // BEGIN Marshal arguments into request. @@ -4811,11 +4707,9 @@ func (client *WANPPPConnection1) GetStatusInfo() (NewConnectionStatus string, Ne // Response structure. response := &struct { - NewConnectionStatus string - + NewConnectionStatus string NewLastConnectionError string - - NewUptime string + NewUptime string }{} // Perform the SOAP call. @@ -4847,8 +4741,7 @@ func (client *WANPPPConnection1) GetLinkLayerMaxBitRates() (NewUpstreamMaxBitRat // Response structure. response := &struct { - NewUpstreamMaxBitRate string - + NewUpstreamMaxBitRate string NewDownstreamMaxBitRate string }{} @@ -5087,8 +4980,7 @@ func (client *WANPPPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewN // Response structure. response := &struct { NewRSIPAvailable string - - NewNATEnabled string + NewNATEnabled string }{} // Perform the SOAP call. @@ -5126,21 +5018,14 @@ func (client *WANPPPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex // Response structure. response := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -5186,11 +5071,9 @@ func (client *WANPPPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. @@ -5207,15 +5090,11 @@ func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost strin // Response structure. response := &struct { - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // Perform the SOAP call. @@ -5252,21 +5131,14 @@ func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost strin func (client *WANPPPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { // Request structure. request := &struct { - NewRemoteHost string - - NewExternalPort string - - NewProtocol string - - NewInternalPort string - - NewInternalClient string - - NewEnabled string - + NewRemoteHost string + NewExternalPort string + NewProtocol string + NewInternalPort string + NewInternalClient string + NewEnabled string NewPortMappingDescription string - - NewLeaseDuration string + NewLeaseDuration string }{} // BEGIN Marshal arguments into request. @@ -5318,11 +5190,9 @@ func (client *WANPPPConnection1) AddPortMapping(NewRemoteHost string, NewExterna func (client *WANPPPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { // Request structure. request := &struct { - NewRemoteHost string - + NewRemoteHost string NewExternalPort string - - NewProtocol string + NewProtocol string }{} // BEGIN Marshal arguments into request. diff --git a/vendor/github.com/huin/goupnp/device.go b/vendor/github.com/huin/goupnp/device.go index e5b658b21a..567ab4cfef 100644 --- a/vendor/github.com/huin/goupnp/device.go +++ b/vendor/github.com/huin/goupnp/device.go @@ -147,9 +147,9 @@ func (srv *Service) String() string { return fmt.Sprintf("Service ID %s : %s", srv.ServiceId, srv.ServiceType) } -// RequestSCDP requests the SCPD (soap actions and state variables description) +// RequestSCPD requests the SCPD (soap actions and state variables description) // for the service. -func (srv *Service) RequestSCDP() (*scpd.SCPD, error) { +func (srv *Service) RequestSCPD() (*scpd.SCPD, error) { if !srv.SCPDURL.Ok { return nil, errors.New("bad/missing SCPD URL, or no URLBase has been set") } @@ -160,6 +160,12 @@ func (srv *Service) RequestSCDP() (*scpd.SCPD, error) { return s, nil } +// RequestSCDP is for compatibility only, prefer RequestSCPD. This was a +// misspelling of RequestSCDP. +func (srv *Service) RequestSCDP() (*scpd.SCPD, error) { + return srv.RequestSCPD() +} + func (srv *Service) NewSOAPClient() *soap.SOAPClient { return soap.NewSOAPClient(srv.ControlURL.URL) } diff --git a/vendor/github.com/huin/goupnp/go.mod b/vendor/github.com/huin/goupnp/go.mod new file mode 100644 index 0000000000..e4a078f6e0 --- /dev/null +++ b/vendor/github.com/huin/goupnp/go.mod @@ -0,0 +1,7 @@ +module github.com/huin/goupnp + +require ( + github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 + golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 + golang.org/x/text v0.3.0 // indirect +) diff --git a/vendor/github.com/huin/goupnp/go.sum b/vendor/github.com/huin/goupnp/go.sum new file mode 100644 index 0000000000..3e7586992d --- /dev/null +++ b/vendor/github.com/huin/goupnp/go.sum @@ -0,0 +1,6 @@ +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/huin/goupnp/goupnp.sublime-project b/vendor/github.com/huin/goupnp/goupnp.sublime-project new file mode 100644 index 0000000000..24db30311b --- /dev/null +++ b/vendor/github.com/huin/goupnp/goupnp.sublime-project @@ -0,0 +1,8 @@ +{ + "folders": + [ + { + "path": "." + } + ] +} diff --git a/vendor/github.com/huin/goupnp/httpu/httpu.go b/vendor/github.com/huin/goupnp/httpu/httpu.go index f52dad68b1..44b0c583ca 100644 --- a/vendor/github.com/huin/goupnp/httpu/httpu.go +++ b/vendor/github.com/huin/goupnp/httpu/httpu.go @@ -122,11 +122,13 @@ func (httpu *HTTPUClient) Do(req *http.Request, timeout time.Duration, numSends // Parse response. response, err := http.ReadResponse(bufio.NewReader(bytes.NewBuffer(responseBytes[:n])), req) if err != nil { - log.Print("httpu: error while parsing response: %v", err) + log.Printf("httpu: error while parsing response: %v", err) continue } responses = append(responses, response) } - return responses, err + + // Timeout reached - return discovered responses. + return responses, nil } diff --git a/vendor/github.com/huin/goupnp/soap/soap.go b/vendor/github.com/huin/goupnp/soap/soap.go index 815610734c..29e89f2a92 100644 --- a/vendor/github.com/huin/goupnp/soap/soap.go +++ b/vendor/github.com/huin/goupnp/soap/soap.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "reflect" + "regexp" ) const ( @@ -126,14 +127,49 @@ func encodeRequestArgs(w *bytes.Buffer, inAction interface{}) error { if value.Kind() != reflect.String { return fmt.Errorf("goupnp: SOAP arg %q is not of type string, but of type %v", argName, value.Type()) } - if err := enc.EncodeElement(value.Interface(), xml.StartElement{xml.Name{"", argName}, nil}); err != nil { - return fmt.Errorf("goupnp: error encoding SOAP arg %q: %v", argName, err) + elem := xml.StartElement{xml.Name{"", argName}, nil} + if err := enc.EncodeToken(elem); err != nil { + return fmt.Errorf("goupnp: error encoding start element for SOAP arg %q: %v", argName, err) + } + if err := enc.Flush(); err != nil { + return fmt.Errorf("goupnp: error flushing start element for SOAP arg %q: %v", argName, err) + } + if _, err := w.Write([]byte(escapeXMLText(value.Interface().(string)))); err != nil { + return fmt.Errorf("goupnp: error writing value for SOAP arg %q: %v", argName, err) + } + if err := enc.EncodeToken(elem.End()); err != nil { + return fmt.Errorf("goupnp: error encoding end element for SOAP arg %q: %v", argName, err) } } enc.Flush() return nil } +var xmlCharRx = regexp.MustCompile("[<>&]") + +// escapeXMLText is used by generated code to escape text in XML, but only +// escaping the characters `<`, `>`, and `&`. +// +// This is provided in order to work around SOAP server implementations that +// fail to decode XML correctly, specifically failing to decode `"`, `'`. Note +// that this can only be safely used for injecting into XML text, but not into +// attributes or other contexts. +func escapeXMLText(s string) string { + return xmlCharRx.ReplaceAllStringFunc(s, replaceEntity) +} + +func replaceEntity(s string) string { + switch s { + case "<": + return "<" + case ">": + return ">" + case "&": + return "&" + } + return s +} + type soapEnvelope struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` EncodingStyle string `xml:"http://schemas.xmlsoap.org/soap/envelope/ encodingStyle,attr"` diff --git a/vendor/github.com/huin/goupnp/soap/types.go b/vendor/github.com/huin/goupnp/soap/types.go index fdbeec8d42..3e73d99d92 100644 --- a/vendor/github.com/huin/goupnp/soap/types.go +++ b/vendor/github.com/huin/goupnp/soap/types.go @@ -47,6 +47,15 @@ func UnmarshalUi4(s string) (uint32, error) { return uint32(v), err } +func MarshalUi8(v uint64) (string, error) { + return strconv.FormatUint(v, 10), nil +} + +func UnmarshalUi8(s string) (uint64, error) { + v, err := strconv.ParseUint(s, 10, 64) + return uint64(v), err +} + func MarshalI1(v int8) (string, error) { return strconv.FormatInt(int64(v), 10), nil } @@ -325,7 +334,7 @@ func UnmarshalTimeOfDay(s string) (TimeOfDay, error) { if err != nil { return TimeOfDay{}, err } else if t.HasOffset { - return TimeOfDay{}, fmt.Errorf("soap time: value %q contains unexpected timezone") + return TimeOfDay{}, fmt.Errorf("soap time: value %q contains unexpected timezone", s) } return t, nil } diff --git a/vendor/github.com/huin/goupnp/ssdp/ssdp.go b/vendor/github.com/huin/goupnp/ssdp/ssdp.go index 8178f5d948..4c03b25565 100644 --- a/vendor/github.com/huin/goupnp/ssdp/ssdp.go +++ b/vendor/github.com/huin/goupnp/ssdp/ssdp.go @@ -20,6 +20,11 @@ const ( ssdpSearchPort = 1900 methodSearch = "M-SEARCH" methodNotify = "NOTIFY" + + // SSDPAll is a value for searchTarget that searches for all devices and services. + SSDPAll = "ssdp:all" + // UPNPRootDevice is a value for searchTarget that searches for all root devices. + UPNPRootDevice = "upnp:rootdevice" ) // SSDPRawSearch performs a fairly raw SSDP search request, and returns the @@ -54,13 +59,15 @@ func SSDPRawSearch(httpu *httpu.HTTPUClient, searchTarget string, maxWaitSeconds if err != nil { return nil, err } + + isExactSearch := searchTarget != SSDPAll && searchTarget != UPNPRootDevice + for _, response := range allResponses { if response.StatusCode != 200 { log.Printf("ssdp: got response status code %q in search response", response.Status) continue } - if st := response.Header.Get("ST"); st != searchTarget { - log.Printf("ssdp: got unexpected search target result %q", st) + if st := response.Header.Get("ST"); isExactSearch && st != searchTarget { continue } location, err := response.Location() diff --git a/vendor/github.com/jackpal/go-nat-pmp/.travis.yml b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml index 9c3f6547da..b939153f70 100644 --- a/vendor/github.com/jackpal/go-nat-pmp/.travis.yml +++ b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml @@ -11,3 +11,10 @@ install: - go get -d -v ./... && go install -race -v ./... script: go test -race -v ./... + +sudo: false + +addons: + apt: + packages: + - iproute2 diff --git a/vendor/github.com/jackpal/go-nat-pmp/natpmp.go b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go index 5ca7680e41..e42065306a 100644 --- a/vendor/github.com/jackpal/go-nat-pmp/natpmp.go +++ b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go @@ -3,7 +3,6 @@ package natpmp import ( "fmt" "net" - "time" ) // Implement the NAT-PMP protocol, typically supported by Apple routers and open source @@ -21,25 +20,17 @@ const RECOMMENDED_MAPPING_LIFETIME_SECONDS = 3600 // Interface used to make remote procedure calls. type caller interface { - call(msg []byte, timeout time.Duration) (result []byte, err error) + call(msg []byte) (result []byte, err error) } // Client is a NAT-PMP protocol client. type Client struct { - caller caller - timeout time.Duration + caller caller } // Create a NAT-PMP client for the NAT-PMP server at the gateway. -// Uses default timeout which is around 128 seconds. func NewClient(gateway net.IP) (nat *Client) { - return &Client{&network{gateway}, 0} -} - -// Create a NAT-PMP client for the NAT-PMP server at the gateway, with a timeout. -// Timeout defines the total amount of time we will keep retrying before giving up. -func NewClientWithTimeout(gateway net.IP, timeout time.Duration) (nat *Client) { - return &Client{&network{gateway}, timeout} + return &Client{&network{gateway}} } // Results of the NAT-PMP GetExternalAddress operation. @@ -101,7 +92,7 @@ func (n *Client) AddPortMapping(protocol string, internalPort, requestedExternal } func (n *Client) rpc(msg []byte, resultSize int) (result []byte, err error) { - result, err = n.caller.call(msg, n.timeout) + result, err = n.caller.call(msg) if err != nil { return } diff --git a/vendor/github.com/jackpal/go-nat-pmp/network.go b/vendor/github.com/jackpal/go-nat-pmp/network.go index c42b4fee9d..9def1acda2 100644 --- a/vendor/github.com/jackpal/go-nat-pmp/network.go +++ b/vendor/github.com/jackpal/go-nat-pmp/network.go @@ -2,6 +2,7 @@ package natpmp import ( "fmt" + "log" "net" "time" ) @@ -15,7 +16,7 @@ type network struct { gateway net.IP } -func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err error) { +func (n *network) call(msg []byte) (result []byte, err error) { var server net.UDPAddr server.IP = n.gateway server.Port = nAT_PMP_PORT @@ -28,18 +29,12 @@ func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err er // 16 bytes is the maximum result size. result = make([]byte, 16) - var finalTimeout time.Time - if timeout != 0 { - finalTimeout = time.Now().Add(timeout) - } - needNewDeadline := true var tries uint - for tries = 0; (tries < nAT_TRIES && finalTimeout.IsZero()) || time.Now().Before(finalTimeout); { + for tries = 0; tries < nAT_TRIES; { if needNewDeadline { - nextDeadline := time.Now().Add((nAT_INITIAL_MS << tries) * time.Millisecond) - err = conn.SetDeadline(minTime(nextDeadline, finalTimeout)) + err = conn.SetDeadline(time.Now().Add((nAT_INITIAL_MS << tries) * time.Millisecond)) if err != nil { return } @@ -61,6 +56,7 @@ func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err er return } if !remoteAddr.IP.Equal(n.gateway) { + log.Printf("Ignoring packet because IPs differ:", remoteAddr, n.gateway) // Ignore this packet. // Continue without increasing retransmission timeout or deadline. continue @@ -74,16 +70,3 @@ func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err er err = fmt.Errorf("Timed out trying to contact gateway") return } - -func minTime(a, b time.Time) time.Time { - if a.IsZero() { - return b - } - if b.IsZero() { - return a - } - if a.Before(b) { - return a - } - return b -} diff --git a/vendor/github.com/jackpal/go-nat-pmp/recorder.go b/vendor/github.com/jackpal/go-nat-pmp/recorder.go index 845703672b..e70a3c65c9 100644 --- a/vendor/github.com/jackpal/go-nat-pmp/recorder.go +++ b/vendor/github.com/jackpal/go-nat-pmp/recorder.go @@ -1,7 +1,5 @@ package natpmp -import "time" - type callObserver interface { observeCall(msg []byte, result []byte, err error) } @@ -12,8 +10,8 @@ type recorder struct { observer callObserver } -func (n *recorder) call(msg []byte, timeout time.Duration) (result []byte, err error) { - result, err = n.child.call(msg, timeout) +func (n *recorder) call(msg []byte) (result []byte, err error) { + result, err = n.child.call(msg) n.observer.observeCall(msg, result, err) return } diff --git a/vendor/github.com/karalabe/usb/.travis.yml b/vendor/github.com/karalabe/usb/.travis.yml index de0337b2b8..7f925fbc0c 100644 --- a/vendor/github.com/karalabe/usb/.travis.yml +++ b/vendor/github.com/karalabe/usb/.travis.yml @@ -32,8 +32,8 @@ matrix: - os: osx go: 1.12.x - os: linux - dist: xenial - go: 1.12.x + dist: bionic + go: 1.13.x services: - docker env: diff --git a/vendor/github.com/karalabe/usb/appveyor.yml b/vendor/github.com/karalabe/usb/appveyor.yml index 73a9664ae7..595fd34ad1 100644 --- a/vendor/github.com/karalabe/usb/appveyor.yml +++ b/vendor/github.com/karalabe/usb/appveyor.yml @@ -22,8 +22,8 @@ environment: install: - rmdir C:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go1.12.9.windows-%GOARCH%.zip - - 7z x go1.12.9.windows-%GOARCH%.zip -y -oC:\ > NUL + - appveyor DownloadFile https://storage.googleapis.com/golang/go1.13.4.windows-%GOARCH%.zip + - 7z x go1.13.4.windows-%GOARCH%.zip -y -oC:\ > NUL - go version - gcc --version diff --git a/vendor/github.com/karalabe/usb/hidapi/windows/hid.c b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c index 4e92cc8bc9..60da64608c 100644 --- a/vendor/github.com/karalabe/usb/hidapi/windows/hid.c +++ b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c @@ -74,6 +74,8 @@ extern "C" { #pragma warning(disable:4996) #endif +#pragma GCC diagnostic ignored "-Wstringop-overflow" + #ifdef __cplusplus extern "C" { #endif @@ -428,7 +430,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); - strncpy(cur_dev->path, str, sizeof(cur_dev->path)); + strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index 82568a1bb9..3cb94106f9 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -1,22 +1,34 @@ package runewidth -import "os" +import ( + "os" +) var ( // EastAsianWidth will be set true if the current locale is CJK EastAsianWidth bool + // ZeroWidthJoiner is flag to set to use UTR#51 ZWJ + ZeroWidthJoiner bool + // DefaultCondition is a condition in current locale - DefaultCondition = &Condition{EastAsianWidth} + DefaultCondition = &Condition{} ) func init() { + handleEnv() +} + +func handleEnv() { env := os.Getenv("RUNEWIDTH_EASTASIAN") if env == "" { EastAsianWidth = IsEastAsian() } else { EastAsianWidth = env == "1" } + // update DefaultCondition + DefaultCondition.EastAsianWidth = EastAsianWidth + DefaultCondition.ZeroWidthJoiner = ZeroWidthJoiner } type interval struct { @@ -44,7 +56,7 @@ func inTable(r rune, t table) bool { bot := 0 top := len(t) - 1 for top >= bot { - mid := (bot + top) / 2 + mid := (bot + top) >> 1 switch { case t[mid].last < r: @@ -66,8 +78,7 @@ var private = table{ var nonprint = table{ {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, - {0x2028, 0x2029}, - {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, } @@ -261,19 +272,54 @@ var ambiguous = table{ } var emoji = table{ - {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F321}, {0x1F324, 0x1F32C}, - {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F396, 0x1F397}, - {0x1F399, 0x1F39B}, {0x1F39E, 0x1F39F}, {0x1F3CB, 0x1F3CE}, - {0x1F3D4, 0x1F3DF}, {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3F7}, - {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FD}, - {0x1F549, 0x1F54A}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F579}, + {0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122}, + {0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA}, + {0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF}, + {0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2}, + {0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0}, + {0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E}, + {0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618}, + {0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623}, + {0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F}, + {0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642}, + {0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663}, + {0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B}, + {0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699}, + {0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26AA, 0x26AB}, + {0x26B0, 0x26B1}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, + {0x26C8, 0x26C8}, {0x26CE, 0x26CF}, {0x26D1, 0x26D1}, + {0x26D3, 0x26D4}, {0x26E9, 0x26EA}, {0x26F0, 0x26F5}, + {0x26F7, 0x26FA}, {0x26FD, 0x26FD}, {0x2702, 0x2702}, + {0x2705, 0x2705}, {0x2708, 0x270D}, {0x270F, 0x270F}, + {0x2712, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716}, + {0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728}, + {0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747}, + {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755}, + {0x2757, 0x2757}, {0x2763, 0x2764}, {0x2795, 0x2797}, + {0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, + {0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030}, + {0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299}, + {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F170, 0x1F171}, + {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, + {0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F202}, {0x1F21A, 0x1F21A}, + {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F250, 0x1F251}, + {0x1F300, 0x1F321}, {0x1F324, 0x1F393}, {0x1F396, 0x1F397}, + {0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0}, {0x1F3F3, 0x1F3F5}, + {0x1F3F7, 0x1F4FD}, {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E}, + {0x1F550, 0x1F567}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A}, {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, - {0x1F5A5, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2}, - {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3}, - {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3}, - {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3}, - {0x1F5FA, 0x1F5FA}, {0x1F6CB, 0x1F6CF}, {0x1F6E0, 0x1F6E5}, - {0x1F6E9, 0x1F6E9}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F3}, + {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, + {0x1F5B1, 0x1F5B2}, {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, + {0x1F5D1, 0x1F5D3}, {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, + {0x1F5E3, 0x1F5E3}, {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, + {0x1F5F3, 0x1F5F3}, {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5}, + {0x1F6CB, 0x1F6D2}, {0x1F6E0, 0x1F6E5}, {0x1F6E9, 0x1F6E9}, + {0x1F6EB, 0x1F6EC}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F9}, + {0x1F910, 0x1F93A}, {0x1F93C, 0x1F93E}, {0x1F940, 0x1F945}, + {0x1F947, 0x1F970}, {0x1F973, 0x1F976}, {0x1F97A, 0x1F97A}, + {0x1F97C, 0x1F9A2}, {0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C2}, + {0x1F9D0, 0x1F9FF}, } var notassigned = table{ @@ -493,314 +539,141 @@ var notassigned = table{ } var neutral = table{ - {0x0000, 0x001F}, {0x007F, 0x007F}, {0x0080, 0x009F}, - {0x00A0, 0x00A0}, {0x00A9, 0x00A9}, {0x00AB, 0x00AB}, - {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, {0x00C0, 0x00C5}, - {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, {0x00D9, 0x00DD}, - {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, {0x00EB, 0x00EB}, - {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, {0x00F4, 0x00F6}, - {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, {0x00FF, 0x00FF}, - {0x0100, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, + {0x0000, 0x001F}, {0x007F, 0x00A0}, {0x00A9, 0x00A9}, + {0x00AB, 0x00AB}, {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, + {0x00C0, 0x00C5}, {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, + {0x00D9, 0x00DD}, {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, + {0x00EB, 0x00EB}, {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, + {0x00F4, 0x00F6}, {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, + {0x00FF, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, - {0x016C, 0x017F}, {0x0180, 0x01BA}, {0x01BB, 0x01BB}, - {0x01BC, 0x01BF}, {0x01C0, 0x01C3}, {0x01C4, 0x01CD}, - {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, {0x01D3, 0x01D3}, - {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, {0x01D9, 0x01D9}, - {0x01DB, 0x01DB}, {0x01DD, 0x024F}, {0x0250, 0x0250}, - {0x0252, 0x0260}, {0x0262, 0x0293}, {0x0294, 0x0294}, - {0x0295, 0x02AF}, {0x02B0, 0x02C1}, {0x02C2, 0x02C3}, - {0x02C5, 0x02C5}, {0x02C6, 0x02C6}, {0x02C8, 0x02C8}, - {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, {0x02D1, 0x02D1}, - {0x02D2, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, - {0x02E0, 0x02E4}, {0x02E5, 0x02EB}, {0x02EC, 0x02EC}, - {0x02ED, 0x02ED}, {0x02EE, 0x02EE}, {0x02EF, 0x02FF}, - {0x0370, 0x0373}, {0x0374, 0x0374}, {0x0375, 0x0375}, - {0x0376, 0x0377}, {0x037A, 0x037A}, {0x037B, 0x037D}, - {0x037E, 0x037E}, {0x037F, 0x037F}, {0x0384, 0x0385}, - {0x0386, 0x0386}, {0x0387, 0x0387}, {0x0388, 0x038A}, - {0x038C, 0x038C}, {0x038E, 0x0390}, {0x03AA, 0x03B0}, - {0x03C2, 0x03C2}, {0x03CA, 0x03F5}, {0x03F6, 0x03F6}, - {0x03F7, 0x03FF}, {0x0400, 0x0400}, {0x0402, 0x040F}, - {0x0450, 0x0450}, {0x0452, 0x0481}, {0x0482, 0x0482}, - {0x0483, 0x0487}, {0x0488, 0x0489}, {0x048A, 0x04FF}, - {0x0500, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x0559}, - {0x055A, 0x055F}, {0x0561, 0x0587}, {0x0589, 0x0589}, - {0x058A, 0x058A}, {0x058D, 0x058E}, {0x058F, 0x058F}, - {0x0591, 0x05BD}, {0x05BE, 0x05BE}, {0x05BF, 0x05BF}, - {0x05C0, 0x05C0}, {0x05C1, 0x05C2}, {0x05C3, 0x05C3}, - {0x05C4, 0x05C5}, {0x05C6, 0x05C6}, {0x05C7, 0x05C7}, - {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x05F3, 0x05F4}, - {0x0600, 0x0605}, {0x0606, 0x0608}, {0x0609, 0x060A}, - {0x060B, 0x060B}, {0x060C, 0x060D}, {0x060E, 0x060F}, - {0x0610, 0x061A}, {0x061B, 0x061B}, {0x061C, 0x061C}, - {0x061E, 0x061F}, {0x0620, 0x063F}, {0x0640, 0x0640}, - {0x0641, 0x064A}, {0x064B, 0x065F}, {0x0660, 0x0669}, - {0x066A, 0x066D}, {0x066E, 0x066F}, {0x0670, 0x0670}, - {0x0671, 0x06D3}, {0x06D4, 0x06D4}, {0x06D5, 0x06D5}, - {0x06D6, 0x06DC}, {0x06DD, 0x06DD}, {0x06DE, 0x06DE}, - {0x06DF, 0x06E4}, {0x06E5, 0x06E6}, {0x06E7, 0x06E8}, - {0x06E9, 0x06E9}, {0x06EA, 0x06ED}, {0x06EE, 0x06EF}, - {0x06F0, 0x06F9}, {0x06FA, 0x06FC}, {0x06FD, 0x06FE}, - {0x06FF, 0x06FF}, {0x0700, 0x070D}, {0x070F, 0x070F}, - {0x0710, 0x0710}, {0x0711, 0x0711}, {0x0712, 0x072F}, - {0x0730, 0x074A}, {0x074D, 0x074F}, {0x0750, 0x077F}, - {0x0780, 0x07A5}, {0x07A6, 0x07B0}, {0x07B1, 0x07B1}, - {0x07C0, 0x07C9}, {0x07CA, 0x07EA}, {0x07EB, 0x07F3}, - {0x07F4, 0x07F5}, {0x07F6, 0x07F6}, {0x07F7, 0x07F9}, - {0x07FA, 0x07FA}, {0x0800, 0x0815}, {0x0816, 0x0819}, - {0x081A, 0x081A}, {0x081B, 0x0823}, {0x0824, 0x0824}, - {0x0825, 0x0827}, {0x0828, 0x0828}, {0x0829, 0x082D}, - {0x0830, 0x083E}, {0x0840, 0x0858}, {0x0859, 0x085B}, - {0x085E, 0x085E}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD}, - {0x08D4, 0x08E1}, {0x08E2, 0x08E2}, {0x08E3, 0x08FF}, - {0x0900, 0x0902}, {0x0903, 0x0903}, {0x0904, 0x0939}, - {0x093A, 0x093A}, {0x093B, 0x093B}, {0x093C, 0x093C}, - {0x093D, 0x093D}, {0x093E, 0x0940}, {0x0941, 0x0948}, - {0x0949, 0x094C}, {0x094D, 0x094D}, {0x094E, 0x094F}, - {0x0950, 0x0950}, {0x0951, 0x0957}, {0x0958, 0x0961}, - {0x0962, 0x0963}, {0x0964, 0x0965}, {0x0966, 0x096F}, - {0x0970, 0x0970}, {0x0971, 0x0971}, {0x0972, 0x097F}, - {0x0980, 0x0980}, {0x0981, 0x0981}, {0x0982, 0x0983}, - {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, - {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, - {0x09BC, 0x09BC}, {0x09BD, 0x09BD}, {0x09BE, 0x09C0}, - {0x09C1, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CC}, - {0x09CD, 0x09CD}, {0x09CE, 0x09CE}, {0x09D7, 0x09D7}, - {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09E2, 0x09E3}, - {0x09E6, 0x09EF}, {0x09F0, 0x09F1}, {0x09F2, 0x09F3}, - {0x09F4, 0x09F9}, {0x09FA, 0x09FA}, {0x09FB, 0x09FB}, - {0x0A01, 0x0A02}, {0x0A03, 0x0A03}, {0x0A05, 0x0A0A}, - {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, - {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, - {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A40}, {0x0A41, 0x0A42}, - {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, - {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A6F}, - {0x0A70, 0x0A71}, {0x0A72, 0x0A74}, {0x0A75, 0x0A75}, - {0x0A81, 0x0A82}, {0x0A83, 0x0A83}, {0x0A85, 0x0A8D}, + {0x016C, 0x01CD}, {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, + {0x01D3, 0x01D3}, {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, + {0x01D9, 0x01D9}, {0x01DB, 0x01DB}, {0x01DD, 0x0250}, + {0x0252, 0x0260}, {0x0262, 0x02C3}, {0x02C5, 0x02C6}, + {0x02C8, 0x02C8}, {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, + {0x02D1, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, + {0x02E0, 0x02FF}, {0x0370, 0x0377}, {0x037A, 0x037F}, + {0x0384, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x0390}, + {0x03AA, 0x03B0}, {0x03C2, 0x03C2}, {0x03CA, 0x0400}, + {0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F}, + {0x0531, 0x0556}, {0x0559, 0x055F}, {0x0561, 0x0587}, + {0x0589, 0x058A}, {0x058D, 0x058F}, {0x0591, 0x05C7}, + {0x05D0, 0x05EA}, {0x05F0, 0x05F4}, {0x0600, 0x061C}, + {0x061E, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1}, + {0x07C0, 0x07FA}, {0x0800, 0x082D}, {0x0830, 0x083E}, + {0x0840, 0x085B}, {0x085E, 0x085E}, {0x08A0, 0x08B4}, + {0x08B6, 0x08BD}, {0x08D4, 0x0983}, {0x0985, 0x098C}, + {0x098F, 0x0990}, {0x0993, 0x09A8}, {0x09AA, 0x09B0}, + {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, {0x09BC, 0x09C4}, + {0x09C7, 0x09C8}, {0x09CB, 0x09CE}, {0x09D7, 0x09D7}, + {0x09DC, 0x09DD}, {0x09DF, 0x09E3}, {0x09E6, 0x09FB}, + {0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10}, + {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33}, + {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A3C, 0x0A3C}, + {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, + {0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, + {0x0A66, 0x0A75}, {0x0A81, 0x0A83}, {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, - {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0ABC}, - {0x0ABD, 0x0ABD}, {0x0ABE, 0x0AC0}, {0x0AC1, 0x0AC5}, - {0x0AC7, 0x0AC8}, {0x0AC9, 0x0AC9}, {0x0ACB, 0x0ACC}, - {0x0ACD, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE1}, - {0x0AE2, 0x0AE3}, {0x0AE6, 0x0AEF}, {0x0AF0, 0x0AF0}, - {0x0AF1, 0x0AF1}, {0x0AF9, 0x0AF9}, {0x0B01, 0x0B01}, - {0x0B02, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, + {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5}, + {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0}, + {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, {0x0AF9, 0x0AF9}, + {0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, - {0x0B35, 0x0B39}, {0x0B3C, 0x0B3C}, {0x0B3D, 0x0B3D}, - {0x0B3E, 0x0B3E}, {0x0B3F, 0x0B3F}, {0x0B40, 0x0B40}, - {0x0B41, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4C}, - {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B57, 0x0B57}, - {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B62, 0x0B63}, - {0x0B66, 0x0B6F}, {0x0B70, 0x0B70}, {0x0B71, 0x0B71}, - {0x0B72, 0x0B77}, {0x0B82, 0x0B82}, {0x0B83, 0x0B83}, + {0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, {0x0B47, 0x0B48}, + {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B5C, 0x0B5D}, + {0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, - {0x0BBE, 0x0BBF}, {0x0BC0, 0x0BC0}, {0x0BC1, 0x0BC2}, - {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCC}, {0x0BCD, 0x0BCD}, - {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BEF}, - {0x0BF0, 0x0BF2}, {0x0BF3, 0x0BF8}, {0x0BF9, 0x0BF9}, - {0x0BFA, 0x0BFA}, {0x0C00, 0x0C00}, {0x0C01, 0x0C03}, - {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, - {0x0C2A, 0x0C39}, {0x0C3D, 0x0C3D}, {0x0C3E, 0x0C40}, - {0x0C41, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, - {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C61}, - {0x0C62, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C78, 0x0C7E}, - {0x0C7F, 0x0C7F}, {0x0C80, 0x0C80}, {0x0C81, 0x0C81}, - {0x0C82, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, + {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD}, + {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA}, + {0x0C00, 0x0C03}, {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, + {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3D, 0x0C44}, + {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, + {0x0C58, 0x0C5A}, {0x0C60, 0x0C63}, {0x0C66, 0x0C6F}, + {0x0C78, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, - {0x0CBC, 0x0CBC}, {0x0CBD, 0x0CBD}, {0x0CBE, 0x0CBE}, - {0x0CBF, 0x0CBF}, {0x0CC0, 0x0CC4}, {0x0CC6, 0x0CC6}, - {0x0CC7, 0x0CC8}, {0x0CCA, 0x0CCB}, {0x0CCC, 0x0CCD}, - {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, - {0x0CE2, 0x0CE3}, {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, - {0x0D01, 0x0D01}, {0x0D02, 0x0D03}, {0x0D05, 0x0D0C}, - {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, {0x0D3D, 0x0D3D}, - {0x0D3E, 0x0D40}, {0x0D41, 0x0D44}, {0x0D46, 0x0D48}, - {0x0D4A, 0x0D4C}, {0x0D4D, 0x0D4D}, {0x0D4E, 0x0D4E}, - {0x0D4F, 0x0D4F}, {0x0D54, 0x0D56}, {0x0D57, 0x0D57}, - {0x0D58, 0x0D5E}, {0x0D5F, 0x0D61}, {0x0D62, 0x0D63}, - {0x0D66, 0x0D6F}, {0x0D70, 0x0D78}, {0x0D79, 0x0D79}, - {0x0D7A, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96}, - {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, - {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD1}, - {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, - {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF3}, {0x0DF4, 0x0DF4}, - {0x0E01, 0x0E30}, {0x0E31, 0x0E31}, {0x0E32, 0x0E33}, - {0x0E34, 0x0E3A}, {0x0E3F, 0x0E3F}, {0x0E40, 0x0E45}, - {0x0E46, 0x0E46}, {0x0E47, 0x0E4E}, {0x0E4F, 0x0E4F}, - {0x0E50, 0x0E59}, {0x0E5A, 0x0E5B}, {0x0E81, 0x0E82}, - {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, - {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, - {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, - {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EB0}, {0x0EB1, 0x0EB1}, - {0x0EB2, 0x0EB3}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, - {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, - {0x0F00, 0x0F00}, {0x0F01, 0x0F03}, {0x0F04, 0x0F12}, - {0x0F13, 0x0F13}, {0x0F14, 0x0F14}, {0x0F15, 0x0F17}, - {0x0F18, 0x0F19}, {0x0F1A, 0x0F1F}, {0x0F20, 0x0F29}, - {0x0F2A, 0x0F33}, {0x0F34, 0x0F34}, {0x0F35, 0x0F35}, - {0x0F36, 0x0F36}, {0x0F37, 0x0F37}, {0x0F38, 0x0F38}, - {0x0F39, 0x0F39}, {0x0F3A, 0x0F3A}, {0x0F3B, 0x0F3B}, - {0x0F3C, 0x0F3C}, {0x0F3D, 0x0F3D}, {0x0F3E, 0x0F3F}, - {0x0F40, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F7E}, - {0x0F7F, 0x0F7F}, {0x0F80, 0x0F84}, {0x0F85, 0x0F85}, - {0x0F86, 0x0F87}, {0x0F88, 0x0F8C}, {0x0F8D, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FBE, 0x0FC5}, {0x0FC6, 0x0FC6}, - {0x0FC7, 0x0FCC}, {0x0FCE, 0x0FCF}, {0x0FD0, 0x0FD4}, - {0x0FD5, 0x0FD8}, {0x0FD9, 0x0FDA}, {0x1000, 0x102A}, - {0x102B, 0x102C}, {0x102D, 0x1030}, {0x1031, 0x1031}, - {0x1032, 0x1037}, {0x1038, 0x1038}, {0x1039, 0x103A}, - {0x103B, 0x103C}, {0x103D, 0x103E}, {0x103F, 0x103F}, - {0x1040, 0x1049}, {0x104A, 0x104F}, {0x1050, 0x1055}, - {0x1056, 0x1057}, {0x1058, 0x1059}, {0x105A, 0x105D}, - {0x105E, 0x1060}, {0x1061, 0x1061}, {0x1062, 0x1064}, - {0x1065, 0x1066}, {0x1067, 0x106D}, {0x106E, 0x1070}, - {0x1071, 0x1074}, {0x1075, 0x1081}, {0x1082, 0x1082}, - {0x1083, 0x1084}, {0x1085, 0x1086}, {0x1087, 0x108C}, - {0x108D, 0x108D}, {0x108E, 0x108E}, {0x108F, 0x108F}, - {0x1090, 0x1099}, {0x109A, 0x109C}, {0x109D, 0x109D}, - {0x109E, 0x109F}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, - {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FB, 0x10FB}, - {0x10FC, 0x10FC}, {0x10FD, 0x10FF}, {0x1160, 0x11FF}, - {0x1200, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, - {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, - {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, - {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, - {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, - {0x1318, 0x135A}, {0x135D, 0x135F}, {0x1360, 0x1368}, - {0x1369, 0x137C}, {0x1380, 0x138F}, {0x1390, 0x1399}, - {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x1400}, - {0x1401, 0x166C}, {0x166D, 0x166E}, {0x166F, 0x167F}, - {0x1680, 0x1680}, {0x1681, 0x169A}, {0x169B, 0x169B}, - {0x169C, 0x169C}, {0x16A0, 0x16EA}, {0x16EB, 0x16ED}, - {0x16EE, 0x16F0}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, - {0x170E, 0x1711}, {0x1712, 0x1714}, {0x1720, 0x1731}, - {0x1732, 0x1734}, {0x1735, 0x1736}, {0x1740, 0x1751}, - {0x1752, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, - {0x1772, 0x1773}, {0x1780, 0x17B3}, {0x17B4, 0x17B5}, - {0x17B6, 0x17B6}, {0x17B7, 0x17BD}, {0x17BE, 0x17C5}, - {0x17C6, 0x17C6}, {0x17C7, 0x17C8}, {0x17C9, 0x17D3}, - {0x17D4, 0x17D6}, {0x17D7, 0x17D7}, {0x17D8, 0x17DA}, - {0x17DB, 0x17DB}, {0x17DC, 0x17DC}, {0x17DD, 0x17DD}, - {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x1805}, - {0x1806, 0x1806}, {0x1807, 0x180A}, {0x180B, 0x180D}, - {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1842}, - {0x1843, 0x1843}, {0x1844, 0x1877}, {0x1880, 0x1884}, - {0x1885, 0x1886}, {0x1887, 0x18A8}, {0x18A9, 0x18A9}, - {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, - {0x1920, 0x1922}, {0x1923, 0x1926}, {0x1927, 0x1928}, - {0x1929, 0x192B}, {0x1930, 0x1931}, {0x1932, 0x1932}, - {0x1933, 0x1938}, {0x1939, 0x193B}, {0x1940, 0x1940}, - {0x1944, 0x1945}, {0x1946, 0x194F}, {0x1950, 0x196D}, - {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, - {0x19D0, 0x19D9}, {0x19DA, 0x19DA}, {0x19DE, 0x19DF}, - {0x19E0, 0x19FF}, {0x1A00, 0x1A16}, {0x1A17, 0x1A18}, - {0x1A19, 0x1A1A}, {0x1A1B, 0x1A1B}, {0x1A1E, 0x1A1F}, - {0x1A20, 0x1A54}, {0x1A55, 0x1A55}, {0x1A56, 0x1A56}, - {0x1A57, 0x1A57}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60}, - {0x1A61, 0x1A61}, {0x1A62, 0x1A62}, {0x1A63, 0x1A64}, - {0x1A65, 0x1A6C}, {0x1A6D, 0x1A72}, {0x1A73, 0x1A7C}, - {0x1A7F, 0x1A7F}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, - {0x1AA0, 0x1AA6}, {0x1AA7, 0x1AA7}, {0x1AA8, 0x1AAD}, - {0x1AB0, 0x1ABD}, {0x1ABE, 0x1ABE}, {0x1B00, 0x1B03}, - {0x1B04, 0x1B04}, {0x1B05, 0x1B33}, {0x1B34, 0x1B34}, - {0x1B35, 0x1B35}, {0x1B36, 0x1B3A}, {0x1B3B, 0x1B3B}, - {0x1B3C, 0x1B3C}, {0x1B3D, 0x1B41}, {0x1B42, 0x1B42}, - {0x1B43, 0x1B44}, {0x1B45, 0x1B4B}, {0x1B50, 0x1B59}, - {0x1B5A, 0x1B60}, {0x1B61, 0x1B6A}, {0x1B6B, 0x1B73}, - {0x1B74, 0x1B7C}, {0x1B80, 0x1B81}, {0x1B82, 0x1B82}, - {0x1B83, 0x1BA0}, {0x1BA1, 0x1BA1}, {0x1BA2, 0x1BA5}, - {0x1BA6, 0x1BA7}, {0x1BA8, 0x1BA9}, {0x1BAA, 0x1BAA}, - {0x1BAB, 0x1BAD}, {0x1BAE, 0x1BAF}, {0x1BB0, 0x1BB9}, - {0x1BBA, 0x1BBF}, {0x1BC0, 0x1BE5}, {0x1BE6, 0x1BE6}, - {0x1BE7, 0x1BE7}, {0x1BE8, 0x1BE9}, {0x1BEA, 0x1BEC}, - {0x1BED, 0x1BED}, {0x1BEE, 0x1BEE}, {0x1BEF, 0x1BF1}, - {0x1BF2, 0x1BF3}, {0x1BFC, 0x1BFF}, {0x1C00, 0x1C23}, - {0x1C24, 0x1C2B}, {0x1C2C, 0x1C33}, {0x1C34, 0x1C35}, - {0x1C36, 0x1C37}, {0x1C3B, 0x1C3F}, {0x1C40, 0x1C49}, - {0x1C4D, 0x1C4F}, {0x1C50, 0x1C59}, {0x1C5A, 0x1C77}, - {0x1C78, 0x1C7D}, {0x1C7E, 0x1C7F}, {0x1C80, 0x1C88}, - {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CD2}, {0x1CD3, 0x1CD3}, - {0x1CD4, 0x1CE0}, {0x1CE1, 0x1CE1}, {0x1CE2, 0x1CE8}, - {0x1CE9, 0x1CEC}, {0x1CED, 0x1CED}, {0x1CEE, 0x1CF1}, - {0x1CF2, 0x1CF3}, {0x1CF4, 0x1CF4}, {0x1CF5, 0x1CF6}, - {0x1CF8, 0x1CF9}, {0x1D00, 0x1D2B}, {0x1D2C, 0x1D6A}, - {0x1D6B, 0x1D77}, {0x1D78, 0x1D78}, {0x1D79, 0x1D7F}, - {0x1D80, 0x1D9A}, {0x1D9B, 0x1DBF}, {0x1DC0, 0x1DF5}, - {0x1DFB, 0x1DFF}, {0x1E00, 0x1EFF}, {0x1F00, 0x1F15}, + {0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, + {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3}, + {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D01, 0x0D03}, + {0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, + {0x0D3D, 0x0D44}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4F}, + {0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, {0x0D82, 0x0D83}, + {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, + {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, + {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, + {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A}, + {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84}, + {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, {0x0E8D, 0x0E8D}, + {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, {0x0EA1, 0x0EA3}, + {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, {0x0EAA, 0x0EAB}, + {0x0EAD, 0x0EB9}, {0x0EBB, 0x0EBD}, {0x0EC0, 0x0EC4}, + {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, + {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C}, + {0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC}, + {0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7}, + {0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248}, + {0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258}, + {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D}, + {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, + {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, + {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, + {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, + {0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8}, + {0x1700, 0x170C}, {0x170E, 0x1714}, {0x1720, 0x1736}, + {0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, + {0x1772, 0x1773}, {0x1780, 0x17DD}, {0x17E0, 0x17E9}, + {0x17F0, 0x17F9}, {0x1800, 0x180E}, {0x1810, 0x1819}, + {0x1820, 0x1877}, {0x1880, 0x18AA}, {0x18B0, 0x18F5}, + {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B}, + {0x1940, 0x1940}, {0x1944, 0x196D}, {0x1970, 0x1974}, + {0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA}, + {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, + {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, + {0x1AB0, 0x1ABE}, {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C}, + {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49}, + {0x1C4D, 0x1C88}, {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CF6}, + {0x1CF8, 0x1CF9}, {0x1D00, 0x1DF5}, {0x1DFB, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, - {0x1FB6, 0x1FBC}, {0x1FBD, 0x1FBD}, {0x1FBE, 0x1FBE}, - {0x1FBF, 0x1FC1}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, - {0x1FCD, 0x1FCF}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, - {0x1FDD, 0x1FDF}, {0x1FE0, 0x1FEC}, {0x1FED, 0x1FEF}, - {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x1FFD, 0x1FFE}, - {0x2000, 0x200A}, {0x200B, 0x200F}, {0x2011, 0x2012}, - {0x2017, 0x2017}, {0x201A, 0x201A}, {0x201B, 0x201B}, - {0x201E, 0x201E}, {0x201F, 0x201F}, {0x2023, 0x2023}, - {0x2028, 0x2028}, {0x2029, 0x2029}, {0x202A, 0x202E}, - {0x202F, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, - {0x2036, 0x2038}, {0x2039, 0x2039}, {0x203A, 0x203A}, - {0x203C, 0x203D}, {0x203F, 0x2040}, {0x2041, 0x2043}, - {0x2044, 0x2044}, {0x2045, 0x2045}, {0x2046, 0x2046}, - {0x2047, 0x2051}, {0x2052, 0x2052}, {0x2053, 0x2053}, - {0x2054, 0x2054}, {0x2055, 0x205E}, {0x205F, 0x205F}, - {0x2060, 0x2064}, {0x2066, 0x206F}, {0x2070, 0x2070}, - {0x2071, 0x2071}, {0x2075, 0x2079}, {0x207A, 0x207C}, - {0x207D, 0x207D}, {0x207E, 0x207E}, {0x2080, 0x2080}, - {0x2085, 0x2089}, {0x208A, 0x208C}, {0x208D, 0x208D}, - {0x208E, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, - {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20DC}, - {0x20DD, 0x20E0}, {0x20E1, 0x20E1}, {0x20E2, 0x20E4}, - {0x20E5, 0x20F0}, {0x2100, 0x2101}, {0x2102, 0x2102}, - {0x2104, 0x2104}, {0x2106, 0x2106}, {0x2107, 0x2107}, - {0x2108, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2114}, - {0x2115, 0x2115}, {0x2117, 0x2117}, {0x2118, 0x2118}, - {0x2119, 0x211D}, {0x211E, 0x2120}, {0x2123, 0x2123}, - {0x2124, 0x2124}, {0x2125, 0x2125}, {0x2127, 0x2127}, - {0x2128, 0x2128}, {0x2129, 0x2129}, {0x212A, 0x212A}, - {0x212C, 0x212D}, {0x212E, 0x212E}, {0x212F, 0x2134}, - {0x2135, 0x2138}, {0x2139, 0x2139}, {0x213A, 0x213B}, - {0x213C, 0x213F}, {0x2140, 0x2144}, {0x2145, 0x2149}, - {0x214A, 0x214A}, {0x214B, 0x214B}, {0x214C, 0x214D}, - {0x214E, 0x214E}, {0x214F, 0x214F}, {0x2150, 0x2152}, + {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB}, + {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE}, + {0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017}, + {0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023}, + {0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, + {0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064}, + {0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080}, + {0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, + {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20F0}, + {0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108}, + {0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120}, + {0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152}, {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, - {0x217A, 0x2182}, {0x2183, 0x2184}, {0x2185, 0x2188}, - {0x218A, 0x218B}, {0x219A, 0x219B}, {0x219C, 0x219F}, - {0x21A0, 0x21A0}, {0x21A1, 0x21A2}, {0x21A3, 0x21A3}, - {0x21A4, 0x21A5}, {0x21A6, 0x21A6}, {0x21A7, 0x21AD}, - {0x21AE, 0x21AE}, {0x21AF, 0x21B7}, {0x21BA, 0x21CD}, - {0x21CE, 0x21CF}, {0x21D0, 0x21D1}, {0x21D3, 0x21D3}, - {0x21D5, 0x21E6}, {0x21E8, 0x21F3}, {0x21F4, 0x21FF}, - {0x2201, 0x2201}, {0x2204, 0x2206}, {0x2209, 0x220A}, - {0x220C, 0x220E}, {0x2210, 0x2210}, {0x2212, 0x2214}, - {0x2216, 0x2219}, {0x221B, 0x221C}, {0x2221, 0x2222}, - {0x2224, 0x2224}, {0x2226, 0x2226}, {0x222D, 0x222D}, - {0x222F, 0x2233}, {0x2238, 0x223B}, {0x223E, 0x2247}, - {0x2249, 0x224B}, {0x224D, 0x2251}, {0x2253, 0x225F}, - {0x2262, 0x2263}, {0x2268, 0x2269}, {0x226C, 0x226D}, - {0x2270, 0x2281}, {0x2284, 0x2285}, {0x2288, 0x2294}, - {0x2296, 0x2298}, {0x229A, 0x22A4}, {0x22A6, 0x22BE}, - {0x22C0, 0x22FF}, {0x2300, 0x2307}, {0x2308, 0x2308}, - {0x2309, 0x2309}, {0x230A, 0x230A}, {0x230B, 0x230B}, - {0x230C, 0x2311}, {0x2313, 0x2319}, {0x231C, 0x231F}, - {0x2320, 0x2321}, {0x2322, 0x2328}, {0x232B, 0x237B}, - {0x237C, 0x237C}, {0x237D, 0x239A}, {0x239B, 0x23B3}, - {0x23B4, 0x23DB}, {0x23DC, 0x23E1}, {0x23E2, 0x23E8}, - {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, - {0x2400, 0x2426}, {0x2440, 0x244A}, {0x24EA, 0x24EA}, - {0x254C, 0x254F}, {0x2574, 0x257F}, {0x2590, 0x2591}, - {0x2596, 0x259F}, {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, - {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, - {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, - {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, {0x25F0, 0x25F7}, - {0x25F8, 0x25FC}, {0x25FF, 0x25FF}, {0x2600, 0x2604}, + {0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7}, + {0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6}, + {0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206}, + {0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210}, + {0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C}, + {0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226}, + {0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B}, + {0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251}, + {0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269}, + {0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285}, + {0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4}, + {0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319}, + {0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF}, + {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, {0x2400, 0x2426}, + {0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F}, + {0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F}, + {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5}, + {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5}, + {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1}, + {0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F}, @@ -811,256 +684,98 @@ var neutral = table{ {0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B}, {0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756}, - {0x2758, 0x2767}, {0x2768, 0x2768}, {0x2769, 0x2769}, - {0x276A, 0x276A}, {0x276B, 0x276B}, {0x276C, 0x276C}, - {0x276D, 0x276D}, {0x276E, 0x276E}, {0x276F, 0x276F}, - {0x2770, 0x2770}, {0x2771, 0x2771}, {0x2772, 0x2772}, - {0x2773, 0x2773}, {0x2774, 0x2774}, {0x2775, 0x2775}, - {0x2780, 0x2793}, {0x2794, 0x2794}, {0x2798, 0x27AF}, - {0x27B1, 0x27BE}, {0x27C0, 0x27C4}, {0x27C5, 0x27C5}, - {0x27C6, 0x27C6}, {0x27C7, 0x27E5}, {0x27EE, 0x27EE}, - {0x27EF, 0x27EF}, {0x27F0, 0x27FF}, {0x2800, 0x28FF}, - {0x2900, 0x297F}, {0x2980, 0x2982}, {0x2983, 0x2983}, - {0x2984, 0x2984}, {0x2987, 0x2987}, {0x2988, 0x2988}, - {0x2989, 0x2989}, {0x298A, 0x298A}, {0x298B, 0x298B}, - {0x298C, 0x298C}, {0x298D, 0x298D}, {0x298E, 0x298E}, - {0x298F, 0x298F}, {0x2990, 0x2990}, {0x2991, 0x2991}, - {0x2992, 0x2992}, {0x2993, 0x2993}, {0x2994, 0x2994}, - {0x2995, 0x2995}, {0x2996, 0x2996}, {0x2997, 0x2997}, - {0x2998, 0x2998}, {0x2999, 0x29D7}, {0x29D8, 0x29D8}, - {0x29D9, 0x29D9}, {0x29DA, 0x29DA}, {0x29DB, 0x29DB}, - {0x29DC, 0x29FB}, {0x29FC, 0x29FC}, {0x29FD, 0x29FD}, - {0x29FE, 0x29FF}, {0x2A00, 0x2AFF}, {0x2B00, 0x2B1A}, - {0x2B1D, 0x2B2F}, {0x2B30, 0x2B44}, {0x2B45, 0x2B46}, - {0x2B47, 0x2B4C}, {0x2B4D, 0x2B4F}, {0x2B51, 0x2B54}, + {0x2758, 0x2775}, {0x2780, 0x2794}, {0x2798, 0x27AF}, + {0x27B1, 0x27BE}, {0x27C0, 0x27E5}, {0x27EE, 0x2984}, + {0x2987, 0x2B1A}, {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9}, {0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF}, - {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2C7B}, - {0x2C7C, 0x2C7D}, {0x2C7E, 0x2C7F}, {0x2C80, 0x2CE4}, - {0x2CE5, 0x2CEA}, {0x2CEB, 0x2CEE}, {0x2CEF, 0x2CF1}, - {0x2CF2, 0x2CF3}, {0x2CF9, 0x2CFC}, {0x2CFD, 0x2CFD}, - {0x2CFE, 0x2CFF}, {0x2D00, 0x2D25}, {0x2D27, 0x2D27}, - {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D6F}, - {0x2D70, 0x2D70}, {0x2D7F, 0x2D7F}, {0x2D80, 0x2D96}, + {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2CF3}, + {0x2CF9, 0x2D25}, {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, + {0x2D30, 0x2D67}, {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, - {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2DFF}, - {0x2E00, 0x2E01}, {0x2E02, 0x2E02}, {0x2E03, 0x2E03}, - {0x2E04, 0x2E04}, {0x2E05, 0x2E05}, {0x2E06, 0x2E08}, - {0x2E09, 0x2E09}, {0x2E0A, 0x2E0A}, {0x2E0B, 0x2E0B}, - {0x2E0C, 0x2E0C}, {0x2E0D, 0x2E0D}, {0x2E0E, 0x2E16}, - {0x2E17, 0x2E17}, {0x2E18, 0x2E19}, {0x2E1A, 0x2E1A}, - {0x2E1B, 0x2E1B}, {0x2E1C, 0x2E1C}, {0x2E1D, 0x2E1D}, - {0x2E1E, 0x2E1F}, {0x2E20, 0x2E20}, {0x2E21, 0x2E21}, - {0x2E22, 0x2E22}, {0x2E23, 0x2E23}, {0x2E24, 0x2E24}, - {0x2E25, 0x2E25}, {0x2E26, 0x2E26}, {0x2E27, 0x2E27}, - {0x2E28, 0x2E28}, {0x2E29, 0x2E29}, {0x2E2A, 0x2E2E}, - {0x2E2F, 0x2E2F}, {0x2E30, 0x2E39}, {0x2E3A, 0x2E3B}, - {0x2E3C, 0x2E3F}, {0x2E40, 0x2E40}, {0x2E41, 0x2E41}, - {0x2E42, 0x2E42}, {0x2E43, 0x2E44}, {0x303F, 0x303F}, - {0x4DC0, 0x4DFF}, {0xA4D0, 0xA4F7}, {0xA4F8, 0xA4FD}, - {0xA4FE, 0xA4FF}, {0xA500, 0xA60B}, {0xA60C, 0xA60C}, - {0xA60D, 0xA60F}, {0xA610, 0xA61F}, {0xA620, 0xA629}, - {0xA62A, 0xA62B}, {0xA640, 0xA66D}, {0xA66E, 0xA66E}, - {0xA66F, 0xA66F}, {0xA670, 0xA672}, {0xA673, 0xA673}, - {0xA674, 0xA67D}, {0xA67E, 0xA67E}, {0xA67F, 0xA67F}, - {0xA680, 0xA69B}, {0xA69C, 0xA69D}, {0xA69E, 0xA69F}, - {0xA6A0, 0xA6E5}, {0xA6E6, 0xA6EF}, {0xA6F0, 0xA6F1}, - {0xA6F2, 0xA6F7}, {0xA700, 0xA716}, {0xA717, 0xA71F}, - {0xA720, 0xA721}, {0xA722, 0xA76F}, {0xA770, 0xA770}, - {0xA771, 0xA787}, {0xA788, 0xA788}, {0xA789, 0xA78A}, - {0xA78B, 0xA78E}, {0xA78F, 0xA78F}, {0xA790, 0xA7AE}, - {0xA7B0, 0xA7B7}, {0xA7F7, 0xA7F7}, {0xA7F8, 0xA7F9}, - {0xA7FA, 0xA7FA}, {0xA7FB, 0xA7FF}, {0xA800, 0xA801}, - {0xA802, 0xA802}, {0xA803, 0xA805}, {0xA806, 0xA806}, - {0xA807, 0xA80A}, {0xA80B, 0xA80B}, {0xA80C, 0xA822}, - {0xA823, 0xA824}, {0xA825, 0xA826}, {0xA827, 0xA827}, - {0xA828, 0xA82B}, {0xA830, 0xA835}, {0xA836, 0xA837}, - {0xA838, 0xA838}, {0xA839, 0xA839}, {0xA840, 0xA873}, - {0xA874, 0xA877}, {0xA880, 0xA881}, {0xA882, 0xA8B3}, - {0xA8B4, 0xA8C3}, {0xA8C4, 0xA8C5}, {0xA8CE, 0xA8CF}, - {0xA8D0, 0xA8D9}, {0xA8E0, 0xA8F1}, {0xA8F2, 0xA8F7}, - {0xA8F8, 0xA8FA}, {0xA8FB, 0xA8FB}, {0xA8FC, 0xA8FC}, - {0xA8FD, 0xA8FD}, {0xA900, 0xA909}, {0xA90A, 0xA925}, - {0xA926, 0xA92D}, {0xA92E, 0xA92F}, {0xA930, 0xA946}, - {0xA947, 0xA951}, {0xA952, 0xA953}, {0xA95F, 0xA95F}, - {0xA980, 0xA982}, {0xA983, 0xA983}, {0xA984, 0xA9B2}, - {0xA9B3, 0xA9B3}, {0xA9B4, 0xA9B5}, {0xA9B6, 0xA9B9}, - {0xA9BA, 0xA9BB}, {0xA9BC, 0xA9BC}, {0xA9BD, 0xA9C0}, - {0xA9C1, 0xA9CD}, {0xA9CF, 0xA9CF}, {0xA9D0, 0xA9D9}, - {0xA9DE, 0xA9DF}, {0xA9E0, 0xA9E4}, {0xA9E5, 0xA9E5}, - {0xA9E6, 0xA9E6}, {0xA9E7, 0xA9EF}, {0xA9F0, 0xA9F9}, - {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA29, 0xAA2E}, - {0xAA2F, 0xAA30}, {0xAA31, 0xAA32}, {0xAA33, 0xAA34}, - {0xAA35, 0xAA36}, {0xAA40, 0xAA42}, {0xAA43, 0xAA43}, - {0xAA44, 0xAA4B}, {0xAA4C, 0xAA4C}, {0xAA4D, 0xAA4D}, - {0xAA50, 0xAA59}, {0xAA5C, 0xAA5F}, {0xAA60, 0xAA6F}, - {0xAA70, 0xAA70}, {0xAA71, 0xAA76}, {0xAA77, 0xAA79}, - {0xAA7A, 0xAA7A}, {0xAA7B, 0xAA7B}, {0xAA7C, 0xAA7C}, - {0xAA7D, 0xAA7D}, {0xAA7E, 0xAA7F}, {0xAA80, 0xAAAF}, - {0xAAB0, 0xAAB0}, {0xAAB1, 0xAAB1}, {0xAAB2, 0xAAB4}, - {0xAAB5, 0xAAB6}, {0xAAB7, 0xAAB8}, {0xAAB9, 0xAABD}, - {0xAABE, 0xAABF}, {0xAAC0, 0xAAC0}, {0xAAC1, 0xAAC1}, - {0xAAC2, 0xAAC2}, {0xAADB, 0xAADC}, {0xAADD, 0xAADD}, - {0xAADE, 0xAADF}, {0xAAE0, 0xAAEA}, {0xAAEB, 0xAAEB}, - {0xAAEC, 0xAAED}, {0xAAEE, 0xAAEF}, {0xAAF0, 0xAAF1}, - {0xAAF2, 0xAAF2}, {0xAAF3, 0xAAF4}, {0xAAF5, 0xAAF5}, - {0xAAF6, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, + {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E44}, + {0x303F, 0x303F}, {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, + {0xA640, 0xA6F7}, {0xA700, 0xA7AE}, {0xA7B0, 0xA7B7}, + {0xA7F7, 0xA82B}, {0xA830, 0xA839}, {0xA840, 0xA877}, + {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, {0xA8E0, 0xA8FD}, + {0xA900, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD}, + {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36}, + {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2}, + {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, - {0xAB30, 0xAB5A}, {0xAB5B, 0xAB5B}, {0xAB5C, 0xAB5F}, - {0xAB60, 0xAB65}, {0xAB70, 0xABBF}, {0xABC0, 0xABE2}, - {0xABE3, 0xABE4}, {0xABE5, 0xABE5}, {0xABE6, 0xABE7}, - {0xABE8, 0xABE8}, {0xABE9, 0xABEA}, {0xABEB, 0xABEB}, - {0xABEC, 0xABEC}, {0xABED, 0xABED}, {0xABF0, 0xABF9}, - {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDB7F}, - {0xDB80, 0xDBFF}, {0xDC00, 0xDFFF}, {0xFB00, 0xFB06}, - {0xFB13, 0xFB17}, {0xFB1D, 0xFB1D}, {0xFB1E, 0xFB1E}, - {0xFB1F, 0xFB28}, {0xFB29, 0xFB29}, {0xFB2A, 0xFB36}, + {0xAB30, 0xAB65}, {0xAB70, 0xABED}, {0xABF0, 0xABF9}, + {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF}, + {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, - {0xFB43, 0xFB44}, {0xFB46, 0xFB4F}, {0xFB50, 0xFBB1}, - {0xFBB2, 0xFBC1}, {0xFBD3, 0xFD3D}, {0xFD3E, 0xFD3E}, - {0xFD3F, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, - {0xFDF0, 0xFDFB}, {0xFDFC, 0xFDFC}, {0xFDFD, 0xFDFD}, + {0xFB43, 0xFB44}, {0xFB46, 0xFBC1}, {0xFBD3, 0xFD3F}, + {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, - {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFC, 0xFFFC}, - {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, - {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D}, - {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133}, - {0x10137, 0x1013F}, {0x10140, 0x10174}, {0x10175, 0x10178}, - {0x10179, 0x10189}, {0x1018A, 0x1018B}, {0x1018C, 0x1018E}, - {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, - {0x101FD, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0}, - {0x102E0, 0x102E0}, {0x102E1, 0x102FB}, {0x10300, 0x1031F}, - {0x10320, 0x10323}, {0x10330, 0x10340}, {0x10341, 0x10341}, - {0x10342, 0x10349}, {0x1034A, 0x1034A}, {0x10350, 0x10375}, - {0x10376, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x1039F}, - {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x103D0, 0x103D0}, - {0x103D1, 0x103D5}, {0x10400, 0x1044F}, {0x10450, 0x1047F}, - {0x10480, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B}, + {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D}, + {0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA}, + {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E}, + {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD}, + {0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB}, + {0x10300, 0x10323}, {0x10330, 0x1034A}, {0x10350, 0x1037A}, + {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5}, + {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, - {0x1083F, 0x1083F}, {0x10840, 0x10855}, {0x10857, 0x10857}, - {0x10858, 0x1085F}, {0x10860, 0x10876}, {0x10877, 0x10878}, - {0x10879, 0x1087F}, {0x10880, 0x1089E}, {0x108A7, 0x108AF}, - {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x108FF}, - {0x10900, 0x10915}, {0x10916, 0x1091B}, {0x1091F, 0x1091F}, - {0x10920, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x1099F}, - {0x109A0, 0x109B7}, {0x109BC, 0x109BD}, {0x109BE, 0x109BF}, - {0x109C0, 0x109CF}, {0x109D2, 0x109FF}, {0x10A00, 0x10A00}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10A40, 0x10A47}, - {0x10A50, 0x10A58}, {0x10A60, 0x10A7C}, {0x10A7D, 0x10A7E}, - {0x10A7F, 0x10A7F}, {0x10A80, 0x10A9C}, {0x10A9D, 0x10A9F}, - {0x10AC0, 0x10AC7}, {0x10AC8, 0x10AC8}, {0x10AC9, 0x10AE4}, - {0x10AE5, 0x10AE6}, {0x10AEB, 0x10AEF}, {0x10AF0, 0x10AF6}, - {0x10B00, 0x10B35}, {0x10B39, 0x10B3F}, {0x10B40, 0x10B55}, - {0x10B58, 0x10B5F}, {0x10B60, 0x10B72}, {0x10B78, 0x10B7F}, - {0x10B80, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, + {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF}, + {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B}, + {0x1091F, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x109B7}, + {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06}, + {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A47}, {0x10A50, 0x10A58}, + {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6}, + {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72}, + {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, - {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x11000}, - {0x11001, 0x11001}, {0x11002, 0x11002}, {0x11003, 0x11037}, - {0x11038, 0x11046}, {0x11047, 0x1104D}, {0x11052, 0x11065}, - {0x11066, 0x1106F}, {0x1107F, 0x1107F}, {0x11080, 0x11081}, - {0x11082, 0x11082}, {0x11083, 0x110AF}, {0x110B0, 0x110B2}, - {0x110B3, 0x110B6}, {0x110B7, 0x110B8}, {0x110B9, 0x110BA}, - {0x110BB, 0x110BC}, {0x110BD, 0x110BD}, {0x110BE, 0x110C1}, - {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11102}, - {0x11103, 0x11126}, {0x11127, 0x1112B}, {0x1112C, 0x1112C}, - {0x1112D, 0x11134}, {0x11136, 0x1113F}, {0x11140, 0x11143}, - {0x11150, 0x11172}, {0x11173, 0x11173}, {0x11174, 0x11175}, - {0x11176, 0x11176}, {0x11180, 0x11181}, {0x11182, 0x11182}, - {0x11183, 0x111B2}, {0x111B3, 0x111B5}, {0x111B6, 0x111BE}, - {0x111BF, 0x111C0}, {0x111C1, 0x111C4}, {0x111C5, 0x111C9}, - {0x111CA, 0x111CC}, {0x111CD, 0x111CD}, {0x111D0, 0x111D9}, - {0x111DA, 0x111DA}, {0x111DB, 0x111DB}, {0x111DC, 0x111DC}, - {0x111DD, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, - {0x11213, 0x1122B}, {0x1122C, 0x1122E}, {0x1122F, 0x11231}, - {0x11232, 0x11233}, {0x11234, 0x11234}, {0x11235, 0x11235}, - {0x11236, 0x11237}, {0x11238, 0x1123D}, {0x1123E, 0x1123E}, + {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x1104D}, + {0x11052, 0x1106F}, {0x1107F, 0x110C1}, {0x110D0, 0x110E8}, + {0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11143}, + {0x11150, 0x11176}, {0x11180, 0x111CD}, {0x111D0, 0x111DF}, + {0x111E1, 0x111F4}, {0x11200, 0x11211}, {0x11213, 0x1123E}, {0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D}, - {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112A9, 0x112A9}, - {0x112B0, 0x112DE}, {0x112DF, 0x112DF}, {0x112E0, 0x112E2}, - {0x112E3, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11301}, - {0x11302, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, - {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, - {0x11335, 0x11339}, {0x1133C, 0x1133C}, {0x1133D, 0x1133D}, - {0x1133E, 0x1133F}, {0x11340, 0x11340}, {0x11341, 0x11344}, + {0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, + {0x112F0, 0x112F9}, {0x11300, 0x11303}, {0x11305, 0x1130C}, + {0x1130F, 0x11310}, {0x11313, 0x11328}, {0x1132A, 0x11330}, + {0x11332, 0x11333}, {0x11335, 0x11339}, {0x1133C, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350}, - {0x11357, 0x11357}, {0x1135D, 0x11361}, {0x11362, 0x11363}, - {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x11434}, - {0x11435, 0x11437}, {0x11438, 0x1143F}, {0x11440, 0x11441}, - {0x11442, 0x11444}, {0x11445, 0x11445}, {0x11446, 0x11446}, - {0x11447, 0x1144A}, {0x1144B, 0x1144F}, {0x11450, 0x11459}, - {0x1145B, 0x1145B}, {0x1145D, 0x1145D}, {0x11480, 0x114AF}, - {0x114B0, 0x114B2}, {0x114B3, 0x114B8}, {0x114B9, 0x114B9}, - {0x114BA, 0x114BA}, {0x114BB, 0x114BE}, {0x114BF, 0x114C0}, - {0x114C1, 0x114C1}, {0x114C2, 0x114C3}, {0x114C4, 0x114C5}, - {0x114C6, 0x114C6}, {0x114C7, 0x114C7}, {0x114D0, 0x114D9}, - {0x11580, 0x115AE}, {0x115AF, 0x115B1}, {0x115B2, 0x115B5}, - {0x115B8, 0x115BB}, {0x115BC, 0x115BD}, {0x115BE, 0x115BE}, - {0x115BF, 0x115C0}, {0x115C1, 0x115D7}, {0x115D8, 0x115DB}, - {0x115DC, 0x115DD}, {0x11600, 0x1162F}, {0x11630, 0x11632}, - {0x11633, 0x1163A}, {0x1163B, 0x1163C}, {0x1163D, 0x1163D}, - {0x1163E, 0x1163E}, {0x1163F, 0x11640}, {0x11641, 0x11643}, - {0x11644, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, - {0x11680, 0x116AA}, {0x116AB, 0x116AB}, {0x116AC, 0x116AC}, - {0x116AD, 0x116AD}, {0x116AE, 0x116AF}, {0x116B0, 0x116B5}, - {0x116B6, 0x116B6}, {0x116B7, 0x116B7}, {0x116C0, 0x116C9}, - {0x11700, 0x11719}, {0x1171D, 0x1171F}, {0x11720, 0x11721}, - {0x11722, 0x11725}, {0x11726, 0x11726}, {0x11727, 0x1172B}, - {0x11730, 0x11739}, {0x1173A, 0x1173B}, {0x1173C, 0x1173E}, - {0x1173F, 0x1173F}, {0x118A0, 0x118DF}, {0x118E0, 0x118E9}, - {0x118EA, 0x118F2}, {0x118FF, 0x118FF}, {0x11AC0, 0x11AF8}, - {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C2F, 0x11C2F}, - {0x11C30, 0x11C36}, {0x11C38, 0x11C3D}, {0x11C3E, 0x11C3E}, - {0x11C3F, 0x11C3F}, {0x11C40, 0x11C40}, {0x11C41, 0x11C45}, - {0x11C50, 0x11C59}, {0x11C5A, 0x11C6C}, {0x11C70, 0x11C71}, - {0x11C72, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CA9}, - {0x11CAA, 0x11CB0}, {0x11CB1, 0x11CB1}, {0x11CB2, 0x11CB3}, - {0x11CB4, 0x11CB4}, {0x11CB5, 0x11CB6}, {0x12000, 0x12399}, + {0x11357, 0x11357}, {0x1135D, 0x11363}, {0x11366, 0x1136C}, + {0x11370, 0x11374}, {0x11400, 0x11459}, {0x1145B, 0x1145B}, + {0x1145D, 0x1145D}, {0x11480, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644}, + {0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B7}, + {0x116C0, 0x116C9}, {0x11700, 0x11719}, {0x1171D, 0x1172B}, + {0x11730, 0x1173F}, {0x118A0, 0x118F2}, {0x118FF, 0x118FF}, + {0x11AC0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, + {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, + {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x12000, 0x12399}, {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F}, - {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF4}, {0x16AF5, 0x16AF5}, - {0x16B00, 0x16B2F}, {0x16B30, 0x16B36}, {0x16B37, 0x16B3B}, - {0x16B3C, 0x16B3F}, {0x16B40, 0x16B43}, {0x16B44, 0x16B44}, - {0x16B45, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, - {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, - {0x16F50, 0x16F50}, {0x16F51, 0x16F7E}, {0x16F8F, 0x16F92}, - {0x16F93, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, - {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9C}, - {0x1BC9D, 0x1BC9E}, {0x1BC9F, 0x1BC9F}, {0x1BCA0, 0x1BCA3}, - {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, - {0x1D165, 0x1D166}, {0x1D167, 0x1D169}, {0x1D16A, 0x1D16C}, - {0x1D16D, 0x1D172}, {0x1D173, 0x1D17A}, {0x1D17B, 0x1D182}, - {0x1D183, 0x1D184}, {0x1D185, 0x1D18B}, {0x1D18C, 0x1D1A9}, - {0x1D1AA, 0x1D1AD}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, - {0x1D242, 0x1D244}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, - {0x1D360, 0x1D371}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, - {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, - {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, - {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, - {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, - {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, - {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, - {0x1D6C1, 0x1D6C1}, {0x1D6C2, 0x1D6DA}, {0x1D6DB, 0x1D6DB}, - {0x1D6DC, 0x1D6FA}, {0x1D6FB, 0x1D6FB}, {0x1D6FC, 0x1D714}, - {0x1D715, 0x1D715}, {0x1D716, 0x1D734}, {0x1D735, 0x1D735}, - {0x1D736, 0x1D74E}, {0x1D74F, 0x1D74F}, {0x1D750, 0x1D76E}, - {0x1D76F, 0x1D76F}, {0x1D770, 0x1D788}, {0x1D789, 0x1D789}, - {0x1D78A, 0x1D7A8}, {0x1D7A9, 0x1D7A9}, {0x1D7AA, 0x1D7C2}, - {0x1D7C3, 0x1D7C3}, {0x1D7C4, 0x1D7CB}, {0x1D7CE, 0x1D7FF}, - {0x1D800, 0x1D9FF}, {0x1DA00, 0x1DA36}, {0x1DA37, 0x1DA3A}, - {0x1DA3B, 0x1DA6C}, {0x1DA6D, 0x1DA74}, {0x1DA75, 0x1DA75}, - {0x1DA76, 0x1DA83}, {0x1DA84, 0x1DA84}, {0x1DA85, 0x1DA86}, - {0x1DA87, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, - {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, - {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, - {0x1E8C7, 0x1E8CF}, {0x1E8D0, 0x1E8D6}, {0x1E900, 0x1E943}, - {0x1E944, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, + {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, + {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, + {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, {0x16F50, 0x16F7E}, + {0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1E8}, + {0x1D200, 0x1D245}, {0x1D300, 0x1D356}, {0x1D360, 0x1D371}, + {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, + {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, + {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, + {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, + {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, + {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, + {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6}, + {0x1E900, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, @@ -1091,12 +806,16 @@ var neutral = table{ // Condition have flag EastAsianWidth whether the current locale is CJK or not. type Condition struct { - EastAsianWidth bool + EastAsianWidth bool + ZeroWidthJoiner bool } // NewCondition return new instance of Condition which is current locale. func NewCondition() *Condition { - return &Condition{EastAsianWidth} + return &Condition{ + EastAsianWidth: EastAsianWidth, + ZeroWidthJoiner: ZeroWidthJoiner, + } } // RuneWidth returns the number of cells in r. @@ -1114,14 +833,37 @@ func (c *Condition) RuneWidth(r rune) int { } } -// StringWidth return width as you can see -func (c *Condition) StringWidth(s string) (width int) { +func (c *Condition) stringWidth(s string) (width int) { for _, r := range []rune(s) { width += c.RuneWidth(r) } return width } +func (c *Condition) stringWidthZeroJoiner(s string) (width int) { + r1, r2 := rune(0), rune(0) + for _, r := range []rune(s) { + if r == 0xFE0E || r == 0xFE0F { + continue + } + w := c.RuneWidth(r) + if r2 == 0x200D && inTables(r, emoji) && inTables(r1, emoji) { + w = 0 + } + width += w + r1, r2 = r2, r + } + return width +} + +// StringWidth return width as you can see +func (c *Condition) StringWidth(s string) (width int) { + if c.ZeroWidthJoiner { + return c.stringWidthZeroJoiner(s) + } + return c.stringWidth(s) +} + // Truncate return string truncated with w cells func (c *Condition) Truncate(s string, w int, tail string) string { if c.StringWidth(s) <= w { diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go new file mode 100644 index 0000000000..7d99f6e521 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go @@ -0,0 +1,8 @@ +// +build appengine + +package runewidth + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + return false +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go index 0ce32c5e7b..c5fdf40baa 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_js.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -1,4 +1,5 @@ // +build js +// +build !appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go index c579e9a314..66a58b5d87 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -1,4 +1,6 @@ -// +build !windows,!js +// +build !windows +// +build !js +// +build !appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go index 0258876b99..d6a61777d7 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -1,3 +1,6 @@ +// +build windows +// +build !appengine + package runewidth import ( diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index 92d71ed48b..33bf20b935 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -233,7 +233,7 @@ table.Render() #### Table with color Output ![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) -#### Example 6 - Set table caption +#### Example 7 - Set table caption ```go data := [][]string{ []string{"A", "The Good", "500"}, @@ -254,7 +254,7 @@ table.Render() // Send output Note: Caption text will wrap with total width of rendered table. -##### Output 6 +##### Output 7 ``` +------+-----------------------+--------+ | NAME | SIGN | RATING | @@ -267,6 +267,41 @@ Note: Caption text will wrap with total width of rendered table. Movie ratings. ``` +#### Example 8 - Set NoWhiteSpace and TablePadding option +```go +data := [][]string{ + {"node1.example.com", "Ready", "compute", "1.11"}, + {"node2.example.com", "Ready", "compute", "1.11"}, + {"node3.example.com", "Ready", "compute", "1.11"}, + {"node4.example.com", "NotReady", "compute", "1.11"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Status", "Role", "Version"}) +table.SetAutoWrapText(false) +table.SetAutoFormatHeaders(true) +table.SetHeaderAlignment(ALIGN_LEFT) +table.SetAlignment(ALIGN_LEFT) +table.SetCenterSeparator("") +table.SetColumnSeparator("") +table.SetRowSeparator("") +table.SetHeaderLine(false) +table.SetBorder(false) +table.SetTablePadding("\t") // pad with tabs +table.SetNoWhiteSpace(true) +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 8 +``` +NAME STATUS ROLE VERSION +node1.example.com Ready compute 1.11 +node2.example.com Ready compute 1.11 +node3.example.com Ready compute 1.11 +node4.example.com NotReady compute 1.11 +``` + #### Render table into a string Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example: @@ -283,7 +318,7 @@ import ( func main() { tableString := &strings.Builder{} - table := tablewriter.NewWriter(tableString) + table := tablewriter.NewWriter(tableString) /* * Code to fill the table diff --git a/vendor/github.com/olekukonko/tablewriter/go.mod b/vendor/github.com/olekukonko/tablewriter/go.mod new file mode 100644 index 0000000000..84b405d35d --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/go.mod @@ -0,0 +1,8 @@ +module github.com/olekukonko/tablewriter + +go 1.12 + +require ( + github.com/mattn/go-runewidth v0.0.4 + github.com/olekukonko/tablewriter v0.0.1 +) diff --git a/vendor/github.com/olekukonko/tablewriter/go.sum b/vendor/github.com/olekukonko/tablewriter/go.sum new file mode 100644 index 0000000000..9d5e335275 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/go.sum @@ -0,0 +1,4 @@ +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go index 3cf09969e6..4c206c8914 100644 --- a/vendor/github.com/olekukonko/tablewriter/table.go +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -72,6 +72,8 @@ type Table struct { newLine string rowLine bool autoMergeCells bool + noWhiteSpace bool + tablePadding string hdrLine bool borders Border colSize int @@ -225,6 +227,16 @@ func (t *Table) SetAlignment(align int) { t.align = align } +// Set No White Space +func (t *Table) SetNoWhiteSpace(allow bool) { + t.noWhiteSpace = allow +} + +// Set Table Padding +func (t *Table) SetTablePadding(padding string) { + t.tablePadding = padding +} + func (t *Table) SetColumnAlignment(keys []int) { for _, v := range keys { switch v { @@ -411,11 +423,14 @@ func (t *Table) printHeading() { for x := 0; x < max; x++ { // Check if border is set // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } for y := 0; y <= end; y++ { v := t.cs[y] h := "" + if y < len(t.headers) && x < len(t.headers[y]) { h = t.headers[y][x] } @@ -423,15 +438,30 @@ func (t *Table) printHeading() { h = Title(h) } pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn) - + if t.noWhiteSpace { + pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding) + } if is_esc_seq { - fmt.Fprintf(t.out, " %s %s", - format(padFunc(h, SPACE, v), - t.headerParams[y]), pad) + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } else { + fmt.Fprintf(t.out, "%s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } } else { - fmt.Fprintf(t.out, " %s %s", - padFunc(h, SPACE, v), - pad) + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + padFunc(h, SPACE, v), + pad) + } else { + // the spaces between breaks the kube formatting + fmt.Fprintf(t.out, "%s%s", + padFunc(h, SPACE, v), + pad) + } } } // Next line @@ -654,9 +684,11 @@ func (t *Table) printRow(columns [][]string, rowIdx int) { for y := 0; y < total; y++ { // Check if border is set - fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + fmt.Fprintf(t.out, SPACE) + } - fmt.Fprintf(t.out, SPACE) str := columns[y][x] // Embedding escape sequence with column value @@ -688,11 +720,17 @@ func (t *Table) printRow(columns [][]string, rowIdx int) { } } - fmt.Fprintf(t.out, SPACE) + if !t.noWhiteSpace { + fmt.Fprintf(t.out, SPACE) + } else { + fmt.Fprintf(t.out, t.tablePadding) + } } // Check if border is set // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } fmt.Fprint(t.out, t.newLine) } @@ -766,7 +804,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx if t.autoMergeCells { //Store the full line to merge mutli-lines cells - fullLine := strings.Join(columns[y], " ") + fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. displayCellBorder = append(displayCellBorder, false) @@ -804,7 +842,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx //The new previous line is the current one previousLine = make([]string, total) for y := 0; y < total; y++ { - previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells } //Returns the newly added line and wether or not a border should be displayed above. return previousLine, displayCellBorder diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml index d8156a60ba..3deb4a1243 100644 --- a/vendor/github.com/pborman/uuid/.travis.yml +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -1,8 +1,9 @@ language: go go: - - 1.4.3 - - 1.5.3 + - "1.9" + - "1.10" + - "1.11" - tip script: diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md index b0396b2747..810ad40dc9 100644 --- a/vendor/github.com/pborman/uuid/README.md +++ b/vendor/github.com/pborman/uuid/README.md @@ -3,6 +3,8 @@ This project was automatically exported from code.google.com/p/go-uuid # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. +This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). + ###### Install `go get github.com/pborman/uuid` diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go index d8bd013e68..727d761674 100644 --- a/vendor/github.com/pborman/uuid/doc.go +++ b/vendor/github.com/pborman/uuid/doc.go @@ -4,5 +4,10 @@ // The uuid package generates and inspects UUIDs. // -// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// This package is a partial wrapper around the github.com/google/uuid package. +// This package represents a UUID as []byte while github.com/google/uuid +// represents a UUID as [16]byte. package uuid diff --git a/vendor/github.com/pborman/uuid/go.mod b/vendor/github.com/pborman/uuid/go.mod new file mode 100644 index 0000000000..099fc7de0d --- /dev/null +++ b/vendor/github.com/pborman/uuid/go.mod @@ -0,0 +1,3 @@ +module github.com/pborman/uuid + +require github.com/google/uuid v1.0.0 diff --git a/vendor/github.com/pborman/uuid/go.sum b/vendor/github.com/pborman/uuid/go.sum new file mode 100644 index 0000000000..db2574a9c3 --- /dev/null +++ b/vendor/github.com/pborman/uuid/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/vendor/github.com/pborman/uuid/marshal.go b/vendor/github.com/pborman/uuid/marshal.go index 6621dd54be..35b89352ad 100644 --- a/vendor/github.com/pborman/uuid/marshal.go +++ b/vendor/github.com/pborman/uuid/marshal.go @@ -7,6 +7,8 @@ package uuid import ( "errors" "fmt" + + guuid "github.com/google/uuid" ) // MarshalText implements encoding.TextMarshaler. @@ -60,11 +62,11 @@ func (u Array) MarshalText() ([]byte, error) { // UnmarshalText implements encoding.TextUnmarshaler. func (u *Array) UnmarshalText(data []byte) error { - id := Parse(string(data)) - if id == nil { - return errors.New("invalid UUID") + id, err := guuid.ParseBytes(data) + if err != nil { + return err } - *u = id.Array() + *u = Array(id) return nil } diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go index 42d60da8f1..e524e0101b 100644 --- a/vendor/github.com/pborman/uuid/node.go +++ b/vendor/github.com/pborman/uuid/node.go @@ -5,24 +5,14 @@ package uuid import ( - "net" - "sync" -) - -var ( - nodeMu sync.Mutex - interfaces []net.Interface // cached list of interfaces - ifname string // name of interface being used - nodeID []byte // hardware for version 1 UUIDs + guuid "github.com/google/uuid" ) // NodeInterface returns the name of the interface from which the NodeID was // derived. The interface "user" is returned if the NodeID was set by // SetNodeID. func NodeInterface() string { - defer nodeMu.Unlock() - nodeMu.Lock() - return ifname + return guuid.NodeInterface() } // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. @@ -32,77 +22,20 @@ func NodeInterface() string { // // SetNodeInterface never fails when name is "". func SetNodeInterface(name string) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - return setNodeInterface(name) -} - -func setNodeInterface(name string) bool { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil && name != "" { - return false - } - } - - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - if setNodeID(ifs.HardwareAddr) { - ifname = ifs.Name - return true - } - } - } - - // We found no interfaces with a valid hardware address. If name - // does not specify a specific interface generate a random Node ID - // (section 4.1.6) - if name == "" { - if nodeID == nil { - nodeID = make([]byte, 6) - } - randomBits(nodeID) - return true - } - return false + return guuid.SetNodeInterface(name) } // NodeID returns a slice of a copy of the current Node ID, setting the Node ID // if not already set. func NodeID() []byte { - defer nodeMu.Unlock() - nodeMu.Lock() - if nodeID == nil { - setNodeInterface("") - } - nid := make([]byte, 6) - copy(nid, nodeID) - return nid + return guuid.NodeID() } // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // of id are used. If id is less than 6 bytes then false is returned and the // Node ID is not set. func SetNodeID(id []byte) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - if setNodeID(id) { - ifname = "user" - return true - } - return false -} - -func setNodeID(id []byte) bool { - if len(id) < 6 { - return false - } - if nodeID == nil { - nodeID = make([]byte, 6) - } - copy(nodeID, id) - return true + return guuid.SetNodeID(id) } // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is diff --git a/vendor/github.com/pborman/uuid/sql.go b/vendor/github.com/pborman/uuid/sql.go index d015bfd132..929c3847e2 100644 --- a/vendor/github.com/pborman/uuid/sql.go +++ b/vendor/github.com/pborman/uuid/sql.go @@ -40,7 +40,9 @@ func (uuid *UUID) Scan(src interface{}) error { // assumes a simple slice of bytes if 16 bytes // otherwise attempts to parse if len(b) == 16 { - *uuid = UUID(b) + parsed := make([]byte, 16) + copy(parsed, b) + *uuid = UUID(parsed) } else { u := Parse(string(b)) diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go index eedf242194..5c0960d872 100644 --- a/vendor/github.com/pborman/uuid/time.go +++ b/vendor/github.com/pborman/uuid/time.go @@ -6,65 +6,18 @@ package uuid import ( "encoding/binary" - "sync" - "time" + + guuid "github.com/google/uuid" ) // A Time represents a time as the number of 100's of nanoseconds since 15 Oct // 1582. -type Time int64 - -const ( - lillian = 2299160 // Julian day of 15 Oct 1582 - unix = 2440587 // Julian day of 1 Jan 1970 - epoch = unix - lillian // Days between epochs - g1582 = epoch * 86400 // seconds between epochs - g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs -) - -var ( - timeMu sync.Mutex - lasttime uint64 // last time we returned - clock_seq uint16 // clock sequence for this run - - timeNow = time.Now // for testing -) - -// UnixTime converts t the number of seconds and nanoseconds using the Unix -// epoch of 1 Jan 1970. -func (t Time) UnixTime() (sec, nsec int64) { - sec = int64(t - g1582ns100) - nsec = (sec % 10000000) * 100 - sec /= 10000000 - return sec, nsec -} +type Time = guuid.Time // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and // clock sequence as well as adjusting the clock sequence as needed. An error // is returned if the current time cannot be determined. -func GetTime() (Time, uint16, error) { - defer timeMu.Unlock() - timeMu.Lock() - return getTime() -} - -func getTime() (Time, uint16, error) { - t := timeNow() - - // If we don't have a clock sequence already, set one. - if clock_seq == 0 { - setClockSequence(-1) - } - now := uint64(t.UnixNano()/100) + g1582ns100 - - // If time has gone backwards with this clock sequence then we - // increment the clock sequence - if now <= lasttime { - clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 - } - lasttime = now - return Time(now), clock_seq, nil -} +func GetTime() (Time, uint16, error) { return guuid.GetTime() } // ClockSequence returns the current clock sequence, generating one if not // already set. The clock sequence is only used for Version 1 UUIDs. @@ -74,39 +27,11 @@ func getTime() (Time, uint16, error) { // clock sequence is generated the first time a clock sequence is requested by // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated // for -func ClockSequence() int { - defer timeMu.Unlock() - timeMu.Lock() - return clockSequence() -} - -func clockSequence() int { - if clock_seq == 0 { - setClockSequence(-1) - } - return int(clock_seq & 0x3fff) -} +func ClockSequence() int { return guuid.ClockSequence() } // SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to // -1 causes a new sequence to be generated. -func SetClockSequence(seq int) { - defer timeMu.Unlock() - timeMu.Lock() - setClockSequence(seq) -} - -func setClockSequence(seq int) { - if seq == -1 { - var b [2]byte - randomBits(b[:]) // clock sequence - seq = int(b[0])<<8 | int(b[1]) - } - old_seq := clock_seq - clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if old_seq != clock_seq { - lasttime = 0 - } -} +func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in // uuid. It returns false if uuid is not valid. The time is only well defined diff --git a/vendor/github.com/pborman/uuid/util.go b/vendor/github.com/pborman/uuid/util.go index fc8e052c7a..255b5e2485 100644 --- a/vendor/github.com/pborman/uuid/util.go +++ b/vendor/github.com/pborman/uuid/util.go @@ -4,17 +4,6 @@ package uuid -import ( - "io" -) - -// randomBits completely fills slice b with random data. -func randomBits(b []byte) { - if _, err := io.ReadFull(rander, b); err != nil { - panic(err.Error()) // rand should never fail - } -} - // xvalues returns the value of a byte as a hexadecimal digit or 255. var xvalues = [256]byte{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go index 7c643cf0a3..3370004207 100644 --- a/vendor/github.com/pborman/uuid/uuid.go +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -8,9 +8,9 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "fmt" "io" - "strings" + + guuid "github.com/google/uuid" ) // Array is a pass-by-value UUID that can be used as an effecient key in a map. @@ -24,7 +24,7 @@ func (uuid Array) UUID() UUID { // String returns the string representation of uuid, // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. func (uuid Array) String() string { - return uuid.UUID().String() + return guuid.UUID(uuid).String() } // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -32,18 +32,18 @@ func (uuid Array) String() string { type UUID []byte // A Version represents a UUIDs version. -type Version byte +type Version = guuid.Version // A Variant represents a UUIDs variant. -type Variant byte +type Variant = guuid.Variant // Constants returned by Variant. const ( - Invalid = Variant(iota) // Invalid UUID - RFC4122 // The variant specified in RFC4122 - Reserved // Reserved, NCS backward compatibility. - Microsoft // Reserved, Microsoft Corporation backward compatibility. - Future // Reserved for future definition. + Invalid = guuid.Invalid // Invalid UUID + RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 + Reserved = guuid.Reserved // Reserved, NCS backward compatibility. + Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future = guuid.Future // Reserved for future definition. ) var rander = rand.Reader // random function @@ -54,35 +54,23 @@ func New() string { return NewRandom().String() } -// Parse decodes s into a UUID or returns nil. Both the UUID form of -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for +// the formats parsed. func Parse(s string) UUID { - if len(s) == 36+9 { - if strings.ToLower(s[:9]) != "urn:uuid:" { - return nil - } - s = s[9:] - } else if len(s) != 36 { - return nil - } - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return nil + gu, err := guuid.Parse(s) + if err == nil { + return gu[:] } - var uuid [16]byte - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(s[x:]); !ok { - return nil - } else { - uuid[i] = v - } + return nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + gu, err := guuid.ParseBytes(b) + if err == nil { + return gu[:], nil } - return uuid[:] + return nil, err } // Equal returns true if uuid1 and uuid2 are equal. @@ -163,29 +151,6 @@ func (uuid UUID) Version() (Version, bool) { return Version(uuid[6] >> 4), true } -func (v Version) String() string { - if v > 15 { - return fmt.Sprintf("BAD_VERSION_%d", v) - } - return fmt.Sprintf("VERSION_%d", v) -} - -func (v Variant) String() string { - switch v { - case RFC4122: - return "RFC4122" - case Reserved: - return "Reserved" - case Microsoft: - return "Microsoft" - case Future: - return "Future" - case Invalid: - return "Invalid" - } - return fmt.Sprintf("BadVariant%d", int(v)) -} - // SetRand sets the random number generator to r, which implements io.Reader. // If r.Read returns an error when the package requests random data then // a panic will be issued. @@ -193,9 +158,5 @@ func (v Variant) String() string { // Calling SetRand with nil sets the random number generator to the default // generator. func SetRand(r io.Reader) { - if r == nil { - rander = rand.Reader - return - } - rander = r + guuid.SetRand(r) } diff --git a/vendor/github.com/pborman/uuid/version1.go b/vendor/github.com/pborman/uuid/version1.go index 0127eacfab..7af948da79 100644 --- a/vendor/github.com/pborman/uuid/version1.go +++ b/vendor/github.com/pborman/uuid/version1.go @@ -5,7 +5,7 @@ package uuid import ( - "encoding/binary" + guuid "github.com/google/uuid" ) // NewUUID returns a Version 1 UUID based on the current NodeID and clock @@ -15,27 +15,9 @@ import ( // SetClockSequence then it will be set automatically. If GetTime fails to // return the current NewUUID returns nil. func NewUUID() UUID { - if nodeID == nil { - SetNodeInterface("") + gu, err := guuid.NewUUID() + if err == nil { + return UUID(gu[:]) } - - now, seq, err := GetTime() - if err != nil { - return nil - } - - uuid := make([]byte, 16) - - time_low := uint32(now & 0xffffffff) - time_mid := uint16((now >> 32) & 0xffff) - time_hi := uint16((now >> 48) & 0x0fff) - time_hi |= 0x1000 // Version 1 - - binary.BigEndian.PutUint32(uuid[0:], time_low) - binary.BigEndian.PutUint16(uuid[4:], time_mid) - binary.BigEndian.PutUint16(uuid[6:], time_hi) - binary.BigEndian.PutUint16(uuid[8:], seq) - copy(uuid[10:], nodeID) - - return uuid + return nil } diff --git a/vendor/github.com/pborman/uuid/version4.go b/vendor/github.com/pborman/uuid/version4.go index b3d4a368dd..b459d46d13 100644 --- a/vendor/github.com/pborman/uuid/version4.go +++ b/vendor/github.com/pborman/uuid/version4.go @@ -4,12 +4,14 @@ package uuid +import guuid "github.com/google/uuid" + // Random returns a Random (Version 4) UUID or panics. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. // -// A note about uniqueness derived from from the UUID Wikipedia entry: +// A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being // hit by a meteorite is estimated to be one chance in 17 billion, that @@ -17,9 +19,8 @@ package uuid // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() UUID { - uuid := make([]byte, 16) - randomBits([]byte(uuid)) - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid + if gu, err := guuid.NewRandom(); err == nil { + return UUID(gu[:]) + } + return nil } diff --git a/vendor/github.com/rds-swarm/config/config.go b/vendor/github.com/rds-swarm/config/config.go deleted file mode 100644 index 1884f140ea..0000000000 --- a/vendor/github.com/rds-swarm/config/config.go +++ /dev/null @@ -1,38 +0,0 @@ -package config - -import ( - "github.com/caarlos0/env" -) - -func init() { - env.Parse(&cfg) - env.Parse(&cfg.ResolverAddresses) -} - -// Configuration is the struct that holds the values of the network configuration -// env and envDefault are required by env library -// it corresponds with the os environment variable name and also its default value if omitted -type Configuration struct { - NetworkNodeAddress string `env:"RNS_NETWORK_NODE_ADDRESS" envDefault:"https://public-node.rsk.co"` - ResolverAddresses struct { - RSK string `env:"RNS_RESOLVER_ADDRESS_RSK" envDefault:"0x4efd25e3d348f8f25a14fb7655fba6f72edfe93a"` - MultiChain string `env:"RNS_RESOLVER_ADDRESS_MULTICHAIN" envDefault:"0x99a12be4C89CbF6CFD11d1F2c029904a7B644368"` - } -} - -var cfg Configuration = Configuration{} - -// GetConfiguration loads the environment variables into a Configuration struct and returns it. -func GetConfiguration() Configuration { - return cfg -} - -// SetRSKConfiguration overrides endpoint and contract to rns node -func SetRSKConfiguration(endpoint string, contract string) { - if endpoint != "" { - cfg.NetworkNodeAddress = endpoint - } - if contract != "" { - cfg.ResolverAddresses.RSK = contract - } -} diff --git a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json deleted file mode 100644 index 962eb5dd95..0000000000 --- a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json +++ /dev/null @@ -1,336 +0,0 @@ -[ - { - "inputs": [ - { - "name": "_rns", - "type": "address" - }, - { - "name": "_publicResolver", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "name": "content", - "type": "bytes32" - } - ], - "name": "ContentChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "name": "chain", - "type": "bytes4" - }, - { - "indexed": false, - "name": "metadata", - "type": "bytes32" - } - ], - "name": "ChainMetadataChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "name": "chain", - "type": "bytes4" - }, - { - "indexed": false, - "name": "addr", - "type": "string" - } - ], - "name": "ChainAddrChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "name": "addr", - "type": "address" - } - ], - "name": "AddrChanged", - "type": "event" - }, - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "addr", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "addrValue", - "type": "address" - } - ], - "name": "setAddr", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "content", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "contentValue", - "type": "bytes32" - } - ], - "name": "setContent", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - } - ], - "name": "chainAddr", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - }, - { - "name": "addrValue", - "type": "string" - } - ], - "name": "setChainAddr", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - } - ], - "name": "chainMetadata", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - }, - { - "name": "metadataValue", - "type": "bytes32" - } - ], - "name": "setChainMetadata", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - } - ], - "name": "chainAddrAndMetadata", - "outputs": [ - { - "name": "", - "type": "string" - }, - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "chain", - "type": "bytes4" - }, - { - "name": "addrValue", - "type": "string" - }, - { - "name": "metadataValue", - "type": "bytes32" - } - ], - "name": "setChainAddrWithMetadata", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ] \ No newline at end of file diff --git a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go b/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go deleted file mode 100644 index 0e4b1a3a21..0000000000 --- a/vendor/github.com/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go +++ /dev/null @@ -1,996 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package multichainresolver - -import ( - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = abi.U256 - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// MultichainresolverABI is the input ABI used to generate the binding from. -const MultichainresolverABI = "[{\"inputs\":[{\"name\":\"_rns\",\"type\":\"address\"},{\"name\":\"_publicResolver\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"content\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"metadata\",\"type\":\"bytes32\"}],\"name\":\"ChainMetadataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chain\",\"type\":\"bytes4\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"string\"}],\"name\":\"ChainAddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentValue\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddr\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"}],\"name\":\"setChainAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"}],\"name\":\"chainAddrAndMetadata\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"chain\",\"type\":\"bytes4\"},{\"name\":\"addrValue\",\"type\":\"string\"},{\"name\":\"metadataValue\",\"type\":\"bytes32\"}],\"name\":\"setChainAddrWithMetadata\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - -// Multichainresolver is an auto generated Go binding around an Ethereum contract. -type Multichainresolver struct { - MultichainresolverCaller // Read-only binding to the contract - MultichainresolverTransactor // Write-only binding to the contract - MultichainresolverFilterer // Log filterer for contract events -} - -// MultichainresolverCaller is an auto generated read-only Go binding around an Ethereum contract. -type MultichainresolverCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MultichainresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. -type MultichainresolverTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MultichainresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type MultichainresolverFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MultichainresolverSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type MultichainresolverSession struct { - Contract *Multichainresolver // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// MultichainresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type MultichainresolverCallerSession struct { - Contract *MultichainresolverCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// MultichainresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type MultichainresolverTransactorSession struct { - Contract *MultichainresolverTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// MultichainresolverRaw is an auto generated low-level Go binding around an Ethereum contract. -type MultichainresolverRaw struct { - Contract *Multichainresolver // Generic contract binding to access the raw methods on -} - -// MultichainresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type MultichainresolverCallerRaw struct { - Contract *MultichainresolverCaller // Generic read-only contract binding to access the raw methods on -} - -// MultichainresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type MultichainresolverTransactorRaw struct { - Contract *MultichainresolverTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewMultichainresolver creates a new instance of Multichainresolver, bound to a specific deployed contract. -func NewMultichainresolver(address common.Address, backend bind.ContractBackend) (*Multichainresolver, error) { - contract, err := bindMultichainresolver(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Multichainresolver{MultichainresolverCaller: MultichainresolverCaller{contract: contract}, MultichainresolverTransactor: MultichainresolverTransactor{contract: contract}, MultichainresolverFilterer: MultichainresolverFilterer{contract: contract}}, nil -} - -// NewMultichainresolverCaller creates a new read-only instance of Multichainresolver, bound to a specific deployed contract. -func NewMultichainresolverCaller(address common.Address, caller bind.ContractCaller) (*MultichainresolverCaller, error) { - contract, err := bindMultichainresolver(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &MultichainresolverCaller{contract: contract}, nil -} - -// NewMultichainresolverTransactor creates a new write-only instance of Multichainresolver, bound to a specific deployed contract. -func NewMultichainresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*MultichainresolverTransactor, error) { - contract, err := bindMultichainresolver(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &MultichainresolverTransactor{contract: contract}, nil -} - -// NewMultichainresolverFilterer creates a new log filterer instance of Multichainresolver, bound to a specific deployed contract. -func NewMultichainresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*MultichainresolverFilterer, error) { - contract, err := bindMultichainresolver(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &MultichainresolverFilterer{contract: contract}, nil -} - -// bindMultichainresolver binds a generic wrapper to an already deployed contract. -func bindMultichainresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(MultichainresolverABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Multichainresolver *MultichainresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Multichainresolver.Contract.MultichainresolverCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Multichainresolver *MultichainresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Multichainresolver *MultichainresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Multichainresolver.Contract.MultichainresolverTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Multichainresolver *MultichainresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Multichainresolver.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Multichainresolver *MultichainresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Multichainresolver.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Multichainresolver *MultichainresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Multichainresolver.Contract.contract.Transact(opts, method, params...) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Multichainresolver *MultichainresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { - var ( - ret0 = new(common.Address) - ) - out := ret0 - err := _Multichainresolver.contract.Call(opts, out, "addr", node) - return *ret0, err -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Multichainresolver *MultichainresolverSession) Addr(node [32]byte) (common.Address, error) { - return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Multichainresolver *MultichainresolverCallerSession) Addr(node [32]byte) (common.Address, error) { - return _Multichainresolver.Contract.Addr(&_Multichainresolver.CallOpts, node) -} - -// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. -// -// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) -func (_Multichainresolver *MultichainresolverCaller) ChainAddr(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, error) { - var ( - ret0 = new(string) - ) - out := ret0 - err := _Multichainresolver.contract.Call(opts, out, "chainAddr", node, chain) - return *ret0, err -} - -// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. -// -// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) -func (_Multichainresolver *MultichainresolverSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { - return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) -} - -// ChainAddr is a free data retrieval call binding the contract method 0x8be4b5f6. -// -// Solidity: function chainAddr(bytes32 node, bytes4 chain) constant returns(string) -func (_Multichainresolver *MultichainresolverCallerSession) ChainAddr(node [32]byte, chain [4]byte) (string, error) { - return _Multichainresolver.Contract.ChainAddr(&_Multichainresolver.CallOpts, node, chain) -} - -// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. -// -// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) -func (_Multichainresolver *MultichainresolverCaller) ChainAddrAndMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) (string, [32]byte, error) { - var ( - ret0 = new(string) - ret1 = new([32]byte) - ) - out := &[]interface{}{ - ret0, - ret1, - } - err := _Multichainresolver.contract.Call(opts, out, "chainAddrAndMetadata", node, chain) - return *ret0, *ret1, err -} - -// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. -// -// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) -func (_Multichainresolver *MultichainresolverSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { - return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) -} - -// ChainAddrAndMetadata is a free data retrieval call binding the contract method 0x82e3bee6. -// -// Solidity: function chainAddrAndMetadata(bytes32 node, bytes4 chain) constant returns(string, bytes32) -func (_Multichainresolver *MultichainresolverCallerSession) ChainAddrAndMetadata(node [32]byte, chain [4]byte) (string, [32]byte, error) { - return _Multichainresolver.Contract.ChainAddrAndMetadata(&_Multichainresolver.CallOpts, node, chain) -} - -// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. -// -// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverCaller) ChainMetadata(opts *bind.CallOpts, node [32]byte, chain [4]byte) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Multichainresolver.contract.Call(opts, out, "chainMetadata", node, chain) - return *ret0, err -} - -// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. -// -// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { - return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) -} - -// ChainMetadata is a free data retrieval call binding the contract method 0xb34e8cd6. -// -// Solidity: function chainMetadata(bytes32 node, bytes4 chain) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverCallerSession) ChainMetadata(node [32]byte, chain [4]byte) ([32]byte, error) { - return _Multichainresolver.Contract.ChainMetadata(&_Multichainresolver.CallOpts, node, chain) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Multichainresolver.contract.Call(opts, out, "content", node) - return *ret0, err -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverSession) Content(node [32]byte) ([32]byte, error) { - return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Multichainresolver *MultichainresolverCallerSession) Content(node [32]byte) ([32]byte, error) { - return _Multichainresolver.Contract.Content(&_Multichainresolver.CallOpts, node) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) -func (_Multichainresolver *MultichainresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Multichainresolver.contract.Call(opts, out, "supportsInterface", interfaceId) - return *ret0, err -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) -func (_Multichainresolver *MultichainresolverSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) constant returns(bool) -func (_Multichainresolver *MultichainresolverCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Multichainresolver.Contract.SupportsInterface(&_Multichainresolver.CallOpts, interfaceId) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Multichainresolver *MultichainresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Multichainresolver.contract.Transact(opts, "setAddr", node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Multichainresolver *MultichainresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Multichainresolver *MultichainresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetAddr(&_Multichainresolver.TransactOpts, node, addrValue) -} - -// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. -// -// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() -func (_Multichainresolver *MultichainresolverTransactor) SetChainAddr(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { - return _Multichainresolver.contract.Transact(opts, "setChainAddr", node, chain, addrValue) -} - -// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. -// -// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() -func (_Multichainresolver *MultichainresolverSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) -} - -// SetChainAddr is a paid mutator transaction binding the contract method 0xd278b400. -// -// Solidity: function setChainAddr(bytes32 node, bytes4 chain, string addrValue) returns() -func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddr(node [32]byte, chain [4]byte, addrValue string) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainAddr(&_Multichainresolver.TransactOpts, node, chain, addrValue) -} - -// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. -// -// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverTransactor) SetChainAddrWithMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.contract.Transact(opts, "setChainAddrWithMetadata", node, chain, addrValue, metadataValue) -} - -// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. -// -// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) -} - -// SetChainAddrWithMetadata is a paid mutator transaction binding the contract method 0xe335bee4. -// -// Solidity: function setChainAddrWithMetadata(bytes32 node, bytes4 chain, string addrValue, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverTransactorSession) SetChainAddrWithMetadata(node [32]byte, chain [4]byte, addrValue string, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainAddrWithMetadata(&_Multichainresolver.TransactOpts, node, chain, addrValue, metadataValue) -} - -// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. -// -// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverTransactor) SetChainMetadata(opts *bind.TransactOpts, node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.contract.Transact(opts, "setChainMetadata", node, chain, metadataValue) -} - -// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. -// -// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) -} - -// SetChainMetadata is a paid mutator transaction binding the contract method 0x245d4d9a. -// -// Solidity: function setChainMetadata(bytes32 node, bytes4 chain, bytes32 metadataValue) returns() -func (_Multichainresolver *MultichainresolverTransactorSession) SetChainMetadata(node [32]byte, chain [4]byte, metadataValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetChainMetadata(&_Multichainresolver.TransactOpts, node, chain, metadataValue) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() -func (_Multichainresolver *MultichainresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, contentValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.contract.Transact(opts, "setContent", node, contentValue) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() -func (_Multichainresolver *MultichainresolverSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 contentValue) returns() -func (_Multichainresolver *MultichainresolverTransactorSession) SetContent(node [32]byte, contentValue [32]byte) (*types.Transaction, error) { - return _Multichainresolver.Contract.SetContent(&_Multichainresolver.TransactOpts, node, contentValue) -} - -// MultichainresolverAddrChangedIterator is returned from FilterAddrChanged and is used to iterate over the raw logs and unpacked data for AddrChanged events raised by the Multichainresolver contract. -type MultichainresolverAddrChangedIterator struct { - Event *MultichainresolverAddrChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *MultichainresolverAddrChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(MultichainresolverAddrChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(MultichainresolverAddrChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *MultichainresolverAddrChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *MultichainresolverAddrChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// MultichainresolverAddrChanged represents a AddrChanged event raised by the Multichainresolver contract. -type MultichainresolverAddrChanged struct { - Node [32]byte - Addr common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterAddrChanged is a free log retrieval operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. -// -// Solidity: event AddrChanged(bytes32 indexed node, address addr) -func (_Multichainresolver *MultichainresolverFilterer) FilterAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverAddrChangedIterator, error) { - - var nodeRule []interface{} - for _, nodeItem := range node { - nodeRule = append(nodeRule, nodeItem) - } - - logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "AddrChanged", nodeRule) - if err != nil { - return nil, err - } - return &MultichainresolverAddrChangedIterator{contract: _Multichainresolver.contract, event: "AddrChanged", logs: logs, sub: sub}, nil -} - -// WatchAddrChanged is a free log subscription operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. -// -// Solidity: event AddrChanged(bytes32 indexed node, address addr) -func (_Multichainresolver *MultichainresolverFilterer) WatchAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverAddrChanged, node [][32]byte) (event.Subscription, error) { - - var nodeRule []interface{} - for _, nodeItem := range node { - nodeRule = append(nodeRule, nodeItem) - } - - logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "AddrChanged", nodeRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(MultichainresolverAddrChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseAddrChanged is a log parse operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2. -// -// Solidity: event AddrChanged(bytes32 indexed node, address addr) -func (_Multichainresolver *MultichainresolverFilterer) ParseAddrChanged(log types.Log) (*MultichainresolverAddrChanged, error) { - event := new(MultichainresolverAddrChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "AddrChanged", log); err != nil { - return nil, err - } - return event, nil -} - -// MultichainresolverChainAddrChangedIterator is returned from FilterChainAddrChanged and is used to iterate over the raw logs and unpacked data for ChainAddrChanged events raised by the Multichainresolver contract. -type MultichainresolverChainAddrChangedIterator struct { - Event *MultichainresolverChainAddrChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *MultichainresolverChainAddrChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(MultichainresolverChainAddrChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(MultichainresolverChainAddrChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *MultichainresolverChainAddrChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *MultichainresolverChainAddrChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// MultichainresolverChainAddrChanged represents a ChainAddrChanged event raised by the Multichainresolver contract. -type MultichainresolverChainAddrChanged struct { - Node [32]byte - Chain [4]byte - Addr string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterChainAddrChanged is a free log retrieval operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. -// -// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) -func (_Multichainresolver *MultichainresolverFilterer) FilterChainAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*MultichainresolverChainAddrChangedIterator, error) { - - var nodeRule []interface{} - for _, nodeItem := range node { - nodeRule = append(nodeRule, nodeItem) - } - - logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainAddrChanged", nodeRule) - if err != nil { - return nil, err - } - return &MultichainresolverChainAddrChangedIterator{contract: _Multichainresolver.contract, event: "ChainAddrChanged", logs: logs, sub: sub}, nil -} - -// WatchChainAddrChanged is a free log subscription operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. -// -// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) -func (_Multichainresolver *MultichainresolverFilterer) WatchChainAddrChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainAddrChanged, node [][32]byte) (event.Subscription, error) { - - var nodeRule []interface{} - for _, nodeItem := range node { - nodeRule = append(nodeRule, nodeItem) - } - - logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainAddrChanged", nodeRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(MultichainresolverChainAddrChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseChainAddrChanged is a log parse operation binding the contract event 0x6a3e28813f2e2e5bcd0436779f8c5cb179ceadf0379291a818b9078e772b178d. -// -// Solidity: event ChainAddrChanged(bytes32 indexed node, bytes4 chain, string addr) -func (_Multichainresolver *MultichainresolverFilterer) ParseChainAddrChanged(log types.Log) (*MultichainresolverChainAddrChanged, error) { - event := new(MultichainresolverChainAddrChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ChainAddrChanged", log); err != nil { - return nil, err - } - return event, nil -} - -// MultichainresolverChainMetadataChangedIterator is returned from FilterChainMetadataChanged and is used to iterate over the raw logs and unpacked data for ChainMetadataChanged events raised by the Multichainresolver contract. -type MultichainresolverChainMetadataChangedIterator struct { - Event *MultichainresolverChainMetadataChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *MultichainresolverChainMetadataChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(MultichainresolverChainMetadataChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(MultichainresolverChainMetadataChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *MultichainresolverChainMetadataChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *MultichainresolverChainMetadataChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// MultichainresolverChainMetadataChanged represents a ChainMetadataChanged event raised by the Multichainresolver contract. -type MultichainresolverChainMetadataChanged struct { - Node [32]byte - Chain [4]byte - Metadata [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterChainMetadataChanged is a free log retrieval operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. -// -// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) -func (_Multichainresolver *MultichainresolverFilterer) FilterChainMetadataChanged(opts *bind.FilterOpts) (*MultichainresolverChainMetadataChangedIterator, error) { - - logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ChainMetadataChanged") - if err != nil { - return nil, err - } - return &MultichainresolverChainMetadataChangedIterator{contract: _Multichainresolver.contract, event: "ChainMetadataChanged", logs: logs, sub: sub}, nil -} - -// WatchChainMetadataChanged is a free log subscription operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. -// -// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) -func (_Multichainresolver *MultichainresolverFilterer) WatchChainMetadataChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverChainMetadataChanged) (event.Subscription, error) { - - logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ChainMetadataChanged") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(MultichainresolverChainMetadataChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseChainMetadataChanged is a log parse operation binding the contract event 0x92c52f77ad49286096555eb922ca7a09249e8dd525cf58cd162fb1165686fad4. -// -// Solidity: event ChainMetadataChanged(bytes32 node, bytes4 chain, bytes32 metadata) -func (_Multichainresolver *MultichainresolverFilterer) ParseChainMetadataChanged(log types.Log) (*MultichainresolverChainMetadataChanged, error) { - event := new(MultichainresolverChainMetadataChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ChainMetadataChanged", log); err != nil { - return nil, err - } - return event, nil -} - -// MultichainresolverContentChangedIterator is returned from FilterContentChanged and is used to iterate over the raw logs and unpacked data for ContentChanged events raised by the Multichainresolver contract. -type MultichainresolverContentChangedIterator struct { - Event *MultichainresolverContentChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *MultichainresolverContentChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(MultichainresolverContentChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(MultichainresolverContentChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *MultichainresolverContentChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *MultichainresolverContentChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// MultichainresolverContentChanged represents a ContentChanged event raised by the Multichainresolver contract. -type MultichainresolverContentChanged struct { - Node [32]byte - Content [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterContentChanged is a free log retrieval operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. -// -// Solidity: event ContentChanged(bytes32 node, bytes32 content) -func (_Multichainresolver *MultichainresolverFilterer) FilterContentChanged(opts *bind.FilterOpts) (*MultichainresolverContentChangedIterator, error) { - - logs, sub, err := _Multichainresolver.contract.FilterLogs(opts, "ContentChanged") - if err != nil { - return nil, err - } - return &MultichainresolverContentChangedIterator{contract: _Multichainresolver.contract, event: "ContentChanged", logs: logs, sub: sub}, nil -} - -// WatchContentChanged is a free log subscription operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. -// -// Solidity: event ContentChanged(bytes32 node, bytes32 content) -func (_Multichainresolver *MultichainresolverFilterer) WatchContentChanged(opts *bind.WatchOpts, sink chan<- *MultichainresolverContentChanged) (event.Subscription, error) { - - logs, sub, err := _Multichainresolver.contract.WatchLogs(opts, "ContentChanged") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(MultichainresolverContentChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseContentChanged is a log parse operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc. -// -// Solidity: event ContentChanged(bytes32 node, bytes32 content) -func (_Multichainresolver *MultichainresolverFilterer) ParseContentChanged(log types.Log) (*MultichainresolverContentChanged, error) { - event := new(MultichainresolverContentChanged) - if err := _Multichainresolver.contract.UnpackLog(event, "ContentChanged", log); err != nil { - return nil, err - } - return event, nil -} diff --git a/vendor/github.com/rds-swarm/resolver/resolver.go b/vendor/github.com/rds-swarm/resolver/resolver.go deleted file mode 100644 index 0699762308..0000000000 --- a/vendor/github.com/rds-swarm/resolver/resolver.go +++ /dev/null @@ -1,153 +0,0 @@ -package resolver - -import ( - "errors" - - config "github.com/rsksmart/rds-swarm/config" - multichainresolver "github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver" - rskresolver "github.com/rsksmart/rds-swarm/resolver/rsk_resolver" - "github.com/rsksmart/rds-swarm/utils" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" -) - -// ErrNoAddress is returned when there is no registered address through RNS -var ErrNoAddress = errors.New("domain without registered address in RNS") - -// ErrNoContent is returned when there is no registered content through RNS -var ErrNoContent = errors.New("domain without registered content in RNS") - -// Resolver interface is implemented by all types which can resolve both the address of a domain as well as its content. -type Resolver interface { - Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) - Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) -} - -func getPublicResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { - resolverAddress := common.HexToAddress(configuration.ResolverAddresses.RSK) - resolver, resolverError := rskresolver.NewRskresolver(resolverAddress, client) - if resolverError != nil { - return nil, resolverError - } - - return resolver, nil -} - -func getMultiChainResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { - resolverAddress := common.HexToAddress(configuration.ResolverAddresses.MultiChain) - resolver, resolverError := multichainresolver.NewMultichainresolver(resolverAddress, client) - if resolverError != nil { - return nil, resolverError - } - - return resolver, nil -} - -func setUpResolver(resolverConstructor func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (Resolver, error) { - configuration := config.GetConfiguration() - - client, clientError := ethclient.Dial(configuration.NetworkNodeAddress) - if clientError != nil { - return nil, clientError - } - defer client.Close() - - resolver, resolverError := resolverConstructor(client, configuration) - if resolverError != nil { - return nil, resolverError - } - - return resolver, nil -} - -func resolveAddressFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (common.Address, error) { - var emptyAddress common.Address - - resolver, resolverError := setUpResolver(getResolverFunction) - if resolverError != nil { - return emptyAddress, resolverError - } - - resolvedAddress, resolutionError := resolveAddress(domainAddress, resolver) - if resolutionError != nil { - return emptyAddress, resolutionError - } - - return resolvedAddress, nil -} - -func resolveAddress(byteArrayAddress [32]byte, resolver Resolver) (common.Address, error) { - return resolver.Addr(&bind.CallOpts{}, byteArrayAddress) -} - -func resolveContentFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) ([32]byte, error) { - var emptyContent [32]byte - - resolver, resolverError := setUpResolver(getResolverFunction) - if resolverError != nil { - return emptyContent, resolverError - } - - resolvedContent, resolutionError := resolveContent(domainAddress, resolver) - if resolutionError != nil { - return emptyContent, resolutionError - } - - return resolvedContent, nil -} - -func resolveContent(byteArrayAddress [32]byte, resolver Resolver) ([32]byte, error) { - return resolver.Content(&bind.CallOpts{}, byteArrayAddress) -} - -// ResolveDomainAddress receives a domain string and returns its RNS-resolved hex address. -// It will attempt to solve the address through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty address. -func ResolveDomainAddress(domain string) (common.Address, error) { - domainAddress := utils.DomainToHashedByteArray(domain) - var emptyAddress, resolvedAddress common.Address - var resolvedError error - - resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getMultiChainResolver) - if resolvedError != nil { - return emptyAddress, resolvedError - } - - if resolvedAddress == emptyAddress { - resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getPublicResolver) - if resolvedError != nil { - return emptyAddress, resolvedError - } - } - - if resolvedAddress == emptyAddress { - resolvedError = ErrNoAddress - } - return resolvedAddress, resolvedError -} - -// ResolveDomainContent receives a domain string and returns its RNS-resolved associated content hash. -// It will attempt to solve the content through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty content. -func ResolveDomainContent(domain string) (common.Hash, error) { - domainAddress := utils.DomainToHashedByteArray(domain) - var emptyContent, resolvedContent [32]byte - var resolvedError error - - resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getMultiChainResolver) - if resolvedError != nil { - return emptyContent, resolvedError - } - - if resolvedContent == emptyContent { - resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getPublicResolver) - if resolvedError != nil { - return emptyContent, resolvedError - } - } - - if resolvedContent == emptyContent { - resolvedError = ErrNoContent - } - return resolvedContent, resolvedError -} diff --git a/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json b/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json deleted file mode 100644 index 513179bdcb..0000000000 --- a/vendor/github.com/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json +++ /dev/null @@ -1,134 +0,0 @@ -[ - { - "inputs": [ - { - "name": "rnsAddr", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "kind", - "type": "bytes32" - } - ], - "name": "has", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "interfaceID", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "addr", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "addrValue", - "type": "address" - } - ], - "name": "setAddr", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "content", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "hash", - "type": "bytes32" - } - ], - "name": "setContent", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ] \ No newline at end of file diff --git a/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go b/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go deleted file mode 100644 index 3915ef1747..0000000000 --- a/vendor/github.com/rds-swarm/resolver/rsk_resolver/rsk_resolver.go +++ /dev/null @@ -1,319 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package rskresolver - -import ( - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = abi.U256 - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// RskresolverABI is the input ABI used to generate the binding from. -const RskresolverABI = "[{\"inputs\":[{\"name\":\"rnsAddr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"kind\",\"type\":\"bytes32\"}],\"name\":\"has\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - -// Rskresolver is an auto generated Go binding around an Ethereum contract. -type Rskresolver struct { - RskresolverCaller // Read-only binding to the contract - RskresolverTransactor // Write-only binding to the contract - RskresolverFilterer // Log filterer for contract events -} - -// RskresolverCaller is an auto generated read-only Go binding around an Ethereum contract. -type RskresolverCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. -type RskresolverTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type RskresolverFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type RskresolverSession struct { - Contract *Rskresolver // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// RskresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type RskresolverCallerSession struct { - Contract *RskresolverCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// RskresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type RskresolverTransactorSession struct { - Contract *RskresolverTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// RskresolverRaw is an auto generated low-level Go binding around an Ethereum contract. -type RskresolverRaw struct { - Contract *Rskresolver // Generic contract binding to access the raw methods on -} - -// RskresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type RskresolverCallerRaw struct { - Contract *RskresolverCaller // Generic read-only contract binding to access the raw methods on -} - -// RskresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type RskresolverTransactorRaw struct { - Contract *RskresolverTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewRskresolver creates a new instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolver(address common.Address, backend bind.ContractBackend) (*Rskresolver, error) { - contract, err := bindRskresolver(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Rskresolver{RskresolverCaller: RskresolverCaller{contract: contract}, RskresolverTransactor: RskresolverTransactor{contract: contract}, RskresolverFilterer: RskresolverFilterer{contract: contract}}, nil -} - -// NewRskresolverCaller creates a new read-only instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverCaller(address common.Address, caller bind.ContractCaller) (*RskresolverCaller, error) { - contract, err := bindRskresolver(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &RskresolverCaller{contract: contract}, nil -} - -// NewRskresolverTransactor creates a new write-only instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*RskresolverTransactor, error) { - contract, err := bindRskresolver(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &RskresolverTransactor{contract: contract}, nil -} - -// NewRskresolverFilterer creates a new log filterer instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*RskresolverFilterer, error) { - contract, err := bindRskresolver(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &RskresolverFilterer{contract: contract}, nil -} - -// bindRskresolver binds a generic wrapper to an already deployed contract. -func bindRskresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(RskresolverABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Rskresolver *RskresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Rskresolver.Contract.RskresolverCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Rskresolver *RskresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Rskresolver.Contract.RskresolverTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Rskresolver *RskresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Rskresolver.Contract.RskresolverTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Rskresolver *RskresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Rskresolver.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Rskresolver *RskresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Rskresolver.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Rskresolver *RskresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Rskresolver.Contract.contract.Transact(opts, method, params...) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { - var ( - ret0 = new(common.Address) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "addr", node) - return *ret0, err -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverSession) Addr(node [32]byte) (common.Address, error) { - return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverCallerSession) Addr(node [32]byte) (common.Address, error) { - return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "content", node) - return *ret0, err -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverSession) Content(node [32]byte) ([32]byte, error) { - return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverCallerSession) Content(node [32]byte) ([32]byte, error) { - return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverCaller) Has(opts *bind.CallOpts, node [32]byte, kind [32]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "has", node, kind) - return *ret0, err -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverSession) Has(node [32]byte, kind [32]byte) (bool, error) { - return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverCallerSession) Has(node [32]byte, kind [32]byte) (bool, error) { - return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "supportsInterface", interfaceID) - return *ret0, err -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverSession) SupportsInterface(interfaceID [4]byte) (bool, error) { - return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) { - return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.contract.Transact(opts, "setAddr", node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.contract.Transact(opts, "setContent", node, hash) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) -} diff --git a/vendor/github.com/rds-swarm/utils/utils.go b/vendor/github.com/rds-swarm/utils/utils.go deleted file mode 100644 index c831dbf4c9..0000000000 --- a/vendor/github.com/rds-swarm/utils/utils.go +++ /dev/null @@ -1,35 +0,0 @@ -package utils - -import ( - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -// DomainToHashedByteArray takes a string containing a domain, hashes it and returns it as an array of 32 bytes. -func DomainToHashedByteArray(domain string) [32]byte { - var byteArrayAddress [32]byte - - hashedAddress := RnsNode(domain) - byteSliceAddress := hashedAddress.Bytes() - copy(byteArrayAddress[:], byteSliceAddress[:32]) - - return byteArrayAddress -} - -// RnsNode takes a string containing a domain, hashes it and returns it as a Keccak256Hash. -func RnsNode(name string) common.Hash { - parentNode, parentLabel := rnsParentNode(name) - return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) -} - -func rnsParentNode(name string) (common.Hash, common.Hash) { - parts := strings.SplitN(name, ".", 2) - label := crypto.Keccak256Hash([]byte(parts[0])) - if len(parts) == 1 { - return [32]byte{}, label - } - parentNode, parentLabel := rnsParentNode(parts[1]) - return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label -} diff --git a/vendor/github.com/rjeczalik/notify/go.mod b/vendor/github.com/rjeczalik/notify/go.mod new file mode 100644 index 0000000000..2bbfbf3bf9 --- /dev/null +++ b/vendor/github.com/rjeczalik/notify/go.mod @@ -0,0 +1,3 @@ +module github.com/rjeczalik/notify + +require golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 diff --git a/vendor/github.com/rs/cors/.travis.yml b/vendor/github.com/rs/cors/.travis.yml index bbb5185a2e..9a68b56762 100644 --- a/vendor/github.com/rs/cors/.travis.yml +++ b/vendor/github.com/rs/cors/.travis.yml @@ -1,4 +1,9 @@ language: go go: -- 1.3 -- 1.4 +- "1.10" +- "1.11" +- "1.12" +- tip +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/rs/cors/README.md b/vendor/github.com/rs/cors/README.md index 4bf56724e6..ecc83b2951 100644 --- a/vendor/github.com/rs/cors/README.md +++ b/vendor/github.com/rs/cors/README.md @@ -49,6 +49,14 @@ The server now runs on `localhost:8080`: {"hello": "world"} +### Allow * With Credentials Security Protection + +This library has been modified to avoid a well known security issue when configured with `AllowedOrigins` to `*` and `AllowCredentials` to `true`. Such setup used to make the library reflects the request `Origin` header value, working around a security protection embedded into the standard that makes clients to refuse such configuration. This behavior has been removed with [#55](https://github.com/rs/cors/issues/55) and [#57](https://github.com/rs/cors/issues/57). + +If you depend on this behavior and understand the implications, you can restore it using the `AllowOriginFunc` with `func(origin string) {return true}`. + +Please refer to [#55](https://github.com/rs/cors/issues/55) for more information about the security implications. + ### More Examples * `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go) @@ -56,6 +64,11 @@ The server now runs on `localhost:8080`: * [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go) * [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go) * [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go) +* [HttpRouter](https://github.com/julienschmidt/httprouter): [examples/httprouter/server.go](https://github.com/rs/cors/blob/master/examples/httprouter/server.go) +* [Gorilla](http://www.gorillatoolkit.org/pkg/mux): [examples/gorilla/server.go](https://github.com/rs/cors/blob/master/examples/gorilla/server.go) +* [Buffalo](https://gobuffalo.io): [examples/buffalo/server.go](https://github.com/rs/cors/blob/master/examples/buffalo/server.go) +* [Gin](https://gin-gonic.github.io/gin): [examples/gin/server.go](https://github.com/rs/cors/blob/master/examples/gin/server.go) +* [Chi](https://github.com/go-chi/chi): [examples/chi/server.go](https://github.com/rs/cors/blob/master/examples/chi/server.go) ## Parameters @@ -63,8 +76,10 @@ Parameters are passed to the middleware thru the `cors.New` method as follow: ```go c := cors.New(cors.Options{ - AllowedOrigins: []string{"http://foo.com"}, + AllowedOrigins: []string{"http://foo.com", "http://foo.com:8080"}, AllowCredentials: true, + // Enable Debugging for testing, consider disabling in production + Debug: true, }) // Insert the middleware @@ -72,7 +87,8 @@ handler = c.Handler(handler) ``` * **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. An origin may contain a wildcard (`*`) to replace 0 or more characters (i.e.: `http://*.domain.com`). Usage of wildcards implies a small performance penality. Only one wildcard can be used per origin. The default value is `*`. -* **AllowOriginFunc** `func (origin string) bool`: A custom function to validate the origin. It take the origin as argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` is ignored +* **AllowOriginFunc** `func (origin string) bool`: A custom function to validate the origin. It takes the origin as an argument and returns true if allowed, or false otherwise. If this option is set, the content of `AllowedOrigins` is ignored. +* **AllowOriginRequestFunc** `func (r *http.Request origin string) bool`: A custom function to validate the origin. It takes the HTTP Request object and the origin as argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` and `AllowOriginFunc` is ignored * **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`). * **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests. * **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go index 4bb22d8fce..2730934630 100644 --- a/vendor/github.com/rs/cors/cors.go +++ b/vendor/github.com/rs/cors/cors.go @@ -5,8 +5,8 @@ as defined by http://www.w3.org/TR/cors/ You can configure it by passing an option struct to cors.New: c := cors.New(cors.Options{ - AllowedOrigins: []string{"foo.com"}, - AllowedMethods: []string{"GET", "POST", "DELETE"}, + AllowedOrigins: []string{"foo.com"}, + AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete}, AllowCredentials: true, }) @@ -26,9 +26,6 @@ import ( "os" "strconv" "strings" - - "github.com/rs/xhandler" - "golang.org/x/net/context" ) // Options is a configuration container to setup the CORS middleware. @@ -36,7 +33,7 @@ type Options struct { // AllowedOrigins is a list of origins a cross-domain request can be executed from. // If the special "*" value is present in the list, all origins will be allowed. // An origin may contain a wildcard (*) to replace 0 or more characters - // (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penality. + // (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty. // Only one wildcard can be used per origin. // Default value is ["*"] AllowedOrigins []string @@ -44,8 +41,12 @@ type Options struct { // as argument and returns true if allowed or false otherwise. If this option is // set, the content of AllowedOrigins is ignored. AllowOriginFunc func(origin string) bool + // AllowOriginFunc is a custom function to validate the origin. It takes the HTTP Request object and the origin as + // argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` + // and `AllowOriginFunc` is ignored. + AllowOriginRequestFunc func(r *http.Request, origin string) bool // AllowedMethods is a list of methods the client is allowed to use with - // cross-domain requests. Default value is simple methods (GET and POST) + // cross-domain requests. Default value is simple methods (HEAD, GET and POST). AllowedMethods []string // AllowedHeaders is list of non simple headers the client is allowed to use with // cross-domain requests. @@ -55,12 +56,12 @@ type Options struct { // ExposedHeaders indicates which headers are safe to expose to the API of a CORS // API specification ExposedHeaders []string - // AllowCredentials indicates whether the request can include user credentials like - // cookies, HTTP authentication or client side SSL certificates. - AllowCredentials bool // MaxAge indicates how long (in seconds) the results of a preflight request // can be cached MaxAge int + // AllowCredentials indicates whether the request can include user credentials like + // cookies, HTTP authentication or client side SSL certificates. + AllowCredentials bool // OptionsPassthrough instructs preflight to let other potential next handlers to // process the OPTIONS method. Turn this on if your application handles OPTIONS. OptionsPassthrough bool @@ -68,41 +69,49 @@ type Options struct { Debug bool } +// Logger generic interface for logger +type Logger interface { + Printf(string, ...interface{}) +} + // Cors http handler type Cors struct { // Debug logger - Log *log.Logger - // Set to true when allowed origins contains a "*" - allowedOriginsAll bool + Log Logger // Normalized list of plain allowed origins allowedOrigins []string // List of allowed origins containing wildcards allowedWOrigins []wildcard // Optional origin validator function allowOriginFunc func(origin string) bool - // Set to true when allowed headers contains a "*" - allowedHeadersAll bool + // Optional origin validator (with request) function + allowOriginRequestFunc func(r *http.Request, origin string) bool // Normalized list of allowed headers allowedHeaders []string // Normalized list of allowed methods allowedMethods []string // Normalized list of exposed headers - exposedHeaders []string + exposedHeaders []string + maxAge int + // Set to true when allowed origins contains a "*" + allowedOriginsAll bool + // Set to true when allowed headers contains a "*" + allowedHeadersAll bool allowCredentials bool - maxAge int optionPassthrough bool } // New creates a new Cors handler with the provided options. func New(options Options) *Cors { c := &Cors{ - exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey), - allowOriginFunc: options.AllowOriginFunc, - allowCredentials: options.AllowCredentials, - maxAge: options.MaxAge, - optionPassthrough: options.OptionsPassthrough, + exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey), + allowOriginFunc: options.AllowOriginFunc, + allowOriginRequestFunc: options.AllowOriginRequestFunc, + allowCredentials: options.AllowCredentials, + maxAge: options.MaxAge, + optionPassthrough: options.OptionsPassthrough, } - if options.Debug { + if options.Debug && c.Log == nil { c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags) } @@ -112,8 +121,10 @@ func New(options Options) *Cors { // Allowed Origins if len(options.AllowedOrigins) == 0 { - // Default is all origins - c.allowedOriginsAll = true + if options.AllowOriginFunc == nil && options.AllowOriginRequestFunc == nil { + // Default is all origins + c.allowedOriginsAll = true + } } else { c.allowedOrigins = []string{} c.allowedWOrigins = []wildcard{} @@ -128,7 +139,7 @@ func New(options Options) *Cors { break } else if i := strings.IndexByte(origin, '*'); i >= 0 { // Split the origin in two: start and end string without the * - w := wildcard{origin[0:i], origin[i+1 : len(origin)]} + w := wildcard{origin[0:i], origin[i+1:]} c.allowedWOrigins = append(c.allowedWOrigins, w) } else { c.allowedOrigins = append(c.allowedOrigins, origin) @@ -139,7 +150,7 @@ func New(options Options) *Cors { // Allowed Headers if len(options.AllowedHeaders) == 0 { // Use sensible defaults - c.allowedHeaders = []string{"Origin", "Accept", "Content-Type"} + c.allowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With"} } else { // Origin is always appended as some browsers will always request for this header at preflight c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey) @@ -155,7 +166,7 @@ func New(options Options) *Cors { // Allowed Methods if len(options.AllowedMethods) == 0 { // Default is spec's "simple" methods - c.allowedMethods = []string{"GET", "POST"} + c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead} } else { c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) } @@ -163,16 +174,34 @@ func New(options Options) *Cors { return c } -// Default creates a new Cors handler with default options +// Default creates a new Cors handler with default options. func Default() *Cors { return New(Options{}) } +// AllowAll create a new Cors handler with permissive configuration allowing all +// origins with all standard methods with any header and credentials. +func AllowAll() *Cors { + return New(Options{ + AllowedOrigins: []string{"*"}, + AllowedMethods: []string{ + http.MethodHead, + http.MethodGet, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + }, + AllowedHeaders: []string{"*"}, + AllowCredentials: false, + }) +} + // Handler apply the CORS specification on the request, and add relevant CORS headers // as necessary. func (c *Cors) Handler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "OPTIONS" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("Handler: Preflight request") c.handlePreflight(w, r) // Preflight requests are standalone and should stop the chain as some other @@ -192,32 +221,9 @@ func (c *Cors) Handler(h http.Handler) http.Handler { }) } -// HandlerC is net/context aware handler -func (c *Cors) HandlerC(h xhandler.HandlerC) xhandler.HandlerC { - return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - if r.Method == "OPTIONS" { - c.logf("Handler: Preflight request") - c.handlePreflight(w, r) - // Preflight requests are standalone and should stop the chain as some other - // middleware may not handle OPTIONS requests correctly. One typical example - // is authentication middleware ; OPTIONS requests won't carry authentication - // headers (see #1) - if c.optionPassthrough { - h.ServeHTTPC(ctx, w, r) - } else { - w.WriteHeader(http.StatusOK) - } - } else { - c.logf("Handler: Actual request") - c.handleActualRequest(w, r) - h.ServeHTTPC(ctx, w, r) - } - }) -} - // HandlerFunc provides Martini compatible handler func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "OPTIONS" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("HandlerFunc: Preflight request") c.handlePreflight(w, r) } else { @@ -228,7 +234,7 @@ func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) { // Negroni compatible interface func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - if r.Method == "OPTIONS" { + if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" { c.logf("ServeHTTP: Preflight request") c.handlePreflight(w, r) // Preflight requests are standalone and should stop the chain as some other @@ -252,7 +258,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") - if r.Method != "OPTIONS" { + if r.Method != http.MethodOptions { c.logf(" Preflight aborted: %s!=OPTIONS", r.Method) return } @@ -267,7 +273,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { c.logf(" Preflight aborted: empty origin") return } - if !c.isOriginAllowed(origin) { + if !c.isOriginAllowed(r, origin) { c.logf(" Preflight aborted: origin '%s' not allowed", origin) return } @@ -282,7 +288,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) return } - headers.Set("Access-Control-Allow-Origin", origin) + if c.allowedOriginsAll { + headers.Set("Access-Control-Allow-Origin", "*") + } else { + headers.Set("Access-Control-Allow-Origin", origin) + } // Spec says: Since the list of methods can be unbounded, simply returning the method indicated // by Access-Control-Request-Method (if supported) can be enough headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod)) @@ -306,17 +316,13 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") - if r.Method == "OPTIONS" { - c.logf(" Actual request no headers added: method == %s", r.Method) - return - } // Always set Vary, see https://github.com/rs/cors/issues/10 headers.Add("Vary", "Origin") if origin == "" { c.logf(" Actual request no headers added: missing origin") return } - if !c.isOriginAllowed(origin) { + if !c.isOriginAllowed(r, origin) { c.logf(" Actual request no headers added: origin '%s' not allowed", origin) return } @@ -330,7 +336,11 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { return } - headers.Set("Access-Control-Allow-Origin", origin) + if c.allowedOriginsAll { + headers.Set("Access-Control-Allow-Origin", "*") + } else { + headers.Set("Access-Control-Allow-Origin", origin) + } if len(c.exposedHeaders) > 0 { headers.Set("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", ")) } @@ -340,7 +350,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { c.logf(" Actual response added headers: %v", headers) } -// convenience method. checks if debugging is turned on before printing +// convenience method. checks if a logger is set. func (c *Cors) logf(format string, a ...interface{}) { if c.Log != nil { c.Log.Printf(format, a...) @@ -349,7 +359,10 @@ func (c *Cors) logf(format string, a ...interface{}) { // isOriginAllowed checks if a given origin is allowed to perform cross-domain requests // on the endpoint -func (c *Cors) isOriginAllowed(origin string) bool { +func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool { + if c.allowOriginRequestFunc != nil { + return c.allowOriginRequestFunc(r, origin) + } if c.allowOriginFunc != nil { return c.allowOriginFunc(origin) } @@ -378,7 +391,7 @@ func (c *Cors) isMethodAllowed(method string) bool { return false } method = strings.ToUpper(method) - if method == "OPTIONS" { + if method == http.MethodOptions { // Always allow preflight requests return true } diff --git a/vendor/github.com/rs/cors/go.mod b/vendor/github.com/rs/cors/go.mod new file mode 100644 index 0000000000..0a4c652105 --- /dev/null +++ b/vendor/github.com/rs/cors/go.mod @@ -0,0 +1 @@ +module github.com/rs/cors diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go index c7a0aa0601..db83ac3ea9 100644 --- a/vendor/github.com/rs/cors/utils.go +++ b/vendor/github.com/rs/cors/utils.go @@ -12,7 +12,7 @@ type wildcard struct { } func (w wildcard) match(s string) bool { - return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) + return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) } // convert converts a list of string using the passed converter function @@ -39,19 +39,20 @@ func parseHeaderList(headerList string) []string { headers := make([]string, 0, t) for i := 0; i < l; i++ { b := headerList[i] - if b >= 'a' && b <= 'z' { + switch { + case b >= 'a' && b <= 'z': if upper { h = append(h, b-toLower) } else { h = append(h, b) } - } else if b >= 'A' && b <= 'Z' { + case b >= 'A' && b <= 'Z': if !upper { h = append(h, b+toLower) } else { h = append(h, b) } - } else if b == '-' || b == '_' || (b >= '0' && b <= '9') { + case b == '-' || b == '_' || (b >= '0' && b <= '9'): h = append(h, b) } diff --git a/vendor/github.com/rs/xhandler/.travis.yml b/vendor/github.com/rs/xhandler/.travis.yml deleted file mode 100644 index b65c7a9f1e..0000000000 --- a/vendor/github.com/rs/xhandler/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go -go: -- 1.5 -- tip -matrix: - allow_failures: - - go: tip diff --git a/vendor/github.com/rs/xhandler/README.md b/vendor/github.com/rs/xhandler/README.md deleted file mode 100644 index 91c594bd25..0000000000 --- a/vendor/github.com/rs/xhandler/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# XHandler - -[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/xhandler) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/xhandler/master/LICENSE) [![Build Status](https://travis-ci.org/rs/xhandler.svg?branch=master)](https://travis-ci.org/rs/xhandler) [![Coverage](http://gocover.io/_badge/github.com/rs/xhandler)](http://gocover.io/github.com/rs/xhandler) - -XHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`. - -It lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router. - -Thanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly. - -You may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler. - -Read more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/). - -## Installing - - go get -u github.com/rs/xhandler - -## Usage - -```go -package main - -import ( - "log" - "net/http" - "time" - - "github.com/rs/cors" - "github.com/rs/xhandler" - "golang.org/x/net/context" -) - -type myMiddleware struct { - next xhandler.HandlerC -} - -func (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) { - ctx = context.WithValue(ctx, "test", "World") - h.next.ServeHTTPC(ctx, w, r) -} - -func main() { - c := xhandler.Chain{} - - // Add close notifier handler so context is cancelled when the client closes - // the connection - c.UseC(xhandler.CloseHandler) - - // Add timeout handler - c.UseC(xhandler.TimeoutHandler(2 * time.Second)) - - // Middleware putting something in the context - c.UseC(func(next xhandler.HandlerC) xhandler.HandlerC { - return myMiddleware{next: next} - }) - - // Mix it with a non-context-aware middleware handler - c.Use(cors.Default().Handler) - - // Final handler (using handlerFuncC), reading from the context - xh := xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - value := ctx.Value("test").(string) - w.Write([]byte("Hello " + value)) - }) - - // Bridge context aware handlers with http.Handler using xhandler.Handle() - http.Handle("/test", c.Handler(xh)) - - if err := http.ListenAndServe(":8080", nil); err != nil { - log.Fatal(err) - } -} -``` - -### Using xmux - -Xhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter): - -```go -package main - -import ( - "fmt" - "log" - "net/http" - "time" - - "github.com/rs/xhandler" - "github.com/rs/xmux" - "golang.org/x/net/context" -) - -func main() { - c := xhandler.Chain{} - - // Append a context-aware middleware handler - c.UseC(xhandler.CloseHandler) - - // Another context-aware middleware handler - c.UseC(xhandler.TimeoutHandler(2 * time.Second)) - - mux := xmux.New() - - // Use c.Handler to terminate the chain with your final handler - mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) { - fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name")) - })) - - if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil { - log.Fatal(err) - } -} -``` - -See [xmux](https://github.com/rs/xmux) for more examples. - -## Context Aware Middleware - -Here is a list of `net/context` aware middleware handlers implementing `xhandler.HandlerC` interface. - -Feel free to put up a PR linking your middleware if you have built one: - -| Middleware | Author | Description | -| ---------- | ------ | ----------- | -| [xmux](https://github.com/rs/xmux) | [Olivier Poitrey](https://github.com/rs) | HTTP request muxer | -| [xlog](https://github.com/rs/xlog) | [Olivier Poitrey](https://github.com/rs) | HTTP handler logger | -| [xstats](https://github.com/rs/xstats) | [Olivier Poitrey](https://github.com/rs) | A generic client for service instrumentation | -| [xaccess](https://github.com/rs/xaccess) | [Olivier Poitrey](https://github.com/rs) | HTTP handler access logger with [xlog](https://github.com/rs/xlog) and [xstats](https://github.com/rs/xstats) | -| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | - -## Licenses - -All source code is licensed under the [MIT License](https://raw.github.com/rs/xhandler/master/LICENSE). diff --git a/vendor/github.com/rs/xhandler/chain.go b/vendor/github.com/rs/xhandler/chain.go deleted file mode 100644 index 3e4bd359c5..0000000000 --- a/vendor/github.com/rs/xhandler/chain.go +++ /dev/null @@ -1,121 +0,0 @@ -package xhandler - -import ( - "net/http" - - "golang.org/x/net/context" -) - -// Chain is a helper for chaining middleware handlers together for easier -// management. -type Chain []func(next HandlerC) HandlerC - -// Add appends a variable number of additional middleware handlers -// to the middleware chain. Middleware handlers can either be -// context-aware or non-context aware handlers with the appropriate -// function signatures. -func (c *Chain) Add(f ...interface{}) { - for _, h := range f { - switch v := h.(type) { - case func(http.Handler) http.Handler: - c.Use(v) - case func(HandlerC) HandlerC: - c.UseC(v) - default: - panic("Adding invalid handler to the middleware chain") - } - } -} - -// With creates a new middleware chain from an existing chain, -// extending it with additional middleware. Middleware handlers -// can either be context-aware or non-context aware handlers -// with the appropriate function signatures. -func (c *Chain) With(f ...interface{}) *Chain { - n := make(Chain, len(*c)) - copy(n, *c) - n.Add(f...) - return &n -} - -// UseC appends a context-aware handler to the middleware chain. -func (c *Chain) UseC(f func(next HandlerC) HandlerC) { - *c = append(*c, f) -} - -// Use appends a standard http.Handler to the middleware chain without -// losing track of the context when inserted between two context aware handlers. -// -// Caveat: the f function will be called on each request so you are better off putting -// any initialization sequence outside of this function. -func (c *Chain) Use(f func(next http.Handler) http.Handler) { - xf := func(next HandlerC) HandlerC { - return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - n := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTPC(ctx, w, r) - }) - f(n).ServeHTTP(w, r) - }) - } - *c = append(*c, xf) -} - -// Handler wraps the provided final handler with all the middleware appended to -// the chain and returns a new standard http.Handler instance. -// The context.Background() context is injected automatically. -func (c Chain) Handler(xh HandlerC) http.Handler { - ctx := context.Background() - return c.HandlerCtx(ctx, xh) -} - -// HandlerFC is a helper to provide a function (HandlerFuncC) to Handler(). -// -// HandlerFC is equivalent to: -// c.Handler(xhandler.HandlerFuncC(xhc)) -func (c Chain) HandlerFC(xhf HandlerFuncC) http.Handler { - ctx := context.Background() - return c.HandlerCtx(ctx, HandlerFuncC(xhf)) -} - -// HandlerH is a helper to provide a standard http handler (http.HandlerFunc) -// to Handler(). Your final handler won't have access to the context though. -func (c Chain) HandlerH(h http.Handler) http.Handler { - ctx := context.Background() - return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - h.ServeHTTP(w, r) - })) -} - -// HandlerF is a helper to provide a standard http handler function -// (http.HandlerFunc) to Handler(). Your final handler won't have access -// to the context though. -func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler { - ctx := context.Background() - return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - hf(w, r) - })) -} - -// HandlerCtx wraps the provided final handler with all the middleware appended to -// the chain and returns a new standard http.Handler instance. -func (c Chain) HandlerCtx(ctx context.Context, xh HandlerC) http.Handler { - return New(ctx, c.HandlerC(xh)) -} - -// HandlerC wraps the provided final handler with all the middleware appended to -// the chain and returns a HandlerC instance. -func (c Chain) HandlerC(xh HandlerC) HandlerC { - for i := len(c) - 1; i >= 0; i-- { - xh = c[i](xh) - } - return xh -} - -// HandlerCF wraps the provided final handler func with all the middleware appended to -// the chain and returns a HandlerC instance. -// -// HandlerCF is equivalent to: -// c.HandlerC(xhandler.HandlerFuncC(xhc)) -func (c Chain) HandlerCF(xhc HandlerFuncC) HandlerC { - return c.HandlerC(HandlerFuncC(xhc)) -} diff --git a/vendor/github.com/rs/xhandler/middleware.go b/vendor/github.com/rs/xhandler/middleware.go deleted file mode 100644 index 7ad8fba625..0000000000 --- a/vendor/github.com/rs/xhandler/middleware.go +++ /dev/null @@ -1,59 +0,0 @@ -package xhandler - -import ( - "net/http" - "time" - - "golang.org/x/net/context" -) - -// CloseHandler returns a Handler, cancelling the context when the client -// connection closes unexpectedly. -func CloseHandler(next HandlerC) HandlerC { - return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - // Cancel the context if the client closes the connection - if wcn, ok := w.(http.CloseNotifier); ok { - var cancel context.CancelFunc - ctx, cancel = context.WithCancel(ctx) - defer cancel() - - notify := wcn.CloseNotify() - go func() { - select { - case <-notify: - cancel() - case <-ctx.Done(): - } - }() - } - - next.ServeHTTPC(ctx, w, r) - }) -} - -// TimeoutHandler returns a Handler which adds a timeout to the context. -// -// Child handlers have the responsability of obeying the context deadline and to return -// an appropriate error (or not) response in case of timeout. -func TimeoutHandler(timeout time.Duration) func(next HandlerC) HandlerC { - return func(next HandlerC) HandlerC { - return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - ctx, _ = context.WithTimeout(ctx, timeout) - next.ServeHTTPC(ctx, w, r) - }) - } -} - -// If is a special handler that will skip insert the condNext handler only if a condition -// applies at runtime. -func If(cond func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool, condNext func(next HandlerC) HandlerC) func(next HandlerC) HandlerC { - return func(next HandlerC) HandlerC { - return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { - if cond(ctx, w, r) { - condNext(next).ServeHTTPC(ctx, w, r) - } else { - next.ServeHTTPC(ctx, w, r) - } - }) - } -} diff --git a/vendor/github.com/rs/xhandler/xhandler.go b/vendor/github.com/rs/xhandler/xhandler.go deleted file mode 100644 index bc832cb1fa..0000000000 --- a/vendor/github.com/rs/xhandler/xhandler.go +++ /dev/null @@ -1,42 +0,0 @@ -// Package xhandler provides a bridge between http.Handler and net/context. -// -// xhandler enforces net/context in your handlers without sacrificing -// compatibility with existing http.Handlers nor imposing a specific router. -// -// Thanks to net/context deadline management, xhandler is able to enforce -// a per request deadline and will cancel the context in when the client close -// the connection unexpectedly. -// -// You may create net/context aware middlewares pretty much the same way as -// you would with http.Handler. -package xhandler // import "github.com/rs/xhandler" - -import ( - "net/http" - - "golang.org/x/net/context" -) - -// HandlerC is a net/context aware http.Handler -type HandlerC interface { - ServeHTTPC(context.Context, http.ResponseWriter, *http.Request) -} - -// HandlerFuncC type is an adapter to allow the use of ordinary functions -// as an xhandler.Handler. If f is a function with the appropriate signature, -// xhandler.HandlerFuncC(f) is a xhandler.Handler object that calls f. -type HandlerFuncC func(context.Context, http.ResponseWriter, *http.Request) - -// ServeHTTPC calls f(ctx, w, r). -func (f HandlerFuncC) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) { - f(ctx, w, r) -} - -// New creates a conventional http.Handler injecting the provided root -// context to sub handlers. This handler is used as a bridge between conventional -// http.Handler and context aware handlers. -func New(ctx context.Context, h HandlerC) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h.ServeHTTPC(ctx, w, r) - }) -} diff --git a/vendor/github.com/caarlos0/env/config/config.go b/vendor/github.com/rsksmart/rds-swarm/config/config.go similarity index 100% rename from vendor/github.com/caarlos0/env/config/config.go rename to vendor/github.com/rsksmart/rds-swarm/config/config.go diff --git a/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json b/vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json similarity index 100% rename from vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/MultiChainResolverABI.json rename to vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json diff --git a/vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go b/vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go similarity index 100% rename from vendor/github.com/caarlos0/env/resolver/multi_chain_resolver/multi_chain_resolver.go rename to vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go diff --git a/vendor/github.com/caarlos0/env/resolver/resolver.go b/vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go similarity index 100% rename from vendor/github.com/caarlos0/env/resolver/resolver.go rename to vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go diff --git a/vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json b/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json similarity index 100% rename from vendor/github.com/caarlos0/env/resolver/rsk_resolver/RSKResolverABI.json rename to vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json diff --git a/vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go b/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go similarity index 100% rename from vendor/github.com/caarlos0/env/resolver/rsk_resolver/rsk_resolver.go rename to vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go diff --git a/vendor/github.com/caarlos0/env/utils/utils.go b/vendor/github.com/rsksmart/rds-swarm/utils/utils.go similarity index 100% rename from vendor/github.com/caarlos0/env/utils/utils.go rename to vendor/github.com/rsksmart/rds-swarm/utils/utils.go diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/batch.go b/vendor/github.com/syndtr/goleveldb/leveldb/batch.go index 225920002d..823be93f93 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/batch.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/batch.go @@ -238,6 +238,11 @@ func newBatch() interface{} { return &Batch{} } +// MakeBatch returns empty batch with preallocated buffer. +func MakeBatch(n int) *Batch { + return &Batch{data: make([]byte, 0, n)} +} + func decodeBatch(data []byte, fn func(i int, index batchIndex) error) error { var index batchIndex for i, o := 0, 0; o < len(data); i++ { diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db.go b/vendor/github.com/syndtr/goleveldb/leveldb/db.go index 0de5ffe8d7..74e9826956 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db.go @@ -38,6 +38,12 @@ type DB struct { inWritePaused int32 // The indicator whether write operation is paused by compaction aliveSnaps, aliveIters int32 + // Compaction statistic + memComp uint32 // The cumulative number of memory compaction + level0Comp uint32 // The cumulative number of level0 compaction + nonLevel0Comp uint32 // The cumulative number of non-level0 compaction + seekComp uint32 // The cumulative number of seek compaction + // Session. s *session @@ -978,6 +984,8 @@ func (db *DB) GetProperty(name string) (value string, err error) { value += fmt.Sprintf(" Total | %10d | %13.5f | %13.5f | %13.5f | %13.5f\n", totalTables, float64(totalSize)/1048576.0, totalDuration.Seconds(), float64(totalRead)/1048576.0, float64(totalWrite)/1048576.0) + case p == "compcount": + value = fmt.Sprintf("MemComp:%d Level0Comp:%d NonLevel0Comp:%d SeekComp:%d", atomic.LoadUint32(&db.memComp), atomic.LoadUint32(&db.level0Comp), atomic.LoadUint32(&db.nonLevel0Comp), atomic.LoadUint32(&db.seekComp)) case p == "iostats": value = fmt.Sprintf("Read(MB):%.5f Write(MB):%.5f", float64(db.s.stor.reads())/1048576.0, @@ -1034,6 +1042,11 @@ type DBStats struct { LevelRead Sizes LevelWrite Sizes LevelDurations []time.Duration + + MemComp uint32 + Level0Comp uint32 + NonLevel0Comp uint32 + SeekComp uint32 } // Stats populates s with database statistics. @@ -1070,16 +1083,17 @@ func (db *DB) Stats(s *DBStats) error { for level, tables := range v.levels { duration, read, write := db.compStats.getStat(level) - if len(tables) == 0 && duration == 0 { - continue - } + s.LevelDurations = append(s.LevelDurations, duration) s.LevelRead = append(s.LevelRead, read) s.LevelWrite = append(s.LevelWrite, write) s.LevelSizes = append(s.LevelSizes, tables.size()) s.LevelTablesCounts = append(s.LevelTablesCounts, len(tables)) } - + s.MemComp = atomic.LoadUint32(&db.memComp) + s.Level0Comp = atomic.LoadUint32(&db.level0Comp) + s.NonLevel0Comp = atomic.LoadUint32(&db.nonLevel0Comp) + s.SeekComp = atomic.LoadUint32(&db.seekComp) return nil } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go index 56f3632a7d..6b70eb2c9d 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go @@ -8,6 +8,7 @@ package leveldb import ( "sync" + "sync/atomic" "time" "github.com/syndtr/goleveldb/leveldb/errors" @@ -324,10 +325,12 @@ func (db *DB) memCompaction() { db.logf("memdb@flush committed F·%d T·%v", len(rec.addedTables), stats.duration) + // Save compaction stats for _, r := range rec.addedTables { stats.write += r.size } db.compStats.addStat(flushLevel, stats) + atomic.AddUint32(&db.memComp, 1) // Drop frozen memdb. db.dropFrozenMem() @@ -588,6 +591,14 @@ func (db *DB) tableCompaction(c *compaction, noTrivial bool) { for i := range stats { db.compStats.addStat(c.sourceLevel+1, &stats[i]) } + switch c.typ { + case level0Compaction: + atomic.AddUint32(&db.level0Comp, 1) + case nonLevel0Compaction: + atomic.AddUint32(&db.nonLevel0Comp, 1) + case seekCompaction: + atomic.AddUint32(&db.seekComp, 1) + } } func (db *DB) tableRangeCompaction(level int, umin, umax []byte) error { diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_iter.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_iter.go index 03c24cdab5..e6e8ca59d0 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_iter.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_iter.go @@ -78,13 +78,17 @@ func (db *DB) newIterator(auxm *memDB, auxt tFiles, seq uint64, slice *util.Rang } rawIter := db.newRawIterator(auxm, auxt, islice, ro) iter := &dbIter{ - db: db, - icmp: db.s.icmp, - iter: rawIter, - seq: seq, - strict: opt.GetStrict(db.s.o.Options, ro, opt.StrictReader), - key: make([]byte, 0), - value: make([]byte, 0), + db: db, + icmp: db.s.icmp, + iter: rawIter, + seq: seq, + strict: opt.GetStrict(db.s.o.Options, ro, opt.StrictReader), + disableSampling: db.s.o.GetDisableSeeksCompaction() || db.s.o.GetIteratorSamplingRate() <= 0, + key: make([]byte, 0), + value: make([]byte, 0), + } + if !iter.disableSampling { + iter.samplingGap = db.iterSamplingRate() } atomic.AddInt32(&db.aliveIters, 1) runtime.SetFinalizer(iter, (*dbIter).Release) @@ -107,13 +111,14 @@ const ( // dbIter represent an interator states over a database session. type dbIter struct { - db *DB - icmp *iComparer - iter iterator.Iterator - seq uint64 - strict bool - - smaplingGap int + db *DB + icmp *iComparer + iter iterator.Iterator + seq uint64 + strict bool + disableSampling bool + + samplingGap int dir dir key []byte value []byte @@ -122,10 +127,14 @@ type dbIter struct { } func (i *dbIter) sampleSeek() { + if i.disableSampling { + return + } + ikey := i.iter.Key() - i.smaplingGap -= len(ikey) + len(i.iter.Value()) - for i.smaplingGap < 0 { - i.smaplingGap += i.db.iterSamplingRate() + i.samplingGap -= len(ikey) + len(i.iter.Value()) + for i.samplingGap < 0 { + i.samplingGap += i.db.iterSamplingRate() i.db.sampleSeek(ikey) } } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go index f145b64fbb..21d1e512f3 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go @@ -69,6 +69,9 @@ func (tr *Transaction) Has(key []byte, ro *opt.ReadOptions) (bool, error) { // DB. And a nil Range.Limit is treated as a key after all keys in // the DB. // +// The returned iterator has locks on its own resources, so it can live beyond +// the lifetime of the transaction who creates them. +// // WARNING: Any slice returned by interator (e.g. slice returned by calling // Iterator.Key() or Iterator.Key() methods), its content should not be modified // unless noted otherwise. @@ -252,13 +255,14 @@ func (tr *Transaction) discard() { // Discard transaction. for _, t := range tr.tables { tr.db.logf("transaction@discard @%d", t.fd.Num) - if err1 := tr.db.s.stor.Remove(t.fd); err1 == nil { - tr.db.s.reuseFileNum(t.fd.Num) - } + // Iterator may still use the table, so we use tOps.remove here. + tr.db.s.tops.remove(t.fd) } } // Discard discards the transaction. +// This method is noop if transaction is already closed (either committed or +// discarded) // // Other methods should not be called after transaction has been discarded. func (tr *Transaction) Discard() { @@ -282,8 +286,10 @@ func (db *DB) waitCompaction() error { // until in-flight transaction is committed or discarded. // The returned transaction handle is safe for concurrent use. // -// Transaction is expensive and can overwhelm compaction, especially if +// Transaction is very expensive and can overwhelm compaction, especially if // transaction size is small. Use with caution. +// The rule of thumb is if you need to merge at least same amount of +// `Options.WriteBuffer` worth of data then use transaction, otherwise don't. // // The transaction must be closed once done, either by committing or discarding // the transaction. diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go b/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go index 528b164233..c02c1e9788 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go @@ -278,6 +278,14 @@ type Options struct { // The default is false. DisableLargeBatchTransaction bool + // DisableSeeksCompaction allows disabling 'seeks triggered compaction'. + // The purpose of 'seeks triggered compaction' is to optimize database so + // that 'level seeks' can be minimized, however this might generate many + // small compaction which may not preferable. + // + // The default is false. + DisableSeeksCompaction bool + // ErrorIfExist defines whether an error should returned if the DB already // exist. // @@ -309,6 +317,8 @@ type Options struct { // IteratorSamplingRate defines approximate gap (in bytes) between read // sampling of an iterator. The samples will be used to determine when // compaction should be triggered. + // Use negative value to disable iterator sampling. + // The iterator sampling is disabled if DisableSeeksCompaction is true. // // The default is 1MiB. IteratorSamplingRate int @@ -526,6 +536,13 @@ func (o *Options) GetDisableLargeBatchTransaction() bool { return o.DisableLargeBatchTransaction } +func (o *Options) GetDisableSeeksCompaction() bool { + if o == nil { + return false + } + return o.DisableSeeksCompaction +} + func (o *Options) GetErrorIfExist() bool { if o == nil { return false @@ -548,8 +565,10 @@ func (o *Options) GetFilter() filter.Filter { } func (o *Options) GetIteratorSamplingRate() int { - if o == nil || o.IteratorSamplingRate <= 0 { + if o == nil || o.IteratorSamplingRate == 0 { return DefaultIteratorSamplingRate + } else if o.IteratorSamplingRate < 0 { + return 0 } return o.IteratorSamplingRate } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session_compaction.go b/vendor/github.com/syndtr/goleveldb/leveldb/session_compaction.go index f6030022de..4c1d336bef 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/session_compaction.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/session_compaction.go @@ -14,6 +14,13 @@ import ( "github.com/syndtr/goleveldb/leveldb/opt" ) +const ( + undefinedCompaction = iota + level0Compaction + nonLevel0Compaction + seekCompaction +) + func (s *session) pickMemdbLevel(umin, umax []byte, maxLevel int) int { v := s.version() defer v.release() @@ -50,6 +57,7 @@ func (s *session) pickCompaction() *compaction { var sourceLevel int var t0 tFiles + var typ int if v.cScore >= 1 { sourceLevel = v.cLevel cptr := s.getCompPtr(sourceLevel) @@ -63,18 +71,24 @@ func (s *session) pickCompaction() *compaction { if len(t0) == 0 { t0 = append(t0, tables[0]) } + if sourceLevel == 0 { + typ = level0Compaction + } else { + typ = nonLevel0Compaction + } } else { if p := atomic.LoadPointer(&v.cSeek); p != nil { ts := (*tSet)(p) sourceLevel = ts.level t0 = append(t0, ts.table) + typ = seekCompaction } else { v.release() return nil } } - return newCompaction(s, v, sourceLevel, t0) + return newCompaction(s, v, sourceLevel, t0, typ) } // Create compaction from given level and range; need external synchronization. @@ -109,13 +123,18 @@ func (s *session) getCompactionRange(sourceLevel int, umin, umax []byte, noLimit } } - return newCompaction(s, v, sourceLevel, t0) + typ := level0Compaction + if sourceLevel != 0 { + typ = nonLevel0Compaction + } + return newCompaction(s, v, sourceLevel, t0, typ) } -func newCompaction(s *session, v *version, sourceLevel int, t0 tFiles) *compaction { +func newCompaction(s *session, v *version, sourceLevel int, t0 tFiles, typ int) *compaction { c := &compaction{ s: s, v: v, + typ: typ, sourceLevel: sourceLevel, levels: [2]tFiles{t0, nil}, maxGPOverlaps: int64(s.o.GetCompactionGPOverlaps(sourceLevel)), @@ -131,6 +150,7 @@ type compaction struct { s *session v *version + typ int sourceLevel int levels [2]tFiles maxGPOverlaps int64 diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go index 67a6df9790..fc56b631f0 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go @@ -308,7 +308,7 @@ func (s *session) setNextFileNum(num int64) { func (s *session) markFileNum(num int64) { nextFileNum := num + 1 for { - old, x := s.stNextFileNum, nextFileNum + old, x := atomic.LoadInt64(&s.stNextFileNum), nextFileNum if old > x { x = old } @@ -326,7 +326,7 @@ func (s *session) allocFileNum() int64 { // Reuse given file number. func (s *session) reuseFileNum(num int64) { for { - old, x := s.stNextFileNum, num + old, x := atomic.LoadInt64(&s.stNextFileNum), num if old != x+1 { x = old } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/table.go b/vendor/github.com/syndtr/goleveldb/leveldb/table.go index 5ad1f80543..b7759b2f5c 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/table.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/table.go @@ -493,6 +493,8 @@ func (t *tOps) remove(fd storage.FileDesc) { if t.evictRemoved && t.bcache != nil { t.bcache.EvictNS(uint64(fd.Num)) } + // Try to reuse file num, useful for discarded transaction. + t.s.reuseFileNum(fd.Num) }) } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/version.go b/vendor/github.com/syndtr/goleveldb/leveldb/version.go index 2664560e1c..9535e35914 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/version.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/version.go @@ -144,6 +144,7 @@ func (v *version) get(aux tFiles, ikey internalKey, ro *opt.ReadOptions, noValue } ukey := ikey.ukey() + sampleSeeks := !v.s.o.GetDisableSeeksCompaction() var ( tset *tSet @@ -161,7 +162,7 @@ func (v *version) get(aux tFiles, ikey internalKey, ro *opt.ReadOptions, noValue // Since entries never hop across level, finding key/value // in smaller level make later levels irrelevant. v.walkOverlapping(aux, ikey, func(level int, t *tFile) bool { - if level >= 0 && !tseek { + if sampleSeeks && level >= 0 && !tseek { if tset == nil { tset = &tSet{level, t} } else { diff --git a/vendor/github.com/tyler-smith/go-bip39/.golangci.yml b/vendor/github.com/tyler-smith/go-bip39/.golangci.yml new file mode 100644 index 0000000000..823061d3ab --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/.golangci.yml @@ -0,0 +1,44 @@ +issues: + max-per-linter: 999999 + max-same: 999999 + +linters-settings: + errcheck: + check-type-assertions: true + check-blank: true + nakedret: + max-func-lines: 0 + misspell: + locale: US + dupl: + threshold: 50 + goconst: + min-occurrences: 2 + gocyclo: + min-complexity: 8 + lll: + line-length: 250 + +linters: + enable: + - gofmt + - golint + - goimports + - unconvert + - ineffassign + - staticcheck + - structcheck + - unused + - unparam + - varcheck + - deadcode + - gosimple + - dupl + - gocyclo + - nakedret + - lll + - goconst + - govet + - megacheck + - errcheck + - prealloc diff --git a/vendor/github.com/tyler-smith/go-bip39/.travis.yml b/vendor/github.com/tyler-smith/go-bip39/.travis.yml index 2b48ff12e0..d8af78aac6 100644 --- a/vendor/github.com/tyler-smith/go-bip39/.travis.yml +++ b/vendor/github.com/tyler-smith/go-bip39/.travis.yml @@ -1,12 +1,18 @@ language: go -go: - - "1.6.x" - - "1.7.x" - - "1.8.x" - - "1.9.x" - - "1.10.x" - - "release" - - "tip" +go: + - "1.6.x" + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + - "1.12.x" + - "release" + - "tip" + +before_install: + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.10 script: - - make profile_tests + - $GOPATH/bin/golangci-lint run + - make profile_tests diff --git a/vendor/github.com/tyler-smith/go-bip39/bip39.go b/vendor/github.com/tyler-smith/go-bip39/bip39.go index 62503b0fd2..72b4d0c49f 100644 --- a/vendor/github.com/tyler-smith/go-bip39/bip39.go +++ b/vendor/github.com/tyler-smith/go-bip39/bip39.go @@ -119,8 +119,8 @@ func EntropyFromMnemonic(mnemonic string) ([]byte, error) { // Decode the words into a big.Int. b := big.NewInt(0) for _, v := range mnemonicSlice { - index, found := wordMap[v] - if found == false { + index, ok := wordMap[v] + if !ok { return nil, fmt.Errorf("word `%v` not found in reverse map", v) } var wordBytes [2]byte @@ -143,7 +143,11 @@ func EntropyFromMnemonic(mnemonic string) ([]byte, error) { entropy = padByteSlice(entropy, len(mnemonicSlice)/3*4) // Generate the checksum and compare with the one we got from the mneomnic. - entropyChecksumBytes := computeChecksum(entropy) + entropyChecksumBytes, err := computeChecksum(entropy) + if err != nil { + return nil, err + } + entropyChecksum := big.NewInt(int64(entropyChecksumBytes[0])) if l := len(mnemonicSlice); l != 24 { checksumShift := wordLengthChecksumShiftMapping[l] @@ -173,7 +177,10 @@ func NewMnemonic(entropy []byte) (string, error) { } // Add checksum to entropy. - entropy = addChecksum(entropy) + entropy, err = addChecksum(entropy) + if err != nil { + return "", err + } // Break entropy up into sentenceLength chunks of 11 bits. // For each word AND mask the rightmost 11 bits and find the word at that index. @@ -241,7 +248,12 @@ func MnemonicToByteArray(mnemonic string, raw ...bool) ([]byte, error) { checksummedEntropyBytes := padByteSlice(checksummedEntropy.Bytes(), fullByteSize) // Validate that the checksum is correct. - newChecksummedEntropyBytes := padByteSlice(addChecksum(rawEntropyBytes), fullByteSize) + unpaddedChecksumedBytes, err := addChecksum(rawEntropyBytes) + if err != nil { + return nil, err + } + + newChecksummedEntropyBytes := padByteSlice(unpaddedChecksumedBytes, fullByteSize) if !compareByteSlices(checksummedEntropyBytes, newChecksummedEntropyBytes) { return nil, ErrChecksumIncorrect } @@ -296,9 +308,13 @@ func IsMnemonicValid(mnemonic string) bool { // Appends to data the first (len(data) / 32)bits of the result of sha256(data) // Currently only supports data up to 32 bytes -func addChecksum(data []byte) []byte { +func addChecksum(data []byte) ([]byte, error) { // Get first byte of sha256 - hash := computeChecksum(data) + hash, err := computeChecksum(data) + if err != nil { + return nil, err + } + firstChecksumByte := hash[0] // len() is in bytes so we divide by 4 @@ -313,18 +329,21 @@ func addChecksum(data []byte) []byte { dataBigInt.Mul(dataBigInt, bigTwo) // Set rightmost bit if leftmost checksum bit is set - if uint8(firstChecksumByte&(1<<(7-i))) > 0 { + if firstChecksumByte&(1<<(7-i)) > 0 { dataBigInt.Or(dataBigInt, bigOne) } } - return dataBigInt.Bytes() + return dataBigInt.Bytes(), nil } -func computeChecksum(data []byte) []byte { +func computeChecksum(data []byte) ([]byte, error) { hasher := sha256.New() - hasher.Write(data) - return hasher.Sum(nil) + _, err := hasher.Write(data) + if err != nil { + return nil, err + } + return hasher.Sum(nil), nil } // validateEntropyBitSize ensures that entropy is the correct size for being a diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h deleted file mode 100644 index b3f74162f6..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/const_amd64.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -#define REDMASK51 0x0007FFFFFFFFFFFF diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s deleted file mode 100644 index ee7b4bd5f8..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/const_amd64.s +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -// These constants cannot be encoded in non-MOVQ immediates. -// We access them directly from memory instead. - -DATA ·_121666_213(SB)/8, $996687872 -GLOBL ·_121666_213(SB), 8, $8 - -DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA -GLOBL ·_2P0(SB), 8, $8 - -DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE -GLOBL ·_2P1234(SB), 8, $8 diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s deleted file mode 100644 index cd793a5b5f..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -// func cswap(inout *[4][5]uint64, v uint64) -TEXT ·cswap(SB),7,$0 - MOVQ inout+0(FP),DI - MOVQ v+8(FP),SI - - SUBQ $1, SI - NOTQ SI - MOVQ SI, X15 - PSHUFD $0x44, X15, X15 - - MOVOU 0(DI), X0 - MOVOU 16(DI), X2 - MOVOU 32(DI), X4 - MOVOU 48(DI), X6 - MOVOU 64(DI), X8 - MOVOU 80(DI), X1 - MOVOU 96(DI), X3 - MOVOU 112(DI), X5 - MOVOU 128(DI), X7 - MOVOU 144(DI), X9 - - MOVO X1, X10 - MOVO X3, X11 - MOVO X5, X12 - MOVO X7, X13 - MOVO X9, X14 - - PXOR X0, X10 - PXOR X2, X11 - PXOR X4, X12 - PXOR X6, X13 - PXOR X8, X14 - PAND X15, X10 - PAND X15, X11 - PAND X15, X12 - PAND X15, X13 - PAND X15, X14 - PXOR X10, X0 - PXOR X10, X1 - PXOR X11, X2 - PXOR X11, X3 - PXOR X12, X4 - PXOR X12, X5 - PXOR X13, X6 - PXOR X13, X7 - PXOR X14, X8 - PXOR X14, X9 - - MOVOU X0, 0(DI) - MOVOU X2, 16(DI) - MOVOU X4, 32(DI) - MOVOU X6, 48(DI) - MOVOU X8, 64(DI) - MOVOU X1, 80(DI) - MOVOU X3, 96(DI) - MOVOU X5, 112(DI) - MOVOU X7, 128(DI) - MOVOU X9, 144(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go index 75f24babb6..4b9a655d1b 100644 --- a/vendor/golang.org/x/crypto/curve25519/curve25519.go +++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -1,834 +1,95 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// We have an implementation in amd64 assembly so this code is only run on -// non-amd64 platforms. The amd64 assembly does not support gccgo. -// +build !amd64 gccgo appengine - -package curve25519 +// Package curve25519 provides an implementation of the X25519 function, which +// performs scalar multiplication on the elliptic curve known as Curve25519. +// See RFC 7748. +package curve25519 // import "golang.org/x/crypto/curve25519" import ( - "encoding/binary" + "crypto/subtle" + "fmt" ) -// This code is a port of the public domain, "ref10" implementation of -// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. - -// fieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type fieldElement [10]int32 - -func feZero(fe *fieldElement) { - for i := range fe { - fe[i] = 0 - } -} - -func feOne(fe *fieldElement) { - feZero(fe) - fe[0] = 1 -} - -func feAdd(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] + b[i] - } -} - -func feSub(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] - b[i] - } -} - -func feCopy(dst, src *fieldElement) { - for i := range dst { - dst[i] = src[i] - } -} - -// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func feCSwap(f, g *fieldElement, b int32) { - b = -b - for i := range f { - t := b & (f[i] ^ g[i]) - f[i] ^= t - g[i] ^= t - } -} - -// load3 reads a 24-bit, little-endian value from in. -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -// load4 reads a 32-bit, little-endian value from in. -func load4(in []byte) int64 { - return int64(binary.LittleEndian.Uint32(in)) -} - -func feFromBytes(dst *fieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 0x7fffff) << 2 - - var carry [10]int64 - carry[9] = (h9 + 1<<24) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + 1<<24) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + 1<<24) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + 1<<24) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + 1<<24) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + 1<<25) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + 1<<25) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + 1<<25) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + 1<<25) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + 1<<25) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - dst[0] = int32(h0) - dst[1] = int32(h1) - dst[2] = int32(h2) - dst[3] = int32(h3) - dst[4] = int32(h4) - dst[5] = int32(h5) - dst[6] = int32(h6) - dst[7] = int32(h7) - dst[8] = int32(h8) - dst[9] = int32(h9) -} - -// feToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) +// Deprecated: when provided a low-order point, ScalarMult will set dst to all +// zeroes, irrespective of the scalar. Instead, use the X25519 function, which +// will return an error. +func ScalarMult(dst, scalar, point *[32]byte) { + scalarMult(dst, scalar, point) } -// feMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. +// ScalarBaseMult sets dst to the product scalar * base where base is the +// standard generator. // -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs can squeeze carries into int32. -func feMul(h, f, g *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - g0 := g[0] - g1 := g[1] - g2 := g[2] - g3 := g[3] - g4 := g[4] - g5 := g[5] - g6 := g[6] - g7 := g[7] - g8 := g[8] - g9 := g[9] - g1_19 := 19 * g1 // 1.4*2^29 - g2_19 := 19 * g2 // 1.4*2^30; still ok - g3_19 := 19 * g3 - g4_19 := 19 * g4 - g5_19 := 19 * g5 - g6_19 := 19 * g6 - g7_19 := 19 * g7 - g8_19 := 19 * g8 - g9_19 := 19 * g9 - f1_2 := 2 * f1 - f3_2 := 2 * f3 - f5_2 := 2 * f5 - f7_2 := 2 * f7 - f9_2 := 2 * f9 - f0g0 := int64(f0) * int64(g0) - f0g1 := int64(f0) * int64(g1) - f0g2 := int64(f0) * int64(g2) - f0g3 := int64(f0) * int64(g3) - f0g4 := int64(f0) * int64(g4) - f0g5 := int64(f0) * int64(g5) - f0g6 := int64(f0) * int64(g6) - f0g7 := int64(f0) * int64(g7) - f0g8 := int64(f0) * int64(g8) - f0g9 := int64(f0) * int64(g9) - f1g0 := int64(f1) * int64(g0) - f1g1_2 := int64(f1_2) * int64(g1) - f1g2 := int64(f1) * int64(g2) - f1g3_2 := int64(f1_2) * int64(g3) - f1g4 := int64(f1) * int64(g4) - f1g5_2 := int64(f1_2) * int64(g5) - f1g6 := int64(f1) * int64(g6) - f1g7_2 := int64(f1_2) * int64(g7) - f1g8 := int64(f1) * int64(g8) - f1g9_38 := int64(f1_2) * int64(g9_19) - f2g0 := int64(f2) * int64(g0) - f2g1 := int64(f2) * int64(g1) - f2g2 := int64(f2) * int64(g2) - f2g3 := int64(f2) * int64(g3) - f2g4 := int64(f2) * int64(g4) - f2g5 := int64(f2) * int64(g5) - f2g6 := int64(f2) * int64(g6) - f2g7 := int64(f2) * int64(g7) - f2g8_19 := int64(f2) * int64(g8_19) - f2g9_19 := int64(f2) * int64(g9_19) - f3g0 := int64(f3) * int64(g0) - f3g1_2 := int64(f3_2) * int64(g1) - f3g2 := int64(f3) * int64(g2) - f3g3_2 := int64(f3_2) * int64(g3) - f3g4 := int64(f3) * int64(g4) - f3g5_2 := int64(f3_2) * int64(g5) - f3g6 := int64(f3) * int64(g6) - f3g7_38 := int64(f3_2) * int64(g7_19) - f3g8_19 := int64(f3) * int64(g8_19) - f3g9_38 := int64(f3_2) * int64(g9_19) - f4g0 := int64(f4) * int64(g0) - f4g1 := int64(f4) * int64(g1) - f4g2 := int64(f4) * int64(g2) - f4g3 := int64(f4) * int64(g3) - f4g4 := int64(f4) * int64(g4) - f4g5 := int64(f4) * int64(g5) - f4g6_19 := int64(f4) * int64(g6_19) - f4g7_19 := int64(f4) * int64(g7_19) - f4g8_19 := int64(f4) * int64(g8_19) - f4g9_19 := int64(f4) * int64(g9_19) - f5g0 := int64(f5) * int64(g0) - f5g1_2 := int64(f5_2) * int64(g1) - f5g2 := int64(f5) * int64(g2) - f5g3_2 := int64(f5_2) * int64(g3) - f5g4 := int64(f5) * int64(g4) - f5g5_38 := int64(f5_2) * int64(g5_19) - f5g6_19 := int64(f5) * int64(g6_19) - f5g7_38 := int64(f5_2) * int64(g7_19) - f5g8_19 := int64(f5) * int64(g8_19) - f5g9_38 := int64(f5_2) * int64(g9_19) - f6g0 := int64(f6) * int64(g0) - f6g1 := int64(f6) * int64(g1) - f6g2 := int64(f6) * int64(g2) - f6g3 := int64(f6) * int64(g3) - f6g4_19 := int64(f6) * int64(g4_19) - f6g5_19 := int64(f6) * int64(g5_19) - f6g6_19 := int64(f6) * int64(g6_19) - f6g7_19 := int64(f6) * int64(g7_19) - f6g8_19 := int64(f6) * int64(g8_19) - f6g9_19 := int64(f6) * int64(g9_19) - f7g0 := int64(f7) * int64(g0) - f7g1_2 := int64(f7_2) * int64(g1) - f7g2 := int64(f7) * int64(g2) - f7g3_38 := int64(f7_2) * int64(g3_19) - f7g4_19 := int64(f7) * int64(g4_19) - f7g5_38 := int64(f7_2) * int64(g5_19) - f7g6_19 := int64(f7) * int64(g6_19) - f7g7_38 := int64(f7_2) * int64(g7_19) - f7g8_19 := int64(f7) * int64(g8_19) - f7g9_38 := int64(f7_2) * int64(g9_19) - f8g0 := int64(f8) * int64(g0) - f8g1 := int64(f8) * int64(g1) - f8g2_19 := int64(f8) * int64(g2_19) - f8g3_19 := int64(f8) * int64(g3_19) - f8g4_19 := int64(f8) * int64(g4_19) - f8g5_19 := int64(f8) * int64(g5_19) - f8g6_19 := int64(f8) * int64(g6_19) - f8g7_19 := int64(f8) * int64(g7_19) - f8g8_19 := int64(f8) * int64(g8_19) - f8g9_19 := int64(f8) * int64(g9_19) - f9g0 := int64(f9) * int64(g0) - f9g1_38 := int64(f9_2) * int64(g1_19) - f9g2_19 := int64(f9) * int64(g2_19) - f9g3_38 := int64(f9_2) * int64(g3_19) - f9g4_19 := int64(f9) * int64(g4_19) - f9g5_38 := int64(f9_2) * int64(g5_19) - f9g6_19 := int64(f9) * int64(g6_19) - f9g7_38 := int64(f9_2) * int64(g7_19) - f9g8_19 := int64(f9) * int64(g8_19) - f9g9_38 := int64(f9_2) * int64(g9_19) - h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 - h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 - h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 - h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 - h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 - h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 - h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 - h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 - h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 - h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 - var carry [10]int64 - - // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - // |h0| <= 2^25 - // |h4| <= 2^25 - // |h1| <= 1.51*2^58 - // |h5| <= 1.51*2^58 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - // |h1| <= 2^24; from now on fits into int32 - // |h5| <= 2^24; from now on fits into int32 - // |h2| <= 1.21*2^59 - // |h6| <= 1.21*2^59 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - // |h2| <= 2^25; from now on fits into int32 unchanged - // |h6| <= 2^25; from now on fits into int32 unchanged - // |h3| <= 1.51*2^58 - // |h7| <= 1.51*2^58 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - // |h3| <= 2^24; from now on fits into int32 unchanged - // |h7| <= 2^24; from now on fits into int32 unchanged - // |h4| <= 1.52*2^33 - // |h8| <= 1.52*2^33 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - // |h4| <= 2^25; from now on fits into int32 unchanged - // |h8| <= 2^25; from now on fits into int32 unchanged - // |h5| <= 1.01*2^24 - // |h9| <= 1.51*2^58 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - // |h9| <= 2^24; from now on fits into int32 unchanged - // |h0| <= 1.8*2^37 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - // |h0| <= 2^25; from now on fits into int32 unchanged - // |h1| <= 1.01*2^24 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) +// It is recommended to use the X25519 function with Basepoint instead, as +// copying into fixed size arrays can lead to unexpected bugs. +func ScalarBaseMult(dst, scalar *[32]byte) { + ScalarMult(dst, scalar, &basePoint) } -// feSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feSquare(h, f *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - f0_2 := 2 * f0 - f1_2 := 2 * f1 - f2_2 := 2 * f2 - f3_2 := 2 * f3 - f4_2 := 2 * f4 - f5_2 := 2 * f5 - f6_2 := 2 * f6 - f7_2 := 2 * f7 - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - f0f0 := int64(f0) * int64(f0) - f0f1_2 := int64(f0_2) * int64(f1) - f0f2_2 := int64(f0_2) * int64(f2) - f0f3_2 := int64(f0_2) * int64(f3) - f0f4_2 := int64(f0_2) * int64(f4) - f0f5_2 := int64(f0_2) * int64(f5) - f0f6_2 := int64(f0_2) * int64(f6) - f0f7_2 := int64(f0_2) * int64(f7) - f0f8_2 := int64(f0_2) * int64(f8) - f0f9_2 := int64(f0_2) * int64(f9) - f1f1_2 := int64(f1_2) * int64(f1) - f1f2_2 := int64(f1_2) * int64(f2) - f1f3_4 := int64(f1_2) * int64(f3_2) - f1f4_2 := int64(f1_2) * int64(f4) - f1f5_4 := int64(f1_2) * int64(f5_2) - f1f6_2 := int64(f1_2) * int64(f6) - f1f7_4 := int64(f1_2) * int64(f7_2) - f1f8_2 := int64(f1_2) * int64(f8) - f1f9_76 := int64(f1_2) * int64(f9_38) - f2f2 := int64(f2) * int64(f2) - f2f3_2 := int64(f2_2) * int64(f3) - f2f4_2 := int64(f2_2) * int64(f4) - f2f5_2 := int64(f2_2) * int64(f5) - f2f6_2 := int64(f2_2) * int64(f6) - f2f7_2 := int64(f2_2) * int64(f7) - f2f8_38 := int64(f2_2) * int64(f8_19) - f2f9_38 := int64(f2) * int64(f9_38) - f3f3_2 := int64(f3_2) * int64(f3) - f3f4_2 := int64(f3_2) * int64(f4) - f3f5_4 := int64(f3_2) * int64(f5_2) - f3f6_2 := int64(f3_2) * int64(f6) - f3f7_76 := int64(f3_2) * int64(f7_38) - f3f8_38 := int64(f3_2) * int64(f8_19) - f3f9_76 := int64(f3_2) * int64(f9_38) - f4f4 := int64(f4) * int64(f4) - f4f5_2 := int64(f4_2) * int64(f5) - f4f6_38 := int64(f4_2) * int64(f6_19) - f4f7_38 := int64(f4) * int64(f7_38) - f4f8_38 := int64(f4_2) * int64(f8_19) - f4f9_38 := int64(f4) * int64(f9_38) - f5f5_38 := int64(f5) * int64(f5_38) - f5f6_38 := int64(f5_2) * int64(f6_19) - f5f7_76 := int64(f5_2) * int64(f7_38) - f5f8_38 := int64(f5_2) * int64(f8_19) - f5f9_76 := int64(f5_2) * int64(f9_38) - f6f6_19 := int64(f6) * int64(f6_19) - f6f7_38 := int64(f6) * int64(f7_38) - f6f8_38 := int64(f6_2) * int64(f8_19) - f6f9_38 := int64(f6) * int64(f9_38) - f7f7_38 := int64(f7) * int64(f7_38) - f7f8_38 := int64(f7_2) * int64(f8_19) - f7f9_76 := int64(f7_2) * int64(f9_38) - f8f8_19 := int64(f8) * int64(f8_19) - f8f9_38 := int64(f8) * int64(f9_38) - f9f9_38 := int64(f9) * int64(f9_38) - h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 - h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 - h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 - h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 - h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 - h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 - h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 - h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 - h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 - h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 - var carry [10]int64 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 +const ( + // ScalarSize is the size of the scalar input to X25519. + ScalarSize = 32 + // PointSize is the size of the point input to X25519. + PointSize = 32 +) - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 +// Basepoint is the canonical Curve25519 generator. +var Basepoint []byte - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 +var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 +func init() { Basepoint = basePoint[:] } - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) +func checkBasepoint() { + if subtle.ConstantTimeCompare(Basepoint, []byte{ + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }) != 1 { + panic("curve25519: global Basepoint value was modified") + } } -// feMul121666 calculates h = f * 121666. Can overlap h with f. +// X25519 returns the result of the scalar multiplication (scalar * point), +// according to RFC 7748, Section 5. scalar, point and the return value are +// slices of 32 bytes. // -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// scalar can be generated at random, for example with crypto/rand. point should +// be either Basepoint or the output of another X25519 call. // -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feMul121666(h, f *fieldElement) { - h0 := int64(f[0]) * 121666 - h1 := int64(f[1]) * 121666 - h2 := int64(f[2]) * 121666 - h3 := int64(f[3]) * 121666 - h4 := int64(f[4]) * 121666 - h5 := int64(f[5]) * 121666 - h6 := int64(f[6]) * 121666 - h7 := int64(f[7]) * 121666 - h8 := int64(f[8]) * 121666 - h9 := int64(f[9]) * 121666 - var carry [10]int64 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feInvert sets out = z^-1. -func feInvert(out, z *fieldElement) { - var t0, t1, t2, t3 fieldElement - var i int - - feSquare(&t0, z) - for i = 1; i < 1; i++ { - feSquare(&t0, &t0) - } - feSquare(&t1, &t0) - for i = 1; i < 2; i++ { - feSquare(&t1, &t1) - } - feMul(&t1, z, &t1) - feMul(&t0, &t0, &t1) - feSquare(&t2, &t0) - for i = 1; i < 1; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t1, &t2) - feSquare(&t2, &t1) - for i = 1; i < 5; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 20; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 100; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t1, &t1) - for i = 1; i < 5; i++ { - feSquare(&t1, &t1) - } - feMul(out, &t1, &t0) +// If point is Basepoint (but not if it's a different slice with the same +// contents) a precomputed implementation might be used for performance. +func X25519(scalar, point []byte) ([]byte, error) { + // Outline the body of function, to let the allocation be inlined in the + // caller, and possibly avoid escaping to the heap. + var dst [32]byte + return x25519(&dst, scalar, point) } -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - - copy(e[:], in[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement - feFromBytes(&x1, base) - feOne(&x2) - feCopy(&x3, &x1) - feOne(&z3) - - swap := int32(0) - for pos := 254; pos >= 0; pos-- { - b := e[pos/8] >> uint(pos&7) - b &= 1 - swap ^= int32(b) - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - swap = int32(b) - - feSub(&tmp0, &x3, &z3) - feSub(&tmp1, &x2, &z2) - feAdd(&x2, &x2, &z2) - feAdd(&z2, &x3, &z3) - feMul(&z3, &tmp0, &x2) - feMul(&z2, &z2, &tmp1) - feSquare(&tmp0, &tmp1) - feSquare(&tmp1, &x2) - feAdd(&x3, &z3, &z2) - feSub(&z2, &z3, &z2) - feMul(&x2, &tmp1, &tmp0) - feSub(&tmp1, &tmp1, &tmp0) - feSquare(&z2, &z2) - feMul121666(&z3, &tmp1) - feSquare(&x3, &x3) - feAdd(&tmp0, &tmp0, &z3) - feMul(&z3, &x1, &z2) - feMul(&z2, &tmp1, &tmp0) - } - - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - - feInvert(&z2, &z2) - feMul(&x2, &x2, &z2) - feToBytes(out, &x2) +func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { + var in [32]byte + if l := len(scalar); l != 32 { + return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32) + } + if l := len(point); l != 32 { + return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32) + } + copy(in[:], scalar) + if &point[0] == &Basepoint[0] { + checkBasepoint() + ScalarBaseMult(dst, &in) + } else { + var base, zero [32]byte + copy(base[:], point) + ScalarMult(dst, &in, &base) + if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { + return nil, fmt.Errorf("bad input point: low order point") + } + } + return dst[:], nil } diff --git a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go similarity index 99% rename from vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go rename to vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go index 5822bd5338..5120b779b9 100644 --- a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!gccgo,!appengine +// +build amd64,!gccgo,!appengine,!purego package curve25519 diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s similarity index 76% rename from vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s rename to vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s index e0ac30c70f..0250c88859 100644 --- a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s @@ -5,9 +5,84 @@ // This code was translated into a form compatible with 6a from the public // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html -// +build amd64,!gccgo,!appengine +// +build amd64,!gccgo,!appengine,!purego -#include "const_amd64.h" +#define REDMASK51 0x0007FFFFFFFFFFFF + +// These constants cannot be encoded in non-MOVQ immediates. +// We access them directly from memory instead. + +DATA ·_121666_213(SB)/8, $996687872 +GLOBL ·_121666_213(SB), 8, $8 + +DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA +GLOBL ·_2P0(SB), 8, $8 + +DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE +GLOBL ·_2P1234(SB), 8, $8 + +// func freeze(inout *[5]uint64) +TEXT ·freeze(SB),7,$0-8 + MOVQ inout+0(FP), DI + + MOVQ 0(DI),SI + MOVQ 8(DI),DX + MOVQ 16(DI),CX + MOVQ 24(DI),R8 + MOVQ 32(DI),R9 + MOVQ $REDMASK51,AX + MOVQ AX,R10 + SUBQ $18,R10 + MOVQ $3,R11 +REDUCELOOP: + MOVQ SI,R12 + SHRQ $51,R12 + ANDQ AX,SI + ADDQ R12,DX + MOVQ DX,R12 + SHRQ $51,R12 + ANDQ AX,DX + ADDQ R12,CX + MOVQ CX,R12 + SHRQ $51,R12 + ANDQ AX,CX + ADDQ R12,R8 + MOVQ R8,R12 + SHRQ $51,R12 + ANDQ AX,R8 + ADDQ R12,R9 + MOVQ R9,R12 + SHRQ $51,R12 + ANDQ AX,R9 + IMUL3Q $19,R12,R12 + ADDQ R12,SI + SUBQ $1,R11 + JA REDUCELOOP + MOVQ $1,R12 + CMPQ R10,SI + CMOVQLT R11,R12 + CMPQ AX,DX + CMOVQNE R11,R12 + CMPQ AX,CX + CMOVQNE R11,R12 + CMPQ AX,R8 + CMOVQNE R11,R12 + CMPQ AX,R9 + CMOVQNE R11,R12 + NEGQ R12 + ANDQ R12,AX + ANDQ R12,R10 + SUBQ R10,SI + SUBQ AX,DX + SUBQ AX,CX + SUBQ AX,R8 + SUBQ AX,R9 + MOVQ SI,0(DI) + MOVQ DX,8(DI) + MOVQ CX,16(DI) + MOVQ R8,24(DI) + MOVQ R9,32(DI) + RET // func ladderstep(inout *[5][5]uint64) TEXT ·ladderstep(SB),0,$296-8 @@ -1375,3 +1450,344 @@ TEXT ·ladderstep(SB),0,$296-8 MOVQ AX,104(DI) MOVQ R10,112(DI) RET + +// func cswap(inout *[4][5]uint64, v uint64) +TEXT ·cswap(SB),7,$0 + MOVQ inout+0(FP),DI + MOVQ v+8(FP),SI + + SUBQ $1, SI + NOTQ SI + MOVQ SI, X15 + PSHUFD $0x44, X15, X15 + + MOVOU 0(DI), X0 + MOVOU 16(DI), X2 + MOVOU 32(DI), X4 + MOVOU 48(DI), X6 + MOVOU 64(DI), X8 + MOVOU 80(DI), X1 + MOVOU 96(DI), X3 + MOVOU 112(DI), X5 + MOVOU 128(DI), X7 + MOVOU 144(DI), X9 + + MOVO X1, X10 + MOVO X3, X11 + MOVO X5, X12 + MOVO X7, X13 + MOVO X9, X14 + + PXOR X0, X10 + PXOR X2, X11 + PXOR X4, X12 + PXOR X6, X13 + PXOR X8, X14 + PAND X15, X10 + PAND X15, X11 + PAND X15, X12 + PAND X15, X13 + PAND X15, X14 + PXOR X10, X0 + PXOR X10, X1 + PXOR X11, X2 + PXOR X11, X3 + PXOR X12, X4 + PXOR X12, X5 + PXOR X13, X6 + PXOR X13, X7 + PXOR X14, X8 + PXOR X14, X9 + + MOVOU X0, 0(DI) + MOVOU X2, 16(DI) + MOVOU X4, 32(DI) + MOVOU X6, 48(DI) + MOVOU X8, 64(DI) + MOVOU X1, 80(DI) + MOVOU X3, 96(DI) + MOVOU X5, 112(DI) + MOVOU X7, 128(DI) + MOVOU X9, 144(DI) + RET + +// func mul(dest, a, b *[5]uint64) +TEXT ·mul(SB),0,$16-24 + MOVQ dest+0(FP), DI + MOVQ a+8(FP), SI + MOVQ b+16(FP), DX + + MOVQ DX,CX + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,0(SP) + MULQ 16(CX) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,8(SP) + MULQ 8(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 0(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 8(CX) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 0(SI),AX + MULQ 16(CX) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 0(SI),AX + MULQ 24(CX) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 0(SI),AX + MULQ 32(CX) + MOVQ AX,BX + MOVQ DX,BP + MOVQ 8(SI),AX + MULQ 0(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SI),AX + MULQ 8(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SI),AX + MULQ 16(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SI),AX + MULQ 24(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 8(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),AX + MULQ 0(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 16(SI),AX + MULQ 8(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 16(SI),AX + MULQ 16(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 24(SI),AX + MULQ 0(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 24(SI),AX + MULQ 8(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 0(SP),AX + MULQ 24(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 0(SP),AX + MULQ 32(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 32(SI),AX + MULQ 0(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 8(SP),AX + MULQ 16(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + MULQ 24(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SP),AX + MULQ 32(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ $REDMASK51,SI + SHLQ $13,R8,R9 + ANDQ SI,R8 + SHLQ $13,R10,R11 + ANDQ SI,R10 + ADDQ R9,R10 + SHLQ $13,R12,R13 + ANDQ SI,R12 + ADDQ R11,R12 + SHLQ $13,R14,R15 + ANDQ SI,R14 + ADDQ R13,R14 + SHLQ $13,BX,BP + ANDQ SI,BX + ADDQ R15,BX + IMUL3Q $19,BP,DX + ADDQ DX,R8 + MOVQ R8,DX + SHRQ $51,DX + ADDQ R10,DX + MOVQ DX,CX + SHRQ $51,DX + ANDQ SI,R8 + ADDQ R12,DX + MOVQ DX,R9 + SHRQ $51,DX + ANDQ SI,CX + ADDQ R14,DX + MOVQ DX,AX + SHRQ $51,DX + ANDQ SI,R9 + ADDQ BX,DX + MOVQ DX,R10 + SHRQ $51,DX + ANDQ SI,AX + IMUL3Q $19,DX,DX + ADDQ DX,R8 + ANDQ SI,R10 + MOVQ R8,0(DI) + MOVQ CX,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + RET + +// func square(out, in *[5]uint64) +TEXT ·square(SB),7,$0-16 + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + + MOVQ 0(SI),AX + MULQ 0(SI) + MOVQ AX,CX + MOVQ DX,R8 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 8(SI) + MOVQ AX,R9 + MOVQ DX,R10 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 16(SI) + MOVQ AX,R11 + MOVQ DX,R12 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 24(SI) + MOVQ AX,R13 + MOVQ DX,R14 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 32(SI) + MOVQ AX,R15 + MOVQ DX,BX + MOVQ 8(SI),AX + MULQ 8(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 16(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 24(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 8(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),AX + MULQ 16(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 24(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ $REDMASK51,SI + SHLQ $13,CX,R8 + ANDQ SI,CX + SHLQ $13,R9,R10 + ANDQ SI,R9 + ADDQ R8,R9 + SHLQ $13,R11,R12 + ANDQ SI,R11 + ADDQ R10,R11 + SHLQ $13,R13,R14 + ANDQ SI,R13 + ADDQ R12,R13 + SHLQ $13,R15,BX + ANDQ SI,R15 + ADDQ R14,R15 + IMUL3Q $19,BX,DX + ADDQ DX,CX + MOVQ CX,DX + SHRQ $51,DX + ADDQ R9,DX + ANDQ SI,CX + MOVQ DX,R8 + SHRQ $51,DX + ADDQ R11,DX + ANDQ SI,R8 + MOVQ DX,R9 + SHRQ $51,DX + ADDQ R13,DX + ANDQ SI,R9 + MOVQ DX,AX + SHRQ $51,DX + ADDQ R15,DX + ANDQ SI,AX + MOVQ DX,R10 + SHRQ $51,DX + IMUL3Q $19,DX,DX + ADDQ DX,CX + ANDQ SI,R10 + MOVQ CX,0(DI) + MOVQ R8,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go b/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go new file mode 100644 index 0000000000..c43b13fc83 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go @@ -0,0 +1,828 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package curve25519 + +import "encoding/binary" + +// This code is a port of the public domain, "ref10" implementation of +// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. + +// fieldElement represents an element of the field GF(2^255 - 19). An element +// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 +// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on +// context. +type fieldElement [10]int32 + +func feZero(fe *fieldElement) { + for i := range fe { + fe[i] = 0 + } +} + +func feOne(fe *fieldElement) { + feZero(fe) + fe[0] = 1 +} + +func feAdd(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] + b[i] + } +} + +func feSub(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] - b[i] + } +} + +func feCopy(dst, src *fieldElement) { + for i := range dst { + dst[i] = src[i] + } +} + +// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +func feCSwap(f, g *fieldElement, b int32) { + b = -b + for i := range f { + t := b & (f[i] ^ g[i]) + f[i] ^= t + g[i] ^= t + } +} + +// load3 reads a 24-bit, little-endian value from in. +func load3(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +// load4 reads a 32-bit, little-endian value from in. +func load4(in []byte) int64 { + return int64(binary.LittleEndian.Uint32(in)) +} + +func feFromBytes(dst *fieldElement, src *[32]byte) { + h0 := load4(src[:]) + h1 := load3(src[4:]) << 6 + h2 := load3(src[7:]) << 5 + h3 := load3(src[10:]) << 3 + h4 := load3(src[13:]) << 2 + h5 := load4(src[16:]) + h6 := load3(src[20:]) << 7 + h7 := load3(src[23:]) << 5 + h8 := load3(src[26:]) << 4 + h9 := (load3(src[29:]) & 0x7fffff) << 2 + + var carry [10]int64 + carry[9] = (h9 + 1<<24) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + 1<<24) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + 1<<24) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + 1<<24) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + 1<<24) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + 1<<25) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + 1<<25) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + 1<<25) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + 1<<25) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + 1<<25) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + dst[0] = int32(h0) + dst[1] = int32(h1) + dst[2] = int32(h2) + dst[3] = int32(h3) + dst[4] = int32(h4) + dst[5] = int32(h5) + dst[6] = int32(h6) + dst[7] = int32(h7) + dst[8] = int32(h8) + dst[9] = int32(h9) +} + +// feToBytes marshals h to s. +// Preconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Write p=2^255-19; q=floor(h/p). +// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). +// +// Proof: +// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. +// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. +// +// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). +// Then 0> 25 + q = (h[0] + q) >> 26 + q = (h[1] + q) >> 25 + q = (h[2] + q) >> 26 + q = (h[3] + q) >> 25 + q = (h[4] + q) >> 26 + q = (h[5] + q) >> 25 + q = (h[6] + q) >> 26 + q = (h[7] + q) >> 25 + q = (h[8] + q) >> 26 + q = (h[9] + q) >> 25 + + // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. + h[0] += 19 * q + // Goal: Output h-2^255 q, which is between 0 and 2^255-20. + + carry[0] = h[0] >> 26 + h[1] += carry[0] + h[0] -= carry[0] << 26 + carry[1] = h[1] >> 25 + h[2] += carry[1] + h[1] -= carry[1] << 25 + carry[2] = h[2] >> 26 + h[3] += carry[2] + h[2] -= carry[2] << 26 + carry[3] = h[3] >> 25 + h[4] += carry[3] + h[3] -= carry[3] << 25 + carry[4] = h[4] >> 26 + h[5] += carry[4] + h[4] -= carry[4] << 26 + carry[5] = h[5] >> 25 + h[6] += carry[5] + h[5] -= carry[5] << 25 + carry[6] = h[6] >> 26 + h[7] += carry[6] + h[6] -= carry[6] << 26 + carry[7] = h[7] >> 25 + h[8] += carry[7] + h[7] -= carry[7] << 25 + carry[8] = h[8] >> 26 + h[9] += carry[8] + h[8] -= carry[8] << 26 + carry[9] = h[9] >> 25 + h[9] -= carry[9] << 25 + // h10 = carry9 + + // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; + // evidently 2^255 h10-2^255 q = 0. + // Goal: Output h[0]+...+2^230 h[9]. + + s[0] = byte(h[0] >> 0) + s[1] = byte(h[0] >> 8) + s[2] = byte(h[0] >> 16) + s[3] = byte((h[0] >> 24) | (h[1] << 2)) + s[4] = byte(h[1] >> 6) + s[5] = byte(h[1] >> 14) + s[6] = byte((h[1] >> 22) | (h[2] << 3)) + s[7] = byte(h[2] >> 5) + s[8] = byte(h[2] >> 13) + s[9] = byte((h[2] >> 21) | (h[3] << 5)) + s[10] = byte(h[3] >> 3) + s[11] = byte(h[3] >> 11) + s[12] = byte((h[3] >> 19) | (h[4] << 6)) + s[13] = byte(h[4] >> 2) + s[14] = byte(h[4] >> 10) + s[15] = byte(h[4] >> 18) + s[16] = byte(h[5] >> 0) + s[17] = byte(h[5] >> 8) + s[18] = byte(h[5] >> 16) + s[19] = byte((h[5] >> 24) | (h[6] << 1)) + s[20] = byte(h[6] >> 7) + s[21] = byte(h[6] >> 15) + s[22] = byte((h[6] >> 23) | (h[7] << 3)) + s[23] = byte(h[7] >> 5) + s[24] = byte(h[7] >> 13) + s[25] = byte((h[7] >> 21) | (h[8] << 4)) + s[26] = byte(h[8] >> 4) + s[27] = byte(h[8] >> 12) + s[28] = byte((h[8] >> 20) | (h[9] << 6)) + s[29] = byte(h[9] >> 2) + s[30] = byte(h[9] >> 10) + s[31] = byte(h[9] >> 18) +} + +// feMul calculates h = f * g +// Can overlap h with f or g. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Notes on implementation strategy: +// +// Using schoolbook multiplication. +// Karatsuba would save a little in some cost models. +// +// Most multiplications by 2 and 19 are 32-bit precomputations; +// cheaper than 64-bit postcomputations. +// +// There is one remaining multiplication by 19 in the carry chain; +// one *19 precomputation can be merged into this, +// but the resulting data flow is considerably less clean. +// +// There are 12 carries below. +// 10 of them are 2-way parallelizable and vectorizable. +// Can get away with 11 carries, but then data flow is much deeper. +// +// With tighter constraints on inputs can squeeze carries into int32. +func feMul(h, f, g *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + g0 := g[0] + g1 := g[1] + g2 := g[2] + g3 := g[3] + g4 := g[4] + g5 := g[5] + g6 := g[6] + g7 := g[7] + g8 := g[8] + g9 := g[9] + g1_19 := 19 * g1 // 1.4*2^29 + g2_19 := 19 * g2 // 1.4*2^30; still ok + g3_19 := 19 * g3 + g4_19 := 19 * g4 + g5_19 := 19 * g5 + g6_19 := 19 * g6 + g7_19 := 19 * g7 + g8_19 := 19 * g8 + g9_19 := 19 * g9 + f1_2 := 2 * f1 + f3_2 := 2 * f3 + f5_2 := 2 * f5 + f7_2 := 2 * f7 + f9_2 := 2 * f9 + f0g0 := int64(f0) * int64(g0) + f0g1 := int64(f0) * int64(g1) + f0g2 := int64(f0) * int64(g2) + f0g3 := int64(f0) * int64(g3) + f0g4 := int64(f0) * int64(g4) + f0g5 := int64(f0) * int64(g5) + f0g6 := int64(f0) * int64(g6) + f0g7 := int64(f0) * int64(g7) + f0g8 := int64(f0) * int64(g8) + f0g9 := int64(f0) * int64(g9) + f1g0 := int64(f1) * int64(g0) + f1g1_2 := int64(f1_2) * int64(g1) + f1g2 := int64(f1) * int64(g2) + f1g3_2 := int64(f1_2) * int64(g3) + f1g4 := int64(f1) * int64(g4) + f1g5_2 := int64(f1_2) * int64(g5) + f1g6 := int64(f1) * int64(g6) + f1g7_2 := int64(f1_2) * int64(g7) + f1g8 := int64(f1) * int64(g8) + f1g9_38 := int64(f1_2) * int64(g9_19) + f2g0 := int64(f2) * int64(g0) + f2g1 := int64(f2) * int64(g1) + f2g2 := int64(f2) * int64(g2) + f2g3 := int64(f2) * int64(g3) + f2g4 := int64(f2) * int64(g4) + f2g5 := int64(f2) * int64(g5) + f2g6 := int64(f2) * int64(g6) + f2g7 := int64(f2) * int64(g7) + f2g8_19 := int64(f2) * int64(g8_19) + f2g9_19 := int64(f2) * int64(g9_19) + f3g0 := int64(f3) * int64(g0) + f3g1_2 := int64(f3_2) * int64(g1) + f3g2 := int64(f3) * int64(g2) + f3g3_2 := int64(f3_2) * int64(g3) + f3g4 := int64(f3) * int64(g4) + f3g5_2 := int64(f3_2) * int64(g5) + f3g6 := int64(f3) * int64(g6) + f3g7_38 := int64(f3_2) * int64(g7_19) + f3g8_19 := int64(f3) * int64(g8_19) + f3g9_38 := int64(f3_2) * int64(g9_19) + f4g0 := int64(f4) * int64(g0) + f4g1 := int64(f4) * int64(g1) + f4g2 := int64(f4) * int64(g2) + f4g3 := int64(f4) * int64(g3) + f4g4 := int64(f4) * int64(g4) + f4g5 := int64(f4) * int64(g5) + f4g6_19 := int64(f4) * int64(g6_19) + f4g7_19 := int64(f4) * int64(g7_19) + f4g8_19 := int64(f4) * int64(g8_19) + f4g9_19 := int64(f4) * int64(g9_19) + f5g0 := int64(f5) * int64(g0) + f5g1_2 := int64(f5_2) * int64(g1) + f5g2 := int64(f5) * int64(g2) + f5g3_2 := int64(f5_2) * int64(g3) + f5g4 := int64(f5) * int64(g4) + f5g5_38 := int64(f5_2) * int64(g5_19) + f5g6_19 := int64(f5) * int64(g6_19) + f5g7_38 := int64(f5_2) * int64(g7_19) + f5g8_19 := int64(f5) * int64(g8_19) + f5g9_38 := int64(f5_2) * int64(g9_19) + f6g0 := int64(f6) * int64(g0) + f6g1 := int64(f6) * int64(g1) + f6g2 := int64(f6) * int64(g2) + f6g3 := int64(f6) * int64(g3) + f6g4_19 := int64(f6) * int64(g4_19) + f6g5_19 := int64(f6) * int64(g5_19) + f6g6_19 := int64(f6) * int64(g6_19) + f6g7_19 := int64(f6) * int64(g7_19) + f6g8_19 := int64(f6) * int64(g8_19) + f6g9_19 := int64(f6) * int64(g9_19) + f7g0 := int64(f7) * int64(g0) + f7g1_2 := int64(f7_2) * int64(g1) + f7g2 := int64(f7) * int64(g2) + f7g3_38 := int64(f7_2) * int64(g3_19) + f7g4_19 := int64(f7) * int64(g4_19) + f7g5_38 := int64(f7_2) * int64(g5_19) + f7g6_19 := int64(f7) * int64(g6_19) + f7g7_38 := int64(f7_2) * int64(g7_19) + f7g8_19 := int64(f7) * int64(g8_19) + f7g9_38 := int64(f7_2) * int64(g9_19) + f8g0 := int64(f8) * int64(g0) + f8g1 := int64(f8) * int64(g1) + f8g2_19 := int64(f8) * int64(g2_19) + f8g3_19 := int64(f8) * int64(g3_19) + f8g4_19 := int64(f8) * int64(g4_19) + f8g5_19 := int64(f8) * int64(g5_19) + f8g6_19 := int64(f8) * int64(g6_19) + f8g7_19 := int64(f8) * int64(g7_19) + f8g8_19 := int64(f8) * int64(g8_19) + f8g9_19 := int64(f8) * int64(g9_19) + f9g0 := int64(f9) * int64(g0) + f9g1_38 := int64(f9_2) * int64(g1_19) + f9g2_19 := int64(f9) * int64(g2_19) + f9g3_38 := int64(f9_2) * int64(g3_19) + f9g4_19 := int64(f9) * int64(g4_19) + f9g5_38 := int64(f9_2) * int64(g5_19) + f9g6_19 := int64(f9) * int64(g6_19) + f9g7_38 := int64(f9_2) * int64(g7_19) + f9g8_19 := int64(f9) * int64(g8_19) + f9g9_38 := int64(f9_2) * int64(g9_19) + h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 + h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 + h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 + h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 + h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 + h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 + h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 + h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 + h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 + h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 + var carry [10]int64 + + // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) + // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 + // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) + // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + // |h0| <= 2^25 + // |h4| <= 2^25 + // |h1| <= 1.51*2^58 + // |h5| <= 1.51*2^58 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + // |h1| <= 2^24; from now on fits into int32 + // |h5| <= 2^24; from now on fits into int32 + // |h2| <= 1.21*2^59 + // |h6| <= 1.21*2^59 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + // |h2| <= 2^25; from now on fits into int32 unchanged + // |h6| <= 2^25; from now on fits into int32 unchanged + // |h3| <= 1.51*2^58 + // |h7| <= 1.51*2^58 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + // |h3| <= 2^24; from now on fits into int32 unchanged + // |h7| <= 2^24; from now on fits into int32 unchanged + // |h4| <= 1.52*2^33 + // |h8| <= 1.52*2^33 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + // |h4| <= 2^25; from now on fits into int32 unchanged + // |h8| <= 2^25; from now on fits into int32 unchanged + // |h5| <= 1.01*2^24 + // |h9| <= 1.51*2^58 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + // |h9| <= 2^24; from now on fits into int32 unchanged + // |h0| <= 1.8*2^37 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + // |h0| <= 2^25; from now on fits into int32 unchanged + // |h1| <= 1.01*2^24 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feSquare calculates h = f*f. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feSquare(h, f *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + f0_2 := 2 * f0 + f1_2 := 2 * f1 + f2_2 := 2 * f2 + f3_2 := 2 * f3 + f4_2 := 2 * f4 + f5_2 := 2 * f5 + f6_2 := 2 * f6 + f7_2 := 2 * f7 + f5_38 := 38 * f5 // 1.31*2^30 + f6_19 := 19 * f6 // 1.31*2^30 + f7_38 := 38 * f7 // 1.31*2^30 + f8_19 := 19 * f8 // 1.31*2^30 + f9_38 := 38 * f9 // 1.31*2^30 + f0f0 := int64(f0) * int64(f0) + f0f1_2 := int64(f0_2) * int64(f1) + f0f2_2 := int64(f0_2) * int64(f2) + f0f3_2 := int64(f0_2) * int64(f3) + f0f4_2 := int64(f0_2) * int64(f4) + f0f5_2 := int64(f0_2) * int64(f5) + f0f6_2 := int64(f0_2) * int64(f6) + f0f7_2 := int64(f0_2) * int64(f7) + f0f8_2 := int64(f0_2) * int64(f8) + f0f9_2 := int64(f0_2) * int64(f9) + f1f1_2 := int64(f1_2) * int64(f1) + f1f2_2 := int64(f1_2) * int64(f2) + f1f3_4 := int64(f1_2) * int64(f3_2) + f1f4_2 := int64(f1_2) * int64(f4) + f1f5_4 := int64(f1_2) * int64(f5_2) + f1f6_2 := int64(f1_2) * int64(f6) + f1f7_4 := int64(f1_2) * int64(f7_2) + f1f8_2 := int64(f1_2) * int64(f8) + f1f9_76 := int64(f1_2) * int64(f9_38) + f2f2 := int64(f2) * int64(f2) + f2f3_2 := int64(f2_2) * int64(f3) + f2f4_2 := int64(f2_2) * int64(f4) + f2f5_2 := int64(f2_2) * int64(f5) + f2f6_2 := int64(f2_2) * int64(f6) + f2f7_2 := int64(f2_2) * int64(f7) + f2f8_38 := int64(f2_2) * int64(f8_19) + f2f9_38 := int64(f2) * int64(f9_38) + f3f3_2 := int64(f3_2) * int64(f3) + f3f4_2 := int64(f3_2) * int64(f4) + f3f5_4 := int64(f3_2) * int64(f5_2) + f3f6_2 := int64(f3_2) * int64(f6) + f3f7_76 := int64(f3_2) * int64(f7_38) + f3f8_38 := int64(f3_2) * int64(f8_19) + f3f9_76 := int64(f3_2) * int64(f9_38) + f4f4 := int64(f4) * int64(f4) + f4f5_2 := int64(f4_2) * int64(f5) + f4f6_38 := int64(f4_2) * int64(f6_19) + f4f7_38 := int64(f4) * int64(f7_38) + f4f8_38 := int64(f4_2) * int64(f8_19) + f4f9_38 := int64(f4) * int64(f9_38) + f5f5_38 := int64(f5) * int64(f5_38) + f5f6_38 := int64(f5_2) * int64(f6_19) + f5f7_76 := int64(f5_2) * int64(f7_38) + f5f8_38 := int64(f5_2) * int64(f8_19) + f5f9_76 := int64(f5_2) * int64(f9_38) + f6f6_19 := int64(f6) * int64(f6_19) + f6f7_38 := int64(f6) * int64(f7_38) + f6f8_38 := int64(f6_2) * int64(f8_19) + f6f9_38 := int64(f6) * int64(f9_38) + f7f7_38 := int64(f7) * int64(f7_38) + f7f8_38 := int64(f7_2) * int64(f8_19) + f7f9_76 := int64(f7_2) * int64(f9_38) + f8f8_19 := int64(f8) * int64(f8_19) + f8f9_38 := int64(f8) * int64(f9_38) + f9f9_38 := int64(f9) * int64(f9_38) + h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 + h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 + h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 + h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 + h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 + h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 + h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 + h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 + h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 + h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 + var carry [10]int64 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feMul121666 calculates h = f * 121666. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feMul121666(h, f *fieldElement) { + h0 := int64(f[0]) * 121666 + h1 := int64(f[1]) * 121666 + h2 := int64(f[2]) * 121666 + h3 := int64(f[3]) * 121666 + h4 := int64(f[4]) * 121666 + h5 := int64(f[5]) * 121666 + h6 := int64(f[6]) * 121666 + h7 := int64(f[7]) * 121666 + h8 := int64(f[8]) * 121666 + h9 := int64(f[9]) * 121666 + var carry [10]int64 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feInvert sets out = z^-1. +func feInvert(out, z *fieldElement) { + var t0, t1, t2, t3 fieldElement + var i int + + feSquare(&t0, z) + for i = 1; i < 1; i++ { + feSquare(&t0, &t0) + } + feSquare(&t1, &t0) + for i = 1; i < 2; i++ { + feSquare(&t1, &t1) + } + feMul(&t1, z, &t1) + feMul(&t0, &t0, &t1) + feSquare(&t2, &t0) + for i = 1; i < 1; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t1, &t2) + feSquare(&t2, &t1) + for i = 1; i < 5; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 20; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 100; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t1, &t1) + for i = 1; i < 5; i++ { + feSquare(&t1, &t1) + } + feMul(out, &t1, &t0) +} + +func scalarMultGeneric(out, in, base *[32]byte) { + var e [32]byte + + copy(e[:], in[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement + feFromBytes(&x1, base) + feOne(&x2) + feCopy(&x3, &x1) + feOne(&z3) + + swap := int32(0) + for pos := 254; pos >= 0; pos-- { + b := e[pos/8] >> uint(pos&7) + b &= 1 + swap ^= int32(b) + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + swap = int32(b) + + feSub(&tmp0, &x3, &z3) + feSub(&tmp1, &x2, &z2) + feAdd(&x2, &x2, &z2) + feAdd(&z2, &x3, &z3) + feMul(&z3, &tmp0, &x2) + feMul(&z2, &z2, &tmp1) + feSquare(&tmp0, &tmp1) + feSquare(&tmp1, &x2) + feAdd(&x3, &z3, &z2) + feSub(&z2, &z3, &z2) + feMul(&x2, &tmp1, &tmp0) + feSub(&tmp1, &tmp1, &tmp0) + feSquare(&z2, &z2) + feMul121666(&z3, &tmp1) + feSquare(&x3, &x3) + feAdd(&tmp0, &tmp0, &z3) + feMul(&z3, &x1, &z2) + feMul(&z2, &tmp1, &tmp0) + } + + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + + feInvert(&z2, &z2) + feMul(&x2, &x2, &z2) + feToBytes(out, &x2) +} diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go new file mode 100644 index 0000000000..047d49afc2 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 gccgo appengine purego + +package curve25519 + +func scalarMult(out, in, base *[32]byte) { + scalarMultGeneric(out, in, base) +} diff --git a/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go deleted file mode 100644 index da9b10d9c1..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package curve25519 provides an implementation of scalar multiplication on -// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html -package curve25519 // import "golang.org/x/crypto/curve25519" - -// basePoint is the x coordinate of the generator of the curve. -var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -// ScalarMult sets dst to the product in*base where dst and base are the x -// coordinates of group points and all values are in little-endian form. -func ScalarMult(dst, in, base *[32]byte) { - scalarMult(dst, in, base) -} - -// ScalarBaseMult sets dst to the product in*base where dst and base are the x -// coordinates of group points, base is the standard generator and all values -// are in little-endian form. -func ScalarBaseMult(dst, in *[32]byte) { - ScalarMult(dst, in, &basePoint) -} diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s deleted file mode 100644 index 390816106e..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func freeze(inout *[5]uint64) -TEXT ·freeze(SB),7,$0-8 - MOVQ inout+0(FP), DI - - MOVQ 0(DI),SI - MOVQ 8(DI),DX - MOVQ 16(DI),CX - MOVQ 24(DI),R8 - MOVQ 32(DI),R9 - MOVQ $REDMASK51,AX - MOVQ AX,R10 - SUBQ $18,R10 - MOVQ $3,R11 -REDUCELOOP: - MOVQ SI,R12 - SHRQ $51,R12 - ANDQ AX,SI - ADDQ R12,DX - MOVQ DX,R12 - SHRQ $51,R12 - ANDQ AX,DX - ADDQ R12,CX - MOVQ CX,R12 - SHRQ $51,R12 - ANDQ AX,CX - ADDQ R12,R8 - MOVQ R8,R12 - SHRQ $51,R12 - ANDQ AX,R8 - ADDQ R12,R9 - MOVQ R9,R12 - SHRQ $51,R12 - ANDQ AX,R9 - IMUL3Q $19,R12,R12 - ADDQ R12,SI - SUBQ $1,R11 - JA REDUCELOOP - MOVQ $1,R12 - CMPQ R10,SI - CMOVQLT R11,R12 - CMPQ AX,DX - CMOVQNE R11,R12 - CMPQ AX,CX - CMOVQNE R11,R12 - CMPQ AX,R8 - CMOVQNE R11,R12 - CMPQ AX,R9 - CMOVQNE R11,R12 - NEGQ R12 - ANDQ R12,AX - ANDQ R12,R10 - SUBQ R10,SI - SUBQ AX,DX - SUBQ AX,CX - SUBQ AX,R8 - SUBQ AX,R9 - MOVQ SI,0(DI) - MOVQ DX,8(DI) - MOVQ CX,16(DI) - MOVQ R8,24(DI) - MOVQ R9,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s deleted file mode 100644 index 1f76d1a3f5..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func mul(dest, a, b *[5]uint64) -TEXT ·mul(SB),0,$16-24 - MOVQ dest+0(FP), DI - MOVQ a+8(FP), SI - MOVQ b+16(FP), DX - - MOVQ DX,CX - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,0(SP) - MULQ 16(CX) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 0(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 8(CX) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SI),AX - MULQ 16(CX) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SI),AX - MULQ 24(CX) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 0(SI),AX - MULQ 32(CX) - MOVQ AX,BX - MOVQ DX,BP - MOVQ 8(SI),AX - MULQ 0(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SI),AX - MULQ 8(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SI),AX - MULQ 16(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SI),AX - MULQ 24(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),AX - MULQ 0(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 16(SI),AX - MULQ 8(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SI),AX - MULQ 16(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 24(SI),AX - MULQ 0(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 24(SI),AX - MULQ 8(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 0(SP),AX - MULQ 24(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 0(SP),AX - MULQ 32(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 32(SI),AX - MULQ 0(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SP),AX - MULQ 16(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 24(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - MULQ 32(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ $REDMASK51,SI - SHLQ $13,R8,R9 - ANDQ SI,R8 - SHLQ $13,R10,R11 - ANDQ SI,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ SI,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ SI,R14 - ADDQ R13,R14 - SHLQ $13,BX,BP - ANDQ SI,BX - ADDQ R15,BX - IMUL3Q $19,BP,DX - ADDQ DX,R8 - MOVQ R8,DX - SHRQ $51,DX - ADDQ R10,DX - MOVQ DX,CX - SHRQ $51,DX - ANDQ SI,R8 - ADDQ R12,DX - MOVQ DX,R9 - SHRQ $51,DX - ANDQ SI,CX - ADDQ R14,DX - MOVQ DX,AX - SHRQ $51,DX - ANDQ SI,R9 - ADDQ BX,DX - MOVQ DX,R10 - SHRQ $51,DX - ANDQ SI,AX - IMUL3Q $19,DX,DX - ADDQ DX,R8 - ANDQ SI,R10 - MOVQ R8,0(DI) - MOVQ CX,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s deleted file mode 100644 index 07511a45af..0000000000 --- a/vendor/golang.org/x/crypto/curve25519/square_amd64.s +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func square(out, in *[5]uint64) -TEXT ·square(SB),7,$0-16 - MOVQ out+0(FP), DI - MOVQ in+8(FP), SI - - MOVQ 0(SI),AX - MULQ 0(SI) - MOVQ AX,CX - MOVQ DX,R8 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 8(SI) - MOVQ AX,R9 - MOVQ DX,R10 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 16(SI) - MOVQ AX,R11 - MOVQ DX,R12 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 24(SI) - MOVQ AX,R13 - MOVQ DX,R14 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 32(SI) - MOVQ AX,R15 - MOVQ DX,BX - MOVQ 8(SI),AX - MULQ 8(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 16(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 24(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 8(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),AX - MULQ 16(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 24(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ $REDMASK51,SI - SHLQ $13,CX,R8 - ANDQ SI,CX - SHLQ $13,R9,R10 - ANDQ SI,R9 - ADDQ R8,R9 - SHLQ $13,R11,R12 - ANDQ SI,R11 - ADDQ R10,R11 - SHLQ $13,R13,R14 - ANDQ SI,R13 - ADDQ R12,R13 - SHLQ $13,R15,BX - ANDQ SI,R15 - ADDQ R14,R15 - IMUL3Q $19,BX,DX - ADDQ DX,CX - MOVQ CX,DX - SHRQ $51,DX - ADDQ R9,DX - ANDQ SI,CX - MOVQ DX,R8 - SHRQ $51,DX - ADDQ R11,DX - ANDQ SI,R8 - MOVQ DX,R9 - SHRQ $51,DX - ADDQ R13,DX - ANDQ SI,R9 - MOVQ DX,AX - SHRQ $51,DX - ADDQ R15,DX - ANDQ SI,AX - MOVQ DX,R10 - SHRQ $51,DX - IMUL3Q $19,DX,DX - ADDQ DX,CX - ANDQ SI,R10 - MOVQ CX,0(DI) - MOVQ R8,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go index 02b372cf37..6d7639722c 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go @@ -5,6 +5,7 @@ package packet import ( + "crypto" "crypto/rsa" "encoding/binary" "io" @@ -78,8 +79,9 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { // padding oracle attacks. switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - k := priv.PrivateKey.(*rsa.PrivateKey) - b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes)) + // Supports both *rsa.PrivateKey and crypto.Decrypter + k := priv.PrivateKey.(crypto.Decrypter) + b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) case PubKeyAlgoElGamal: c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go index 6f8ec09384..81abb7cef9 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go @@ -31,7 +31,7 @@ type PrivateKey struct { encryptedData []byte cipher CipherFunction s2k func(out, in []byte) - PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). sha1Checksum bool iv []byte } diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go index c4ff3f6e66..f455147d21 100644 --- a/vendor/golang.org/x/crypto/sha3/hashes_generic.go +++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build gccgo appengine !s390x +// +build gccgo appengine !s390x package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go index b12a35c87f..ba269a0730 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3.go +++ b/vendor/golang.org/x/crypto/sha3/sha3.go @@ -38,8 +38,9 @@ type state struct { // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and // Extendable-Output Functions (May 2014)" - dsbyte byte - storage [maxRate]byte + dsbyte byte + + storage storageBuf // Specific to SHA-3 and SHAKE. outputLen int // the default output size in bytes @@ -60,15 +61,15 @@ func (d *state) Reset() { d.a[i] = 0 } d.state = spongeAbsorbing - d.buf = d.storage[:0] + d.buf = d.storage.asBytes()[:0] } func (d *state) clone() *state { ret := *d if ret.state == spongeAbsorbing { - ret.buf = ret.storage[:len(ret.buf)] + ret.buf = ret.storage.asBytes()[:len(ret.buf)] } else { - ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] + ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate] } return &ret @@ -82,13 +83,13 @@ func (d *state) permute() { // If we're absorbing, we need to xor the input into the state // before applying the permutation. xorIn(d, d.buf) - d.buf = d.storage[:0] + d.buf = d.storage.asBytes()[:0] keccakF1600(&d.a) case spongeSqueezing: // If we're squeezing, we need to apply the permutatin before // copying more output. keccakF1600(&d.a) - d.buf = d.storage[:d.rate] + d.buf = d.storage.asBytes()[:d.rate] copyOut(d, d.buf) } } @@ -97,7 +98,7 @@ func (d *state) permute() { // the multi-bitrate 10..1 padding rule, and permutes the state. func (d *state) padAndPermute(dsbyte byte) { if d.buf == nil { - d.buf = d.storage[:0] + d.buf = d.storage.asBytes()[:0] } // Pad with this instance's domain-separator bits. We know that there's // at least one byte of space in d.buf because, if it were full, @@ -105,7 +106,7 @@ func (d *state) padAndPermute(dsbyte byte) { // first one bit for the padding. See the comment in the state struct. d.buf = append(d.buf, dsbyte) zerosStart := len(d.buf) - d.buf = d.storage[:d.rate] + d.buf = d.storage.asBytes()[:d.rate] for i := zerosStart; i < d.rate; i++ { d.buf[i] = 0 } @@ -116,7 +117,7 @@ func (d *state) padAndPermute(dsbyte byte) { // Apply the permutation d.permute() d.state = spongeSqueezing - d.buf = d.storage[:d.rate] + d.buf = d.storage.asBytes()[:d.rate] copyOut(d, d.buf) } @@ -127,7 +128,7 @@ func (d *state) Write(p []byte) (written int, err error) { panic("sha3: write to sponge after read") } if d.buf == nil { - d.buf = d.storage[:0] + d.buf = d.storage.asBytes()[:0] } written = len(p) diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go index b6cbc5c41b..c13ec85b50 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build !gccgo,!appengine +// +build !gccgo,!appengine package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s index b2ef69f8cc..8a4458f63f 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build !gccgo,!appengine +// +build !gccgo,!appengine #include "textflag.h" diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go index 73d0c90bf5..add4e73396 100644 --- a/vendor/golang.org/x/crypto/sha3/shake_generic.go +++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build gccgo appengine !s390x +// +build gccgo appengine !s390x package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go index 46a0d63a6d..079b650141 100644 --- a/vendor/golang.org/x/crypto/sha3/xor.go +++ b/vendor/golang.org/x/crypto/sha3/xor.go @@ -6,6 +6,13 @@ package sha3 +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate]byte + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(b) +} + var ( xorIn = xorInGeneric copyOut = copyOutGeneric diff --git a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go index 929a486a79..a3d068634c 100644 --- a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go +++ b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go @@ -9,9 +9,16 @@ package sha3 import "unsafe" +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate / 8]uint64 + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(unsafe.Pointer(b)) +} + func xorInUnaligned(d *state, buf []byte) { - bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) n := len(buf) + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] if n >= 72 { d.a[0] ^= bw[0] d.a[1] ^= bw[1] diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go deleted file mode 100644 index 5d052781bc..0000000000 --- a/vendor/golang.org/x/net/html/atom/gen.go +++ /dev/null @@ -1,712 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -//go:generate go run gen.go -//go:generate go run gen.go -test - -package main - -import ( - "bytes" - "flag" - "fmt" - "go/format" - "io/ioutil" - "math/rand" - "os" - "sort" - "strings" -) - -// identifier converts s to a Go exported identifier. -// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". -func identifier(s string) string { - b := make([]byte, 0, len(s)) - cap := true - for _, c := range s { - if c == '-' { - cap = true - continue - } - if cap && 'a' <= c && c <= 'z' { - c -= 'a' - 'A' - } - cap = false - b = append(b, byte(c)) - } - return string(b) -} - -var test = flag.Bool("test", false, "generate table_test.go") - -func genFile(name string, buf *bytes.Buffer) { - b, err := format.Source(buf.Bytes()) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - if err := ioutil.WriteFile(name, b, 0644); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func main() { - flag.Parse() - - var all []string - all = append(all, elements...) - all = append(all, attributes...) - all = append(all, eventHandlers...) - all = append(all, extra...) - sort.Strings(all) - - // uniq - lists have dups - w := 0 - for _, s := range all { - if w == 0 || all[w-1] != s { - all[w] = s - w++ - } - } - all = all[:w] - - if *test { - var buf bytes.Buffer - fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") - fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") - fmt.Fprintln(&buf, "package atom\n") - fmt.Fprintln(&buf, "var testAtomList = []string{") - for _, s := range all { - fmt.Fprintf(&buf, "\t%q,\n", s) - } - fmt.Fprintln(&buf, "}") - - genFile("table_test.go", &buf) - return - } - - // Find hash that minimizes table size. - var best *table - for i := 0; i < 1000000; i++ { - if best != nil && 1<<(best.k-1) < len(all) { - break - } - h := rand.Uint32() - for k := uint(0); k <= 16; k++ { - if best != nil && k >= best.k { - break - } - var t table - if t.init(h, k, all) { - best = &t - break - } - } - } - if best == nil { - fmt.Fprintf(os.Stderr, "failed to construct string table\n") - os.Exit(1) - } - - // Lay out strings, using overlaps when possible. - layout := append([]string{}, all...) - - // Remove strings that are substrings of other strings - for changed := true; changed; { - changed = false - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i != j && t != "" && strings.Contains(s, t) { - changed = true - layout[j] = "" - } - } - } - } - - // Join strings where one suffix matches another prefix. - for { - // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], - // maximizing overlap length k. - besti := -1 - bestj := -1 - bestk := 0 - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i == j { - continue - } - for k := bestk + 1; k <= len(s) && k <= len(t); k++ { - if s[len(s)-k:] == t[:k] { - besti = i - bestj = j - bestk = k - } - } - } - } - if bestk > 0 { - layout[besti] += layout[bestj][bestk:] - layout[bestj] = "" - continue - } - break - } - - text := strings.Join(layout, "") - - atom := map[string]uint32{} - for _, s := range all { - off := strings.Index(text, s) - if off < 0 { - panic("lost string " + s) - } - atom[s] = uint32(off<<8 | len(s)) - } - - var buf bytes.Buffer - // Generate the Go code. - fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") - fmt.Fprintln(&buf, "//go:generate go run gen.go\n") - fmt.Fprintln(&buf, "package atom\n\nconst (") - - // compute max len - maxLen := 0 - for _, s := range all { - if maxLen < len(s) { - maxLen = len(s) - } - fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) - } - fmt.Fprintln(&buf, ")\n") - - fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) - fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) - - fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) - for i, s := range best.tab { - if s == "" { - continue - } - fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) - } - fmt.Fprintf(&buf, "}\n") - datasize := (1 << best.k) * 4 - - fmt.Fprintln(&buf, "const atomText =") - textsize := len(text) - for len(text) > 60 { - fmt.Fprintf(&buf, "\t%q +\n", text[:60]) - text = text[60:] - } - fmt.Fprintf(&buf, "\t%q\n\n", text) - - genFile("table.go", &buf) - - fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) -} - -type byLen []string - -func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } -func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byLen) Len() int { return len(x) } - -// fnv computes the FNV hash with an arbitrary starting value h. -func fnv(h uint32, s string) uint32 { - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - return h -} - -// A table represents an attempt at constructing the lookup table. -// The lookup table uses cuckoo hashing, meaning that each string -// can be found in one of two positions. -type table struct { - h0 uint32 - k uint - mask uint32 - tab []string -} - -// hash returns the two hashes for s. -func (t *table) hash(s string) (h1, h2 uint32) { - h := fnv(t.h0, s) - h1 = h & t.mask - h2 = (h >> 16) & t.mask - return -} - -// init initializes the table with the given parameters. -// h0 is the initial hash value, -// k is the number of bits of hash value to use, and -// x is the list of strings to store in the table. -// init returns false if the table cannot be constructed. -func (t *table) init(h0 uint32, k uint, x []string) bool { - t.h0 = h0 - t.k = k - t.tab = make([]string, 1< len(t.tab) { - return false - } - s := t.tab[i] - h1, h2 := t.hash(s) - j := h1 + h2 - i - if t.tab[j] != "" && !t.push(j, depth+1) { - return false - } - t.tab[j] = s - return true -} - -// The lists of element names and attribute keys were taken from -// https://html.spec.whatwg.org/multipage/indices.html#index -// as of the "HTML Living Standard - Last Updated 16 April 2018" version. - -// "command", "keygen" and "menuitem" have been removed from the spec, -// but are kept here for backwards compatibility. -var elements = []string{ - "a", - "abbr", - "address", - "area", - "article", - "aside", - "audio", - "b", - "base", - "bdi", - "bdo", - "blockquote", - "body", - "br", - "button", - "canvas", - "caption", - "cite", - "code", - "col", - "colgroup", - "command", - "data", - "datalist", - "dd", - "del", - "details", - "dfn", - "dialog", - "div", - "dl", - "dt", - "em", - "embed", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "hgroup", - "hr", - "html", - "i", - "iframe", - "img", - "input", - "ins", - "kbd", - "keygen", - "label", - "legend", - "li", - "link", - "main", - "map", - "mark", - "menu", - "menuitem", - "meta", - "meter", - "nav", - "noscript", - "object", - "ol", - "optgroup", - "option", - "output", - "p", - "param", - "picture", - "pre", - "progress", - "q", - "rp", - "rt", - "ruby", - "s", - "samp", - "script", - "section", - "select", - "slot", - "small", - "source", - "span", - "strong", - "style", - "sub", - "summary", - "sup", - "table", - "tbody", - "td", - "template", - "textarea", - "tfoot", - "th", - "thead", - "time", - "title", - "tr", - "track", - "u", - "ul", - "var", - "video", - "wbr", -} - -// https://html.spec.whatwg.org/multipage/indices.html#attributes-3 -// -// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", -// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, -// but are kept here for backwards compatibility. -var attributes = []string{ - "abbr", - "accept", - "accept-charset", - "accesskey", - "action", - "allowfullscreen", - "allowpaymentrequest", - "allowusermedia", - "alt", - "as", - "async", - "autocomplete", - "autofocus", - "autoplay", - "challenge", - "charset", - "checked", - "cite", - "class", - "color", - "cols", - "colspan", - "command", - "content", - "contenteditable", - "contextmenu", - "controls", - "coords", - "crossorigin", - "data", - "datetime", - "default", - "defer", - "dir", - "dirname", - "disabled", - "download", - "draggable", - "dropzone", - "enctype", - "for", - "form", - "formaction", - "formenctype", - "formmethod", - "formnovalidate", - "formtarget", - "headers", - "height", - "hidden", - "high", - "href", - "hreflang", - "http-equiv", - "icon", - "id", - "inputmode", - "integrity", - "is", - "ismap", - "itemid", - "itemprop", - "itemref", - "itemscope", - "itemtype", - "keytype", - "kind", - "label", - "lang", - "list", - "loop", - "low", - "manifest", - "max", - "maxlength", - "media", - "mediagroup", - "method", - "min", - "minlength", - "multiple", - "muted", - "name", - "nomodule", - "nonce", - "novalidate", - "open", - "optimum", - "pattern", - "ping", - "placeholder", - "playsinline", - "poster", - "preload", - "radiogroup", - "readonly", - "referrerpolicy", - "rel", - "required", - "reversed", - "rows", - "rowspan", - "sandbox", - "spellcheck", - "scope", - "scoped", - "seamless", - "selected", - "shape", - "size", - "sizes", - "sortable", - "sorted", - "slot", - "span", - "spellcheck", - "src", - "srcdoc", - "srclang", - "srcset", - "start", - "step", - "style", - "tabindex", - "target", - "title", - "translate", - "type", - "typemustmatch", - "updateviacache", - "usemap", - "value", - "width", - "workertype", - "wrap", -} - -// "onautocomplete", "onautocompleteerror", "onmousewheel", -// "onshow" and "onsort" have been removed from the spec, -// but are kept here for backwards compatibility. -var eventHandlers = []string{ - "onabort", - "onautocomplete", - "onautocompleteerror", - "onauxclick", - "onafterprint", - "onbeforeprint", - "onbeforeunload", - "onblur", - "oncancel", - "oncanplay", - "oncanplaythrough", - "onchange", - "onclick", - "onclose", - "oncontextmenu", - "oncopy", - "oncuechange", - "oncut", - "ondblclick", - "ondrag", - "ondragend", - "ondragenter", - "ondragexit", - "ondragleave", - "ondragover", - "ondragstart", - "ondrop", - "ondurationchange", - "onemptied", - "onended", - "onerror", - "onfocus", - "onhashchange", - "oninput", - "oninvalid", - "onkeydown", - "onkeypress", - "onkeyup", - "onlanguagechange", - "onload", - "onloadeddata", - "onloadedmetadata", - "onloadend", - "onloadstart", - "onmessage", - "onmessageerror", - "onmousedown", - "onmouseenter", - "onmouseleave", - "onmousemove", - "onmouseout", - "onmouseover", - "onmouseup", - "onmousewheel", - "onwheel", - "onoffline", - "ononline", - "onpagehide", - "onpageshow", - "onpaste", - "onpause", - "onplay", - "onplaying", - "onpopstate", - "onprogress", - "onratechange", - "onreset", - "onresize", - "onrejectionhandled", - "onscroll", - "onsecuritypolicyviolation", - "onseeked", - "onseeking", - "onselect", - "onshow", - "onsort", - "onstalled", - "onstorage", - "onsubmit", - "onsuspend", - "ontimeupdate", - "ontoggle", - "onunhandledrejection", - "onunload", - "onvolumechange", - "onwaiting", -} - -// extra are ad-hoc values not covered by any of the lists above. -var extra = []string{ - "acronym", - "align", - "annotation", - "annotation-xml", - "applet", - "basefont", - "bgsound", - "big", - "blink", - "center", - "color", - "desc", - "face", - "font", - "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. - "foreignobject", - "frame", - "frameset", - "image", - "isindex", - "listing", - "malignmark", - "marquee", - "math", - "mglyph", - "mi", - "mn", - "mo", - "ms", - "mtext", - "nobr", - "noembed", - "noframes", - "plaintext", - "prompt", - "public", - "rb", - "rtc", - "spacer", - "strike", - "svg", - "system", - "tt", - "xmp", -} diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go index 1565cf2702..97f17831fc 100644 --- a/vendor/golang.org/x/net/http2/hpack/encode.go +++ b/vendor/golang.org/x/net/http2/hpack/encode.go @@ -150,7 +150,7 @@ func appendIndexed(dst []byte, i uint64) []byte { // extended buffer. // // If f.Sensitive is true, "Never Indexed" representation is used. If -// f.Sensitive is false and indexing is true, "Inremental Indexing" +// f.Sensitive is false and indexing is true, "Incremental Indexing" // representation is used. func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 57334dc79b..b7524ba268 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -52,10 +52,11 @@ import ( ) const ( - prefaceTimeout = 10 * time.Second - firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway - handlerChunkWriteSize = 4 << 10 - defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + prefaceTimeout = 10 * time.Second + firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway + handlerChunkWriteSize = 4 << 10 + defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + maxQueuedControlFrames = 10000 ) var ( @@ -163,6 +164,15 @@ func (s *Server) maxConcurrentStreams() uint32 { return defaultMaxStreams } +// maxQueuedControlFrames is the maximum number of control frames like +// SETTINGS, PING and RST_STREAM that will be queued for writing before +// the connection is closed to prevent memory exhaustion attacks. +func (s *Server) maxQueuedControlFrames() int { + // TODO: if anybody asks, add a Server field, and remember to define the + // behavior of negative values. + return maxQueuedControlFrames +} + type serverInternalState struct { mu sync.Mutex activeConns map[*serverConn]struct{} @@ -312,7 +322,7 @@ type ServeConnOpts struct { } func (o *ServeConnOpts) context() context.Context { - if o.Context != nil { + if o != nil && o.Context != nil { return o.Context } return context.Background() @@ -506,6 +516,7 @@ type serverConn struct { sawFirstSettings bool // got the initial SETTINGS frame after the preface needToSendSettingsAck bool unackedSettings int // how many SETTINGS have we sent without ACKs? + queuedControlFrames int // control frames in the writeSched queue clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client @@ -894,6 +905,14 @@ func (sc *serverConn) serve() { } } + // If the peer is causing us to generate a lot of control frames, + // but not reading them from us, assume they are trying to make us + // run out of memory. + if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() { + sc.vlogf("http2: too many control frames in send queue, closing connection") + return + } + // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY // with no error code (graceful shutdown), don't start the timer until // all open streams have been completed. @@ -1093,6 +1112,14 @@ func (sc *serverConn) writeFrame(wr FrameWriteRequest) { } if !ignoreWrite { + if wr.isControl() { + sc.queuedControlFrames++ + // For extra safety, detect wraparounds, which should not happen, + // and pull the plug. + if sc.queuedControlFrames < 0 { + sc.conn.Close() + } + } sc.writeSched.Push(wr) } sc.scheduleFrameWrite() @@ -1210,10 +1237,8 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) { // If a frame is already being written, nothing happens. This will be called again // when the frame is done being written. // -// If a frame isn't being written we need to send one, the best frame -// to send is selected, preferring first things that aren't -// stream-specific (e.g. ACKing settings), and then finding the -// highest priority stream. +// If a frame isn't being written and we need to send one, the best frame +// to send is selected by writeSched. // // If a frame isn't being written and there's nothing else to send, we // flush the write buffer. @@ -1241,6 +1266,9 @@ func (sc *serverConn) scheduleFrameWrite() { } if !sc.inGoAway || sc.goAwayCode == ErrCodeNo { if wr, ok := sc.writeSched.Pop(); ok { + if wr.isControl() { + sc.queuedControlFrames-- + } sc.startFrameWrite(wr) continue } @@ -1533,6 +1561,8 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error { if err := f.ForeachSetting(sc.processSetting); err != nil { return err } + // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be + // acknowledged individually, even if multiple are received before the ACK. sc.needToSendSettingsAck = true sc.scheduleFrameWrite() return nil @@ -2494,7 +2524,7 @@ const TrailerPrefix = "Trailer:" // trailers. That worked for a while, until we found the first major // user of Trailers in the wild: gRPC (using them only over http2), // and gRPC libraries permit setting trailers mid-stream without -// predeclarnig them. So: change of plans. We still permit the old +// predeclaring them. So: change of plans. We still permit the old // way, but we also permit this hack: if a Header() key begins with // "Trailer:", the suffix of that key is a Trailer. Because ':' is an // invalid token byte anyway, there is no ambiguity. (And it's already @@ -2794,7 +2824,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) { // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that // is in either the "open" or "half-closed (remote)" state. if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { - // responseWriter.Push checks that the stream is peer-initiaed. + // responseWriter.Push checks that the stream is peer-initiated. msg.done <- errStreamClosed return } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index aeac7d8a51..c51a73c069 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -1216,6 +1216,8 @@ var ( // abort request body write, but send stream reset of cancel. errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") + + errReqBodyTooLong = errors.New("http2: request body larger than specified content length") ) func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { @@ -1238,10 +1240,32 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) ( req := cs.req hasTrailers := req.Trailer != nil + remainLen := actualContentLength(req) + hasContentLen := remainLen != -1 var sawEOF bool for !sawEOF { - n, err := body.Read(buf) + n, err := body.Read(buf[:len(buf)-1]) + if hasContentLen { + remainLen -= int64(n) + if remainLen == 0 && err == nil { + // The request body's Content-Length was predeclared and + // we just finished reading it all, but the underlying io.Reader + // returned the final chunk with a nil error (which is one of + // the two valid things a Reader can do at EOF). Because we'd prefer + // to send the END_STREAM bit early, double-check that we're actually + // at EOF. Subsequent reads should return (0, EOF) at this point. + // If either value is different, we return an error in one of two ways below. + var n1 int + n1, err = body.Read(buf[n:]) + remainLen -= int64(n1) + } + if remainLen < 0 { + err = errReqBodyTooLong + cc.writeStreamReset(cs.ID, ErrCodeCancel, err) + return err + } + } if err == io.EOF { sawEOF = true err = nil diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go index 4fe3073073..f24d2b1e7d 100644 --- a/vendor/golang.org/x/net/http2/writesched.go +++ b/vendor/golang.org/x/net/http2/writesched.go @@ -32,7 +32,7 @@ type WriteScheduler interface { // Pop dequeues the next frame to write. Returns false if no frames can // be written. Frames with a given wr.StreamID() are Pop'd in the same - // order they are Push'd. + // order they are Push'd. No frames should be discarded except by CloseStream. Pop() (wr FrameWriteRequest, ok bool) } @@ -76,6 +76,12 @@ func (wr FrameWriteRequest) StreamID() uint32 { return wr.stream.id } +// isControl reports whether wr is a control frame for MaxQueuedControlFrames +// purposes. That includes non-stream frames and RST_STREAM frames. +func (wr FrameWriteRequest) isControl() bool { + return wr.stream == nil +} + // DataSize returns the number of flow control bytes that must be consumed // to write this entire frame. This is 0 for non-DATA frames. func (wr FrameWriteRequest) DataSize() int { diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go index 848fed6ec7..2618b2c11d 100644 --- a/vendor/golang.org/x/net/http2/writesched_priority.go +++ b/vendor/golang.org/x/net/http2/writesched_priority.go @@ -149,7 +149,7 @@ func (n *priorityNode) addBytes(b int64) { } // walkReadyInOrder iterates over the tree in priority order, calling f for each node -// with a non-empty write queue. When f returns true, this funcion returns true and the +// with a non-empty write queue. When f returns true, this function returns true and the // walk halts. tmp is used as scratch space for sorting. // // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go index 6929a9fd5c..97db2340ec 100644 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ b/vendor/golang.org/x/net/internal/socks/socks.go @@ -127,7 +127,7 @@ type Dialer struct { // establishing the transport connection. ProxyDial func(context.Context, string, string) (net.Conn, error) - // AuthMethods specifies the list of request authention + // AuthMethods specifies the list of request authentication // methods. // If empty, SOCKS client requests only AuthMethodNotRequired. AuthMethods []AuthMethod diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go new file mode 100644 index 0000000000..200617ea86 --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/list.go @@ -0,0 +1,181 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// Package publicsuffix provides a public suffix list based on data from +// https://publicsuffix.org/ +// +// A public suffix is one under which Internet users can directly register +// names. It is related to, but different from, a TLD (top level domain). +// +// "com" is a TLD (top level domain). Top level means it has no dots. +// +// "com" is also a public suffix. Amazon and Google have registered different +// siblings under that domain: "amazon.com" and "google.com". +// +// "au" is another TLD, again because it has no dots. But it's not "amazon.au". +// Instead, it's "amazon.com.au". +// +// "com.au" isn't an actual TLD, because it's not at the top level (it has +// dots). But it is an eTLD (effective TLD), because that's the branching point +// for domain name registrars. +// +// Another name for "an eTLD" is "a public suffix". Often, what's more of +// interest is the eTLD+1, or one more label than the public suffix. For +// example, browsers partition read/write access to HTTP cookies according to +// the eTLD+1. Web pages served from "amazon.com.au" can't read cookies from +// "google.com.au", but web pages served from "maps.google.com" can share +// cookies from "www.google.com", so you don't have to sign into Google Maps +// separately from signing into Google Web Search. Note that all four of those +// domains have 3 labels and 2 dots. The first two domains are each an eTLD+1, +// the last two are not (but share the same eTLD+1: "google.com"). +// +// All of these domains have the same eTLD+1: +// - "www.books.amazon.co.uk" +// - "books.amazon.co.uk" +// - "amazon.co.uk" +// Specifically, the eTLD+1 is "amazon.co.uk", because the eTLD is "co.uk". +// +// There is no closed form algorithm to calculate the eTLD of a domain. +// Instead, the calculation is data driven. This package provides a +// pre-compiled snapshot of Mozilla's PSL (Public Suffix List) data at +// https://publicsuffix.org/ +package publicsuffix // import "golang.org/x/net/publicsuffix" + +// TODO: specify case sensitivity and leading/trailing dot behavior for +// func PublicSuffix and func EffectiveTLDPlusOne. + +import ( + "fmt" + "net/http/cookiejar" + "strings" +) + +// List implements the cookiejar.PublicSuffixList interface by calling the +// PublicSuffix function. +var List cookiejar.PublicSuffixList = list{} + +type list struct{} + +func (list) PublicSuffix(domain string) string { + ps, _ := PublicSuffix(domain) + return ps +} + +func (list) String() string { + return version +} + +// PublicSuffix returns the public suffix of the domain using a copy of the +// publicsuffix.org database compiled into the library. +// +// icann is whether the public suffix is managed by the Internet Corporation +// for Assigned Names and Numbers. If not, the public suffix is either a +// privately managed domain (and in practice, not a top level domain) or an +// unmanaged top level domain (and not explicitly mentioned in the +// publicsuffix.org list). For example, "foo.org" and "foo.co.uk" are ICANN +// domains, "foo.dyndns.org" and "foo.blogspot.co.uk" are private domains and +// "cromulent" is an unmanaged top level domain. +// +// Use cases for distinguishing ICANN domains like "foo.com" from private +// domains like "foo.appspot.com" can be found at +// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases +func PublicSuffix(domain string) (publicSuffix string, icann bool) { + lo, hi := uint32(0), uint32(numTLD) + s, suffix, icannNode, wildcard := domain, len(domain), false, false +loop: + for { + dot := strings.LastIndex(s, ".") + if wildcard { + icann = icannNode + suffix = 1 + dot + } + if lo == hi { + break + } + f := find(s[1+dot:], lo, hi) + if f == notFound { + break + } + + u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) + icannNode = u&(1<>= nodesBitsICANN + u = children[u&(1<>= childrenBitsLo + hi = u & (1<>= childrenBitsHi + switch u & (1<>= childrenBitsNodeType + wildcard = u&(1<>= nodesBitsTextLength + offset := x & (1<>1&(m0&m) + x&(m0&m) - // x = x>>2&(m1&m) + x&(m1&m) - // x = x>>4&(m2&m) + x&(m2&m) - // x = x>>8&(m3&m) + x&(m3&m) - // x = x>>16&(m4&m) + x&(m4&m) - // x = x>>32&(m5&m) + x&(m5&m) - // return int(x) - // - // Masking (& operations) can be left away when there's no - // danger that a field's sum will carry over into the next - // field: Since the result cannot be > 64, 8 bits is enough - // and we can ignore the masks for the shifts by 8 and up. - // Per "Hacker's Delight", the first line can be simplified - // more, but it saves at best one instruction, so we leave - // it alone for clarity. - const m = 1<<64 - 1 - x = x>>1&(m0&m) + x&(m0&m) - x = x>>2&(m1&m) + x&(m1&m) - x = (x>>4 + x) & (m2 & m) - x += x >> 8 - x += x >> 16 - x += x >> 32 - return int(x) & (1<<7 - 1) -} diff --git a/vendor/golang.org/x/sys/unix/bluetooth_linux.go b/vendor/golang.org/x/sys/unix/bluetooth_linux.go index 6e32296970..a178a6149b 100644 --- a/vendor/golang.org/x/sys/unix/bluetooth_linux.go +++ b/vendor/golang.org/x/sys/unix/bluetooth_linux.go @@ -23,6 +23,7 @@ const ( HCI_CHANNEL_USER = 1 HCI_CHANNEL_MONITOR = 2 HCI_CHANNEL_CONTROL = 3 + HCI_CHANNEL_LOGGING = 4 ) // Socketoption Level diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go new file mode 100644 index 0000000000..b27be0a014 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/fdset.go @@ -0,0 +1,29 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package unix + +// Set adds fd to the set fds. +func (fds *FdSet) Set(fd int) { + fds.Bits[fd/NFDBITS] |= (1 << (uintptr(fd) % NFDBITS)) +} + +// Clear removes fd from the set fds. +func (fds *FdSet) Clear(fd int) { + fds.Bits[fd/NFDBITS] &^= (1 << (uintptr(fd) % NFDBITS)) +} + +// IsSet returns whether fd is in the set fds. +func (fds *FdSet) IsSet(fd int) bool { + return fds.Bits[fd/NFDBITS]&(1<<(uintptr(fd)%NFDBITS)) != 0 +} + +// Zero clears the set fds. +func (fds *FdSet) Zero() { + for i := range fds.Bits { + fds.Bits[i] = 0 + } +} diff --git a/vendor/golang.org/x/sys/unix/ioctl.go b/vendor/golang.org/x/sys/unix/ioctl.go index f121a8d64b..3559e5dcb2 100644 --- a/vendor/golang.org/x/sys/unix/ioctl.go +++ b/vendor/golang.org/x/sys/unix/ioctl.go @@ -6,7 +6,19 @@ package unix -import "runtime" +import ( + "runtime" + "unsafe" +) + +// ioctl itself should not be exposed directly, but additional get/set +// functions for specific types are permissible. + +// IoctlSetInt performs an ioctl operation which sets an integer value +// on fd, using the specified request number. +func IoctlSetInt(fd int, req uint, value int) error { + return ioctl(fd, req, uintptr(value)) +} // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // @@ -14,7 +26,7 @@ import "runtime" func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // TODO: if we get the chance, remove the req parameter and // hardcode TIOCSWINSZ. - err := ioctlSetWinsize(fd, req, value) + err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } @@ -24,7 +36,30 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // The req value will usually be TCSETA or TIOCSETA. func IoctlSetTermios(fd int, req uint, value *Termios) error { // TODO: if we get the chance, remove the req parameter. - err := ioctlSetTermios(fd, req, value) + err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } + +// IoctlGetInt performs an ioctl operation which gets an integer value +// from fd, using the specified request number. +// +// A few ioctl requests use the return value as an output parameter; +// for those, IoctlRetInt should be used instead of this function. +func IoctlGetInt(fd int, req uint) (int, error) { + var value int + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return value, err +} + +func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { + var value Winsize + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return &value, err +} + +func IoctlGetTermios(fd int, req uint) (*Termios, error) { + var value Termios + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return &value, err +} diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index 5a22eca967..890ec464c7 100644 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -212,9 +212,11 @@ esac echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; elif [ "$GOOS" == "darwin" ]; then # pre-1.12, direct syscalls - echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go"; + echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go"; # 1.12 and later, syscalls via libSystem echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; + # 1.13 and later, syscalls via libSystem (including syscallPtr) + echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go"; else echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi diff --git a/vendor/golang.org/x/sys/unix/mkasm_darwin.go b/vendor/golang.org/x/sys/unix/mkasm_darwin.go deleted file mode 100644 index 4548b993db..0000000000 --- a/vendor/golang.org/x/sys/unix/mkasm_darwin.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go. -//This program must be run after mksyscall.go. -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "os" - "strings" -) - -func main() { - in1, err := ioutil.ReadFile("syscall_darwin.go") - if err != nil { - log.Fatalf("can't open syscall_darwin.go: %s", err) - } - arch := os.Args[1] - in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) - if err != nil { - log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err) - } - in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) - if err != nil { - log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err) - } - in := string(in1) + string(in2) + string(in3) - - trampolines := map[string]bool{} - - var out bytes.Buffer - - fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " ")) - fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n") - fmt.Fprintf(&out, "\n") - fmt.Fprintf(&out, "// +build go1.12\n") - fmt.Fprintf(&out, "\n") - fmt.Fprintf(&out, "#include \"textflag.h\"\n") - for _, line := range strings.Split(in, "\n") { - if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") { - continue - } - fn := line[5 : len(line)-13] - if !trampolines[fn] { - trampolines[fn] = true - fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn) - fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn) - } - } - err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) - if err != nil { - log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) - } -} diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 14624b9531..4da0a63d2f 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -60,6 +60,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ includes_Darwin=' includes_DragonFly=' #include #include +#include #include #include #include @@ -103,6 +105,7 @@ includes_FreeBSD=' #include #include #include +#include #include #include #include @@ -179,24 +182,32 @@ struct ltchars { #include #include #include +#include #include #include #include #include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include #include #include #include @@ -206,26 +217,23 @@ struct ltchars { #include #include #include +#include #include +#include #include #include +#include #include -#include #include #include -#include -#include -#include #include -#include -#include +#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include + #include #include @@ -264,6 +272,11 @@ struct ltchars { #define FS_KEY_DESC_PREFIX "fscrypt:" #define FS_KEY_DESC_PREFIX_SIZE 8 #define FS_MAX_KEY_SIZE 64 + +// The code generator produces -0x1 for (~0), but an unsigned value is necessary +// for the tipc_subscr timeout __u32 field. +#undef TIPC_WAIT_FOREVER +#define TIPC_WAIT_FOREVER 0xffffffff ' includes_NetBSD=' @@ -273,6 +286,7 @@ includes_NetBSD=' #include #include #include +#include #include #include #include @@ -299,6 +313,7 @@ includes_OpenBSD=' #include #include #include +#include #include #include #include @@ -335,6 +350,7 @@ includes_OpenBSD=' includes_SunOS=' #include #include +#include #include #include #include @@ -427,6 +443,7 @@ ccflags="$@" $2 == "XCASE" || $2 == "ALTWERASE" || $2 == "NOKERNINFO" || + $2 == "NFDBITS" || $2 ~ /^PAR/ || $2 ~ /^SIG[^_]/ || $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || @@ -451,6 +468,7 @@ ccflags="$@" $2 ~ /^SYSCTL_VERS/ || $2 !~ "MNT_BITS" && $2 ~ /^(MS|MNT|UMOUNT)_/ || + $2 ~ /^NS_GET_/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || $2 ~ /^KEXEC_/ || @@ -506,6 +524,8 @@ ccflags="$@" $2 ~ /^XDP_/ || $2 ~ /^(HDIO|WIN|SMART)_/ || $2 ~ /^CRYPTO_/ || + $2 ~ /^TIPC_/ || + $2 ~ /^DEVLINK_/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || $2 ~/^PPPIOC/ || diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go deleted file mode 100644 index eb4332059a..0000000000 --- a/vendor/golang.org/x/sys/unix/mkpost.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// mkpost processes the output of cgo -godefs to -// modify the generated types. It is used to clean up -// the sys API in an architecture specific manner. -// -// mkpost is run after cgo -godefs; see README.md. -package main - -import ( - "bytes" - "fmt" - "go/format" - "io/ioutil" - "log" - "os" - "regexp" -) - -func main() { - // Get the OS and architecture (using GOARCH_TARGET if it exists) - goos := os.Getenv("GOOS") - goarch := os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check that we are using the Docker-based build system if we should be. - if goos == "linux" { - if os.Getenv("GOLANG_SYS_BUILD") != "docker" { - os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n") - os.Stderr.WriteString("See README.md\n") - os.Exit(1) - } - } - - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatal(err) - } - - if goos == "aix" { - // Replace type of Atim, Mtim and Ctim by Timespec in Stat_t - // to avoid having both StTimespec and Timespec. - sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`) - b = sttimespec.ReplaceAll(b, []byte("Timespec")) - } - - // Intentionally export __val fields in Fsid and Sigset_t - valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`) - b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}")) - - // Intentionally export __fds_bits field in FdSet - fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`) - b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}")) - - // If we have empty Ptrace structs, we should delete them. Only s390x emits - // nonempty Ptrace structs. - ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`) - b = ptraceRexexp.ReplaceAll(b, nil) - - // Replace the control_regs union with a blank identifier for now. - controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`) - b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64")) - - // Remove fields that are added by glibc - // Note that this is unstable as the identifers are private. - removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`) - b = removeFieldsRegex.ReplaceAll(b, []byte("_")) - - // Convert [65]int8 to [65]byte in Utsname members to simplify - // conversion to string; see golang.org/issue/20753 - convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`) - b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte")) - - // Convert [1024]int8 to [1024]byte in Ptmget members - convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`) - b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte")) - - // Remove spare fields (e.g. in Statx_t) - spareFieldsRegex := regexp.MustCompile(`X__spare\S*`) - b = spareFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove cgo padding fields - removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) - b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove padding, hidden, or unused fields - removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`) - b = removeFieldsRegex.ReplaceAll(b, []byte("_")) - - // Remove the first line of warning from cgo - b = b[bytes.IndexByte(b, '\n')+1:] - // Modify the command in the header to include: - // mkpost, our own warning, and a build tag. - replacement := fmt.Sprintf(`$1 | go run mkpost.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s,%s`, goarch, goos) - cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`) - b = cgoCommandRegex.ReplaceAll(b, []byte(replacement)) - - // Rename Stat_t time fields - if goos == "freebsd" && goarch == "386" { - // Hide Stat_t.[AMCB]tim_ext fields - renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`) - b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_")) - } - renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`) - b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}")) - - // gofmt - b, err = format.Source(b) - if err != nil { - log.Fatal(err) - } - - os.Stdout.Write(b) -} diff --git a/vendor/golang.org/x/sys/unix/mksyscall.go b/vendor/golang.org/x/sys/unix/mksyscall.go deleted file mode 100644 index e4af9424e9..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall.go +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_darwin.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named errno. - -A line beginning with //sysnb is like //sys, except that the -goroutine will not be suspended during the execution of the system -call. This must only be used for system calls which can never -block, as otherwise the system call could cause all goroutines to -hang. -*/ -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - plan9 = flag.Bool("plan9", false, "plan9") - openbsd = flag.Bool("openbsd", false, "openbsd") - netbsd = flag.Bool("netbsd", false, "netbsd") - dragonfly = flag.Bool("dragonfly", false, "dragonfly") - arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair - tags = flag.String("tags", "", "build tags") - filename = flag.String("output", "", "output file name (standard output if omitted)") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - // Get the OS and architecture (using GOARCH_TARGET if it exists) - goos := os.Getenv("GOOS") - if goos == "" { - fmt.Fprintln(os.Stderr, "GOOS not defined in environment") - os.Exit(1) - } - goarch := os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - - // Check that we are using the Docker-based build system if we should - if goos == "linux" { - if os.Getenv("GOLANG_SYS_BUILD") != "docker" { - fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n") - fmt.Fprintf(os.Stderr, "See README.md\n") - os.Exit(1) - } - } - - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - libc := false - if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") { - libc = true - } - trampolines := map[string]bool{} - - text := "" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, errno error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, sysname := f[2], f[3], f[4], f[5] - - // ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers. - if goos == "darwin" && !libc && funct == "ClockGettime" { - continue - } - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // Go function header. - outDecl := "" - if len(out) > 0 { - outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", ")) - } - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl) - - // Check if err return available - errvar := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - break - } - } - - // Prepare arguments to Syscall. - var args []string - n := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\tvar _p%d *byte\n", n) - text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name) - text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\tvar _p%d *byte\n", n) - text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass dummy pointer in that case. - // Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). - text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name) - text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n) - args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) - n++ - } else if p.Type == "int64" && (*openbsd || *netbsd) { - args = append(args, "0") - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else if endianness == "little-endian" { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } else if p.Type == "int64" && *dragonfly { - if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil { - args = append(args, "0") - } - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else if endianness == "little-endian" { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" { - if len(args)%2 == 1 && *arm { - // arm abi specifies 64-bit argument uses - // (even, odd) pair - args = append(args, "0") - } - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } - - // Determine which form to use; pad args with zeros. - asm := "Syscall" - if nonblock != nil { - if errvar == "" && goos == "linux" { - asm = "RawSyscallNoError" - } else { - asm = "RawSyscall" - } - } else { - if errvar == "" && goos == "linux" { - asm = "SyscallNoError" - } - } - if len(args) <= 3 { - for len(args) < 3 { - args = append(args, "0") - } - } else if len(args) <= 6 { - asm += "6" - for len(args) < 6 { - args = append(args, "0") - } - } else if len(args) <= 9 { - asm += "9" - for len(args) < 9 { - args = append(args, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct) - } - - // System call number. - if sysname == "" { - sysname = "SYS_" + funct - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToUpper(sysname) - } - - var libcFn string - if libc { - asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call - sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_ - sysname = strings.ToLower(sysname) // lowercase - if sysname == "getdirentries64" { - // Special case - libSystem name and - // raw syscall name don't match. - sysname = "__getdirentries64" - } - libcFn = sysname - sysname = "funcPC(libc_" + sysname + "_trampoline)" - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist) - - // Assign return values. - body := "" - ret := []string{"_", "_", "_"} - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" && !*plan9 { - reg = "e1" - ret[2] = reg - doErrno = true - } else if p.Name == "err" && *plan9 { - ret[0] = "r0" - ret[2] = "e1" - break - } else { - reg = fmt.Sprintf("r%d", i) - ret[i] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%s != 0", reg) - } - if p.Type == "int64" && endianness != "" { - // 64-bit number in r1:r0 or r0:r1. - if i+2 > len(out) { - fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct) - } - if endianness == "big-endian" { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) - } else { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) - } - ret[i] = fmt.Sprintf("r%d", i) - ret[i+1] = fmt.Sprintf("r%d", i+1) - } - if reg != "e1" || *plan9 { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { - text += fmt.Sprintf("\t%s\n", call) - } else { - if errvar == "" && goos == "linux" { - // raw syscall without error on Linux, see golang.org/issue/22924 - text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call) - } else { - text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) - } - } - text += body - - if *plan9 && ret[2] == "e1" { - text += "\tif int32(r0) == -1 {\n" - text += "\t\terr = e1\n" - text += "\t}\n" - } else if doErrno { - text += "\tif e1 != 0 {\n" - text += "\t\terr = errnoErr(e1)\n" - text += "\t}\n" - } - text += "\treturn\n" - text += "}\n\n" - - if libc && !trampolines[libcFn] { - // some system calls share a trampoline, like read and readlen. - trampolines[libcFn] = true - // Declare assembly trampoline. - text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn) - // Assembly trampoline calls the libc_* function, which this magic - // redirects to use the function from libSystem. - text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn) - text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn) - text += "\n" - } - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go deleted file mode 100644 index 3be3cdfc3b..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_aix.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt -*/ -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - aix = flag.Bool("aix", false, "aix") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - text := "" - cExtern := "/*\n#include \n#include \n" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // Check if value return, err return available - errvar := "" - retvar := "" - rettype := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - } else { - retvar = p.Name - rettype = p.Type - } - } - - // System call name. - if sysname == "" { - sysname = funct - } - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - cRettype := "" - if rettype == "unsafe.Pointer" { - cRettype = "uintptr_t" - } else if rettype == "uintptr" { - cRettype = "uintptr_t" - } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { - cRettype = "uintptr_t" - } else if rettype == "int" { - cRettype = "int" - } else if rettype == "int32" { - cRettype = "int" - } else if rettype == "int64" { - cRettype = "long long" - } else if rettype == "uint32" { - cRettype = "unsigned int" - } else if rettype == "uint64" { - cRettype = "unsigned long long" - } else { - cRettype = "int" - } - if sysname == "exit" { - cRettype = "void" - } - - // Change p.Types to c - var cIn []string - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "string" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t", "size_t") - } else if p.Type == "unsafe.Pointer" { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "uintptr" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "int" { - cIn = append(cIn, "int") - } else if p.Type == "int32" { - cIn = append(cIn, "int") - } else if p.Type == "int64" { - cIn = append(cIn, "long long") - } else if p.Type == "uint32" { - cIn = append(cIn, "unsigned int") - } else if p.Type == "uint64" { - cIn = append(cIn, "unsigned long long") - } else { - cIn = append(cIn, "int") - } - } - - if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - cExtern += "#define c_select select\n" - } - // Imports of system calls from libc - cExtern += fmt.Sprintf("%s %s", cRettype, sysname) - cIn := strings.Join(cIn, ", ") - cExtern += fmt.Sprintf("(%s);\n", cIn) - } - - // So file name. - if *aix { - if modname == "" { - modname = "libc.a/shr_64.o" - } else { - fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) - os.Exit(1) - } - } - - strconvfunc := "C.CString" - - // Go function header. - if outps != "" { - outps = fmt.Sprintf(" (%s)", outps) - } - if text != "" { - text += "\n" - } - - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) - - // Prepare arguments to Syscall. - var args []string - n := 0 - argN := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) - n++ - text += fmt.Sprintf("\tvar _p%d int\n", n) - text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) - args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) - n++ - } else if p.Type == "int64" && endianness != "" { - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - n++ - } else if p.Type == "bool" { - text += fmt.Sprintf("\tvar _p%d uint32\n", n) - text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) - args = append(args, fmt.Sprintf("_p%d", n)) - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) - } else if p.Type == "unsafe.Pointer" { - args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) - } else if p.Type == "int" { - if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { - args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) - } else if argN == 0 && funct == "fcntl" { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } - } else if p.Type == "int32" { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } else if p.Type == "int64" { - args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) - } else if p.Type == "uint32" { - args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) - } else if p.Type == "uint64" { - args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) - } else if p.Type == "uintptr" { - args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) - } - argN++ - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := "" - if sysname == "exit" { - if errvar != "" { - call += "er :=" - } else { - call += "" - } - } else if errvar != "" { - call += "r0,er :=" - } else if retvar != "" { - call += "r0,_ :=" - } else { - call += "" - } - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist) - } else { - call += fmt.Sprintf("C.%s(%s)", sysname, arglist) - } - - // Assign return values. - body := "" - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - } else { - reg = "r0" - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - - // verify return - if sysname != "exit" && errvar != "" { - if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { - body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } else { - body += "\tif (r0 ==-1 && er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } - } else if errvar != "" { - body += "\tif (er != nil) {\n" - body += fmt.Sprintf("\t\t%s = er\n", errvar) - body += "\t}\n" - } - - text += fmt.Sprintf("\t%s\n", call) - text += body - - text += "\treturn\n" - text += "}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - - -%s -*/ -import "C" -import ( - "unsafe" -) - - -%s - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go deleted file mode 100644 index c960099517..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -This program reads a file containing function prototypes -(like syscall_aix.go) and generates system call bodies. -The prototypes are marked by lines beginning with "//sys" -and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt - - -This program will generate three files and handle both gc and gccgo implementation: - - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) - - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 - - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. - - The generated code looks like this - -zsyscall_aix_ppc64.go -func asyscall(...) (n int, err error) { - // Pointer Creation - r1, e1 := callasyscall(...) - // Type Conversion - // Error Handler - return -} - -zsyscall_aix_ppc64_gc.go -//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" -//go:linkname libc_asyscall libc_asyscall -var asyscall syscallFunc - -func callasyscall(...) (r1 uintptr, e1 Errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) - return -} - -zsyscall_aix_ppc64_ggcgo.go - -// int asyscall(...) - -import "C" - -func callasyscall(...) (r1 uintptr, e1 Errno) { - r1 = uintptr(C.asyscall(...)) - e1 = syscall.GetErrno() - return -} -*/ - -package main - -import ( - "bufio" - "flag" - "fmt" - "io/ioutil" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - aix = flag.Bool("aix", false, "aix") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - // GCCGO - textgccgo := "" - cExtern := "/*\n#include \n" - // GC - textgc := "" - dynimports := "" - linknames := "" - var vars []string - // COMMON - textcommon := "" - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - if sysname == "" { - sysname = funct - } - - onlyCommon := false - if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" { - // This function call another syscall which is already implemented. - // Therefore, the gc and gccgo part must not be generated. - onlyCommon = true - } - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - - textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - if !onlyCommon { - textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - } - - // Check if value return, err return available - errvar := "" - rettype := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - } else { - rettype = p.Type - } - } - - sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - // GCCGO Prototype return type - cRettype := "" - if rettype == "unsafe.Pointer" { - cRettype = "uintptr_t" - } else if rettype == "uintptr" { - cRettype = "uintptr_t" - } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { - cRettype = "uintptr_t" - } else if rettype == "int" { - cRettype = "int" - } else if rettype == "int32" { - cRettype = "int" - } else if rettype == "int64" { - cRettype = "long long" - } else if rettype == "uint32" { - cRettype = "unsigned int" - } else if rettype == "uint64" { - cRettype = "unsigned long long" - } else { - cRettype = "int" - } - if sysname == "exit" { - cRettype = "void" - } - - // GCCGO Prototype arguments type - var cIn []string - for i, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "string" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t", "size_t") - } else if p.Type == "unsafe.Pointer" { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "uintptr" { - cIn = append(cIn, "uintptr_t") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { - cIn = append(cIn, "uintptr_t") - } else if p.Type == "int" { - if (i == 0 || i == 2) && funct == "fcntl" { - // These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock - cIn = append(cIn, "uintptr_t") - } else { - cIn = append(cIn, "int") - } - - } else if p.Type == "int32" { - cIn = append(cIn, "int") - } else if p.Type == "int64" { - cIn = append(cIn, "long long") - } else if p.Type == "uint32" { - cIn = append(cIn, "unsigned int") - } else if p.Type == "uint64" { - cIn = append(cIn, "unsigned long long") - } else { - cIn = append(cIn, "int") - } - } - - if !onlyCommon { - // GCCGO Prototype Generation - // Imports of system calls from libc - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - cExtern += "#define c_select select\n" - } - cExtern += fmt.Sprintf("%s %s", cRettype, sysname) - cIn := strings.Join(cIn, ", ") - cExtern += fmt.Sprintf("(%s);\n", cIn) - } - // GC Library name - if modname == "" { - modname = "libc.a/shr_64.o" - } else { - fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) - os.Exit(1) - } - sysvarname := fmt.Sprintf("libc_%s", sysname) - - if !onlyCommon { - // GC Runtime import of function to allow cross-platform builds. - dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname) - // GC Link symbol to proc address variable. - linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname) - // GC Library proc address variable. - vars = append(vars, sysvarname) - } - - strconvfunc := "BytePtrFromString" - strconvtype := "*byte" - - // Go function header. - if outps != "" { - outps = fmt.Sprintf(" (%s)", outps) - } - if textcommon != "" { - textcommon += "\n" - } - - textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) - - // Prepare arguments tocall. - var argscommon []string // Arguments in the common part - var argscall []string // Arguments for call prototype - var argsgc []string // Arguments for gc call (with syscall6) - var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall) - n := 0 - argN := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if p.Type == "string" && errvar != "" { - textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) - n++ - } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) - textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) - argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) - n++ - } else if p.Type == "int64" && endianness != "" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") - } else if p.Type == "bool" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") - } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { - argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else if p.Type == "int" { - if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { - // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock - argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - - } else { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } - } else if p.Type == "int32" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } else if p.Type == "int64" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) - } else if p.Type == "uint32" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) - } else if p.Type == "uint64" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) - } else if p.Type == "uintptr" { - argscommon = append(argscommon, p.Name) - argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) - argsgc = append(argsgc, p.Name) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) - } else { - argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) - argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) - argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) - argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) - } - argN++ - } - nargs := len(argsgc) - - // COMMON function generation - argscommonlist := strings.Join(argscommon, ", ") - callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) - ret := []string{"_", "_"} - body := "" - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - ret[1] = reg - doErrno = true - } else { - reg = "r0" - ret[0] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%s != 0", reg) - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" { - textcommon += fmt.Sprintf("\t%s\n", callcommon) - } else { - textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) - } - textcommon += body - - if doErrno { - textcommon += "\tif e1 != 0 {\n" - textcommon += "\t\terr = errnoErr(e1)\n" - textcommon += "\t}\n" - } - textcommon += "\treturn\n" - textcommon += "}\n" - - if onlyCommon { - continue - } - - // CALL Prototype - callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) - - // GC function generation - asm := "syscall6" - if nonblock != nil { - asm = "rawSyscall6" - } - - if len(argsgc) <= 6 { - for len(argsgc) < 6 { - argsgc = append(argsgc, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) - os.Exit(1) - } - argsgclist := strings.Join(argsgc, ", ") - callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) - - textgc += callProto - textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) - textgc += "\treturn\n}\n" - - // GCCGO function generation - argsgccgolist := strings.Join(argsgccgo, ", ") - var callgccgo string - if sysname == "select" { - // select is a keyword of Go. Its name is - // changed to c_select. - callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist) - } else { - callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) - } - textgccgo += callProto - textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) - textgccgo += "\te1 = syscall.GetErrno()\n" - textgccgo += "\treturn\n}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - - // Print zsyscall_aix_ppc64.go - err := ioutil.WriteFile("zsyscall_aix_ppc64.go", - []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - // Print zsyscall_aix_ppc64_gc.go - vardecls := "\t" + strings.Join(vars, ",\n\t") - vardecls += " syscallFunc" - err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", - []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - // Print zsyscall_aix_ppc64_gccgo.go - err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", - []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), - 0644) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } -} - -const srcTemplate1 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - -import ( - "unsafe" -) - - -%s - -%s -` -const srcTemplate2 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s -// +build !gccgo - -package %s - -import ( - "unsafe" -) -%s -%s -%s -type syscallFunc uintptr - -var ( -%s -) - -// Implemented in runtime/syscall_aix.go. -func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - -%s -` -const srcTemplate3 = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s -// +build gccgo - -package %s - -%s -*/ -import "C" -import ( - "syscall" -) - - -%s - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go deleted file mode 100644 index 3d864738b6..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* - This program reads a file containing function prototypes - (like syscall_solaris.go) and generates system call bodies. - The prototypes are marked by lines beginning with "//sys" - and read like func declarations if //sys is replaced by func, but: - * The parameter lists must give a name for each argument. - This includes return parameters. - * The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - * If the return parameter is an error number, it must be named err. - * If go func name needs to be different than its libc name, - * or the function is not in libc, name could be specified - * at the end, after "=" sign, like - //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt -*/ - -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "regexp" - "strings" -) - -var ( - b32 = flag.Bool("b32", false, "32bit big-endian") - l32 = flag.Bool("l32", false, "32bit little-endian") - tags = flag.String("tags", "", "build tags") -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return *tags -} - -// Param is function parameter -type Param struct { - Name string - Type string -} - -// usage prints the program usage -func usage() { - fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n") - os.Exit(1) -} - -// parseParamList parses parameter list and returns a slice of parameters -func parseParamList(list string) []string { - list = strings.TrimSpace(list) - if list == "" { - return []string{} - } - return regexp.MustCompile(`\s*,\s*`).Split(list, -1) -} - -// parseParam splits a parameter into name and type -func parseParam(p string) Param { - ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) - if ps == nil { - fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) - os.Exit(1) - } - return Param{ps[1], ps[2]} -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - endianness := "" - if *b32 { - endianness = "big-endian" - } else if *l32 { - endianness = "little-endian" - } - - pack := "" - text := "" - dynimports := "" - linknames := "" - var vars []string - for _, path := range flag.Args() { - file, err := os.Open(path) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - t := s.Text() - t = strings.TrimSpace(t) - t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) - if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { - pack = p[1] - } - nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) - if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { - continue - } - - // Line must be of the form - // func Open(path string, mode int, perm int) (fd int, err error) - // Split into name, in params, out params. - f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) - if f == nil { - fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) - os.Exit(1) - } - funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] - - // Split argument lists on comma. - in := parseParamList(inps) - out := parseParamList(outps) - - inps = strings.Join(in, ", ") - outps = strings.Join(out, ", ") - - // Try in vain to keep people from editing this file. - // The theory is that they jump into the middle of the file - // without reading the header. - text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" - - // So file name. - if modname == "" { - modname = "libc" - } - - // System call name. - if sysname == "" { - sysname = funct - } - - // System call pointer variable name. - sysvarname := fmt.Sprintf("proc%s", sysname) - - strconvfunc := "BytePtrFromString" - strconvtype := "*byte" - - sysname = strings.ToLower(sysname) // All libc functions are lowercase. - - // Runtime import of function to allow cross-platform builds. - dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname) - // Link symbol to proc address variable. - linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname) - // Library proc address variable. - vars = append(vars, sysvarname) - - // Go function header. - outlist := strings.Join(out, ", ") - if outlist != "" { - outlist = fmt.Sprintf(" (%s)", outlist) - } - if text != "" { - text += "\n" - } - text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist) - - // Check if err return available - errvar := "" - for _, param := range out { - p := parseParam(param) - if p.Type == "error" { - errvar = p.Name - continue - } - } - - // Prepare arguments to Syscall. - var args []string - n := 0 - for _, param := range in { - p := parseParam(param) - if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { - args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") - } else if p.Type == "string" && errvar != "" { - text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) - text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if p.Type == "string" { - fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") - text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) - text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) - n++ - } else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil { - // Convert slice into pointer, length. - // Have to be careful not to take address of &a[0] if len == 0: - // pass nil in that case. - text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1]) - text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) - args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) - n++ - } else if p.Type == "int64" && endianness != "" { - if endianness == "big-endian" { - args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) - } - } else if p.Type == "bool" { - text += fmt.Sprintf("\tvar _p%d uint32\n", n) - text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) - args = append(args, fmt.Sprintf("uintptr(_p%d)", n)) - n++ - } else { - args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) - } - } - nargs := len(args) - - // Determine which form to use; pad args with zeros. - asm := "sysvicall6" - if nonblock != nil { - asm = "rawSysvicall6" - } - if len(args) <= 6 { - for len(args) < 6 { - args = append(args, "0") - } - } else { - fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path) - os.Exit(1) - } - - // Actual call. - arglist := strings.Join(args, ", ") - call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist) - - // Assign return values. - body := "" - ret := []string{"_", "_", "_"} - doErrno := false - for i := 0; i < len(out); i++ { - p := parseParam(out[i]) - reg := "" - if p.Name == "err" { - reg = "e1" - ret[2] = reg - doErrno = true - } else { - reg = fmt.Sprintf("r%d", i) - ret[i] = reg - } - if p.Type == "bool" { - reg = fmt.Sprintf("%d != 0", reg) - } - if p.Type == "int64" && endianness != "" { - // 64-bit number in r1:r0 or r0:r1. - if i+2 > len(out) { - fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path) - os.Exit(1) - } - if endianness == "big-endian" { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) - } else { - reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) - } - ret[i] = fmt.Sprintf("r%d", i) - ret[i+1] = fmt.Sprintf("r%d", i+1) - } - if reg != "e1" { - body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) - } - } - if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { - text += fmt.Sprintf("\t%s\n", call) - } else { - text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) - } - text += body - - if doErrno { - text += "\tif e1 != 0 {\n" - text += "\t\terr = e1\n" - text += "\t}\n" - } - text += "\treturn\n" - text += "}\n" - } - if err := s.Err(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - file.Close() - } - imp := "" - if pack != "unix" { - imp = "import \"golang.org/x/sys/unix\"\n" - - } - vardecls := "\t" + strings.Join(vars, ",\n\t") - vardecls += " syscallFunc" - fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text) -} - -const srcTemplate = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package %s - -import ( - "syscall" - "unsafe" -) -%s -%s -%s -var ( -%s -) - -%s -` diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go deleted file mode 100644 index b6b409909c..0000000000 --- a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Parse the header files for OpenBSD and generate a Go usable sysctl MIB. -// -// Build a MIB with each entry being an array containing the level, type and -// a hash that will contain additional entries if the current entry is a node. -// We then walk this MIB and create a flattened sysctl name to OID hash. - -package main - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "regexp" - "sort" - "strings" -) - -var ( - goos, goarch string -) - -// cmdLine returns this programs's commandline arguments. -func cmdLine() string { - return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags. -func buildTags() string { - return fmt.Sprintf("%s,%s", goarch, goos) -} - -// reMatch performs regular expression match and stores the substring slice to value pointed by m. -func reMatch(re *regexp.Regexp, str string, m *[]string) bool { - *m = re.FindStringSubmatch(str) - if *m != nil { - return true - } - return false -} - -type nodeElement struct { - n int - t string - pE *map[string]nodeElement -} - -var ( - debugEnabled bool - mib map[string]nodeElement - node *map[string]nodeElement - nodeMap map[string]string - sysCtl []string -) - -var ( - ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`) - ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`) - ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`) - netInetRE = regexp.MustCompile(`^netinet/`) - netInet6RE = regexp.MustCompile(`^netinet6/`) - netRE = regexp.MustCompile(`^net/`) - bracesRE = regexp.MustCompile(`{.*}`) - ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`) - fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`) -) - -func debug(s string) { - if debugEnabled { - fmt.Fprintln(os.Stderr, s) - } -} - -// Walk the MIB and build a sysctl name to OID mapping. -func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) { - lNode := pNode // local copy of pointer to node - var keys []string - for k := range *lNode { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, key := range keys { - nodename := name - if name != "" { - nodename += "." - } - nodename += key - - nodeoid := append(oid, (*pNode)[key].n) - - if (*pNode)[key].t == `CTLTYPE_NODE` { - if _, ok := nodeMap[nodename]; ok { - lNode = &mib - ctlName := nodeMap[nodename] - for _, part := range strings.Split(ctlName, ".") { - lNode = ((*lNode)[part]).pE - } - } else { - lNode = (*pNode)[key].pE - } - buildSysctl(lNode, nodename, nodeoid) - } else if (*pNode)[key].t != "" { - oidStr := []string{} - for j := range nodeoid { - oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j])) - } - text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n" - sysCtl = append(sysCtl, text) - } - } -} - -func main() { - // Get the OS (using GOOS_TARGET if it exist) - goos = os.Getenv("GOOS_TARGET") - if goos == "" { - goos = os.Getenv("GOOS") - } - // Get the architecture (using GOARCH_TARGET if it exists) - goarch = os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check if GOOS and GOARCH environment variables are defined - if goarch == "" || goos == "" { - fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") - os.Exit(1) - } - - mib = make(map[string]nodeElement) - headers := [...]string{ - `sys/sysctl.h`, - `sys/socket.h`, - `sys/tty.h`, - `sys/malloc.h`, - `sys/mount.h`, - `sys/namei.h`, - `sys/sem.h`, - `sys/shm.h`, - `sys/vmmeter.h`, - `uvm/uvmexp.h`, - `uvm/uvm_param.h`, - `uvm/uvm_swap_encrypt.h`, - `ddb/db_var.h`, - `net/if.h`, - `net/if_pfsync.h`, - `net/pipex.h`, - `netinet/in.h`, - `netinet/icmp_var.h`, - `netinet/igmp_var.h`, - `netinet/ip_ah.h`, - `netinet/ip_carp.h`, - `netinet/ip_divert.h`, - `netinet/ip_esp.h`, - `netinet/ip_ether.h`, - `netinet/ip_gre.h`, - `netinet/ip_ipcomp.h`, - `netinet/ip_ipip.h`, - `netinet/pim_var.h`, - `netinet/tcp_var.h`, - `netinet/udp_var.h`, - `netinet6/in6.h`, - `netinet6/ip6_divert.h`, - `netinet6/pim6_var.h`, - `netinet/icmp6.h`, - `netmpls/mpls.h`, - } - - ctls := [...]string{ - `kern`, - `vm`, - `fs`, - `net`, - //debug /* Special handling required */ - `hw`, - //machdep /* Arch specific */ - `user`, - `ddb`, - //vfs /* Special handling required */ - `fs.posix`, - `kern.forkstat`, - `kern.intrcnt`, - `kern.malloc`, - `kern.nchstats`, - `kern.seminfo`, - `kern.shminfo`, - `kern.timecounter`, - `kern.tty`, - `kern.watchdog`, - `net.bpf`, - `net.ifq`, - `net.inet`, - `net.inet.ah`, - `net.inet.carp`, - `net.inet.divert`, - `net.inet.esp`, - `net.inet.etherip`, - `net.inet.gre`, - `net.inet.icmp`, - `net.inet.igmp`, - `net.inet.ip`, - `net.inet.ip.ifq`, - `net.inet.ipcomp`, - `net.inet.ipip`, - `net.inet.mobileip`, - `net.inet.pfsync`, - `net.inet.pim`, - `net.inet.tcp`, - `net.inet.udp`, - `net.inet6`, - `net.inet6.divert`, - `net.inet6.ip6`, - `net.inet6.icmp6`, - `net.inet6.pim6`, - `net.inet6.tcp6`, - `net.inet6.udp6`, - `net.mpls`, - `net.mpls.ifq`, - `net.key`, - `net.pflow`, - `net.pfsync`, - `net.pipex`, - `net.rt`, - `vm.swapencrypt`, - //vfsgenctl /* Special handling required */ - } - - // Node name "fixups" - ctlMap := map[string]string{ - "ipproto": "net.inet", - "net.inet.ipproto": "net.inet", - "net.inet6.ipv6proto": "net.inet6", - "net.inet6.ipv6": "net.inet6.ip6", - "net.inet.icmpv6": "net.inet6.icmp6", - "net.inet6.divert6": "net.inet6.divert", - "net.inet6.tcp6": "net.inet.tcp", - "net.inet6.udp6": "net.inet.udp", - "mpls": "net.mpls", - "swpenc": "vm.swapencrypt", - } - - // Node mappings - nodeMap = map[string]string{ - "net.inet.ip.ifq": "net.ifq", - "net.inet.pfsync": "net.pfsync", - "net.mpls.ifq": "net.ifq", - } - - mCtls := make(map[string]bool) - for _, ctl := range ctls { - mCtls[ctl] = true - } - - for _, header := range headers { - debug("Processing " + header) - file, err := os.Open(filepath.Join("/usr/include", header)) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - s := bufio.NewScanner(file) - for s.Scan() { - var sub []string - if reMatch(ctlNames1RE, s.Text(), &sub) || - reMatch(ctlNames2RE, s.Text(), &sub) || - reMatch(ctlNames3RE, s.Text(), &sub) { - if sub[1] == `CTL_NAMES` { - // Top level. - node = &mib - } else { - // Node. - nodename := strings.ToLower(sub[2]) - ctlName := "" - if reMatch(netInetRE, header, &sub) { - ctlName = "net.inet." + nodename - } else if reMatch(netInet6RE, header, &sub) { - ctlName = "net.inet6." + nodename - } else if reMatch(netRE, header, &sub) { - ctlName = "net." + nodename - } else { - ctlName = nodename - ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) - } - - if val, ok := ctlMap[ctlName]; ok { - ctlName = val - } - if _, ok := mCtls[ctlName]; !ok { - debug("Ignoring " + ctlName + "...") - continue - } - - // Walk down from the top of the MIB. - node = &mib - for _, part := range strings.Split(ctlName, ".") { - if _, ok := (*node)[part]; !ok { - debug("Missing node " + part) - (*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} - } - node = (*node)[part].pE - } - } - - // Populate current node with entries. - i := -1 - for !strings.HasPrefix(s.Text(), "}") { - s.Scan() - if reMatch(bracesRE, s.Text(), &sub) { - i++ - } - if !reMatch(ctlTypeRE, s.Text(), &sub) { - continue - } - (*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} - } - } - } - err = s.Err() - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - file.Close() - } - buildSysctl(&mib, "", []int{}) - - sort.Strings(sysCtl) - text := strings.Join(sysCtl, "") - - fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) -} - -const srcTemplate = `// %s -// Code generated by the command above; DO NOT EDIT. - -// +build %s - -package unix - -type mibentry struct { - ctlname string - ctloid []_C_int -} - -var sysctlMib = []mibentry { -%s -} -` diff --git a/vendor/golang.org/x/sys/unix/mksysnum.go b/vendor/golang.org/x/sys/unix/mksysnum.go deleted file mode 100644 index baa6ecd850..0000000000 --- a/vendor/golang.org/x/sys/unix/mksysnum.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Generate system call table for DragonFly, NetBSD, -// FreeBSD, OpenBSD or Darwin from master list -// (for example, /usr/src/sys/kern/syscalls.master or -// sys/syscall.h). -package main - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "regexp" - "strings" -) - -var ( - goos, goarch string -) - -// cmdLine returns this programs's commandline arguments -func cmdLine() string { - return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") -} - -// buildTags returns build tags -func buildTags() string { - return fmt.Sprintf("%s,%s", goarch, goos) -} - -func checkErr(err error) { - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } -} - -// source string and substring slice for regexp -type re struct { - str string // source string - sub []string // matched sub-string -} - -// Match performs regular expression match -func (r *re) Match(exp string) bool { - r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) - if r.sub != nil { - return true - } - return false -} - -// fetchFile fetches a text file from URL -func fetchFile(URL string) io.Reader { - resp, err := http.Get(URL) - checkErr(err) - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - checkErr(err) - return strings.NewReader(string(body)) -} - -// readFile reads a text file from path -func readFile(path string) io.Reader { - file, err := os.Open(os.Args[1]) - checkErr(err) - return file -} - -func format(name, num, proto string) string { - name = strings.ToUpper(name) - // There are multiple entries for enosys and nosys, so comment them out. - nm := re{str: name} - if nm.Match(`^SYS_E?NOSYS$`) { - name = fmt.Sprintf("// %s", name) - } - if name == `SYS_SYS_EXIT` { - name = `SYS_EXIT` - } - return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) -} - -func main() { - // Get the OS (using GOOS_TARGET if it exist) - goos = os.Getenv("GOOS_TARGET") - if goos == "" { - goos = os.Getenv("GOOS") - } - // Get the architecture (using GOARCH_TARGET if it exists) - goarch = os.Getenv("GOARCH_TARGET") - if goarch == "" { - goarch = os.Getenv("GOARCH") - } - // Check if GOOS and GOARCH environment variables are defined - if goarch == "" || goos == "" { - fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") - os.Exit(1) - } - - file := strings.TrimSpace(os.Args[1]) - var syscalls io.Reader - if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { - // Download syscalls.master file - syscalls = fetchFile(file) - } else { - syscalls = readFile(file) - } - - var text, line string - s := bufio.NewScanner(syscalls) - for s.Scan() { - t := re{str: line} - if t.Match(`^(.*)\\$`) { - // Handle continuation - line = t.sub[1] - line += strings.TrimLeft(s.Text(), " \t") - } else { - // New line - line = s.Text() - } - t = re{str: line} - if t.Match(`\\$`) { - continue - } - t = re{str: line} - - switch goos { - case "dragonfly": - if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { - num, proto := t.sub[1], t.sub[2] - name := fmt.Sprintf("SYS_%s", t.sub[3]) - text += format(name, num, proto) - } - case "freebsd": - if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { - num, proto := t.sub[1], t.sub[2] - name := fmt.Sprintf("SYS_%s", t.sub[3]) - text += format(name, num, proto) - } - case "openbsd": - if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { - num, proto, name := t.sub[1], t.sub[3], t.sub[4] - text += format(name, num, proto) - } - case "netbsd": - if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { - num, proto, compat := t.sub[1], t.sub[6], t.sub[8] - name := t.sub[7] + "_" + t.sub[9] - if t.sub[11] != "" { - name = t.sub[7] + "_" + t.sub[11] - } - name = strings.ToUpper(name) - if compat == "" || compat == "13" || compat == "30" || compat == "50" { - text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) - } - } - case "darwin": - if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) { - name, num := t.sub[1], t.sub[2] - name = strings.ToUpper(name) - text += fmt.Sprintf(" SYS_%s = %s;\n", name, num) - } - default: - fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) - os.Exit(1) - - } - } - err := s.Err() - checkErr(err) - - fmt.Printf(template, cmdLine(), buildTags(), text) -} - -const template = `// %s -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build %s - -package unix - -const( -%s)` diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go b/vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go new file mode 100644 index 0000000000..5144deeccd --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go @@ -0,0 +1,16 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +// Round the length of a raw sockaddr up to align it properly. +func cmsgAlignOf(salen int) int { + salign := SizeofPtr + if SizeofPtr == 8 && !supportsABI(_dragonflyABIChangeVersion) { + // 64-bit Dragonfly before the September 2019 ABI changes still requires + // 32-bit aligned access to network subsystem. + salign = 4 + } + return (salen + salign - 1) & ^(salign - 1) +} diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go index 6079eb4ac1..8bf4570594 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go @@ -17,7 +17,7 @@ func UnixCredentials(ucred *Ucred) []byte { h.Level = SOL_SOCKET h.Type = SCM_CREDENTIALS h.SetLen(CmsgLen(SizeofUcred)) - *((*Ucred)(cmsgData(h))) = *ucred + *(*Ucred)(h.data(0)) = *ucred return b } diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go index 062bcabab1..003916ed7a 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go @@ -9,35 +9,9 @@ package unix import ( - "runtime" "unsafe" ) -// Round the length of a raw sockaddr up to align it properly. -func cmsgAlignOf(salen int) int { - salign := SizeofPtr - - switch runtime.GOOS { - case "aix": - // There is no alignment on AIX. - salign = 1 - case "darwin", "dragonfly", "solaris", "illumos": - // NOTE: It seems like 64-bit Darwin, DragonFly BSD, - // illumos, and Solaris kernels still require 32-bit - // aligned access to network subsystem. - if SizeofPtr == 8 { - salign = 4 - } - case "netbsd", "openbsd": - // NetBSD and OpenBSD armv7 require 64-bit alignment. - if runtime.GOARCH == "arm" { - salign = 8 - } - } - - return (salen + salign - 1) & ^(salign - 1) -} - // CmsgLen returns the value to store in the Len field of the Cmsghdr // structure, taking into account any necessary alignment. func CmsgLen(datalen int) int { @@ -50,8 +24,8 @@ func CmsgSpace(datalen int) int { return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen) } -func cmsgData(h *Cmsghdr) unsafe.Pointer { - return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr))) +func (h *Cmsghdr) data(offset uintptr) unsafe.Pointer { + return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)) + offset) } // SocketControlMessage represents a socket control message. @@ -94,10 +68,8 @@ func UnixRights(fds ...int) []byte { h.Level = SOL_SOCKET h.Type = SCM_RIGHTS h.SetLen(CmsgLen(datalen)) - data := cmsgData(h) - for _, fd := range fds { - *(*int32)(data) = int32(fd) - data = unsafe.Pointer(uintptr(data) + 4) + for i, fd := range fds { + *(*int32)(h.data(4 * uintptr(i))) = int32(fd) } return b } diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go new file mode 100644 index 0000000000..7d08dae5ba --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go @@ -0,0 +1,38 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix darwin freebsd linux netbsd openbsd solaris + +package unix + +import ( + "runtime" +) + +// Round the length of a raw sockaddr up to align it properly. +func cmsgAlignOf(salen int) int { + salign := SizeofPtr + + // dragonfly needs to check ABI version at runtime, see cmsgAlignOf in + // sockcmsg_dragonfly.go + switch runtime.GOOS { + case "aix": + // There is no alignment on AIX. + salign = 1 + case "darwin", "illumos", "solaris": + // NOTE: It seems like 64-bit Darwin, Illumos and Solaris + // kernels still require 32-bit aligned access to network + // subsystem. + if SizeofPtr == 8 { + salign = 4 + } + case "netbsd", "openbsd": + // NetBSD and OpenBSD armv7 require 64-bit alignment. + if runtime.GOARCH == "arm" { + salign = 8 + } + } + + return (salen + salign - 1) & ^(salign - 1) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index 1aa065f9c9..9ad8a0d4a5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -350,49 +350,12 @@ func (w WaitStatus) Signal() Signal { func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } -func (w WaitStatus) CoreDump() bool { return w&0x200 != 0 } +func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 } func (w WaitStatus) TrapCause() int { return -1 } //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // There is no way to create a custom fcntl and to keep //sys fcntl easily, // Therefore, the programmer must call dup2 instead of fcntl in this case. diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go index bf05603f15..b3c8e3301c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go @@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go index 13d4321f4c..9a6e024179 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go @@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd.go b/vendor/golang.org/x/sys/unix/syscall_bsd.go index 97a8eef6fa..d52bcc41c3 100644 --- a/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -237,7 +237,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { break } } - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] + bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] sa.Name = string(bytes) return sa, nil @@ -413,8 +413,6 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err e return kevent(kq, change, len(changes), event, len(events), timeout) } -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL - // sysctlmib translates name to mib number and appends any additional args. func sysctlmib(name string, args ...int) ([]_C_int, error) { // Translate name to mib number. diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go b/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go new file mode 100644 index 0000000000..6a15cba611 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go @@ -0,0 +1,29 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,go1.12,!go1.13 + +package unix + +import ( + "unsafe" +) + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + // To implement this using libSystem we'd need syscall_syscallPtr for + // fdopendir. However, syscallPtr was only added in Go 1.13, so we fall + // back to raw syscalls for this func on Go 1.12. + var p unsafe.Pointer + if len(buf) > 0 { + p = unsafe.Pointer(&buf[0]) + } else { + p = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + n = int(r0) + if e1 != 0 { + return n, errnoErr(e1) + } + return n, nil +} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go b/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go new file mode 100644 index 0000000000..f911617be9 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go @@ -0,0 +1,101 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,go1.13 + +package unix + +import "unsafe" + +//sys closedir(dir uintptr) (err error) +//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) + +func fdopendir(fd int) (dir uintptr, err error) { + r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0) + dir = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_fdopendir_trampoline() + +//go:linkname libc_fdopendir libc_fdopendir +//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + // Simulate Getdirentries using fdopendir/readdir_r/closedir. + // We store the number of entries to skip in the seek + // offset of fd. See issue #31368. + // It's not the full required semantics, but should handle the case + // of calling Getdirentries or ReadDirent repeatedly. + // It won't handle assigning the results of lseek to *basep, or handle + // the directory being edited underfoot. + skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) + if err != nil { + return 0, err + } + + // We need to duplicate the incoming file descriptor + // because the caller expects to retain control of it, but + // fdopendir expects to take control of its argument. + // Just Dup'ing the file descriptor is not enough, as the + // result shares underlying state. Use Openat to make a really + // new file descriptor referring to the same directory. + fd2, err := Openat(fd, ".", O_RDONLY, 0) + if err != nil { + return 0, err + } + d, err := fdopendir(fd2) + if err != nil { + Close(fd2) + return 0, err + } + defer closedir(d) + + var cnt int64 + for { + var entry Dirent + var entryp *Dirent + e := readdir_r(d, &entry, &entryp) + if e != 0 { + return n, errnoErr(e) + } + if entryp == nil { + break + } + if skip > 0 { + skip-- + cnt++ + continue + } + reclen := int(entry.Reclen) + if reclen > len(buf) { + // Not enough room. Return for now. + // The counter will let us know where we should start up again. + // Note: this strategy for suspending in the middle and + // restarting is O(n^2) in the length of the directory. Oh well. + break + } + // Copy entry into return buffer. + s := struct { + ptr unsafe.Pointer + siz int + cap int + }{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen} + copy(buf, *(*[]byte)(unsafe.Pointer(&s))) + buf = buf[reclen:] + n += reclen + cnt++ + } + // Set the seek offset of the input fd to record + // how many files we've already returned. + _, err = Seek(fd, cnt, 0 /* SEEK_SET */) + if err != nil { + return n, err + } + + return n, nil +} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 216b4ac9e8..0a1cc74b3e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -89,7 +89,6 @@ func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } @@ -340,42 +339,7 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} @@ -498,7 +462,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go new file mode 100644 index 0000000000..6b223f91a5 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go @@ -0,0 +1,9 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,386,!go1.12 + +package unix + +//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go b/vendor/golang.org/x/sys/unix/syscall_darwin_386.go index 489726fa9b..707ba4f59a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_386.go @@ -10,6 +10,8 @@ import ( "syscall" ) +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: int32(sec), Nsec: int32(nsec)} } @@ -43,6 +45,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } @@ -56,7 +62,6 @@ const SYS___SYSCTL = SYS_SYSCTL //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 -//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go new file mode 100644 index 0000000000..68ebd6fab2 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go @@ -0,0 +1,9 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,amd64,!go1.12 + +package unix + +//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index 914b89bde5..fdbfb5911a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -10,6 +10,8 @@ import ( "syscall" ) +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} } @@ -43,6 +45,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } @@ -56,7 +62,6 @@ const SYS___SYSCTL = SYS_SYSCTL //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 -//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go new file mode 100644 index 0000000000..c81510da27 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,386,!go1.12 + +package unix + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + return 0, ENOSYS +} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go index 4a284cf502..f8bc4cfb1f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go @@ -8,6 +8,10 @@ import ( "syscall" ) +func ptrace(request int, pid int, addr uintptr, data uintptr) error { + return ENOTSUP +} + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: int32(sec), Nsec: int32(nsec)} } @@ -41,6 +45,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } @@ -58,7 +66,3 @@ const SYS___SYSCTL = SYS_SYSCTL //sys Lstat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - return 0, ENOSYS -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go new file mode 100644 index 0000000000..01d450406b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,arm64,!go1.12 + +package unix + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + return 0, ENOSYS +} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index 52dcd88f6b..5ede3ac316 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -10,6 +10,10 @@ import ( "syscall" ) +func ptrace(request int, pid int, addr uintptr, data uintptr) error { + return ENOTSUP +} + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} } @@ -43,6 +47,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } @@ -60,7 +68,3 @@ const SYS___SYSCTL = SYS_SYSCTL //sys Lstat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - return 0, ENOSYS -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go index 4b4ae460f2..f34c86c899 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go @@ -15,6 +15,7 @@ func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // 32-bit only func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) //go:linkname syscall_syscall syscall.syscall //go:linkname syscall_syscall6 syscall.syscall6 @@ -22,6 +23,7 @@ func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, er //go:linkname syscall_syscall9 syscall.syscall9 //go:linkname syscall_rawSyscall syscall.rawSyscall //go:linkname syscall_rawSyscall6 syscall.rawSyscall6 +//go:linkname syscall_syscallPtr syscall.syscallPtr // Find the entry point for f. See comments in runtime/proc.go for the // function of the same name. diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 260a400f91..8a195ae586 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -12,7 +12,25 @@ package unix -import "unsafe" +import ( + "sync" + "unsafe" +) + +// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h +var ( + osreldateOnce sync.Once + osreldate uint32 +) + +// First __DragonFly_version after September 2019 ABI changes +// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html +const _dragonflyABIChangeVersion = 500705 + +func supportsABI(ver uint32) bool { + osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") }) + return osreldate >= ver +} // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { @@ -150,42 +168,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error { err := sysctl(mib, old, oldlen, nil, 0) @@ -325,7 +308,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go index 9babb31ea7..a6b4830ac8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 329d240b90..34918d8ed7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -201,42 +201,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} @@ -497,8 +462,12 @@ func convertFromDirents11(buf []byte, old []byte) int { dstPos := 0 srcPos := 0 for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) { - dstDirent := (*Dirent)(unsafe.Pointer(&buf[dstPos])) - srcDirent := (*dirent_freebsd11)(unsafe.Pointer(&old[srcPos])) + var dstDirent Dirent + var srcDirent dirent_freebsd11 + + // If multiple direntries are written, sometimes when we reach the final one, + // we may have cap of old less than size of dirent_freebsd11. + copy((*[unsafe.Sizeof(srcDirent)]byte)(unsafe.Pointer(&srcDirent))[:], old[srcPos:]) reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8) if dstPos+reclen > len(buf) { @@ -514,6 +483,7 @@ func convertFromDirents11(buf []byte, old []byte) int { dstDirent.Pad1 = 0 copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen]) + copy(buf[dstPos:], (*[unsafe.Sizeof(dstDirent)]byte)(unsafe.Pointer(&dstDirent))[:]) padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen] for i := range padding { padding[i] = 0 @@ -688,7 +658,7 @@ func PtraceSingleStep(pid int) (err error) { //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go index 21e03958cd..dcc56457a0 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go index 9c945a6579..321c3baceb 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go index 5cd6243f2a..6977008313 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go index a318054878..dbbbfd6035 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 637b5017b8..26903bca8c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -71,6 +71,17 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { // ioctl itself should not be exposed directly, but additional get/set // functions for specific types are permissible. +// IoctlRetInt performs an ioctl operation specified by req on a device +// associated with opened file descriptor fd, and returns a non-negative +// integer that is returned by the ioctl syscall. +func IoctlRetInt(fd int, req uint) (int, error) { + ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0) + if err != 0 { + return 0, err + } + return int(ret), nil +} + // IoctlSetPointerInt performs an ioctl operation which sets an // integer value on fd, using the specified request number. The ioctl // argument is called with a pointer to the integer value, rather than @@ -80,52 +91,18 @@ func IoctlSetPointerInt(fd int, req uint, value int) error { return ioctl(fd, req, uintptr(unsafe.Pointer(&v))) } -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - func IoctlSetRTCTime(fd int, value *RTCTime) error { err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - func IoctlGetUint32(fd int, req uint) (uint32, error) { var value uint32 err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) return value, err } -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func IoctlGetRTCTime(fd int) (*RTCTime, error) { var value RTCTime err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) @@ -798,6 +775,70 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil } +// SockaddrTIPC implements the Sockaddr interface for AF_TIPC type sockets. +// For more information on TIPC, see: http://tipc.sourceforge.net/. +type SockaddrTIPC struct { + // Scope is the publication scopes when binding service/service range. + // Should be set to TIPC_CLUSTER_SCOPE or TIPC_NODE_SCOPE. + Scope int + + // Addr is the type of address used to manipulate a socket. Addr must be + // one of: + // - *TIPCSocketAddr: "id" variant in the C addr union + // - *TIPCServiceRange: "nameseq" variant in the C addr union + // - *TIPCServiceName: "name" variant in the C addr union + // + // If nil, EINVAL will be returned when the structure is used. + Addr TIPCAddr + + raw RawSockaddrTIPC +} + +// TIPCAddr is implemented by types that can be used as an address for +// SockaddrTIPC. It is only implemented by *TIPCSocketAddr, *TIPCServiceRange, +// and *TIPCServiceName. +type TIPCAddr interface { + tipcAddrtype() uint8 + tipcAddr() [12]byte +} + +func (sa *TIPCSocketAddr) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCSocketAddr{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCSocketAddr) tipcAddrtype() uint8 { return TIPC_SOCKET_ADDR } + +func (sa *TIPCServiceRange) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceRange{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCServiceRange) tipcAddrtype() uint8 { return TIPC_SERVICE_RANGE } + +func (sa *TIPCServiceName) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceName{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCServiceName) tipcAddrtype() uint8 { return TIPC_SERVICE_ADDR } + +func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Addr == nil { + return nil, 0, EINVAL + } + + sa.raw.Family = AF_TIPC + sa.raw.Scope = int8(sa.Scope) + sa.raw.Addrtype = sa.Addr.tipcAddrtype() + sa.raw.Addr = sa.Addr.tipcAddr() + + return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil +} + func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_NETLINK: @@ -843,7 +884,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] + bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] sa.Name = string(bytes) return sa, nil @@ -923,6 +964,27 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { break } } + return sa, nil + case AF_TIPC: + pp := (*RawSockaddrTIPC)(unsafe.Pointer(rsa)) + + sa := &SockaddrTIPC{ + Scope: int(pp.Scope), + } + + // Determine which union variant is present in pp.Addr by checking + // pp.Addrtype. + switch pp.Addrtype { + case TIPC_SERVICE_RANGE: + sa.Addr = (*TIPCServiceRange)(unsafe.Pointer(&pp.Addr)) + case TIPC_SERVICE_ADDR: + sa.Addr = (*TIPCServiceName)(unsafe.Pointer(&pp.Addr)) + case TIPC_SOCKET_ADDR: + sa.Addr = (*TIPCSocketAddr)(unsafe.Pointer(&pp.Addr)) + default: + return nil, EINVAL + } + return sa, nil } return nil, EAFNOSUPPORT @@ -1160,6 +1222,34 @@ func KeyctlDHCompute(params *KeyctlDHParams, buffer []byte) (size int, err error return keyctlDH(KEYCTL_DH_COMPUTE, params, buffer) } +// KeyctlRestrictKeyring implements the KEYCTL_RESTRICT_KEYRING command. This +// command limits the set of keys that can be linked to the keyring, regardless +// of keyring permissions. The command requires the "setattr" permission. +// +// When called with an empty keyType the command locks the keyring, preventing +// any further keys from being linked to the keyring. +// +// The "asymmetric" keyType defines restrictions requiring key payloads to be +// DER encoded X.509 certificates signed by keys in another keyring. Restrictions +// for "asymmetric" include "builtin_trusted", "builtin_and_secondary_trusted", +// "key_or_keyring:", and "key_or_keyring::chain". +// +// As of Linux 4.12, only the "asymmetric" keyType defines type-specific +// restrictions. +// +// See the full documentation at: +// http://man7.org/linux/man-pages/man3/keyctl_restrict_keyring.3.html +// http://man7.org/linux/man-pages/man2/keyctl.2.html +func KeyctlRestrictKeyring(ringid int, keyType string, restriction string) error { + if keyType == "" { + return keyctlRestrictKeyring(KEYCTL_RESTRICT_KEYRING, ringid) + } + return keyctlRestrictKeyringByType(KEYCTL_RESTRICT_KEYRING, ringid, keyType, restriction) +} + +//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL +//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL + func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { var msg Msghdr var rsa RawSockaddrAny @@ -1403,8 +1493,12 @@ func PtraceSyscall(pid int, signal int) (err error) { func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } +func PtraceInterrupt(pid int) (err error) { return ptrace(PTRACE_INTERRUPT, pid, 0, 0) } + func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } +func PtraceSeize(pid int) (err error) { return ptrace(PTRACE_SEIZE, pid, 0, 0) } + func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) @@ -1761,6 +1855,17 @@ func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err erro return openByHandleAt(mountFD, handle.fileHandle, flags) } +// Klogset wraps the sys_syslog system call; it sets console_loglevel to +// the value specified by arg and passes a dummy pointer to bufp. +func Klogset(typ int, arg int) (err error) { + var p unsafe.Pointer + _, _, errno := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(p), uintptr(arg)) + if errno != 0 { + return errnoErr(errno) + } + return nil +} + /* * Unimplemented */ diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index e2f8cf6e5a..e7fa665e68 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -372,6 +372,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 87a30744d6..088ce0f935 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -163,6 +163,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index f626794439..11930fc8fa 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -252,6 +252,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } 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 cb20b15d5d..251e2d9715 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -180,6 +180,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index b3b21ec1e2..7562fe97b8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -208,6 +208,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 5144d4e133..a939ff8f21 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -220,6 +220,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 0a100b66a3..28d6d0f229 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -91,6 +91,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 6230f64052..6798c26258 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -179,6 +179,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index f81dbdc9c8..eb5cb1a71d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -120,6 +120,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index b69565616f..37321c12ef 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -107,6 +107,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 5ef3090401..211131d9cf 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -187,42 +187,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func IoctlGetPtmget(fd int, req uint) (*Ptmget, error) { var value Ptmget @@ -365,7 +330,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go index 24f74e58ce..24da8b5245 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go index 6878bf7ff9..25a0ac8258 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go index dbbfcf71db..21591ecd4d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go index f3434465a1..8047496350 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 1a074b2fe1..92ed67de0b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -178,42 +178,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) @@ -340,7 +305,7 @@ func Uname(uname *Utsname) error { //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index d62da60d1f..42b5a0e51e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go index 9a35334cba..6ea4b48831 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 5d812aaea5..1c3d26fa2c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go index 0fb39cf5eb..a8c458cb03 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 0153a316dd..0e2a696ad3 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -391,7 +391,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] + bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] sa.Name = string(bytes) return sa, nil @@ -553,40 +553,10 @@ func Minor(dev uint64) uint32 { //sys ioctl(fd int, req uint, arg uintptr) (err error) -func IoctlSetInt(fd int, req uint, value int) (err error) { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - func IoctlSetTermio(fd int, req uint, value *Termio) (err error) { return ioctl(fd, req, uintptr(unsafe.Pointer(value))) } -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func IoctlGetTermio(fd int, req uint) (*Termio, error) { var value Termio err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) @@ -679,7 +649,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go index 91c32ddf02..b22a34d7ae 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -18,6 +18,10 @@ func (iov *Iovec) SetLen(length int) { iov.Len = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/types_aix.go b/vendor/golang.org/x/sys/unix/types_aix.go deleted file mode 100644 index 40d2beede5..0000000000 --- a/vendor/golang.org/x/sys/unix/types_aix.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore -// +build aix - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - - -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -type off64 C.off64_t -type off C.off_t -type Mode_t C.mode_t - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -type Timex C.struct_timex - -type Time_t C.time_t - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -type Timezone C.struct_timezone - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit64 - -type Pid_t C.pid_t - -type _Gid_t C.gid_t - -type dev_t C.dev_t - -// Files - -type Stat_t C.struct_stat - -type StatxTimestamp C.struct_statx_timestamp - -type Statx_t C.struct_statx - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Cmsghdr C.struct_cmsghdr - -type ICMPv6Filter C.struct_icmp6_filter - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type Linger C.struct_linger - -type Msghdr C.struct_msghdr - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr -) - -type IfMsgHdr C.struct_if_msghdr - -// Misc - -type FdSet C.fd_set - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -type Sigset_t C.sigset_t - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// Terminal handling - -type Termios C.struct_termios - -type Termio C.struct_termio - -type Winsize C.struct_winsize - -//poll - -type PollFd struct { - Fd int32 - Events uint16 - Revents uint16 -} - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -//flock_t - -type Flock_t C.struct_flock64 - -// Statfs - -type Fsid_t C.struct_fsid_t -type Fsid64_t C.struct_fsid64_t - -type Statfs_t C.struct_statfs - -const RNDGETENTCNT = 0x80045200 diff --git a/vendor/golang.org/x/sys/unix/types_darwin.go b/vendor/golang.org/x/sys/unix/types_darwin.go deleted file mode 100644 index 155c2e692b..0000000000 --- a/vendor/golang.org/x/sys/unix/types_darwin.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define __DARWIN_UNIX03 0 -#define KERNEL -#define _DARWIN_USE_64_BIT_INODE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat64 - -type Statfs_t C.struct_statfs64 - -type Flock_t C.struct_flock - -type Fstore_t C.struct_fstore - -type Radvisory_t C.struct_radvisory - -type Fbootstraptransfer_t C.struct_fbootstraptransfer - -type Log2phys_t C.struct_log2phys - -type Fsid C.struct_fsid - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet4Pktinfo C.struct_in_pktinfo - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfmaMsghdr2 C.struct_ifma_msghdr2 - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// uname - -type Utsname C.struct_utsname - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_dragonfly.go b/vendor/golang.org/x/sys/unix/types_dragonfly.go deleted file mode 100644 index 3365dd79d0..0000000000 --- a/vendor/golang.org/x/sys/unix/types_dragonfly.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.struct_fsid - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Uname - -type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go deleted file mode 100644 index a121dc3368..0000000000 --- a/vendor/golang.org/x/sys/unix/types_freebsd.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define _WANT_FREEBSD11_STAT 1 -#define _WANT_FREEBSD11_STATFS 1 -#define _WANT_FREEBSD11_DIRENT 1 -#define _WANT_FREEBSD11_KEVENT 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -// This structure is a duplicate of if_data on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_data8 { - u_char ifi_type; - u_char ifi_physical; - u_char ifi_addrlen; - u_char ifi_hdrlen; - u_char ifi_link_state; - u_char ifi_spare_char1; - u_char ifi_spare_char2; - u_char ifi_datalen; - u_long ifi_mtu; - u_long ifi_metric; - u_long ifi_baudrate; - u_long ifi_ipackets; - u_long ifi_ierrors; - u_long ifi_opackets; - u_long ifi_oerrors; - u_long ifi_collisions; - u_long ifi_ibytes; - u_long ifi_obytes; - u_long ifi_imcasts; - u_long ifi_omcasts; - u_long ifi_iqdrops; - u_long ifi_noproto; - u_long ifi_hwassist; -// FIXME: these are now unions, so maybe need to change definitions? -#undef ifi_epoch - time_t ifi_epoch; -#undef ifi_lastchange - struct timeval ifi_lastchange; -}; - -// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_msghdr8 { - u_short ifm_msglen; - u_char ifm_version; - u_char ifm_type; - int ifm_addrs; - int ifm_flags; - u_short ifm_index; - struct if_data8 ifm_data; -}; -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( - _statfsVersion = C.STATFS_VERSION - _dirblksiz = C.DIRBLKSIZ -) - -type Stat_t C.struct_stat - -type stat_freebsd11_t C.struct_freebsd11_stat - -type Statfs_t C.struct_statfs - -type statfs_freebsd11_t C.struct_freebsd11_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type dirent_freebsd11 C.struct_freebsd11_dirent - -type Fsid C.struct_fsid - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPMreqn C.struct_ip_mreqn - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPMreqn = C.sizeof_struct_ip_mreqn - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_ATTACH = C.PT_ATTACH - PTRACE_CONT = C.PT_CONTINUE - PTRACE_DETACH = C.PT_DETACH - PTRACE_GETFPREGS = C.PT_GETFPREGS - PTRACE_GETFSBASE = C.PT_GETFSBASE - PTRACE_GETLWPLIST = C.PT_GETLWPLIST - PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS - PTRACE_GETREGS = C.PT_GETREGS - PTRACE_GETXSTATE = C.PT_GETXSTATE - PTRACE_IO = C.PT_IO - PTRACE_KILL = C.PT_KILL - PTRACE_LWPEVENTS = C.PT_LWP_EVENTS - PTRACE_LWPINFO = C.PT_LWPINFO - PTRACE_SETFPREGS = C.PT_SETFPREGS - PTRACE_SETREGS = C.PT_SETREGS - PTRACE_SINGLESTEP = C.PT_STEP - PTRACE_TRACEME = C.PT_TRACE_ME -) - -const ( - PIOD_READ_D = C.PIOD_READ_D - PIOD_WRITE_D = C.PIOD_WRITE_D - PIOD_READ_I = C.PIOD_READ_I - PIOD_WRITE_I = C.PIOD_WRITE_I -) - -const ( - PL_FLAG_BORN = C.PL_FLAG_BORN - PL_FLAG_EXITED = C.PL_FLAG_EXITED - PL_FLAG_SI = C.PL_FLAG_SI -) - -const ( - TRAP_BRKPT = C.TRAP_BRKPT - TRAP_TRACE = C.TRAP_TRACE -) - -type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo - -type __Siginfo C.struct___siginfo - -type Sigset_t C.sigset_t - -type Reg C.struct_reg - -type FpReg C.struct_fpreg - -type PtraceIoDesc C.struct_ptrace_io_desc - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent_freebsd11 - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - sizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 - sizeofIfData = C.sizeof_struct_if_data - SizeofIfData = C.sizeof_struct_if_data8 - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type ifMsghdr C.struct_if_msghdr - -type IfMsghdr C.struct_if_msghdr8 - -type ifData C.struct_if_data - -type IfData C.struct_if_data8 - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr - SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfZbuf C.struct_bpf_zbuf - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfZbufHeader C.struct_bpf_zbuf_header - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLINIGNEOF = C.POLLINIGNEOF - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Capabilities - -type CapRights C.struct_cap_rights - -// Uname - -type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_netbsd.go b/vendor/golang.org/x/sys/unix/types_netbsd.go deleted file mode 100644 index 4a96d72c37..0000000000 --- a/vendor/golang.org/x/sys/unix/types_netbsd.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -type Ptmget C.struct_ptmget - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Sysctl - -type Sysctlnode C.struct_sysctlnode - -// Uname - -type Utsname C.struct_utsname - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go deleted file mode 100644 index 775cb57dc8..0000000000 --- a/vendor/golang.org/x/sys/unix/types_openbsd.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// File system limits - -const ( - PathMax = C.PATH_MAX -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios - -type Winsize C.struct_winsize - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) - -// Signal Sets - -type Sigset_t C.sigset_t - -// Uname - -type Utsname C.struct_utsname - -// Uvmexp - -const SizeofUvmexp = C.sizeof_struct_uvmexp - -type Uvmexp C.struct_uvmexp - -// Clockinfo - -const SizeofClockinfo = C.sizeof_struct_clockinfo - -type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go deleted file mode 100644 index 2b716f9348..0000000000 --- a/vendor/golang.org/x/sys/unix/types_solaris.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See README.md -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -// These defines ensure that builds done on newer versions of Solaris are -// backwards-compatible with older versions of Solaris and -// OpenSolaris-based derivatives. -#define __USE_SUNOS_SOCKETS__ // msghdr -#define __USE_LEGACY_PROTOTYPES__ // iovec -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics - -const ( - SizeofPtr = C.sizeofPtr - SizeofShort = C.sizeof_short - SizeofInt = C.sizeof_int - SizeofLong = C.sizeof_long - SizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX - MaxHostNameLen = C.MAXHOSTNAMELEN -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -// Filesystems - -type _Fsblkcnt_t C.fsblkcnt_t - -type Statvfs_t C.struct_statvfs - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Select - -type FdSet C.fd_set - -// Misc - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_EACCESS = C.AT_EACCESS -) - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfTimeval C.struct_bpf_timeval - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -type Termio C.struct_termio - -type Winsize C.struct_winsize - -// poll - -type PollFd C.struct_pollfd - -const ( - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLIN = C.POLLIN - POLLNVAL = C.POLLNVAL - POLLOUT = C.POLLOUT - POLLPRI = C.POLLPRI - POLLRDBAND = C.POLLRDBAND - POLLRDNORM = C.POLLRDNORM - POLLWRBAND = C.POLLWRBAND - POLLWRNORM = C.POLLWRNORM -) diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go index 3b39d7408a..6217cdba57 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go @@ -3,7 +3,7 @@ // +build 386,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index 8fe5547775..e3ff2ee3d4 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -3,7 +3,7 @@ // +build amd64,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go index 7a977770d0..3e417571a9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go @@ -3,7 +3,7 @@ // +build arm,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index 6d56d8a059..cbd8ed18b9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -3,7 +3,7 @@ // +build arm64,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index bbe6089bb7..6130471748 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -938,6 +938,7 @@ const ( NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 NET_RT_MAXID = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index d2bbaabc87..b72544fcd2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -3,7 +3,7 @@ // +build 386,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -1055,6 +1055,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index 4f8db783d3..9f382678e5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1056,6 +1056,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index 53e5de6051..16db56abc4 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -3,7 +3,7 @@ // +build arm,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go package unix @@ -1063,6 +1063,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index d4a192fefe..1a1de34543 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -3,7 +3,7 @@ // +build arm64,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1056,6 +1056,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 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 5213d820a9..97332d03c3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -722,6 +732,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -987,6 +998,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1085,6 +1097,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1097,6 +1120,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1342,6 +1367,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1406,6 +1432,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1701,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1686,6 +1718,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1724,6 +1757,10 @@ const ( PTRACE_SINGLEBLOCK = 0x21 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 @@ -1784,7 +1821,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1894,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1919,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1927,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1939,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1948,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2034,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2174,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2432,6 +2475,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2445,7 +2553,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2644,6 +2752,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2660,6 +2770,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 39b630cc51..d81d30b732 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -722,6 +732,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -987,6 +998,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1085,6 +1097,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1097,6 +1120,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1342,6 +1367,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1406,6 +1432,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1672,6 +1702,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1687,6 +1719,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1725,6 +1758,10 @@ const ( PTRACE_SINGLEBLOCK = 0x21 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 @@ -1785,7 +1822,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1858,6 +1895,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1882,6 +1920,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1889,7 +1928,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1901,6 +1940,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1909,8 +1949,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1995,6 +2035,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2133,6 +2175,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2433,6 +2476,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2446,7 +2554,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2644,6 +2752,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2660,6 +2770,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 c59a1beb36..0d22b52b6e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1722,7 @@ const ( PTRACE_GETSIGMASK = 0x420a PTRACE_GETVFPREGS = 0x1b PTRACE_GETWMMXREGS = 0x12 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x16 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1730,6 +1763,10 @@ const ( PTRACE_SET_SYSCALL = 0x17 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 PT_DATA_ADDR = 0x10004 PT_TEXT_ADDR = 0x10000 @@ -1791,7 +1828,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1864,6 +1901,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1888,6 +1926,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1895,7 +1934,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1907,6 +1946,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1915,8 +1955,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2001,6 +2041,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2139,6 +2181,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2439,6 +2482,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2452,7 +2560,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2650,6 +2758,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2666,6 +2776,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 5f35c19d14..0a0267d7d3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -561,6 +570,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -724,6 +734,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -989,6 +1000,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1087,6 +1099,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1099,6 +1122,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1343,6 +1368,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1407,6 +1433,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1672,6 +1702,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1685,6 +1717,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1717,6 +1750,12 @@ const ( PTRACE_SETSIGMASK = 0x420b PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 + PTRACE_SYSEMU = 0x1f + PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1775,7 +1814,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1848,6 +1887,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1872,6 +1912,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1879,7 +1920,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1891,6 +1932,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1899,8 +1941,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1985,6 +2027,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2123,6 +2167,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2424,6 +2469,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2437,7 +2547,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2635,6 +2745,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2651,6 +2763,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 7f1b7bef28..33dd99eeb8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1715,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1759,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1821,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1894,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1919,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1927,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1939,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1948,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2034,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2174,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2477,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2555,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2754,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2772,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 603d88b8bb..b7040c9bc5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1715,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1759,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1821,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1894,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1919,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1927,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1939,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1948,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2034,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2174,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2477,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2555,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2754,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2772,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 ed178f8a72..e0e89aa54e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1715,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1759,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1821,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1894,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1919,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1927,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1939,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1948,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2034,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2174,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2477,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2555,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2754,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2772,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 080b789335..fc68959112 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1715,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1759,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1821,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1894,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1919,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1927,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1939,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1948,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2034,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2174,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2477,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2555,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2754,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2772,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 961e8eabef..bd64b9a91d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1339,6 +1364,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1405,6 +1431,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80000000 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1701,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1722,7 @@ const ( PTRACE_GETVRREGS = 0x12 PTRACE_GETVSRREGS = 0x1b PTRACE_GET_DEBUGREG = 0x19 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1762,10 @@ const ( PTRACE_SINGLEBLOCK = 0x100 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1d PTRACE_SYSEMU_SINGLESTEP = 0x1e PTRACE_TRACEME = 0x0 @@ -1842,7 +1879,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1915,6 +1952,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1939,6 +1977,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1946,7 +1985,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1958,6 +1997,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1966,8 +2006,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2052,6 +2092,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2190,6 +2232,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2494,6 +2537,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x400000 TPACKET_ALIGNMENT = 0x10 @@ -2507,7 +2615,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2705,6 +2813,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2721,6 +2831,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0xc00 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 6e0538f224..d9ec0566a9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1339,6 +1364,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1405,6 +1431,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80000000 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1701,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1722,7 @@ const ( PTRACE_GETVRREGS = 0x12 PTRACE_GETVSRREGS = 0x1b PTRACE_GET_DEBUGREG = 0x19 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1762,10 @@ const ( PTRACE_SINGLEBLOCK = 0x100 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1d PTRACE_SYSEMU_SINGLESTEP = 0x1e PTRACE_TRACEME = 0x0 @@ -1842,7 +1879,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1915,6 +1952,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1939,6 +1977,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1946,7 +1985,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1958,6 +1997,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1966,8 +2006,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2052,6 +2092,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2190,6 +2232,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2494,6 +2537,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x400000 TPACKET_ALIGNMENT = 0x10 @@ -2507,7 +2615,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2705,6 +2813,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2721,6 +2831,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0xc00 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 06c0148c17..ac8a4983b4 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1699,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1682,6 +1714,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1714,6 +1747,10 @@ const ( PTRACE_SETSIGMASK = 0x420b PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1772,7 +1809,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1845,6 +1882,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1869,6 +1907,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1876,7 +1915,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1888,6 +1927,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1896,8 +1936,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1982,6 +2022,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2120,6 +2162,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2420,6 +2463,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2433,7 +2541,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2631,6 +2739,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2647,6 +2757,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 39875095c6..452eeb048a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -459,7 +461,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +569,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +731,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +997,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1096,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1119,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1365,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1430,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1701,8 @@ const ( PTRACE_DETACH = 0x11 PTRACE_DISABLE_TE = 0x5010 PTRACE_ENABLE_TE = 0x5009 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1685,6 +1717,7 @@ const ( PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a PTRACE_GET_LAST_BREAK = 0x5006 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1728,6 +1761,10 @@ const ( PTRACE_SINGLEBLOCK = 0xc PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TE_ABORT_RAND = 0x5011 PTRACE_TRACEME = 0x0 PT_ACR0 = 0x90 @@ -1845,7 +1882,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1918,6 +1955,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1942,6 +1980,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1949,7 +1988,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1961,6 +2000,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1969,8 +2009,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2055,6 +2095,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2193,6 +2235,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2493,6 +2536,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2506,7 +2614,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2704,6 +2812,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2720,6 +2830,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) 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 8d80f99bc0..e93c0c8315 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -256,6 +256,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -307,9 +308,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -462,7 +464,14 @@ const ( CSUSP = 0x1a DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 + DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d + DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" + DEVLINK_GENL_NAME = "devlink" + DEVLINK_GENL_VERSION = 0x1 + DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -564,6 +573,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -725,6 +735,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x1 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -990,6 +1001,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1088,6 +1100,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1100,6 +1123,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1344,6 +1369,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1408,6 +1434,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1673,6 +1703,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1722,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1762,10 @@ const ( PTRACE_SINGLESTEP = 0x9 PTRACE_SPARC_DETACH = 0xb PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 PTRACE_WRITEDATA = 0x11 PTRACE_WRITETEXT = 0x13 @@ -1837,7 +1874,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1910,6 +1947,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1934,6 +1972,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1941,7 +1980,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1953,6 +1992,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1961,8 +2001,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2047,6 +2087,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2185,6 +2227,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x47 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2482,6 +2525,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x20005437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2495,7 +2603,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2693,6 +2801,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2709,6 +2819,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 __TIOCFLUSH = 0x80047410 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go index 78cc04ea6d..96b9b8ab30 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -3,7 +3,7 @@ // +build 386,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -1085,6 +1085,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index 92185e693f..ed522a84e8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1075,6 +1075,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go index 373ad4543d..c8d36fe998 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -3,7 +3,7 @@ // +build arm,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -marm _const.go package unix @@ -1065,6 +1065,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go index fb6c60441d..f1c146a74c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go @@ -3,7 +3,7 @@ // +build arm64,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1075,6 +1075,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index d8be045189..5402bd55ce 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -3,7 +3,7 @@ // +build 386,openbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -881,14 +881,15 @@ const ( MADV_SPACEAVAIL = 0x5 MADV_WILLNEED = 0x3 MAP_ANON = 0x1000 - MAP_COPY = 0x4 + MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 + MAP_COPY = 0x2 MAP_FILE = 0x0 MAP_FIXED = 0x10 - MAP_FLAGMASK = 0x1ff7 - MAP_HASSEMAPHORE = 0x200 - MAP_INHERIT = 0x80 + MAP_FLAGMASK = 0xfff7 + MAP_HASSEMAPHORE = 0x0 + MAP_INHERIT = 0x0 MAP_INHERIT_COPY = 0x1 - MAP_INHERIT_DONATE_COPY = 0x3 MAP_INHERIT_NONE = 0x2 MAP_INHERIT_SHARE = 0x0 MAP_NOEXTEND = 0x100 @@ -896,7 +897,8 @@ const ( MAP_PRIVATE = 0x2 MAP_RENAME = 0x20 MAP_SHARED = 0x1 - MAP_TRYFIXED = 0x400 + MAP_STACK = 0x4000 + MAP_TRYFIXED = 0x0 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MNT_ASYNC = 0x40 @@ -946,6 +948,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index 1f9e8a29ea..ffaf2d2f9f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,openbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -920,10 +920,11 @@ const ( MADV_WILLNEED = 0x3 MAP_ANON = 0x1000 MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 MAP_COPY = 0x2 MAP_FILE = 0x0 MAP_FIXED = 0x10 - MAP_FLAGMASK = 0x7ff7 + MAP_FLAGMASK = 0xfff7 MAP_HASSEMAPHORE = 0x0 MAP_INHERIT = 0x0 MAP_INHERIT_COPY = 0x1 @@ -990,6 +991,7 @@ const ( NET_RT_MAXID = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 79d5695c37..7aa796a642 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -1,11 +1,11 @@ // mkerrors.sh // Code generated by the command above; see README.md. DO NOT EDIT. -// Created by cgo -godefs - DO NOT EDIT -// cgo -godefs -- _const.go - // +build arm,openbsd +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs -- _const.go + package unix import "syscall" @@ -881,10 +881,11 @@ const ( MADV_WILLNEED = 0x3 MAP_ANON = 0x1000 MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 MAP_COPY = 0x2 MAP_FILE = 0x0 MAP_FIXED = 0x10 - MAP_FLAGMASK = 0x3ff7 + MAP_FLAGMASK = 0xfff7 MAP_HASSEMAPHORE = 0x0 MAP_INHERIT = 0x0 MAP_INHERIT_COPY = 0x1 @@ -896,6 +897,7 @@ const ( MAP_PRIVATE = 0x2 MAP_RENAME = 0x0 MAP_SHARED = 0x1 + MAP_STACK = 0x4000 MAP_TRYFIXED = 0x0 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 @@ -947,6 +949,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go index ec5f92de88..1792d3f13e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go @@ -996,6 +996,7 @@ const ( NET_RT_MAXID = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 22569db31d..46e054ccb0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -3,7 +3,7 @@ // +build amd64,solaris -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -666,6 +666,7 @@ const ( M_FLUSH = 0x86 NAME_MAX = 0xff NEWDEV = 0x1 + NFDBITS = 0x40 NL0 = 0x0 NL1 = 0x100 NLDLY = 0x100 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go index c4ec7ff87c..b5ed805899 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -l32 -tags darwin,386,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.go +// go run mksyscall.go -l32 -tags darwin,386,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.1_11.go syscall_darwin_386.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build darwin,386,!go1.12 @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -573,6 +547,22 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) if e1 != 0 { @@ -1352,8 +1342,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -1691,6 +1682,33 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) sec = int32(r0) @@ -1738,23 +1756,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go new file mode 100644 index 0000000000..e263fbdb8b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go @@ -0,0 +1,41 @@ +// go run mksyscall.go -l32 -tags darwin,386,go1.13 syscall_darwin.1_13.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build darwin,386,go1.13 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_closedir_trampoline() + +//go:linkname libc_closedir libc_closedir +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +func libc_readdir_r_trampoline() + +//go:linkname libc_readdir_r libc_readdir_r +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s new file mode 100644 index 0000000000..00da1ebfca --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s @@ -0,0 +1,12 @@ +// go run mkasm_darwin.go 386 +// Code generated by the command above; DO NOT EDIT. + +// +build go1.13 + +#include "textflag.h" +TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go index 23346dc68f..cdf8a70002 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -793,6 +757,27 @@ func libc_ioctl_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_sysctl_trampoline() + +//go:linkname libc_sysctl libc_sysctl +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall9(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) if e1 != 0 { @@ -943,6 +928,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1872,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -2341,6 +2342,21 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) sec = int32(r0) @@ -2408,28 +2424,6 @@ func libc_fstatfs64_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___getdirentries64_trampoline() - -//go:linkname libc___getdirentries64 libc___getdirentries64 -//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s index 37b85b4f61..9cae5b1da3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -92,6 +88,8 @@ TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 JMP libc_kill(SB) TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 JMP libc_ioctl(SB) +TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 @@ -264,6 +262,8 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 JMP libc_gettimeofday(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 @@ -272,8 +272,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstatat64(SB) TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstatfs64(SB) -TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0 - JMP libc___getdirentries64(SB) TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat64(SB) TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go index 2581e8960f..8bde8235a0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags darwin,amd64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.go +// go run mksyscall.go -tags darwin,amd64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.1_11.go syscall_darwin_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build darwin,amd64,!go1.12 @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -573,6 +547,22 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { @@ -1352,8 +1342,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -1691,6 +1682,33 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) sec = int64(r0) @@ -1738,23 +1756,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go new file mode 100644 index 0000000000..314042a9d4 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go @@ -0,0 +1,41 @@ +// go run mksyscall.go -tags darwin,amd64,go1.13 syscall_darwin.1_13.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build darwin,amd64,go1.13 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_closedir_trampoline() + +//go:linkname libc_closedir libc_closedir +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +func libc_readdir_r_trampoline() + +//go:linkname libc_readdir_r libc_readdir_r +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s new file mode 100644 index 0000000000..d671e8311f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s @@ -0,0 +1,12 @@ +// go run mkasm_darwin.go amd64 +// Code generated by the command above; DO NOT EDIT. + +// +build go1.13 + +#include "textflag.h" +TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index c142e33e92..63b51fbf00 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -793,6 +757,27 @@ func libc_ioctl_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_sysctl_trampoline() + +//go:linkname libc_sysctl libc_sysctl +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { @@ -1887,8 +1872,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -2356,6 +2342,21 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) sec = int64(r0) @@ -2423,28 +2424,6 @@ func libc_fstatfs64_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___getdirentries64_trampoline() - -//go:linkname libc___getdirentries64 libc___getdirentries64 -//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 1a3915197d..1a0e52aa20 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -92,6 +88,8 @@ TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 JMP libc_kill(SB) TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 JMP libc_ioctl(SB) +TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 @@ -266,6 +264,8 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 JMP libc_gettimeofday(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 @@ -274,8 +274,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstatat64(SB) TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstatfs64(SB) -TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0 - JMP libc___getdirentries64(SB) TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat64(SB) TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go index f8caecef02..63a236b504 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -l32 -tags darwin,arm,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.go +// go run mksyscall.go -l32 -tags darwin,arm,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.1_11.go syscall_darwin_arm.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build darwin,arm,!go1.12 @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -573,6 +547,22 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) if e1 != 0 { @@ -1352,8 +1342,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go new file mode 100644 index 0000000000..f519ce9afb --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go @@ -0,0 +1,41 @@ +// go run mksyscall.go -l32 -tags darwin,arm,go1.13 syscall_darwin.1_13.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build darwin,arm,go1.13 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_closedir_trampoline() + +//go:linkname libc_closedir libc_closedir +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +func libc_readdir_r_trampoline() + +//go:linkname libc_readdir_r libc_readdir_r +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s new file mode 100644 index 0000000000..488e55707a --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s @@ -0,0 +1,12 @@ +// go run mkasm_darwin.go arm +// Code generated by the command above; DO NOT EDIT. + +// +build go1.13 + +#include "textflag.h" +TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go index 01cffbf46c..adb8668c2b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -793,6 +757,27 @@ func libc_ioctl_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_sysctl_trampoline() + +//go:linkname libc_sysctl libc_sysctl +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall9(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) if e1 != 0 { @@ -943,6 +928,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1872,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s index 994056f359..5bebb1bbd0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -108,6 +104,8 @@ TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 JMP libc_chown(SB) TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 JMP libc_chroot(SB) +TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 JMP libc_close(SB) TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go index 3fd0f3c854..87c0b61221 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags darwin,arm64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.go +// go run mksyscall.go -tags darwin,arm64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.1_11.go syscall_darwin_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. // +build darwin,arm64,!go1.12 @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -573,6 +547,22 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { @@ -1352,8 +1342,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go new file mode 100644 index 0000000000..d64e6c806f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go @@ -0,0 +1,41 @@ +// go run mksyscall.go -tags darwin,arm64,go1.13 syscall_darwin.1_13.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build darwin,arm64,go1.13 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_closedir_trampoline() + +//go:linkname libc_closedir libc_closedir +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +func libc_readdir_r_trampoline() + +//go:linkname libc_readdir_r libc_readdir_r +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s new file mode 100644 index 0000000000..b29dabb0f0 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s @@ -0,0 +1,12 @@ +// go run mkasm_darwin.go arm64 +// Code generated by the command above; DO NOT EDIT. + +// +build go1.13 + +#include "textflag.h" +TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 8f2691deea..c882a4f9d2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -793,6 +757,27 @@ func libc_ioctl_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_sysctl_trampoline() + +//go:linkname libc_sysctl libc_sysctl +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { @@ -943,6 +928,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1872,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 61dc0d4c12..19faa4d8d6 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -92,6 +88,8 @@ TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 JMP libc_kill(SB) TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 JMP libc_ioctl(SB) +TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index cdfe9318ba..df199b3454 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -1272,8 +1272,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index a783306b2a..e68185f1e3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index f995520d38..2f77f93c4e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,8 +361,14 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } @@ -387,8 +377,8 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -424,6 +414,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index d681acd430..e9a12c9d93 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,8 +361,14 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } @@ -387,8 +377,8 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -424,6 +414,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go index 5049b2ede4..27ab0fbda0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { @@ -404,8 +404,8 @@ func Getcwd(buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -414,8 +414,8 @@ func ptrace(request int, pid int, addr uintptr, data int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index c5e46e4cf6..fe5d462e49 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index da8819e480..536abcea33 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 6ad9be6dd4..37823cd6bf 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { 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 f88331782b..794f61264a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 8eebc6c77c..1b34b550c3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index ecf62a677d..5714e25922 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 1ba0f7b6f4..88a6b3362f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 20012b2f0e..c09dbe3454 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index 2b520deaa2..42f6c21039 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index d9f044c953..de2cd8db91 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 9feed65eb0..d51bf07fc5 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 0a65150881..1e3a3cb732 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index e27f66930c..3c97008cd0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 7e05826647..5ade42cce0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index d94d076aa0..3e0bbc5f10 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index cf5bf3d054..cb0af13a3c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index 243a9317cf..6fd48d3dcd 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index a9532d0787..2938e4124e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 0cb9f01774..22b79ab0e2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 6fc99b5494..cb921f37af 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index 27878a72b8..5a74380355 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 5f614760c6..a96165d4bf 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -1478,8 +1478,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = 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 e869c06031..7aae554f21 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -429,4 +429,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 4917b8ab6d..7968439a92 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -351,4 +351,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 f85fcb4f80..3c663c69d4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 678a119bc9..753def987e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -296,4 +296,5 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 ) 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 222c9f9a2f..ac86bd5446 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -414,4 +414,5 @@ const ( SYS_FSCONFIG = 4431 SYS_FSMOUNT = 4432 SYS_FSPICK = 4433 + SYS_PIDFD_OPEN = 4434 ) 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 28e6d0e9d6..1f5705b588 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -344,4 +344,5 @@ const ( SYS_FSCONFIG = 5431 SYS_FSMOUNT = 5432 SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 ) 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 e643c6f632..d9ed953264 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -344,4 +344,5 @@ const ( SYS_FSCONFIG = 5431 SYS_FSMOUNT = 5432 SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 ) 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 01d93c420f..94266b65a4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -414,4 +414,5 @@ const ( SYS_FSCONFIG = 4431 SYS_FSMOUNT = 4432 SYS_FSPICK = 4433 + SYS_PIDFD_OPEN = 4434 ) 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 5744149ebf..52e3da6490 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 21c8320428..6141f90a82 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 c1bb6d8f2d..4f7261a884 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -295,4 +295,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 bc3cc6b5b2..f47014ac05 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -358,4 +358,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) 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 0a2841ba8c..dd78abb0d6 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -373,4 +373,5 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 1542a87734..c681d7dbcd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -397,7 +397,7 @@ type Reg struct { } type FpReg struct { - Fp_q [32]uint128 + Fp_q [512]uint8 Fp_sr uint32 Fp_cr uint32 } 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 50bc4128ff..2c94373ea5 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -425,6 +432,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -591,22 +599,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -614,6 +606,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -664,6 +657,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2468,6 +2468,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2521,3 +2557,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 055eaa76a4..1eedcb2386 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -426,6 +433,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -592,22 +600,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -615,6 +607,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -665,6 +658,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2481,6 +2481,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2535,3 +2571,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 66019c9cfe..35ef7b35d9 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -289,6 +289,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -429,6 +436,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -595,22 +603,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -618,6 +610,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -668,6 +661,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2459,6 +2459,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2512,3 +2548,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 3104798c40..054b1870ea 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -593,22 +601,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -616,6 +608,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +659,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2460,6 +2460,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2514,3 +2550,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 46c86021b7..615ea3ef97 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -288,6 +288,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -594,22 +602,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -617,6 +609,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +660,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2465,6 +2465,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2518,3 +2554,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 c2fe1a62a6..81a818b09d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -593,22 +601,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -616,6 +608,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +659,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2462,6 +2462,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2516,3 +2552,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 f1eb0d3979..214e345b7c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -593,22 +601,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -616,6 +608,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +659,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2462,6 +2462,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2516,3 +2552,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 8759bc36b8..9741cff6c4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -288,6 +288,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -594,22 +602,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -617,6 +609,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +660,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2465,6 +2465,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2518,3 +2554,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 a812005412..123e875041 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -287,6 +287,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -594,22 +602,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -617,6 +609,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +660,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2470,6 +2470,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2524,3 +2560,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 74b7a9199b..c9ca0a286d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -287,6 +287,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -594,22 +602,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -617,6 +609,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +660,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2470,6 +2470,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2524,3 +2560,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 8344583e73..9b205aa1a4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -593,22 +601,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -616,6 +608,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +659,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -808,6 +808,7 @@ type Ustat_t struct { type EpollEvent struct { Events uint32 + _ int32 Fd int32 Pad int32 } @@ -2487,6 +2488,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2541,3 +2578,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 d8fc0bc1cd..9a95c5b9f5 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -426,6 +433,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -592,22 +600,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -615,6 +607,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -665,6 +658,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2484,6 +2484,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2538,3 +2574,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) 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 5e0ab93292..eb72393d13 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -289,6 +289,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -430,6 +437,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -596,22 +604,6 @@ const ( RTN_THROW = 0x9 RTN_NAT = 0xa RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -619,6 +611,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -669,6 +662,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2465,6 +2465,42 @@ const ( BPF_FD_TYPE_URETPROBE = 0x5 ) +const ( + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_DECnet_IFADDR = 0xd + RTNLGRP_NOP2 = 0xe + RTNLGRP_DECnet_ROUTE = 0xf + RTNLGRP_DECnet_RULE = 0x10 + RTNLGRP_NOP4 = 0x11 + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + RTNLGRP_PHONET_IFADDR = 0x15 + RTNLGRP_PHONET_ROUTE = 0x16 + RTNLGRP_DCB = 0x17 + RTNLGRP_IPV4_NETCONF = 0x18 + RTNLGRP_IPV6_NETCONF = 0x19 + RTNLGRP_MDB = 0x1a + RTNLGRP_MPLS_ROUTE = 0x1b + RTNLGRP_NSID = 0x1c + RTNLGRP_MPLS_NETCONF = 0x1d + RTNLGRP_IPV4_MROUTE_R = 0x1e + RTNLGRP_IPV6_MROUTE_R = 0x1f + RTNLGRP_NEXTHOP = 0x20 +) + type CapUserHeader struct { Version uint32 Pid int32 @@ -2519,3 +2555,201 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) + +const ( + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYSLOG_ACTION_SIZE_BUFFER = 10 +) + +const ( + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_MAX = 0x3c + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_MAX = 0x80 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 +) diff --git a/vendor/golang.org/x/sys/windows/asm_windows_386.s b/vendor/golang.org/x/sys/windows/asm_windows_386.s deleted file mode 100644 index 21d994d318..0000000000 --- a/vendor/golang.org/x/sys/windows/asm_windows_386.s +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// -// System calls for 386, Windows are implemented in runtime/syscall_windows.goc -// - -TEXT ·getprocaddress(SB), 7, $0-16 - JMP syscall·getprocaddress(SB) - -TEXT ·loadlibrary(SB), 7, $0-12 - JMP syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/asm_windows_amd64.s b/vendor/golang.org/x/sys/windows/asm_windows_amd64.s deleted file mode 100644 index 5bfdf79741..0000000000 --- a/vendor/golang.org/x/sys/windows/asm_windows_amd64.s +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// -// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc -// - -TEXT ·getprocaddress(SB), 7, $0-32 - JMP syscall·getprocaddress(SB) - -TEXT ·loadlibrary(SB), 7, $0-24 - JMP syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/asm_windows_arm.s b/vendor/golang.org/x/sys/windows/asm_windows_arm.s deleted file mode 100644 index 55d8b91a28..0000000000 --- a/vendor/golang.org/x/sys/windows/asm_windows_arm.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -TEXT ·getprocaddress(SB),NOSPLIT,$0 - B syscall·getprocaddress(SB) - -TEXT ·loadlibrary(SB),NOSPLIT,$0 - B syscall·loadlibrary(SB) diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index ba67658db1..d777113415 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -11,6 +11,18 @@ import ( "unsafe" ) +// We need to use LoadLibrary and GetProcAddress from the Go runtime, because +// the these symbols are loaded by the system linker and are required to +// dynamically load additional symbols. Note that in the Go runtime, these +// return syscall.Handle and syscall.Errno, but these are the same, in fact, +// as windows.Handle and windows.Errno, and we intend to keep these the same. + +//go:linkname syscall_loadlibrary syscall.loadlibrary +func syscall_loadlibrary(filename *uint16) (handle Handle, err Errno) + +//go:linkname syscall_getprocaddress syscall.getprocaddress +func syscall_getprocaddress(handle Handle, procname *uint8) (proc uintptr, err Errno) + // DLLError describes reasons for DLL load failures. type DLLError struct { Err error @@ -20,10 +32,6 @@ type DLLError struct { func (e *DLLError) Error() string { return e.Msg } -// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file. -func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno) -func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno) - // A DLL implements access to a single DLL. type DLL struct { Name string @@ -40,7 +48,7 @@ func LoadDLL(name string) (dll *DLL, err error) { if err != nil { return nil, err } - h, e := loadlibrary(namep) + h, e := syscall_loadlibrary(namep) if e != 0 { return nil, &DLLError{ Err: e, @@ -50,7 +58,7 @@ func LoadDLL(name string) (dll *DLL, err error) { } d := &DLL{ Name: name, - Handle: Handle(h), + Handle: h, } return d, nil } @@ -71,7 +79,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) { if err != nil { return nil, err } - a, e := getprocaddress(uintptr(d.Handle), namep) + a, e := syscall_getprocaddress(d.Handle, namep) if e != 0 { return nil, &DLLError{ Err: e, diff --git a/vendor/golang.org/x/sys/windows/mksyscall.go b/vendor/golang.org/x/sys/windows/mksyscall.go index 6277057274..328e3b2ace 100644 --- a/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/mksyscall.go @@ -6,4 +6,4 @@ package windows -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index 61b49647b9..d88ed91a84 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -9,14 +9,6 @@ import ( "unsafe" ) -const ( - STANDARD_RIGHTS_REQUIRED = 0xf0000 - STANDARD_RIGHTS_READ = 0x20000 - STANDARD_RIGHTS_WRITE = 0x20000 - STANDARD_RIGHTS_EXECUTE = 0x20000 - STANDARD_RIGHTS_ALL = 0x1F0000 -) - const ( NameUnknown = 0 NameFullyQualifiedDN = 1 @@ -235,16 +227,17 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32, } } -// String converts SID to a string format -// suitable for display, storage, or transmission. -func (sid *SID) String() (string, error) { +// String converts SID to a string format suitable for display, storage, or transmission. +func (sid *SID) String() string { + // From https://docs.microsoft.com/en-us/windows/win32/secbiomet/general-constants + const SecurityMaxSidSize = 68 var s *uint16 e := ConvertSidToStringSid(sid, &s) if e != nil { - return "", e + return "" } defer LocalFree((Handle)(unsafe.Pointer(s))) - return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil + return UTF16ToString((*[SecurityMaxSidSize]uint16)(unsafe.Pointer(s))[:]) } // Len returns the length, in bytes, of a valid security identifier SID. @@ -644,6 +637,8 @@ func (tml *Tokenmandatorylabel) Size() uint32 { //sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW //sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW +//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW +//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW // An access token contains the security information for a logon session. // The system creates an access token when a user logs on, and every @@ -654,21 +649,16 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // system-related operations on the local computer. type Token Handle -// OpenCurrentProcessToken opens the access token -// associated with current process. It is a real -// token that needs to be closed, unlike -// GetCurrentProcessToken. +// OpenCurrentProcessToken opens an access token associated with current +// process with TOKEN_QUERY access. It is a real token that needs to be closed. +// +// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...) +// with the desired access instead, or use GetCurrentProcessToken for a +// TOKEN_QUERY token. func OpenCurrentProcessToken() (Token, error) { - p, e := GetCurrentProcess() - if e != nil { - return 0, e - } - var t Token - e = OpenProcessToken(p, TOKEN_QUERY, &t) - if e != nil { - return 0, e - } - return t, nil + var token Token + err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token) + return token, err } // GetCurrentProcessToken returns the access token associated with @@ -785,8 +775,8 @@ func (token Token) GetLinkedToken() (Token, error) { return linkedToken, nil } -// GetSystemDirectory retrieves path to current location of the system -// directory, which is typically, though not always, C:\Windows\System32. +// GetSystemDirectory retrieves the path to current location of the system +// directory, which is typically, though not always, `C:\Windows\System32`. func GetSystemDirectory() (string, error) { n := uint32(MAX_PATH) for { @@ -802,6 +792,42 @@ func GetSystemDirectory() (string, error) { } } +// GetWindowsDirectory retrieves the path to current location of the Windows +// directory, which is typically, though not always, `C:\Windows`. This may +// be a private user directory in the case that the application is running +// under a terminal server. +func GetWindowsDirectory() (string, error) { + n := uint32(MAX_PATH) + for { + b := make([]uint16, n) + l, e := getWindowsDirectory(&b[0], n) + if e != nil { + return "", e + } + if l <= n { + return UTF16ToString(b[:l]), nil + } + n = l + } +} + +// GetSystemWindowsDirectory retrieves the path to current location of the +// Windows directory, which is typically, though not always, `C:\Windows`. +func GetSystemWindowsDirectory() (string, error) { + n := uint32(MAX_PATH) + for { + b := make([]uint16, n) + l, e := getSystemWindowsDirectory(&b[0], n) + if e != nil { + return "", e + } + if l <= n { + return UTF16ToString(b[:l]), nil + } + n = l + } +} + // IsMember reports whether the access token t is a member of the provided SID. func (t Token) IsMember(sid *SID) (bool, error) { var b int32 @@ -852,3 +878,521 @@ type WTS_SESSION_INFO struct { //sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken //sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW //sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory + +type ACL struct { + aclRevision byte + sbz1 byte + aclSize uint16 + aceCount uint16 + sbz2 uint16 +} + +type SECURITY_DESCRIPTOR struct { + revision byte + sbz1 byte + control SECURITY_DESCRIPTOR_CONTROL + owner *SID + group *SID + sacl *ACL + dacl *ACL +} + +type SecurityAttributes struct { + Length uint32 + SecurityDescriptor *SECURITY_DESCRIPTOR + InheritHandle uint32 +} + +type SE_OBJECT_TYPE uint32 + +// Constants for type SE_OBJECT_TYPE +const ( + SE_UNKNOWN_OBJECT_TYPE = 0 + SE_FILE_OBJECT = 1 + SE_SERVICE = 2 + SE_PRINTER = 3 + SE_REGISTRY_KEY = 4 + SE_LMSHARE = 5 + SE_KERNEL_OBJECT = 6 + SE_WINDOW_OBJECT = 7 + SE_DS_OBJECT = 8 + SE_DS_OBJECT_ALL = 9 + SE_PROVIDER_DEFINED_OBJECT = 10 + SE_WMIGUID_OBJECT = 11 + SE_REGISTRY_WOW64_32KEY = 12 + SE_REGISTRY_WOW64_64KEY = 13 +) + +type SECURITY_INFORMATION uint32 + +// Constants for type SECURITY_INFORMATION +const ( + OWNER_SECURITY_INFORMATION = 0x00000001 + GROUP_SECURITY_INFORMATION = 0x00000002 + DACL_SECURITY_INFORMATION = 0x00000004 + SACL_SECURITY_INFORMATION = 0x00000008 + LABEL_SECURITY_INFORMATION = 0x00000010 + ATTRIBUTE_SECURITY_INFORMATION = 0x00000020 + SCOPE_SECURITY_INFORMATION = 0x00000040 + BACKUP_SECURITY_INFORMATION = 0x00010000 + PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 + PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 + UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 + UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 +) + +type SECURITY_DESCRIPTOR_CONTROL uint16 + +// Constants for type SECURITY_DESCRIPTOR_CONTROL +const ( + SE_OWNER_DEFAULTED = 0x0001 + SE_GROUP_DEFAULTED = 0x0002 + SE_DACL_PRESENT = 0x0004 + SE_DACL_DEFAULTED = 0x0008 + SE_SACL_PRESENT = 0x0010 + SE_SACL_DEFAULTED = 0x0020 + SE_DACL_AUTO_INHERIT_REQ = 0x0100 + SE_SACL_AUTO_INHERIT_REQ = 0x0200 + SE_DACL_AUTO_INHERITED = 0x0400 + SE_SACL_AUTO_INHERITED = 0x0800 + SE_DACL_PROTECTED = 0x1000 + SE_SACL_PROTECTED = 0x2000 + SE_RM_CONTROL_VALID = 0x4000 + SE_SELF_RELATIVE = 0x8000 +) + +type ACCESS_MASK uint32 + +// Constants for type ACCESS_MASK +const ( + DELETE = 0x00010000 + READ_CONTROL = 0x00020000 + WRITE_DAC = 0x00040000 + WRITE_OWNER = 0x00080000 + SYNCHRONIZE = 0x00100000 + STANDARD_RIGHTS_REQUIRED = 0x000F0000 + STANDARD_RIGHTS_READ = READ_CONTROL + STANDARD_RIGHTS_WRITE = READ_CONTROL + STANDARD_RIGHTS_EXECUTE = READ_CONTROL + STANDARD_RIGHTS_ALL = 0x001F0000 + SPECIFIC_RIGHTS_ALL = 0x0000FFFF + ACCESS_SYSTEM_SECURITY = 0x01000000 + MAXIMUM_ALLOWED = 0x02000000 + GENERIC_READ = 0x80000000 + GENERIC_WRITE = 0x40000000 + GENERIC_EXECUTE = 0x20000000 + GENERIC_ALL = 0x10000000 +) + +type ACCESS_MODE uint32 + +// Constants for type ACCESS_MODE +const ( + NOT_USED_ACCESS = 0 + GRANT_ACCESS = 1 + SET_ACCESS = 2 + DENY_ACCESS = 3 + REVOKE_ACCESS = 4 + SET_AUDIT_SUCCESS = 5 + SET_AUDIT_FAILURE = 6 +) + +// Constants for AceFlags and Inheritance fields +const ( + NO_INHERITANCE = 0x0 + SUB_OBJECTS_ONLY_INHERIT = 0x1 + SUB_CONTAINERS_ONLY_INHERIT = 0x2 + SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3 + INHERIT_NO_PROPAGATE = 0x4 + INHERIT_ONLY = 0x8 + INHERITED_ACCESS_ENTRY = 0x10 + INHERITED_PARENT = 0x10000000 + INHERITED_GRANDPARENT = 0x20000000 + OBJECT_INHERIT_ACE = 0x1 + CONTAINER_INHERIT_ACE = 0x2 + NO_PROPAGATE_INHERIT_ACE = 0x4 + INHERIT_ONLY_ACE = 0x8 + INHERITED_ACE = 0x10 + VALID_INHERIT_FLAGS = 0x1F +) + +type MULTIPLE_TRUSTEE_OPERATION uint32 + +// Constants for MULTIPLE_TRUSTEE_OPERATION +const ( + NO_MULTIPLE_TRUSTEE = 0 + TRUSTEE_IS_IMPERSONATE = 1 +) + +type TRUSTEE_FORM uint32 + +// Constants for TRUSTEE_FORM +const ( + TRUSTEE_IS_SID = 0 + TRUSTEE_IS_NAME = 1 + TRUSTEE_BAD_FORM = 2 + TRUSTEE_IS_OBJECTS_AND_SID = 3 + TRUSTEE_IS_OBJECTS_AND_NAME = 4 +) + +type TRUSTEE_TYPE uint32 + +// Constants for TRUSTEE_TYPE +const ( + TRUSTEE_IS_UNKNOWN = 0 + TRUSTEE_IS_USER = 1 + TRUSTEE_IS_GROUP = 2 + TRUSTEE_IS_DOMAIN = 3 + TRUSTEE_IS_ALIAS = 4 + TRUSTEE_IS_WELL_KNOWN_GROUP = 5 + TRUSTEE_IS_DELETED = 6 + TRUSTEE_IS_INVALID = 7 + TRUSTEE_IS_COMPUTER = 8 +) + +// Constants for ObjectsPresent field +const ( + ACE_OBJECT_TYPE_PRESENT = 0x1 + ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2 +) + +type EXPLICIT_ACCESS struct { + AccessPermissions ACCESS_MASK + AccessMode ACCESS_MODE + Inheritance uint32 + Trustee TRUSTEE +} + +// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. +type TrusteeValue uintptr + +func TrusteeValueFromString(str string) TrusteeValue { + return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str))) +} +func TrusteeValueFromSID(sid *SID) TrusteeValue { + return TrusteeValue(unsafe.Pointer(sid)) +} +func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue { + return TrusteeValue(unsafe.Pointer(objectsAndSid)) +} +func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue { + return TrusteeValue(unsafe.Pointer(objectsAndName)) +} + +type TRUSTEE struct { + MultipleTrustee *TRUSTEE + MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION + TrusteeForm TRUSTEE_FORM + TrusteeType TRUSTEE_TYPE + TrusteeValue TrusteeValue +} + +type OBJECTS_AND_SID struct { + ObjectsPresent uint32 + ObjectTypeGuid GUID + InheritedObjectTypeGuid GUID + Sid *SID +} + +type OBJECTS_AND_NAME struct { + ObjectsPresent uint32 + ObjectType SE_OBJECT_TYPE + ObjectTypeName *uint16 + InheritedObjectTypeName *uint16 + Name *uint16 +} + +//sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo +//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo +//sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW +//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW + +//sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW +//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor + +//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl +//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl +//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl +//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner +//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup +//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength +//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl +//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor + +//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl +//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl +//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl +//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner +//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup +//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl + +//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW +//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW + +//sys makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD +//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD + +//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW + +// Control returns the security descriptor control bits. +func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { + err = getSecurityDescriptorControl(sd, &control, &revision) + return +} + +// SetControl sets the security descriptor control bits. +func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error { + return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet) +} + +// RMControl returns the security descriptor resource manager control bits. +func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) { + err = getSecurityDescriptorRMControl(sd, &control) + return +} + +// SetRMControl sets the security descriptor resource manager control bits. +func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) { + setSecurityDescriptorRMControl(sd, &rmControl) +} + +// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil +// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns +// ERROR_OBJECT_NOT_FOUND. +func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) { + var present bool + err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted) + if !present { + err = ERROR_OBJECT_NOT_FOUND + } + return +} + +// SetDACL sets the absolute security descriptor DACL. +func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error { + return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted) +} + +// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil +// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns +// ERROR_OBJECT_NOT_FOUND. +func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) { + var present bool + err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted) + if !present { + err = ERROR_OBJECT_NOT_FOUND + } + return +} + +// SetSACL sets the absolute security descriptor SACL. +func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error { + return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted) +} + +// Owner returns the security descriptor owner and whether it was defaulted. +func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) { + err = getSecurityDescriptorOwner(sd, &owner, &defaulted) + return +} + +// SetOwner sets the absolute security descriptor owner. +func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error { + return setSecurityDescriptorOwner(absoluteSD, owner, defaulted) +} + +// Group returns the security descriptor group and whether it was defaulted. +func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) { + err = getSecurityDescriptorGroup(sd, &group, &defaulted) + return +} + +// SetGroup sets the absolute security descriptor owner. +func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error { + return setSecurityDescriptorGroup(absoluteSD, group, defaulted) +} + +// Length returns the length of the security descriptor. +func (sd *SECURITY_DESCRIPTOR) Length() uint32 { + return getSecurityDescriptorLength(sd) +} + +// IsValid returns whether the security descriptor is valid. +func (sd *SECURITY_DESCRIPTOR) IsValid() bool { + return isValidSecurityDescriptor(sd) +} + +// String returns the SDDL form of the security descriptor, with a function signature that can be +// used with %v formatting directives. +func (sd *SECURITY_DESCRIPTOR) String() string { + var sddl *uint16 + err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil) + if err != nil { + return "" + } + defer LocalFree(Handle(unsafe.Pointer(sddl))) + return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:]) +} + +// ToAbsolute converts a self-relative security descriptor into an absolute one. +func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) { + control, _, err := selfRelativeSD.Control() + if err != nil { + return + } + if control&SE_SELF_RELATIVE == 0 { + err = ERROR_INVALID_PARAMETER + return + } + var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32 + err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize, + nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize) + switch err { + case ERROR_INSUFFICIENT_BUFFER: + case nil: + // makeAbsoluteSD is expected to fail, but it succeeds. + return nil, ERROR_INTERNAL_ERROR + default: + return nil, err + } + if absoluteSDSize > 0 { + absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0])) + } + var ( + dacl *ACL + sacl *ACL + owner *SID + group *SID + ) + if daclSize > 0 { + dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0])) + } + if saclSize > 0 { + sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0])) + } + if ownerSize > 0 { + owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0])) + } + if groupSize > 0 { + group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0])) + } + err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize, + dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize) + return +} + +// ToSelfRelative converts an absolute security descriptor into a self-relative one. +func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) { + control, _, err := absoluteSD.Control() + if err != nil { + return + } + if control&SE_SELF_RELATIVE != 0 { + err = ERROR_INVALID_PARAMETER + return + } + var selfRelativeSDSize uint32 + err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize) + switch err { + case ERROR_INSUFFICIENT_BUFFER: + case nil: + // makeSelfRelativeSD is expected to fail, but it succeeds. + return nil, ERROR_INTERNAL_ERROR + default: + return nil, err + } + if selfRelativeSDSize > 0 { + selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0])) + } + err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize) + return +} + +func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR { + sdBytes := make([]byte, selfRelativeSD.Length()) + copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)]) + return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0])) +} + +// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a +// self-relative security descriptor object allocated on the Go heap. +func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// GetSecurityInfo queries the security information for a given handle and returns the self-relative security +// descriptor result on the Go heap. +func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security +// descriptor result on the Go heap. +func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and +// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor +// result on the Go heap. +func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + var winHeapSDSize uint32 + var firstAccessEntry *EXPLICIT_ACCESS + if len(accessEntries) > 0 { + firstAccessEntry = &accessEntries[0] + } + var firstAuditEntry *EXPLICIT_ACCESS + if len(auditEntries) > 0 { + firstAuditEntry = &auditEntries[0] + } + err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// NewSecurityDescriptor creates and initializes a new absolute security descriptor. +func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) { + absoluteSD = &SECURITY_DESCRIPTOR{} + err = initializeSecurityDescriptor(absoluteSD, 1) + return +} + +// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL. +// Both explicitEntries and mergedACL are optional and can be nil. +func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) { + var firstExplicitEntry *EXPLICIT_ACCESS + if len(explicitEntries) > 0 { + firstExplicitEntry = &explicitEntries[0] + } + var winHeapACL *ACL + err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapACL))) + aclBytes := make([]byte, winHeapACL.aclSize) + copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)]) + return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil +} diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index b23050924f..fe8e42cff1 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -57,6 +57,10 @@ const ( FILE_VOLUME_IS_COMPRESSED = 0x00008000 FILE_VOLUME_QUOTAS = 0x00000020 + // Flags for LockFileEx. + LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 + LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 + // Return values of SleepEx and other APC functions STATUS_USER_APC = 0x000000C0 WAIT_IO_COMPLETION = STATUS_USER_APC @@ -136,6 +140,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW //sys FreeLibrary(handle Handle) (err error) //sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) +//sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW +//sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW //sys GetVersion() (ver uint32, err error) //sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW //sys ExitProcess(exitcode uint32) @@ -160,6 +166,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys DeleteFile(path *uint16) (err error) = DeleteFileW //sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW //sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW +//sys LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) +//sys UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) //sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW //sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW //sys SetEndOfFile(handle Handle) (err error) @@ -173,13 +181,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CancelIoEx(s Handle, o *Overlapped) (err error) //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) -//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) = shell32.ShellExecuteW +//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) = shell32.SHGetKnownFolderPath //sys TerminateProcess(handle Handle, exitcode uint32) (err error) //sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) //sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW -//sys GetCurrentProcess() (pseudoHandle Handle, err error) -//sys GetCurrentThread() (pseudoHandle Handle, err error) //sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) //sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) //sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] @@ -257,6 +263,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetEvent(event Handle) (err error) = kernel32.SetEvent //sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent //sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent +//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) = kernel32.CreateMutexW +//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateMutexExW +//sys OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenMutexW +//sys ReleaseMutex(mutex Handle) (err error) = kernel32.ReleaseMutex //sys SleepEx(milliseconds uint32, alertable bool) (ret uint32) = kernel32.SleepEx //sys CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) = kernel32.CreateJobObjectW //sys AssignProcessToJobObject(job Handle, process Handle) (err error) = kernel32.AssignProcessToJobObject @@ -269,6 +279,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) //sys GetProcessId(process Handle) (id uint32, err error) //sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) +//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost // Volume Management Functions //sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW @@ -279,6 +290,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) = FindNextVolumeMountPointW //sys FindVolumeClose(findVolume Handle) (err error) //sys FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) +//sys GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = GetDiskFreeSpaceExW //sys GetDriveType(rootPathName *uint16) (driveType uint32) = GetDriveTypeW //sys GetLogicalDrives() (drivesBitMask uint32, err error) [failretval==0] //sys GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) [failretval==0] = GetLogicalDriveStringsW @@ -291,14 +303,50 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW //sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW //sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW +//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx +//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW +//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters +//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters //sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString //sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2 //sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid //sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree //sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion +//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers + +// Process Status API (PSAPI) +//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses // syscall interface implementation for other packages +// GetCurrentProcess returns the handle for the current process. +// It is a pseudo handle that does not need to be closed. +// The returned error is always nil. +// +// Deprecated: use CurrentProcess for the same Handle without the nil +// error. +func GetCurrentProcess() (Handle, error) { + return CurrentProcess(), nil +} + +// CurrentProcess returns the handle for the current process. +// It is a pseudo handle that does not need to be closed. +func CurrentProcess() Handle { return Handle(^uintptr(1 - 1)) } + +// GetCurrentThread returns the handle for the current thread. +// It is a pseudo handle that does not need to be closed. +// The returned error is always nil. +// +// Deprecated: use CurrentThread for the same Handle without the nil +// error. +func GetCurrentThread() (Handle, error) { + return CurrentThread(), nil +} + +// CurrentThread returns the handle for the current thread. +// It is a pseudo handle that does not need to be closed. +func CurrentThread() Handle { return Handle(^uintptr(2 - 1)) } + // GetProcAddressByOrdinal retrieves the address of the exported // function from module by ordinal. func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) { @@ -365,7 +413,11 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) { default: createmode = OPEN_EXISTING } - h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0) + var attrs uint32 = FILE_ATTRIBUTE_NORMAL + if perm&S_IWRITE == 0 { + attrs = FILE_ATTRIBUTE_READONLY + } + h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) return h, e } @@ -812,7 +864,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] + bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] sa.Name = string(bytes) return sa, nil @@ -1306,8 +1358,8 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil } -// RtlGetVersion returns the true version of the underlying operating system, ignoring -// any manifesting or compatibility layers on top of the win32 layer. +// RtlGetVersion returns the version of the underlying operating system, ignoring +// manifest semantics but is affected by the application compatibility layer. func RtlGetVersion() *OsVersionInfoEx { info := &OsVersionInfoEx{} info.osVersionInfoSize = uint32(unsafe.Sizeof(*info)) @@ -1318,3 +1370,11 @@ func RtlGetVersion() *OsVersionInfoEx { _ = rtlGetVersion(info) return info } + +// RtlGetNtVersionNumbers returns the version of the underlying operating system, +// ignoring manifest semantics and the application compatibility layer. +func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) { + rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber) + buildNumber &= 0xffff + return +} diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 1e3947f0f6..7f178bb91e 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -62,11 +62,6 @@ var signals = [...]string{ } const ( - GENERIC_READ = 0x80000000 - GENERIC_WRITE = 0x40000000 - GENERIC_EXECUTE = 0x20000000 - GENERIC_ALL = 0x10000000 - FILE_LIST_DIRECTORY = 0x00000001 FILE_APPEND_DATA = 0x00000004 FILE_WRITE_ATTRIBUTES = 0x00000100 @@ -158,13 +153,6 @@ const ( WAIT_OBJECT_0 = 0x00000000 WAIT_FAILED = 0xFFFFFFFF - // Standard access rights. - DELETE = 0x00010000 - READ_CONTROL = 0x00020000 - SYNCHRONIZE = 0x00100000 - WRITE_DAC = 0x00040000 - WRITE_OWNER = 0x00080000 - // Access rights for process. PROCESS_CREATE_PROCESS = 0x0080 PROCESS_CREATE_THREAD = 0x0002 @@ -483,12 +471,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) { return } -type SecurityAttributes struct { - Length uint32 - SecurityDescriptor uintptr - InheritHandle uint32 -} - type Overlapped struct { Internal uintptr InternalHigh uintptr @@ -1190,6 +1172,28 @@ const ( REG_QWORD = REG_QWORD_LITTLE_ENDIAN ) +const ( + EVENT_MODIFY_STATE = 0x0002 + EVENT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3 + + MUTANT_QUERY_STATE = 0x0001 + MUTANT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | MUTANT_QUERY_STATE + + SEMAPHORE_MODIFY_STATE = 0x0002 + SEMAPHORE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3 + + TIMER_QUERY_STATE = 0x0001 + TIMER_MODIFY_STATE = 0x0002 + TIMER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | TIMER_QUERY_STATE | TIMER_MODIFY_STATE + + MUTEX_MODIFY_STATE = MUTANT_QUERY_STATE + MUTEX_ALL_ACCESS = MUTANT_ALL_ACCESS + + CREATE_EVENT_MANUAL_RESET = 0x1 + CREATE_EVENT_INITIAL_SET = 0x2 + CREATE_MUTEX_INITIAL_OWNER = 0x1 +) + type AddrinfoW struct { Flags int32 Family int32 @@ -1666,3 +1670,75 @@ type OsVersionInfoEx struct { ProductType byte _ byte } + +const ( + EWX_LOGOFF = 0x00000000 + EWX_SHUTDOWN = 0x00000001 + EWX_REBOOT = 0x00000002 + EWX_FORCE = 0x00000004 + EWX_POWEROFF = 0x00000008 + EWX_FORCEIFHUNG = 0x00000010 + EWX_QUICKRESOLVE = 0x00000020 + EWX_RESTARTAPPS = 0x00000040 + EWX_HYBRID_SHUTDOWN = 0x00400000 + EWX_BOOTOPTIONS = 0x01000000 + + SHTDN_REASON_FLAG_COMMENT_REQUIRED = 0x01000000 + SHTDN_REASON_FLAG_DIRTY_PROBLEM_ID_REQUIRED = 0x02000000 + SHTDN_REASON_FLAG_CLEAN_UI = 0x04000000 + SHTDN_REASON_FLAG_DIRTY_UI = 0x08000000 + SHTDN_REASON_FLAG_USER_DEFINED = 0x40000000 + SHTDN_REASON_FLAG_PLANNED = 0x80000000 + SHTDN_REASON_MAJOR_OTHER = 0x00000000 + SHTDN_REASON_MAJOR_NONE = 0x00000000 + SHTDN_REASON_MAJOR_HARDWARE = 0x00010000 + SHTDN_REASON_MAJOR_OPERATINGSYSTEM = 0x00020000 + SHTDN_REASON_MAJOR_SOFTWARE = 0x00030000 + SHTDN_REASON_MAJOR_APPLICATION = 0x00040000 + SHTDN_REASON_MAJOR_SYSTEM = 0x00050000 + SHTDN_REASON_MAJOR_POWER = 0x00060000 + SHTDN_REASON_MAJOR_LEGACY_API = 0x00070000 + SHTDN_REASON_MINOR_OTHER = 0x00000000 + SHTDN_REASON_MINOR_NONE = 0x000000ff + SHTDN_REASON_MINOR_MAINTENANCE = 0x00000001 + SHTDN_REASON_MINOR_INSTALLATION = 0x00000002 + SHTDN_REASON_MINOR_UPGRADE = 0x00000003 + SHTDN_REASON_MINOR_RECONFIG = 0x00000004 + SHTDN_REASON_MINOR_HUNG = 0x00000005 + SHTDN_REASON_MINOR_UNSTABLE = 0x00000006 + SHTDN_REASON_MINOR_DISK = 0x00000007 + SHTDN_REASON_MINOR_PROCESSOR = 0x00000008 + SHTDN_REASON_MINOR_NETWORKCARD = 0x00000009 + SHTDN_REASON_MINOR_POWER_SUPPLY = 0x0000000a + SHTDN_REASON_MINOR_CORDUNPLUGGED = 0x0000000b + SHTDN_REASON_MINOR_ENVIRONMENT = 0x0000000c + SHTDN_REASON_MINOR_HARDWARE_DRIVER = 0x0000000d + SHTDN_REASON_MINOR_OTHERDRIVER = 0x0000000e + SHTDN_REASON_MINOR_BLUESCREEN = 0x0000000F + SHTDN_REASON_MINOR_SERVICEPACK = 0x00000010 + SHTDN_REASON_MINOR_HOTFIX = 0x00000011 + SHTDN_REASON_MINOR_SECURITYFIX = 0x00000012 + SHTDN_REASON_MINOR_SECURITY = 0x00000013 + SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY = 0x00000014 + SHTDN_REASON_MINOR_WMI = 0x00000015 + SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL = 0x00000016 + SHTDN_REASON_MINOR_HOTFIX_UNINSTALL = 0x00000017 + SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL = 0x00000018 + SHTDN_REASON_MINOR_MMC = 0x00000019 + SHTDN_REASON_MINOR_SYSTEMRESTORE = 0x0000001a + SHTDN_REASON_MINOR_TERMSRV = 0x00000020 + SHTDN_REASON_MINOR_DC_PROMOTION = 0x00000021 + SHTDN_REASON_MINOR_DC_DEMOTION = 0x00000022 + SHTDN_REASON_UNKNOWN = SHTDN_REASON_MINOR_NONE + SHTDN_REASON_LEGACY_API = SHTDN_REASON_MAJOR_LEGACY_API | SHTDN_REASON_FLAG_PLANNED + SHTDN_REASON_VALID_BIT_MASK = 0xc0ffffff + + SHUTDOWN_NORETRY = 0x1 +) + +// Flags used for GetModuleHandleEx +const ( + GET_MODULE_HANDLE_EX_FLAG_PIN = 1 + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2 + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4 +) diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index d461bed98a..6658ccd1b0 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -44,6 +44,7 @@ var ( moduser32 = NewLazySystemDLL("user32.dll") modole32 = NewLazySystemDLL("ole32.dll") modntdll = NewLazySystemDLL("ntdll.dll") + modpsapi = NewLazySystemDLL("psapi.dll") modws2_32 = NewLazySystemDLL("ws2_32.dll") moddnsapi = NewLazySystemDLL("dnsapi.dll") modiphlpapi = NewLazySystemDLL("iphlpapi.dll") @@ -51,261 +52,302 @@ var ( modnetapi32 = NewLazySystemDLL("netapi32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") - procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") - procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") - procReportEventW = modadvapi32.NewProc("ReportEventW") - procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") - procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") - procCreateServiceW = modadvapi32.NewProc("CreateServiceW") - procOpenServiceW = modadvapi32.NewProc("OpenServiceW") - procDeleteService = modadvapi32.NewProc("DeleteService") - procStartServiceW = modadvapi32.NewProc("StartServiceW") - procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") - procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") - procControlService = modadvapi32.NewProc("ControlService") - procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") - procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") - procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") - procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") - procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") - procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") - procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") - procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") - procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") - procGetLastError = modkernel32.NewProc("GetLastError") - procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") - procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") - procFreeLibrary = modkernel32.NewProc("FreeLibrary") - procGetProcAddress = modkernel32.NewProc("GetProcAddress") - procGetVersion = modkernel32.NewProc("GetVersion") - procFormatMessageW = modkernel32.NewProc("FormatMessageW") - procExitProcess = modkernel32.NewProc("ExitProcess") - procIsWow64Process = modkernel32.NewProc("IsWow64Process") - procCreateFileW = modkernel32.NewProc("CreateFileW") - procReadFile = modkernel32.NewProc("ReadFile") - procWriteFile = modkernel32.NewProc("WriteFile") - procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") - procSetFilePointer = modkernel32.NewProc("SetFilePointer") - procCloseHandle = modkernel32.NewProc("CloseHandle") - procGetStdHandle = modkernel32.NewProc("GetStdHandle") - procSetStdHandle = modkernel32.NewProc("SetStdHandle") - procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") - procFindNextFileW = modkernel32.NewProc("FindNextFileW") - procFindClose = modkernel32.NewProc("FindClose") - procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") - procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") - procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") - procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") - procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") - procDeleteFileW = modkernel32.NewProc("DeleteFileW") - procMoveFileW = modkernel32.NewProc("MoveFileW") - procMoveFileExW = modkernel32.NewProc("MoveFileExW") - procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") - procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") - procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") - procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") - procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") - procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") - procCancelIo = modkernel32.NewProc("CancelIo") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procCreateProcessW = modkernel32.NewProc("CreateProcessW") - procOpenProcess = modkernel32.NewProc("OpenProcess") - procShellExecuteW = modshell32.NewProc("ShellExecuteW") - procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") - procTerminateProcess = modkernel32.NewProc("TerminateProcess") - procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") - procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") - procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") - procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") - procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") - procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") - procGetTempPathW = modkernel32.NewProc("GetTempPathW") - procCreatePipe = modkernel32.NewProc("CreatePipe") - procGetFileType = modkernel32.NewProc("GetFileType") - procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") - procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") - procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") - procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") - procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") - procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") - procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") - procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") - procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") - procGetTickCount64 = modkernel32.NewProc("GetTickCount64") - procSetFileTime = modkernel32.NewProc("SetFileTime") - procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") - procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") - procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") - procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") - procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") - procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") - procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") - procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") - procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") - procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") - procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") - procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") - procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") - procVirtualLock = modkernel32.NewProc("VirtualLock") - procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") - procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") - procVirtualFree = modkernel32.NewProc("VirtualFree") - procVirtualProtect = modkernel32.NewProc("VirtualProtect") - procTransmitFile = modmswsock.NewProc("TransmitFile") - procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") - procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") - procCertOpenStore = modcrypt32.NewProc("CertOpenStore") - procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") - procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") - procCertCloseStore = modcrypt32.NewProc("CertCloseStore") - procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") - procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") - procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") - procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") - procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") - procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") - procRegCloseKey = modadvapi32.NewProc("RegCloseKey") - procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") - procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") - procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") - procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") - procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") - procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") - procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") - procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") - procReadConsoleW = modkernel32.NewProc("ReadConsoleW") - procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") - procProcess32FirstW = modkernel32.NewProc("Process32FirstW") - procProcess32NextW = modkernel32.NewProc("Process32NextW") - procThread32First = modkernel32.NewProc("Thread32First") - procThread32Next = modkernel32.NewProc("Thread32Next") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") - procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") - procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") - procCreateEventW = modkernel32.NewProc("CreateEventW") - procCreateEventExW = modkernel32.NewProc("CreateEventExW") - procOpenEventW = modkernel32.NewProc("OpenEventW") - procSetEvent = modkernel32.NewProc("SetEvent") - procResetEvent = modkernel32.NewProc("ResetEvent") - procPulseEvent = modkernel32.NewProc("PulseEvent") - procSleepEx = modkernel32.NewProc("SleepEx") - procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") - procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") - procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") - procSetErrorMode = modkernel32.NewProc("SetErrorMode") - procResumeThread = modkernel32.NewProc("ResumeThread") - procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") - procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") - procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") - procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") - procGetProcessId = modkernel32.NewProc("GetProcessId") - procOpenThread = modkernel32.NewProc("OpenThread") - procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW") - procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") - procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") - procFindFirstVolumeMountPointW = modkernel32.NewProc("FindFirstVolumeMountPointW") - procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") - procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW") - procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") - procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") - procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") - procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") - procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") - procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") - procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW") - procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW") - procGetVolumePathNameW = modkernel32.NewProc("GetVolumePathNameW") - procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") - procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") - procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") - procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") - procMessageBoxW = moduser32.NewProc("MessageBoxW") - procCLSIDFromString = modole32.NewProc("CLSIDFromString") - procStringFromGUID2 = modole32.NewProc("StringFromGUID2") - procCoCreateGuid = modole32.NewProc("CoCreateGuid") - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") - procRtlGetVersion = modntdll.NewProc("RtlGetVersion") - procWSAStartup = modws2_32.NewProc("WSAStartup") - procWSACleanup = modws2_32.NewProc("WSACleanup") - procWSAIoctl = modws2_32.NewProc("WSAIoctl") - procsocket = modws2_32.NewProc("socket") - procsetsockopt = modws2_32.NewProc("setsockopt") - procgetsockopt = modws2_32.NewProc("getsockopt") - procbind = modws2_32.NewProc("bind") - procconnect = modws2_32.NewProc("connect") - procgetsockname = modws2_32.NewProc("getsockname") - procgetpeername = modws2_32.NewProc("getpeername") - proclisten = modws2_32.NewProc("listen") - procshutdown = modws2_32.NewProc("shutdown") - procclosesocket = modws2_32.NewProc("closesocket") - procAcceptEx = modmswsock.NewProc("AcceptEx") - procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") - procWSARecv = modws2_32.NewProc("WSARecv") - procWSASend = modws2_32.NewProc("WSASend") - procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") - procWSASendTo = modws2_32.NewProc("WSASendTo") - procgethostbyname = modws2_32.NewProc("gethostbyname") - procgetservbyname = modws2_32.NewProc("getservbyname") - procntohs = modws2_32.NewProc("ntohs") - procgetprotobyname = modws2_32.NewProc("getprotobyname") - procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") - procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") - procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") - procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") - procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") - procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") - procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") - procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") - procGetACP = modkernel32.NewProc("GetACP") - procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") - procTranslateNameW = modsecur32.NewProc("TranslateNameW") - procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") - procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") - procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") - procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") - procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") - procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procGetLengthSid = modadvapi32.NewProc("GetLengthSid") - procCopySid = modadvapi32.NewProc("CopySid") - procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") - procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") - procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") - procFreeSid = modadvapi32.NewProc("FreeSid") - procEqualSid = modadvapi32.NewProc("EqualSid") - procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") - procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") - procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") - procIsValidSid = modadvapi32.NewProc("IsValidSid") - procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") - procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procSetThreadToken = modadvapi32.NewProc("SetThreadToken") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") - procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") - procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") - procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") - procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") - procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") - procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") - procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") - procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") + procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") + procReportEventW = modadvapi32.NewProc("ReportEventW") + procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") + procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") + procCreateServiceW = modadvapi32.NewProc("CreateServiceW") + procOpenServiceW = modadvapi32.NewProc("OpenServiceW") + procDeleteService = modadvapi32.NewProc("DeleteService") + procStartServiceW = modadvapi32.NewProc("StartServiceW") + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") + procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") + procControlService = modadvapi32.NewProc("ControlService") + procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") + procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") + procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") + procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") + procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") + procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") + procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") + procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") + procGetLastError = modkernel32.NewProc("GetLastError") + procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") + procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") + procFreeLibrary = modkernel32.NewProc("FreeLibrary") + procGetProcAddress = modkernel32.NewProc("GetProcAddress") + procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") + procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW") + procGetVersion = modkernel32.NewProc("GetVersion") + procFormatMessageW = modkernel32.NewProc("FormatMessageW") + procExitProcess = modkernel32.NewProc("ExitProcess") + procIsWow64Process = modkernel32.NewProc("IsWow64Process") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procReadFile = modkernel32.NewProc("ReadFile") + procWriteFile = modkernel32.NewProc("WriteFile") + procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") + procSetFilePointer = modkernel32.NewProc("SetFilePointer") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procGetStdHandle = modkernel32.NewProc("GetStdHandle") + procSetStdHandle = modkernel32.NewProc("SetStdHandle") + procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") + procFindNextFileW = modkernel32.NewProc("FindNextFileW") + procFindClose = modkernel32.NewProc("FindClose") + procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") + procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") + procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procDeleteFileW = modkernel32.NewProc("DeleteFileW") + procMoveFileW = modkernel32.NewProc("MoveFileW") + procMoveFileExW = modkernel32.NewProc("MoveFileExW") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") + procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") + procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") + procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") + procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") + procCancelIo = modkernel32.NewProc("CancelIo") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCreateProcessW = modkernel32.NewProc("CreateProcessW") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procShellExecuteW = modshell32.NewProc("ShellExecuteW") + procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") + procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") + procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") + procGetTempPathW = modkernel32.NewProc("GetTempPathW") + procCreatePipe = modkernel32.NewProc("CreatePipe") + procGetFileType = modkernel32.NewProc("GetFileType") + procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") + procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") + procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") + procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") + procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") + procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") + procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") + procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") + procGetTickCount64 = modkernel32.NewProc("GetTickCount64") + procSetFileTime = modkernel32.NewProc("SetFileTime") + procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") + procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") + procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") + procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") + procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") + procLocalFree = modkernel32.NewProc("LocalFree") + procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") + procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") + procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") + procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") + procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") + procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") + procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") + procVirtualLock = modkernel32.NewProc("VirtualLock") + procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") + procVirtualFree = modkernel32.NewProc("VirtualFree") + procVirtualProtect = modkernel32.NewProc("VirtualProtect") + procTransmitFile = modmswsock.NewProc("TransmitFile") + procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") + procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") + procCertOpenStore = modcrypt32.NewProc("CertOpenStore") + procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") + procCertCloseStore = modcrypt32.NewProc("CertCloseStore") + procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") + procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") + procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") + procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") + procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") + procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") + procRegCloseKey = modadvapi32.NewProc("RegCloseKey") + procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") + procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") + procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") + procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") + procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") + procReadConsoleW = modkernel32.NewProc("ReadConsoleW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procThread32First = modkernel32.NewProc("Thread32First") + procThread32Next = modkernel32.NewProc("Thread32Next") + procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") + procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") + procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procCreateEventExW = modkernel32.NewProc("CreateEventExW") + procOpenEventW = modkernel32.NewProc("OpenEventW") + procSetEvent = modkernel32.NewProc("SetEvent") + procResetEvent = modkernel32.NewProc("ResetEvent") + procPulseEvent = modkernel32.NewProc("PulseEvent") + procCreateMutexW = modkernel32.NewProc("CreateMutexW") + procCreateMutexExW = modkernel32.NewProc("CreateMutexExW") + procOpenMutexW = modkernel32.NewProc("OpenMutexW") + procReleaseMutex = modkernel32.NewProc("ReleaseMutex") + procSleepEx = modkernel32.NewProc("SleepEx") + procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") + procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") + procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") + procSetErrorMode = modkernel32.NewProc("SetErrorMode") + procResumeThread = modkernel32.NewProc("ResumeThread") + procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") + procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") + procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") + procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") + procGetProcessId = modkernel32.NewProc("GetProcessId") + procOpenThread = modkernel32.NewProc("OpenThread") + procSetProcessPriorityBoost = modkernel32.NewProc("SetProcessPriorityBoost") + procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW") + procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") + procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") + procFindFirstVolumeMountPointW = modkernel32.NewProc("FindFirstVolumeMountPointW") + procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") + procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW") + procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") + procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") + procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") + procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") + procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") + procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") + procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW") + procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW") + procGetVolumePathNameW = modkernel32.NewProc("GetVolumePathNameW") + procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") + procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") + procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") + procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") + procMessageBoxW = moduser32.NewProc("MessageBoxW") + procExitWindowsEx = moduser32.NewProc("ExitWindowsEx") + procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW") + procSetProcessShutdownParameters = modkernel32.NewProc("SetProcessShutdownParameters") + procGetProcessShutdownParameters = modkernel32.NewProc("GetProcessShutdownParameters") + procCLSIDFromString = modole32.NewProc("CLSIDFromString") + procStringFromGUID2 = modole32.NewProc("StringFromGUID2") + procCoCreateGuid = modole32.NewProc("CoCreateGuid") + procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") + procRtlGetVersion = modntdll.NewProc("RtlGetVersion") + procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") + procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procWSAStartup = modws2_32.NewProc("WSAStartup") + procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSAIoctl = modws2_32.NewProc("WSAIoctl") + procsocket = modws2_32.NewProc("socket") + procsetsockopt = modws2_32.NewProc("setsockopt") + procgetsockopt = modws2_32.NewProc("getsockopt") + procbind = modws2_32.NewProc("bind") + procconnect = modws2_32.NewProc("connect") + procgetsockname = modws2_32.NewProc("getsockname") + procgetpeername = modws2_32.NewProc("getpeername") + proclisten = modws2_32.NewProc("listen") + procshutdown = modws2_32.NewProc("shutdown") + procclosesocket = modws2_32.NewProc("closesocket") + procAcceptEx = modmswsock.NewProc("AcceptEx") + procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") + procWSARecv = modws2_32.NewProc("WSARecv") + procWSASend = modws2_32.NewProc("WSASend") + procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") + procWSASendTo = modws2_32.NewProc("WSASendTo") + procgethostbyname = modws2_32.NewProc("gethostbyname") + procgetservbyname = modws2_32.NewProc("getservbyname") + procntohs = modws2_32.NewProc("ntohs") + procgetprotobyname = modws2_32.NewProc("getprotobyname") + procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") + procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") + procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") + procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") + procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") + procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procGetACP = modkernel32.NewProc("GetACP") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") + procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") + procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") + procGetLengthSid = modadvapi32.NewProc("GetLengthSid") + procCopySid = modadvapi32.NewProc("CopySid") + procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") + procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") + procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") + procFreeSid = modadvapi32.NewProc("FreeSid") + procEqualSid = modadvapi32.NewProc("EqualSid") + procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") + procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") + procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") + procIsValidSid = modadvapi32.NewProc("IsValidSid") + procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") + procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procSetThreadToken = modadvapi32.NewProc("SetThreadToken") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") + procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") + procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") + procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") + procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") + procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") + procGetSystemWindowsDirectoryW = modkernel32.NewProc("GetSystemWindowsDirectoryW") + procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") + procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") + procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") + procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") + procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo") + procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") + procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW") + procBuildSecurityDescriptorW = modadvapi32.NewProc("BuildSecurityDescriptorW") + procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor") + procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") + procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl") + procGetSecurityDescriptorSacl = modadvapi32.NewProc("GetSecurityDescriptorSacl") + procGetSecurityDescriptorOwner = modadvapi32.NewProc("GetSecurityDescriptorOwner") + procGetSecurityDescriptorGroup = modadvapi32.NewProc("GetSecurityDescriptorGroup") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procGetSecurityDescriptorRMControl = modadvapi32.NewProc("GetSecurityDescriptorRMControl") + procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor") + procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl") + procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") + procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") + procSetSecurityDescriptorOwner = modadvapi32.NewProc("SetSecurityDescriptorOwner") + procSetSecurityDescriptorGroup = modadvapi32.NewProc("SetSecurityDescriptorGroup") + procSetSecurityDescriptorRMControl = modadvapi32.NewProc("SetSecurityDescriptorRMControl") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") + procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") + procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") + procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") ) func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { @@ -646,6 +688,31 @@ func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { return } +func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { + r1, _, e1 := syscall.Syscall(procGetModuleHandleExW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func GetVersion() (ver uint32, err error) { r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) ver = uint32(r0) @@ -682,7 +749,14 @@ func ExitProcess(exitcode uint32) { } func IsWow64Process(handle Handle, isWow64 *bool) (err error) { - r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(isWow64)), 0) + var _p0 uint32 + if *isWow64 { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) + *isWow64 = _p0 != 0 if r1 == 0 { if e1 != 0 { err = errnoErr(e1) @@ -952,6 +1026,30 @@ func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { return } +func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func GetComputerName(buf *uint16, n *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) if r1 == 0 { @@ -1111,7 +1209,7 @@ func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (ha func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) - if r1 == 0 { + if r1 <= 32 { if e1 != 0 { err = errnoErr(e1) } else { @@ -1165,32 +1263,6 @@ func GetStartupInfo(startupInfo *StartupInfo) (err error) { return } -func GetCurrentProcess() (pseudoHandle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0) - pseudoHandle = Handle(r0) - if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetCurrentThread() (pseudoHandle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) - pseudoHandle = Handle(r0) - if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) if r1 == 0 { @@ -2105,6 +2177,69 @@ func PulseEvent(event Handle) (err error) { return } +func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if initialOwner { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReleaseMutex(mutex Handle) (err error) { + r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { var _p0 uint32 if alertable { @@ -2255,6 +2390,24 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand return } +func SetProcessPriorityBoost(process Handle, disable bool) (err error) { + var _p0 uint32 + if disable { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) if r1 == 0 { @@ -2353,6 +2506,18 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { return } +func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { + r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func GetDriveType(rootPathName *uint16) (driveType uint32) { r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) driveType = uint32(r0) @@ -2495,6 +2660,66 @@ func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret return } +func ExitWindowsEx(flags uint32, reason uint32) (err error) { + r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) { + var _p0 uint32 + if forceAppsClosed { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if rebootAfterShutdown { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) if r0 != 0 { @@ -2530,6 +2755,27 @@ func rtlGetVersion(info *OsVersionInfoEx) (ret error) { return } +func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { + syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) + return +} + +func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { + var _p0 *uint32 + if len(processIds) > 0 { + _p0 = &processIds[0] + } + r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(processIds)), uintptr(unsafe.Pointer(bytesReturned))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) if r0 != 0 { @@ -3307,6 +3553,32 @@ func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { return } +func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func WTSQueryUserToken(session uint32, token *Token) (err error) { r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) if r1 == 0 { @@ -3335,3 +3607,358 @@ func WTSFreeMemory(ptr uintptr) { syscall.Syscall(procWTSFreeMemory.Addr(), 1, uintptr(ptr), 0, 0) return } + +func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { + syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + return +} + +func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _getNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl, sd) +} + +func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _SetNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl) +} + +func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { + r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) { + var _p0 uint32 + if *daclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if *daclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *daclPresent = _p0 != 0 + *daclDefaulted = _p1 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) { + var _p0 uint32 + if *saclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if *saclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *saclPresent = _p0 != 0 + *saclDefaulted = _p1 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) { + var _p0 uint32 + if *ownerDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) + *ownerDefaulted = _p0 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) { + var _p0 uint32 + if *groupDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) + *groupDefaulted = _p0 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + len = uint32(r0) + return +} + +func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { + r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + isValid = r0 != 0 + return +} + +func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) { + var _p0 uint32 + if daclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if daclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) { + var _p0 uint32 + if saclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if saclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) { + var _p0 uint32 + if ownerDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) { + var _p0 uint32 + if groupDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { + syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { + r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} diff --git a/vendor/golang.org/x/text/encoding/charmap/maketables.go b/vendor/golang.org/x/text/encoding/charmap/maketables.go deleted file mode 100644 index f7941701e8..0000000000 --- a/vendor/golang.org/x/text/encoding/charmap/maketables.go +++ /dev/null @@ -1,556 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" - "unicode/utf8" - - "golang.org/x/text/encoding" - "golang.org/x/text/internal/gen" -) - -const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - ` !"#$%&'()*+,-./0123456789:;<=>?` + - `@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` + - "`abcdefghijklmnopqrstuvwxyz{|}~\u007f" - -var encodings = []struct { - name string - mib string - comment string - varName string - replacement byte - mapping string -}{ - { - "IBM Code Page 037", - "IBM037", - "", - "CodePage037", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm", - }, - { - "IBM Code Page 437", - "PC8CodePage437", - "", - "CodePage437", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm", - }, - { - "IBM Code Page 850", - "PC850Multilingual", - "", - "CodePage850", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm", - }, - { - "IBM Code Page 852", - "PCp852", - "", - "CodePage852", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm", - }, - { - "IBM Code Page 855", - "IBM855", - "", - "CodePage855", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm", - }, - { - "Windows Code Page 858", // PC latin1 with Euro - "IBM00858", - "", - "CodePage858", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm", - }, - { - "IBM Code Page 860", - "IBM860", - "", - "CodePage860", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm", - }, - { - "IBM Code Page 862", - "PC862LatinHebrew", - "", - "CodePage862", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm", - }, - { - "IBM Code Page 863", - "IBM863", - "", - "CodePage863", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm", - }, - { - "IBM Code Page 865", - "IBM865", - "", - "CodePage865", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm", - }, - { - "IBM Code Page 866", - "IBM866", - "", - "CodePage866", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-ibm866.txt", - }, - { - "IBM Code Page 1047", - "IBM1047", - "", - "CodePage1047", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm", - }, - { - "IBM Code Page 1140", - "IBM01140", - "", - "CodePage1140", - 0x3f, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm", - }, - { - "ISO 8859-1", - "ISOLatin1", - "", - "ISO8859_1", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm", - }, - { - "ISO 8859-2", - "ISOLatin2", - "", - "ISO8859_2", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-2.txt", - }, - { - "ISO 8859-3", - "ISOLatin3", - "", - "ISO8859_3", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-3.txt", - }, - { - "ISO 8859-4", - "ISOLatin4", - "", - "ISO8859_4", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-4.txt", - }, - { - "ISO 8859-5", - "ISOLatinCyrillic", - "", - "ISO8859_5", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-5.txt", - }, - { - "ISO 8859-6", - "ISOLatinArabic", - "", - "ISO8859_6,ISO8859_6E,ISO8859_6I", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-6.txt", - }, - { - "ISO 8859-7", - "ISOLatinGreek", - "", - "ISO8859_7", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-7.txt", - }, - { - "ISO 8859-8", - "ISOLatinHebrew", - "", - "ISO8859_8,ISO8859_8E,ISO8859_8I", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-8.txt", - }, - { - "ISO 8859-9", - "ISOLatin5", - "", - "ISO8859_9", - encoding.ASCIISub, - "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm", - }, - { - "ISO 8859-10", - "ISOLatin6", - "", - "ISO8859_10", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-10.txt", - }, - { - "ISO 8859-13", - "ISO885913", - "", - "ISO8859_13", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-13.txt", - }, - { - "ISO 8859-14", - "ISO885914", - "", - "ISO8859_14", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-14.txt", - }, - { - "ISO 8859-15", - "ISO885915", - "", - "ISO8859_15", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-15.txt", - }, - { - "ISO 8859-16", - "ISO885916", - "", - "ISO8859_16", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-iso-8859-16.txt", - }, - { - "KOI8-R", - "KOI8R", - "", - "KOI8R", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-koi8-r.txt", - }, - { - "KOI8-U", - "KOI8U", - "", - "KOI8U", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-koi8-u.txt", - }, - { - "Macintosh", - "Macintosh", - "", - "Macintosh", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-macintosh.txt", - }, - { - "Macintosh Cyrillic", - "MacintoshCyrillic", - "", - "MacintoshCyrillic", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt", - }, - { - "Windows 874", - "Windows874", - "", - "Windows874", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-874.txt", - }, - { - "Windows 1250", - "Windows1250", - "", - "Windows1250", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1250.txt", - }, - { - "Windows 1251", - "Windows1251", - "", - "Windows1251", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1251.txt", - }, - { - "Windows 1252", - "Windows1252", - "", - "Windows1252", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1252.txt", - }, - { - "Windows 1253", - "Windows1253", - "", - "Windows1253", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1253.txt", - }, - { - "Windows 1254", - "Windows1254", - "", - "Windows1254", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1254.txt", - }, - { - "Windows 1255", - "Windows1255", - "", - "Windows1255", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1255.txt", - }, - { - "Windows 1256", - "Windows1256", - "", - "Windows1256", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1256.txt", - }, - { - "Windows 1257", - "Windows1257", - "", - "Windows1257", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1257.txt", - }, - { - "Windows 1258", - "Windows1258", - "", - "Windows1258", - encoding.ASCIISub, - "http://encoding.spec.whatwg.org/index-windows-1258.txt", - }, - { - "X-User-Defined", - "XUserDefined", - "It is defined at http://encoding.spec.whatwg.org/#x-user-defined", - "XUserDefined", - encoding.ASCIISub, - ascii + - "\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" + - "\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" + - "\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" + - "\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" + - "\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" + - "\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" + - "\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" + - "\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" + - "\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" + - "\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" + - "\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" + - "\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" + - "\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" + - "\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" + - "\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" + - "\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff", - }, -} - -func getWHATWG(url string) string { - res, err := http.Get(url) - if err != nil { - log.Fatalf("%q: Get: %v", url, err) - } - defer res.Body.Close() - - mapping := make([]rune, 128) - for i := range mapping { - mapping[i] = '\ufffd' - } - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := 0, 0 - if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 128 <= x { - log.Fatalf("code %d is out of range", x) - } - if 0x80 <= y && y < 0xa0 { - // We diverge from the WHATWG spec by mapping control characters - // in the range [0x80, 0xa0) to U+FFFD. - continue - } - mapping[x] = rune(y) - } - return ascii + string(mapping) -} - -func getUCM(url string) string { - res, err := http.Get(url) - if err != nil { - log.Fatalf("%q: Get: %v", url, err) - } - defer res.Body.Close() - - mapping := make([]rune, 256) - for i := range mapping { - mapping[i] = '\ufffd' - } - - charsFound := 0 - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - var c byte - var r rune - if _, err := fmt.Sscanf(s, ` \x%x |0`, &r, &c); err != nil { - continue - } - mapping[c] = r - charsFound++ - } - - if charsFound < 200 { - log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound) - } - - return string(mapping) -} - -func main() { - mibs := map[string]bool{} - all := []string{} - - w := gen.NewCodeWriter() - defer w.WriteGoFile("tables.go", "charmap") - - printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) } - - printf("import (\n") - printf("\t\"golang.org/x/text/encoding\"\n") - printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n") - printf(")\n\n") - for _, e := range encodings { - varNames := strings.Split(e.varName, ",") - all = append(all, varNames...) - varName := varNames[0] - switch { - case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"): - e.mapping = getWHATWG(e.mapping) - case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"): - e.mapping = getUCM(e.mapping) - } - - asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00 - if asciiSuperset { - low = 0x80 - } - lvn := 1 - if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") { - lvn = 3 - } - lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:] - printf("// %s is the %s encoding.\n", varName, e.name) - if e.comment != "" { - printf("//\n// %s\n", e.comment) - } - printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n", - varName, lowerVarName, lowerVarName, e.name) - if mibs[e.mib] { - log.Fatalf("MIB type %q declared multiple times.", e.mib) - } - printf("mib: identifier.%s,\n", e.mib) - printf("asciiSuperset: %t,\n", asciiSuperset) - printf("low: 0x%02x,\n", low) - printf("replacement: 0x%02x,\n", e.replacement) - - printf("decode: [256]utf8Enc{\n") - i, backMapping := 0, map[rune]byte{} - for _, c := range e.mapping { - if _, ok := backMapping[c]; !ok && c != utf8.RuneError { - backMapping[c] = byte(i) - } - var buf [8]byte - n := utf8.EncodeRune(buf[:], c) - if n > 3 { - panic(fmt.Sprintf("rune %q (%U) is too long", c, c)) - } - printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2]) - if i%2 == 1 { - printf("\n") - } - i++ - } - printf("},\n") - - printf("encode: [256]uint32{\n") - encode := make([]uint32, 0, 256) - for c, i := range backMapping { - encode = append(encode, uint32(i)<<24|uint32(c)) - } - sort.Sort(byRune(encode)) - for len(encode) < cap(encode) { - encode = append(encode, encode[len(encode)-1]) - } - for i, enc := range encode { - printf("0x%08x,", enc) - if i%8 == 7 { - printf("\n") - } - } - printf("},\n}\n") - - // Add an estimate of the size of a single Charmap{} struct value, which - // includes two 256 elem arrays of 4 bytes and some extra fields, which - // align to 3 uint64s on 64-bit architectures. - w.Size += 2*4*256 + 3*8 - } - // TODO: add proper line breaking. - printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n")) -} - -type byRune []uint32 - -func (b byRune) Len() int { return len(b) } -func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff } -func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/htmlindex/gen.go b/vendor/golang.org/x/text/encoding/htmlindex/gen.go deleted file mode 100644 index ac6b4a77fd..0000000000 --- a/vendor/golang.org/x/text/encoding/htmlindex/gen.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "strings" - - "golang.org/x/text/internal/gen" -) - -type group struct { - Encodings []struct { - Labels []string - Name string - } -} - -func main() { - gen.Init() - - r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") - var groups []group - if err := json.NewDecoder(r).Decode(&groups); err != nil { - log.Fatalf("Error reading encodings.json: %v", err) - } - - w := &bytes.Buffer{} - fmt.Fprintln(w, "type htmlEncoding byte") - fmt.Fprintln(w, "const (") - for i, g := range groups { - for _, e := range g.Encodings { - key := strings.ToLower(e.Name) - name := consts[key] - if name == "" { - log.Fatalf("No const defined for %s.", key) - } - if i == 0 { - fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) - } else { - fmt.Fprintf(w, "%s\n", name) - } - } - } - fmt.Fprintln(w, "numEncodings") - fmt.Fprint(w, ")\n\n") - - fmt.Fprintln(w, "var canonical = [numEncodings]string{") - for _, g := range groups { - for _, e := range g.Encodings { - fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) - } - } - fmt.Fprint(w, "}\n\n") - - fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") - for _, g := range groups { - for _, e := range g.Encodings { - for _, l := range e.Labels { - key := strings.ToLower(e.Name) - name := consts[key] - fmt.Fprintf(w, "%q: %s,\n", l, name) - } - } - } - fmt.Fprint(w, "}\n\n") - - var tags []string - fmt.Fprintln(w, "var localeMap = []htmlEncoding{") - for _, loc := range locales { - tags = append(tags, loc.tag) - fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) - } - fmt.Fprint(w, "}\n\n") - - fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) - - gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) -} - -// consts maps canonical encoding name to internal constant. -var consts = map[string]string{ - "utf-8": "utf8", - "ibm866": "ibm866", - "iso-8859-2": "iso8859_2", - "iso-8859-3": "iso8859_3", - "iso-8859-4": "iso8859_4", - "iso-8859-5": "iso8859_5", - "iso-8859-6": "iso8859_6", - "iso-8859-7": "iso8859_7", - "iso-8859-8": "iso8859_8", - "iso-8859-8-i": "iso8859_8I", - "iso-8859-10": "iso8859_10", - "iso-8859-13": "iso8859_13", - "iso-8859-14": "iso8859_14", - "iso-8859-15": "iso8859_15", - "iso-8859-16": "iso8859_16", - "koi8-r": "koi8r", - "koi8-u": "koi8u", - "macintosh": "macintosh", - "windows-874": "windows874", - "windows-1250": "windows1250", - "windows-1251": "windows1251", - "windows-1252": "windows1252", - "windows-1253": "windows1253", - "windows-1254": "windows1254", - "windows-1255": "windows1255", - "windows-1256": "windows1256", - "windows-1257": "windows1257", - "windows-1258": "windows1258", - "x-mac-cyrillic": "macintoshCyrillic", - "gbk": "gbk", - "gb18030": "gb18030", - // "hz-gb-2312": "hzgb2312", // Was removed from WhatWG - "big5": "big5", - "euc-jp": "eucjp", - "iso-2022-jp": "iso2022jp", - "shift_jis": "shiftJIS", - "euc-kr": "euckr", - "replacement": "replacement", - "utf-16be": "utf16be", - "utf-16le": "utf16le", - "x-user-defined": "xUserDefined", -} - -// locales is taken from -// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm. -var locales = []struct{ tag, name string }{ - // The default value. Explicitly state latin to benefit from the exact - // script option, while still making 1252 the default encoding for languages - // written in Latin script. - {"und_Latn", "windows-1252"}, - {"ar", "windows-1256"}, - {"ba", "windows-1251"}, - {"be", "windows-1251"}, - {"bg", "windows-1251"}, - {"cs", "windows-1250"}, - {"el", "iso-8859-7"}, - {"et", "windows-1257"}, - {"fa", "windows-1256"}, - {"he", "windows-1255"}, - {"hr", "windows-1250"}, - {"hu", "iso-8859-2"}, - {"ja", "shift_jis"}, - {"kk", "windows-1251"}, - {"ko", "euc-kr"}, - {"ku", "windows-1254"}, - {"ky", "windows-1251"}, - {"lt", "windows-1257"}, - {"lv", "windows-1257"}, - {"mk", "windows-1251"}, - {"pl", "iso-8859-2"}, - {"ru", "windows-1251"}, - {"sah", "windows-1251"}, - {"sk", "windows-1250"}, - {"sl", "iso-8859-2"}, - {"sr", "windows-1251"}, - {"tg", "windows-1251"}, - {"th", "windows-874"}, - {"tr", "windows-1254"}, - {"tt", "windows-1251"}, - {"uk", "windows-1251"}, - {"vi", "windows-1258"}, - {"zh-hans", "gb18030"}, - {"zh-hant", "big5"}, -} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go deleted file mode 100644 index 26cfef9c6b..0000000000 --- a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "bytes" - "encoding/xml" - "fmt" - "io" - "log" - "strings" - - "golang.org/x/text/internal/gen" -) - -type registry struct { - XMLName xml.Name `xml:"registry"` - Updated string `xml:"updated"` - Registry []struct { - ID string `xml:"id,attr"` - Record []struct { - Name string `xml:"name"` - Xref []struct { - Type string `xml:"type,attr"` - Data string `xml:"data,attr"` - } `xml:"xref"` - Desc struct { - Data string `xml:",innerxml"` - // Any []struct { - // Data string `xml:",chardata"` - // } `xml:",any"` - // Data string `xml:",chardata"` - } `xml:"description,"` - MIB string `xml:"value"` - Alias []string `xml:"alias"` - MIME string `xml:"preferred_alias"` - } `xml:"record"` - } `xml:"registry"` -} - -func main() { - r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") - reg := ®istry{} - if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { - log.Fatalf("Error decoding charset registry: %v", err) - } - if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { - log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) - } - - w := &bytes.Buffer{} - fmt.Fprintf(w, "const (\n") - for _, rec := range reg.Registry[0].Record { - constName := "" - for _, a := range rec.Alias { - if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { - // Some of the constant definitions have comments in them. Strip those. - constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) - } - } - if constName == "" { - switch rec.MIB { - case "2085": - constName = "HZGB2312" // Not listed as alias for some reason. - default: - log.Fatalf("No cs alias defined for %s.", rec.MIB) - } - } - if rec.MIME != "" { - rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) - } - fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) - if len(rec.Desc.Data) > 0 { - fmt.Fprint(w, "// ") - d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) - inElem := true - attr := "" - for { - t, err := d.Token() - if err != nil { - if err != io.EOF { - log.Fatal(err) - } - break - } - switch x := t.(type) { - case xml.CharData: - attr = "" // Don't need attribute info. - a := bytes.Split([]byte(x), []byte("\n")) - for i, b := range a { - if b = bytes.TrimSpace(b); len(b) != 0 { - if !inElem && i > 0 { - fmt.Fprint(w, "\n// ") - } - inElem = false - fmt.Fprintf(w, "%s ", string(b)) - } - } - case xml.StartElement: - if x.Name.Local == "xref" { - inElem = true - use := false - for _, a := range x.Attr { - if a.Name.Local == "type" { - use = use || a.Value != "person" - } - if a.Name.Local == "data" && use { - // Patch up URLs to use https. From some links, the - // https version is different from the http one. - s := a.Value - s = strings.Replace(s, "http://", "https://", -1) - s = strings.Replace(s, "/unicode/", "/", -1) - attr = s + " " - } - } - } - case xml.EndElement: - inElem = false - fmt.Fprint(w, attr) - } - } - fmt.Fprint(w, "\n") - } - for _, x := range rec.Xref { - switch x.Type { - case "rfc": - fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) - case "uri": - fmt.Fprintf(w, "// Reference: %s\n", x.Data) - } - } - fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) - fmt.Fprintln(w) - } - fmt.Fprintln(w, ")") - - gen.WriteGoFile("mib.go", "identifier", w.Bytes()) -} diff --git a/vendor/golang.org/x/text/encoding/japanese/maketables.go b/vendor/golang.org/x/text/encoding/japanese/maketables.go deleted file mode 100644 index 023957a672..0000000000 --- a/vendor/golang.org/x/text/encoding/japanese/maketables.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -// TODO: Emoji extensions? -// https://www.unicode.org/faq/emoji_dingbats.html -// https://www.unicode.org/Public/UNIDATA/EmojiSources.txt - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -type entry struct { - jisCode, table int -} - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n") - fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n") - - reverse := [65536]entry{} - for i := range reverse { - reverse[i].table = -1 - } - - tables := []struct { - url string - name string - }{ - {"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"}, - {"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"}, - } - for i, table := range tables { - res, err := http.Get(table.url) - if err != nil { - log.Fatalf("%q: Get: %v", table.url, err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := 0, uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("%q: could not parse %q", table.url, s) - } - if x < 0 || 120*94 <= x { - log.Fatalf("%q: JIS code %d is out of range", table.url, x) - } - mapping[x] = y - if reverse[y].table == -1 { - reverse[y] = entry{jisCode: x, table: i} - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("%q: scanner error: %v", table.url, err) - } - - fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n", - table.name, table.name, table.url) - fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name) - for i, m := range mapping { - if m != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, m) - } - } - fmt.Printf("}\n\n") - } - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v.table == -1 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const (\n") - fmt.Printf("\tjis0208 = 1\n") - fmt.Printf("\tjis0212 = 2\n") - fmt.Printf("\tcodeMask = 0x7f\n") - fmt.Printf("\tcodeShift = 7\n") - fmt.Printf("\ttableShift = 14\n") - fmt.Printf(")\n\n") - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("//\n") - fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n") - fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n") - fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n") - fmt.Printf("// JIS code (94*j1 + j2) within that table.\n") - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x.table == -1 { - continue - } - fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n", - j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/korean/maketables.go b/vendor/golang.org/x/text/encoding/korean/maketables.go deleted file mode 100644 index c84034fb67..0000000000 --- a/vendor/golang.org/x/text/encoding/korean/maketables.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") - fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") - - res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - reverse := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { - log.Fatalf("EUC-KR code %d is out of range", x) - } - mapping[x] = y - if reverse[y] == 0 { - c0, c1 := uint16(0), uint16(0) - if x < 178*(0xc7-0x81) { - c0 = uint16(x/178) + 0x81 - c1 = uint16(x % 178) - switch { - case c1 < 1*26: - c1 += 0x41 - case c1 < 2*26: - c1 += 0x47 - default: - c1 += 0x4d - } - } else { - x -= 178 * (0xc7 - 0x81) - c0 = uint16(x/94) + 0xc7 - c1 = uint16(x%94) + 0xa1 - } - reverse[y] = c0<<8 | c1 - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") - fmt.Printf("var decode = [...]uint16{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go deleted file mode 100644 index 55016c7862..0000000000 --- a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") - fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") - - printGB18030() - printGBK() -} - -func printGB18030() { - res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") - fmt.Printf("var gb18030 = [...][2]uint16{\n") - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint32(0), uint32(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0x10000 && y < 0x10000 { - fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) - } - } - fmt.Printf("}\n\n") -} - -func printGBK() { - res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint16{} - reverse := [65536]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint16(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 126*190 <= x { - log.Fatalf("GBK code %d is out of range", x) - } - mapping[x] = y - if reverse[y] == 0 { - c0, c1 := x/190, x%190 - if c1 >= 0x3f { - c1++ - } - reverse[y] = (0x81+c0)<<8 | (0x40 + c1) - } - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") - fmt.Printf("var decode = [...]uint16{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%04X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go deleted file mode 100644 index cf7fdb31a5..0000000000 --- a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates tables.go: -// go run maketables.go | gofmt > tables.go - -import ( - "bufio" - "fmt" - "log" - "net/http" - "sort" - "strings" -) - -func main() { - fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") - fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") - fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") - - res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") - if err != nil { - log.Fatalf("Get: %v", err) - } - defer res.Body.Close() - - mapping := [65536]uint32{} - reverse := [65536 * 4]uint16{} - - scanner := bufio.NewScanner(res.Body) - for scanner.Scan() { - s := strings.TrimSpace(scanner.Text()) - if s == "" || s[0] == '#' { - continue - } - x, y := uint16(0), uint32(0) - if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { - log.Fatalf("could not parse %q", s) - } - if x < 0 || 126*157 <= x { - log.Fatalf("Big5 code %d is out of range", x) - } - mapping[x] = y - - // The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that - // "The index pointer for code point in index is the first pointer - // corresponding to code point in index", which would normally mean - // that the code below should be guarded by "if reverse[y] == 0", but - // last instead of first seems to match the behavior of - // "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in - // http://encoding.spec.whatwg.org/index-big5.txt, as index 2148 - // (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc") - // and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc". - c0, c1 := x/157, x%157 - if c1 < 0x3f { - c1 += 0x40 - } else { - c1 += 0x62 - } - reverse[y] = (0x81+c0)<<8 | c1 - } - if err := scanner.Err(); err != nil { - log.Fatalf("scanner error: %v", err) - } - - fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") - fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") - fmt.Printf("var decode = [...]uint32{\n") - for i, v := range mapping { - if v != 0 { - fmt.Printf("\t%d: 0x%08X,\n", i, v) - } - } - fmt.Printf("}\n\n") - - // Any run of at least separation continuous zero entries in the reverse map will - // be a separate encode table. - const separation = 1024 - - intervals := []interval(nil) - low, high := -1, -1 - for i, v := range reverse { - if v == 0 { - continue - } - if low < 0 { - low = i - } else if i-high >= separation { - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - low = i - } - high = i + 1 - } - if high >= 0 { - intervals = append(intervals, interval{low, high}) - } - sort.Sort(byDecreasingLength(intervals)) - - fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) - fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") - fmt.Printf("// sorted by decreasing length.\n") - for i, v := range intervals { - fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) - } - fmt.Printf("\n") - - for i, v := range intervals { - fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) - fmt.Printf("var encode%d = [...]uint16{\n", i) - for j := v.low; j < v.high; j++ { - x := reverse[j] - if x == 0 { - continue - } - fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) - } - fmt.Printf("}\n\n") - } -} - -// interval is a half-open interval [low, high). -type interval struct { - low, high int -} - -func (i interval) len() int { return i.high - i.low } - -// byDecreasingLength sorts intervals by decreasing length. -type byDecreasingLength []interval - -func (b byDecreasingLength) Len() int { return len(b) } -func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } -func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/internal/language/compact/gen.go b/vendor/golang.org/x/text/internal/language/compact/gen.go deleted file mode 100644 index 0c36a052f6..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Language tag table generator. -// Data read from the web. - -package main - -import ( - "flag" - "fmt" - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/unicode/cldr" -) - -var ( - test = flag.Bool("test", - false, - "test existing tables; can be used to compare web data with package data.") - outputFile = flag.String("output", - "tables.go", - "output file for generated tables") -) - -func main() { - gen.Init() - - w := gen.NewCodeWriter() - defer w.WriteGoFile("tables.go", "compact") - - fmt.Fprintln(w, `import "golang.org/x/text/internal/language"`) - - b := newBuilder(w) - gen.WriteCLDRVersion(w) - - b.writeCompactIndex() -} - -type builder struct { - w *gen.CodeWriter - data *cldr.CLDR - supp *cldr.SupplementalData -} - -func newBuilder(w *gen.CodeWriter) *builder { - r := gen.OpenCLDRCoreZip() - defer r.Close() - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - if err != nil { - log.Fatal(err) - } - b := builder{ - w: w, - data: data, - supp: data.Supplemental(), - } - return &b -} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_index.go b/vendor/golang.org/x/text/internal/language/compact/gen_index.go deleted file mode 100644 index 136cefaf08..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen_index.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This file generates derivative tables based on the language package itself. - -import ( - "fmt" - "log" - "sort" - "strings" - - "golang.org/x/text/internal/language" -) - -// Compact indices: -// Note -va-X variants only apply to localization variants. -// BCP variants only ever apply to language. -// The only ambiguity between tags is with regions. - -func (b *builder) writeCompactIndex() { - // Collect all language tags for which we have any data in CLDR. - m := map[language.Tag]bool{} - for _, lang := range b.data.Locales() { - // We include all locales unconditionally to be consistent with en_US. - // We want en_US, even though it has no data associated with it. - - // TODO: put any of the languages for which no data exists at the end - // of the index. This allows all components based on ICU to use that - // as the cutoff point. - // if x := data.RawLDML(lang); false || - // x.LocaleDisplayNames != nil || - // x.Characters != nil || - // x.Delimiters != nil || - // x.Measurement != nil || - // x.Dates != nil || - // x.Numbers != nil || - // x.Units != nil || - // x.ListPatterns != nil || - // x.Collations != nil || - // x.Segmentations != nil || - // x.Rbnf != nil || - // x.Annotations != nil || - // x.Metadata != nil { - - // TODO: support POSIX natively, albeit non-standard. - tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1)) - m[tag] = true - // } - } - - // TODO: plural rules are also defined for the deprecated tags: - // iw mo sh tl - // Consider removing these as compact tags. - - // Include locales for plural rules, which uses a different structure. - for _, plurals := range b.supp.Plurals { - for _, rules := range plurals.PluralRules { - for _, lang := range strings.Split(rules.Locales, " ") { - m[language.Make(lang)] = true - } - } - } - - var coreTags []language.CompactCoreInfo - var special []string - - for t := range m { - if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { - log.Fatalf("Unexpected extension %v in %v", x, t) - } - if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { - cci, ok := language.GetCompactCore(t) - if !ok { - log.Fatalf("Locale for non-basic language %q", t) - } - coreTags = append(coreTags, cci) - } else { - special = append(special, t.String()) - } - } - - w := b.w - - sort.Slice(coreTags, func(i, j int) bool { return coreTags[i] < coreTags[j] }) - sort.Strings(special) - - w.WriteComment(` - NumCompactTags is the number of common tags. The maximum tag is - NumCompactTags-1.`) - w.WriteConst("NumCompactTags", len(m)) - - fmt.Fprintln(w, "const (") - for i, t := range coreTags { - fmt.Fprintf(w, "%s ID = %d\n", ident(t.Tag().String()), i) - } - for i, t := range special { - fmt.Fprintf(w, "%s ID = %d\n", ident(t), i+len(coreTags)) - } - fmt.Fprintln(w, ")") - - w.WriteVar("coreTags", coreTags) - - w.WriteConst("specialTagsStr", strings.Join(special, " ")) -} - -func ident(s string) string { - return strings.Replace(s, "-", "", -1) + "Index" -} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go deleted file mode 100644 index 9543d58323..0000000000 --- a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/language" - "golang.org/x/text/internal/language/compact" - "golang.org/x/text/unicode/cldr" -) - -func main() { - r := gen.OpenCLDRCoreZip() - defer r.Close() - - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - if err != nil { - log.Fatalf("DecodeZip: %v", err) - } - - w := gen.NewCodeWriter() - defer w.WriteGoFile("parents.go", "compact") - - // Create parents table. - type ID uint16 - parents := make([]ID, compact.NumCompactTags) - for _, loc := range data.Locales() { - tag := language.MustParse(loc) - index, ok := compact.FromTag(tag) - if !ok { - continue - } - parentIndex := compact.ID(0) // und - for p := tag.Parent(); p != language.Und; p = p.Parent() { - if x, ok := compact.FromTag(p); ok { - parentIndex = x - break - } - } - parents[index] = ID(parentIndex) - } - - w.WriteComment(` - parents maps a compact index of a tag to the compact index of the parent of - this tag.`) - w.WriteVar("parents", parents) -} diff --git a/vendor/golang.org/x/text/internal/language/gen.go b/vendor/golang.org/x/text/internal/language/gen.go deleted file mode 100644 index cdcc7febcb..0000000000 --- a/vendor/golang.org/x/text/internal/language/gen.go +++ /dev/null @@ -1,1520 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Language tag table generator. -// Data read from the web. - -package main - -import ( - "bufio" - "flag" - "fmt" - "io" - "io/ioutil" - "log" - "math" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/tag" - "golang.org/x/text/unicode/cldr" -) - -var ( - test = flag.Bool("test", - false, - "test existing tables; can be used to compare web data with package data.") - outputFile = flag.String("output", - "tables.go", - "output file for generated tables") -) - -var comment = []string{ - ` -lang holds an alphabetically sorted list of ISO-639 language identifiers. -All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag. -For 2-byte language identifiers, the two successive bytes have the following meaning: - - if the first letter of the 2- and 3-letter ISO codes are the same: - the second and third letter of the 3-letter ISO code. - - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3. -For 3-byte language identifiers the 4th byte is 0.`, - ` -langNoIndex is a bit vector of all 3-letter language codes that are not used as an index -in lookup tables. The language ids for these language codes are derived directly -from the letters and are not consecutive.`, - ` -altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives -to 2-letter language codes that cannot be derived using the method described above. -Each 3-letter code is followed by its 1-byte langID.`, - ` -altLangIndex is used to convert indexes in altLangISO3 to langIDs.`, - ` -AliasMap maps langIDs to their suggested replacements.`, - ` -script is an alphabetically sorted list of ISO 15924 codes. The index -of the script in the string, divided by 4, is the internal scriptID.`, - ` -isoRegionOffset needs to be added to the index of regionISO to obtain the regionID -for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for -the UN.M49 codes used for groups.)`, - ` -regionISO holds a list of alphabetically sorted 2-letter ISO region codes. -Each 2-letter codes is followed by two bytes with the following meaning: - - [A-Z}{2}: the first letter of the 2-letter code plus these two - letters form the 3-letter ISO code. - - 0, n: index into altRegionISO3.`, - ` -regionTypes defines the status of a region for various standards.`, - ` -m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are -codes indicating collections of regions.`, - ` -m49Index gives indexes into fromM49 based on the three most significant bits -of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in - fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]] -for an entry where the first 7 bits match the 7 lsb of the UN.M49 code. -The region code is stored in the 9 lsb of the indexed value.`, - ` -fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.`, - ` -altRegionISO3 holds a list of 3-letter region codes that cannot be -mapped to 2-letter codes using the default algorithm. This is a short list.`, - ` -altRegionIDs holds a list of regionIDs the positions of which match those -of the 3-letter ISO codes in altRegionISO3.`, - ` -variantNumSpecialized is the number of specialized variants in variants.`, - ` -suppressScript is an index from langID to the dominant script for that language, -if it exists. If a script is given, it should be suppressed from the language tag.`, - ` -likelyLang is a lookup table, indexed by langID, for the most likely -scripts and regions given incomplete information. If more entries exist for a -given language, region and script are the index and size respectively -of the list in likelyLangList.`, - ` -likelyLangList holds lists info associated with likelyLang.`, - ` -likelyRegion is a lookup table, indexed by regionID, for the most likely -languages and scripts given incomplete information. If more entries exist -for a given regionID, lang and script are the index and size respectively -of the list in likelyRegionList. -TODO: exclude containers and user-definable regions from the list.`, - ` -likelyRegionList holds lists info associated with likelyRegion.`, - ` -likelyScript is a lookup table, indexed by scriptID, for the most likely -languages and regions given a script.`, - ` -nRegionGroups is the number of region groups.`, - ` -regionInclusion maps region identifiers to sets of regions in regionInclusionBits, -where each set holds all groupings that are directly connected in a region -containment graph.`, - ` -regionInclusionBits is an array of bit vectors where every vector represents -a set of region groupings. These sets are used to compute the distance -between two regions for the purpose of language matching.`, - ` -regionInclusionNext marks, for each entry in regionInclusionBits, the set of -all groups that are reachable from the groups set in the respective entry.`, -} - -// TODO: consider changing some of these structures to tries. This can reduce -// memory, but may increase the need for memory allocations. This could be -// mitigated if we can piggyback on language tags for common cases. - -func failOnError(e error) { - if e != nil { - log.Panic(e) - } -} - -type setType int - -const ( - Indexed setType = 1 + iota // all elements must be of same size - Linear -) - -type stringSet struct { - s []string - sorted, frozen bool - - // We often need to update values after the creation of an index is completed. - // We include a convenience map for keeping track of this. - update map[string]string - typ setType // used for checking. -} - -func (ss *stringSet) clone() stringSet { - c := *ss - c.s = append([]string(nil), c.s...) - return c -} - -func (ss *stringSet) setType(t setType) { - if ss.typ != t && ss.typ != 0 { - log.Panicf("type %d cannot be assigned as it was already %d", t, ss.typ) - } -} - -// parse parses a whitespace-separated string and initializes ss with its -// components. -func (ss *stringSet) parse(s string) { - scan := bufio.NewScanner(strings.NewReader(s)) - scan.Split(bufio.ScanWords) - for scan.Scan() { - ss.add(scan.Text()) - } -} - -func (ss *stringSet) assertChangeable() { - if ss.frozen { - log.Panic("attempt to modify a frozen stringSet") - } -} - -func (ss *stringSet) add(s string) { - ss.assertChangeable() - ss.s = append(ss.s, s) - ss.sorted = ss.frozen -} - -func (ss *stringSet) freeze() { - ss.compact() - ss.frozen = true -} - -func (ss *stringSet) compact() { - if ss.sorted { - return - } - a := ss.s - sort.Strings(a) - k := 0 - for i := 1; i < len(a); i++ { - if a[k] != a[i] { - a[k+1] = a[i] - k++ - } - } - ss.s = a[:k+1] - ss.sorted = ss.frozen -} - -type funcSorter struct { - fn func(a, b string) bool - sort.StringSlice -} - -func (s funcSorter) Less(i, j int) bool { - return s.fn(s.StringSlice[i], s.StringSlice[j]) -} - -func (ss *stringSet) sortFunc(f func(a, b string) bool) { - ss.compact() - sort.Sort(funcSorter{f, sort.StringSlice(ss.s)}) -} - -func (ss *stringSet) remove(s string) { - ss.assertChangeable() - if i, ok := ss.find(s); ok { - copy(ss.s[i:], ss.s[i+1:]) - ss.s = ss.s[:len(ss.s)-1] - } -} - -func (ss *stringSet) replace(ol, nu string) { - ss.s[ss.index(ol)] = nu - ss.sorted = ss.frozen -} - -func (ss *stringSet) index(s string) int { - ss.setType(Indexed) - i, ok := ss.find(s) - if !ok { - if i < len(ss.s) { - log.Panicf("find: item %q is not in list. Closest match is %q.", s, ss.s[i]) - } - log.Panicf("find: item %q is not in list", s) - - } - return i -} - -func (ss *stringSet) find(s string) (int, bool) { - ss.compact() - i := sort.SearchStrings(ss.s, s) - return i, i != len(ss.s) && ss.s[i] == s -} - -func (ss *stringSet) slice() []string { - ss.compact() - return ss.s -} - -func (ss *stringSet) updateLater(v, key string) { - if ss.update == nil { - ss.update = map[string]string{} - } - ss.update[v] = key -} - -// join joins the string and ensures that all entries are of the same length. -func (ss *stringSet) join() string { - ss.setType(Indexed) - n := len(ss.s[0]) - for _, s := range ss.s { - if len(s) != n { - log.Panicf("join: not all entries are of the same length: %q", s) - } - } - ss.s = append(ss.s, strings.Repeat("\xff", n)) - return strings.Join(ss.s, "") -} - -// ianaEntry holds information for an entry in the IANA Language Subtag Repository. -// All types use the same entry. -// See http://tools.ietf.org/html/bcp47#section-5.1 for a description of the various -// fields. -type ianaEntry struct { - typ string - description []string - scope string - added string - preferred string - deprecated string - suppressScript string - macro string - prefix []string -} - -type builder struct { - w *gen.CodeWriter - hw io.Writer // MultiWriter for w and w.Hash - data *cldr.CLDR - supp *cldr.SupplementalData - - // indices - locale stringSet // common locales - lang stringSet // canonical language ids (2 or 3 letter ISO codes) with data - langNoIndex stringSet // 3-letter ISO codes with no associated data - script stringSet // 4-letter ISO codes - region stringSet // 2-letter ISO or 3-digit UN M49 codes - variant stringSet // 4-8-alphanumeric variant code. - - // Region codes that are groups with their corresponding group IDs. - groups map[int]index - - // langInfo - registry map[string]*ianaEntry -} - -type index uint - -func newBuilder(w *gen.CodeWriter) *builder { - r := gen.OpenCLDRCoreZip() - defer r.Close() - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - failOnError(err) - b := builder{ - w: w, - hw: io.MultiWriter(w, w.Hash), - data: data, - supp: data.Supplemental(), - } - b.parseRegistry() - return &b -} - -func (b *builder) parseRegistry() { - r := gen.OpenIANAFile("assignments/language-subtag-registry") - defer r.Close() - b.registry = make(map[string]*ianaEntry) - - scan := bufio.NewScanner(r) - scan.Split(bufio.ScanWords) - var record *ianaEntry - for more := scan.Scan(); more; { - key := scan.Text() - more = scan.Scan() - value := scan.Text() - switch key { - case "Type:": - record = &ianaEntry{typ: value} - case "Subtag:", "Tag:": - if s := strings.SplitN(value, "..", 2); len(s) > 1 { - for a := s[0]; a <= s[1]; a = inc(a) { - b.addToRegistry(a, record) - } - } else { - b.addToRegistry(value, record) - } - case "Suppress-Script:": - record.suppressScript = value - case "Added:": - record.added = value - case "Deprecated:": - record.deprecated = value - case "Macrolanguage:": - record.macro = value - case "Preferred-Value:": - record.preferred = value - case "Prefix:": - record.prefix = append(record.prefix, value) - case "Scope:": - record.scope = value - case "Description:": - buf := []byte(value) - for more = scan.Scan(); more; more = scan.Scan() { - b := scan.Bytes() - if b[0] == '%' || b[len(b)-1] == ':' { - break - } - buf = append(buf, ' ') - buf = append(buf, b...) - } - record.description = append(record.description, string(buf)) - continue - default: - continue - } - more = scan.Scan() - } - if scan.Err() != nil { - log.Panic(scan.Err()) - } -} - -func (b *builder) addToRegistry(key string, entry *ianaEntry) { - if info, ok := b.registry[key]; ok { - if info.typ != "language" || entry.typ != "extlang" { - log.Fatalf("parseRegistry: tag %q already exists", key) - } - } else { - b.registry[key] = entry - } -} - -var commentIndex = make(map[string]string) - -func init() { - for _, s := range comment { - key := strings.TrimSpace(strings.SplitN(s, " ", 2)[0]) - commentIndex[key] = s - } -} - -func (b *builder) comment(name string) { - if s := commentIndex[name]; len(s) > 0 { - b.w.WriteComment(s) - } else { - fmt.Fprintln(b.w) - } -} - -func (b *builder) pf(f string, x ...interface{}) { - fmt.Fprintf(b.hw, f, x...) - fmt.Fprint(b.hw, "\n") -} - -func (b *builder) p(x ...interface{}) { - fmt.Fprintln(b.hw, x...) -} - -func (b *builder) addSize(s int) { - b.w.Size += s - b.pf("// Size: %d bytes", s) -} - -func (b *builder) writeConst(name string, x interface{}) { - b.comment(name) - b.w.WriteConst(name, x) -} - -// writeConsts computes f(v) for all v in values and writes the results -// as constants named _v to a single constant block. -func (b *builder) writeConsts(f func(string) int, values ...string) { - b.pf("const (") - for _, v := range values { - b.pf("\t_%s = %v", v, f(v)) - } - b.pf(")") -} - -// writeType writes the type of the given value, which must be a struct. -func (b *builder) writeType(value interface{}) { - b.comment(reflect.TypeOf(value).Name()) - b.w.WriteType(value) -} - -func (b *builder) writeSlice(name string, ss interface{}) { - b.writeSliceAddSize(name, 0, ss) -} - -func (b *builder) writeSliceAddSize(name string, extraSize int, ss interface{}) { - b.comment(name) - b.w.Size += extraSize - v := reflect.ValueOf(ss) - t := v.Type().Elem() - b.pf("// Size: %d bytes, %d elements", v.Len()*int(t.Size())+extraSize, v.Len()) - - fmt.Fprintf(b.w, "var %s = ", name) - b.w.WriteArray(ss) - b.p() -} - -type FromTo struct { - From, To uint16 -} - -func (b *builder) writeSortedMap(name string, ss *stringSet, index func(s string) uint16) { - ss.sortFunc(func(a, b string) bool { - return index(a) < index(b) - }) - m := []FromTo{} - for _, s := range ss.s { - m = append(m, FromTo{index(s), index(ss.update[s])}) - } - b.writeSlice(name, m) -} - -const base = 'z' - 'a' + 1 - -func strToInt(s string) uint { - v := uint(0) - for i := 0; i < len(s); i++ { - v *= base - v += uint(s[i] - 'a') - } - return v -} - -// converts the given integer to the original ASCII string passed to strToInt. -// len(s) must match the number of characters obtained. -func intToStr(v uint, s []byte) { - for i := len(s) - 1; i >= 0; i-- { - s[i] = byte(v%base) + 'a' - v /= base - } -} - -func (b *builder) writeBitVector(name string, ss []string) { - vec := make([]uint8, int(math.Ceil(math.Pow(base, float64(len(ss[0])))/8))) - for _, s := range ss { - v := strToInt(s) - vec[v/8] |= 1 << (v % 8) - } - b.writeSlice(name, vec) -} - -// TODO: convert this type into a list or two-stage trie. -func (b *builder) writeMapFunc(name string, m map[string]string, f func(string) uint16) { - b.comment(name) - v := reflect.ValueOf(m) - sz := v.Len() * (2 + int(v.Type().Key().Size())) - for _, k := range m { - sz += len(k) - } - b.addSize(sz) - keys := []string{} - b.pf(`var %s = map[string]uint16{`, name) - for k := range m { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - b.pf("\t%q: %v,", k, f(m[k])) - } - b.p("}") -} - -func (b *builder) writeMap(name string, m interface{}) { - b.comment(name) - v := reflect.ValueOf(m) - sz := v.Len() * (2 + int(v.Type().Key().Size()) + int(v.Type().Elem().Size())) - b.addSize(sz) - f := strings.FieldsFunc(fmt.Sprintf("%#v", m), func(r rune) bool { - return strings.IndexRune("{}, ", r) != -1 - }) - sort.Strings(f[1:]) - b.pf(`var %s = %s{`, name, f[0]) - for _, kv := range f[1:] { - b.pf("\t%s,", kv) - } - b.p("}") -} - -func (b *builder) langIndex(s string) uint16 { - if s == "und" { - return 0 - } - if i, ok := b.lang.find(s); ok { - return uint16(i) - } - return uint16(strToInt(s)) + uint16(len(b.lang.s)) -} - -// inc advances the string to its lexicographical successor. -func inc(s string) string { - const maxTagLength = 4 - var buf [maxTagLength]byte - intToStr(strToInt(strings.ToLower(s))+1, buf[:len(s)]) - for i := 0; i < len(s); i++ { - if s[i] <= 'Z' { - buf[i] -= 'a' - 'A' - } - } - return string(buf[:len(s)]) -} - -func (b *builder) parseIndices() { - meta := b.supp.Metadata - - for k, v := range b.registry { - var ss *stringSet - switch v.typ { - case "language": - if len(k) == 2 || v.suppressScript != "" || v.scope == "special" { - b.lang.add(k) - continue - } else { - ss = &b.langNoIndex - } - case "region": - ss = &b.region - case "script": - ss = &b.script - case "variant": - ss = &b.variant - default: - continue - } - ss.add(k) - } - // Include any language for which there is data. - for _, lang := range b.data.Locales() { - if x := b.data.RawLDML(lang); false || - x.LocaleDisplayNames != nil || - x.Characters != nil || - x.Delimiters != nil || - x.Measurement != nil || - x.Dates != nil || - x.Numbers != nil || - x.Units != nil || - x.ListPatterns != nil || - x.Collations != nil || - x.Segmentations != nil || - x.Rbnf != nil || - x.Annotations != nil || - x.Metadata != nil { - - from := strings.Split(lang, "_") - if lang := from[0]; lang != "root" { - b.lang.add(lang) - } - } - } - // Include locales for plural rules, which uses a different structure. - for _, plurals := range b.data.Supplemental().Plurals { - for _, rules := range plurals.PluralRules { - for _, lang := range strings.Split(rules.Locales, " ") { - if lang = strings.Split(lang, "_")[0]; lang != "root" { - b.lang.add(lang) - } - } - } - } - // Include languages in likely subtags. - for _, m := range b.supp.LikelySubtags.LikelySubtag { - from := strings.Split(m.From, "_") - b.lang.add(from[0]) - } - // Include ISO-639 alpha-3 bibliographic entries. - for _, a := range meta.Alias.LanguageAlias { - if a.Reason == "bibliographic" { - b.langNoIndex.add(a.Type) - } - } - // Include regions in territoryAlias (not all are in the IANA registry!) - for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { - if len(reg.Type) == 2 { - b.region.add(reg.Type) - } - } - - for _, s := range b.lang.s { - if len(s) == 3 { - b.langNoIndex.remove(s) - } - } - b.writeConst("NumLanguages", len(b.lang.slice())+len(b.langNoIndex.slice())) - b.writeConst("NumScripts", len(b.script.slice())) - b.writeConst("NumRegions", len(b.region.slice())) - - // Add dummy codes at the start of each list to represent "unspecified". - b.lang.add("---") - b.script.add("----") - b.region.add("---") - - // common locales - b.locale.parse(meta.DefaultContent.Locales) -} - -// TODO: region inclusion data will probably not be use used in future matchers. - -func (b *builder) computeRegionGroups() { - b.groups = make(map[int]index) - - // Create group indices. - for i := 1; b.region.s[i][0] < 'A'; i++ { // Base M49 indices on regionID. - b.groups[i] = index(len(b.groups)) - } - for _, g := range b.supp.TerritoryContainment.Group { - // Skip UN and EURO zone as they are flattening the containment - // relationship. - if g.Type == "EZ" || g.Type == "UN" { - continue - } - group := b.region.index(g.Type) - if _, ok := b.groups[group]; !ok { - b.groups[group] = index(len(b.groups)) - } - } - if len(b.groups) > 64 { - log.Fatalf("only 64 groups supported, found %d", len(b.groups)) - } - b.writeConst("nRegionGroups", len(b.groups)) -} - -var langConsts = []string{ - "af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", - "et", "fa", "fi", "fil", "fr", "gu", "he", "hi", "hr", "hu", "hy", "id", "is", - "it", "ja", "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", - "mn", "mo", "mr", "ms", "mul", "my", "nb", "ne", "nl", "no", "pa", "pl", "pt", - "ro", "ru", "sh", "si", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", - "tl", "tn", "tr", "uk", "ur", "uz", "vi", "zh", "zu", - - // constants for grandfathered tags (if not already defined) - "jbo", "ami", "bnn", "hak", "tlh", "lb", "nv", "pwn", "tao", "tay", "tsu", - "nn", "sfb", "vgt", "sgg", "cmn", "nan", "hsn", -} - -// writeLanguage generates all tables needed for language canonicalization. -func (b *builder) writeLanguage() { - meta := b.supp.Metadata - - b.writeConst("nonCanonicalUnd", b.lang.index("und")) - b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...) - b.writeConst("langPrivateStart", b.langIndex("qaa")) - b.writeConst("langPrivateEnd", b.langIndex("qtz")) - - // Get language codes that need to be mapped (overlong 3-letter codes, - // deprecated 2-letter codes, legacy and grandfathered tags.) - langAliasMap := stringSet{} - aliasTypeMap := map[string]AliasType{} - - // altLangISO3 get the alternative ISO3 names that need to be mapped. - altLangISO3 := stringSet{} - // Add dummy start to avoid the use of index 0. - altLangISO3.add("---") - altLangISO3.updateLater("---", "aa") - - lang := b.lang.clone() - for _, a := range meta.Alias.LanguageAlias { - if a.Replacement == "" { - a.Replacement = "und" - } - // TODO: support mapping to tags - repl := strings.SplitN(a.Replacement, "_", 2)[0] - if a.Reason == "overlong" { - if len(a.Replacement) == 2 && len(a.Type) == 3 { - lang.updateLater(a.Replacement, a.Type) - } - } else if len(a.Type) <= 3 { - switch a.Reason { - case "macrolanguage": - aliasTypeMap[a.Type] = Macro - case "deprecated": - // handled elsewhere - continue - case "bibliographic", "legacy": - if a.Type == "no" { - continue - } - aliasTypeMap[a.Type] = Legacy - default: - log.Fatalf("new %s alias: %s", a.Reason, a.Type) - } - langAliasMap.add(a.Type) - langAliasMap.updateLater(a.Type, repl) - } - } - // Manually add the mapping of "nb" (Norwegian) to its macro language. - // This can be removed if CLDR adopts this change. - langAliasMap.add("nb") - langAliasMap.updateLater("nb", "no") - aliasTypeMap["nb"] = Macro - - for k, v := range b.registry { - // Also add deprecated values for 3-letter ISO codes, which CLDR omits. - if v.typ == "language" && v.deprecated != "" && v.preferred != "" { - langAliasMap.add(k) - langAliasMap.updateLater(k, v.preferred) - aliasTypeMap[k] = Deprecated - } - } - // Fix CLDR mappings. - lang.updateLater("tl", "tgl") - lang.updateLater("sh", "hbs") - lang.updateLater("mo", "mol") - lang.updateLater("no", "nor") - lang.updateLater("tw", "twi") - lang.updateLater("nb", "nob") - lang.updateLater("ak", "aka") - lang.updateLater("bh", "bih") - - // Ensure that each 2-letter code is matched with a 3-letter code. - for _, v := range lang.s[1:] { - s, ok := lang.update[v] - if !ok { - if s, ok = lang.update[langAliasMap.update[v]]; !ok { - continue - } - lang.update[v] = s - } - if v[0] != s[0] { - altLangISO3.add(s) - altLangISO3.updateLater(s, v) - } - } - - // Complete canonicalized language tags. - lang.freeze() - for i, v := range lang.s { - // We can avoid these manual entries by using the IANA registry directly. - // Seems easier to update the list manually, as changes are rare. - // The panic in this loop will trigger if we miss an entry. - add := "" - if s, ok := lang.update[v]; ok { - if s[0] == v[0] { - add = s[1:] - } else { - add = string([]byte{0, byte(altLangISO3.index(s))}) - } - } else if len(v) == 3 { - add = "\x00" - } else { - log.Panicf("no data for long form of %q", v) - } - lang.s[i] += add - } - b.writeConst("lang", tag.Index(lang.join())) - - b.writeConst("langNoIndexOffset", len(b.lang.s)) - - // space of all valid 3-letter language identifiers. - b.writeBitVector("langNoIndex", b.langNoIndex.slice()) - - altLangIndex := []uint16{} - for i, s := range altLangISO3.slice() { - altLangISO3.s[i] += string([]byte{byte(len(altLangIndex))}) - if i > 0 { - idx := b.lang.index(altLangISO3.update[s]) - altLangIndex = append(altLangIndex, uint16(idx)) - } - } - b.writeConst("altLangISO3", tag.Index(altLangISO3.join())) - b.writeSlice("altLangIndex", altLangIndex) - - b.writeSortedMap("AliasMap", &langAliasMap, b.langIndex) - types := make([]AliasType, len(langAliasMap.s)) - for i, s := range langAliasMap.s { - types[i] = aliasTypeMap[s] - } - b.writeSlice("AliasTypes", types) -} - -var scriptConsts = []string{ - "Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy", - "Zzzz", -} - -func (b *builder) writeScript() { - b.writeConsts(b.script.index, scriptConsts...) - b.writeConst("script", tag.Index(b.script.join())) - - supp := make([]uint8, len(b.lang.slice())) - for i, v := range b.lang.slice()[1:] { - if sc := b.registry[v].suppressScript; sc != "" { - supp[i+1] = uint8(b.script.index(sc)) - } - } - b.writeSlice("suppressScript", supp) - - // There is only one deprecated script in CLDR. This value is hard-coded. - // We check here if the code must be updated. - for _, a := range b.supp.Metadata.Alias.ScriptAlias { - if a.Type != "Qaai" { - log.Panicf("unexpected deprecated stript %q", a.Type) - } - } -} - -func parseM49(s string) int16 { - if len(s) == 0 { - return 0 - } - v, err := strconv.ParseUint(s, 10, 10) - failOnError(err) - return int16(v) -} - -var regionConsts = []string{ - "001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US", - "ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo. -} - -func (b *builder) writeRegion() { - b.writeConsts(b.region.index, regionConsts...) - - isoOffset := b.region.index("AA") - m49map := make([]int16, len(b.region.slice())) - fromM49map := make(map[int16]int) - altRegionISO3 := "" - altRegionIDs := []uint16{} - - b.writeConst("isoRegionOffset", isoOffset) - - // 2-letter region lookup and mapping to numeric codes. - regionISO := b.region.clone() - regionISO.s = regionISO.s[isoOffset:] - regionISO.sorted = false - - regionTypes := make([]byte, len(b.region.s)) - - // Is the region valid BCP 47? - for s, e := range b.registry { - if len(s) == 2 && s == strings.ToUpper(s) { - i := b.region.index(s) - for _, d := range e.description { - if strings.Contains(d, "Private use") { - regionTypes[i] = iso3166UserAssigned - } - } - regionTypes[i] |= bcp47Region - } - } - - // Is the region a valid ccTLD? - r := gen.OpenIANAFile("domains/root/db") - defer r.Close() - - buf, err := ioutil.ReadAll(r) - failOnError(err) - re := regexp.MustCompile(`"/domains/root/db/([a-z]{2}).html"`) - for _, m := range re.FindAllSubmatch(buf, -1) { - i := b.region.index(strings.ToUpper(string(m[1]))) - regionTypes[i] |= ccTLD - } - - b.writeSlice("regionTypes", regionTypes) - - iso3Set := make(map[string]int) - update := func(iso2, iso3 string) { - i := regionISO.index(iso2) - if j, ok := iso3Set[iso3]; !ok && iso3[0] == iso2[0] { - regionISO.s[i] += iso3[1:] - iso3Set[iso3] = -1 - } else { - if ok && j >= 0 { - regionISO.s[i] += string([]byte{0, byte(j)}) - } else { - iso3Set[iso3] = len(altRegionISO3) - regionISO.s[i] += string([]byte{0, byte(len(altRegionISO3))}) - altRegionISO3 += iso3 - altRegionIDs = append(altRegionIDs, uint16(isoOffset+i)) - } - } - } - for _, tc := range b.supp.CodeMappings.TerritoryCodes { - i := regionISO.index(tc.Type) + isoOffset - if d := m49map[i]; d != 0 { - log.Panicf("%s found as a duplicate UN.M49 code of %03d", tc.Numeric, d) - } - m49 := parseM49(tc.Numeric) - m49map[i] = m49 - if r := fromM49map[m49]; r == 0 { - fromM49map[m49] = i - } else if r != i { - dep := b.registry[regionISO.s[r-isoOffset]].deprecated - if t := b.registry[tc.Type]; t != nil && dep != "" && (t.deprecated == "" || t.deprecated > dep) { - fromM49map[m49] = i - } - } - } - for _, ta := range b.supp.Metadata.Alias.TerritoryAlias { - if len(ta.Type) == 3 && ta.Type[0] <= '9' && len(ta.Replacement) == 2 { - from := parseM49(ta.Type) - if r := fromM49map[from]; r == 0 { - fromM49map[from] = regionISO.index(ta.Replacement) + isoOffset - } - } - } - for _, tc := range b.supp.CodeMappings.TerritoryCodes { - if len(tc.Alpha3) == 3 { - update(tc.Type, tc.Alpha3) - } - } - // This entries are not included in territoryCodes. Mostly 3-letter variants - // of deleted codes and an entry for QU. - for _, m := range []struct{ iso2, iso3 string }{ - {"CT", "CTE"}, - {"DY", "DHY"}, - {"HV", "HVO"}, - {"JT", "JTN"}, - {"MI", "MID"}, - {"NH", "NHB"}, - {"NQ", "ATN"}, - {"PC", "PCI"}, - {"PU", "PUS"}, - {"PZ", "PCZ"}, - {"RH", "RHO"}, - {"VD", "VDR"}, - {"WK", "WAK"}, - // These three-letter codes are used for others as well. - {"FQ", "ATF"}, - } { - update(m.iso2, m.iso3) - } - for i, s := range regionISO.s { - if len(s) != 4 { - regionISO.s[i] = s + " " - } - } - b.writeConst("regionISO", tag.Index(regionISO.join())) - b.writeConst("altRegionISO3", altRegionISO3) - b.writeSlice("altRegionIDs", altRegionIDs) - - // Create list of deprecated regions. - // TODO: consider inserting SF -> FI. Not included by CLDR, but is the only - // Transitionally-reserved mapping not included. - regionOldMap := stringSet{} - // Include regions in territoryAlias (not all are in the IANA registry!) - for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { - if len(reg.Type) == 2 && reg.Reason == "deprecated" && len(reg.Replacement) == 2 { - regionOldMap.add(reg.Type) - regionOldMap.updateLater(reg.Type, reg.Replacement) - i, _ := regionISO.find(reg.Type) - j, _ := regionISO.find(reg.Replacement) - if k := m49map[i+isoOffset]; k == 0 { - m49map[i+isoOffset] = m49map[j+isoOffset] - } - } - } - b.writeSortedMap("regionOldMap", ®ionOldMap, func(s string) uint16 { - return uint16(b.region.index(s)) - }) - // 3-digit region lookup, groupings. - for i := 1; i < isoOffset; i++ { - m := parseM49(b.region.s[i]) - m49map[i] = m - fromM49map[m] = i - } - b.writeSlice("m49", m49map) - - const ( - searchBits = 7 - regionBits = 9 - ) - if len(m49map) >= 1< %d", len(m49map), 1<>searchBits] = int16(len(fromM49)) - } - b.writeSlice("m49Index", m49Index) - b.writeSlice("fromM49", fromM49) -} - -const ( - // TODO: put these lists in regionTypes as user data? Could be used for - // various optimizations and refinements and could be exposed in the API. - iso3166Except = "AC CP DG EA EU FX IC SU TA UK" - iso3166Trans = "AN BU CS NT TP YU ZR" // SF is not in our set of Regions. - // DY and RH are actually not deleted, but indeterminately reserved. - iso3166DelCLDR = "CT DD DY FQ HV JT MI NH NQ PC PU PZ RH VD WK YD" -) - -const ( - iso3166UserAssigned = 1 << iota - ccTLD - bcp47Region -) - -func find(list []string, s string) int { - for i, t := range list { - if t == s { - return i - } - } - return -1 -} - -// writeVariants generates per-variant information and creates a map from variant -// name to index value. We assign index values such that sorting multiple -// variants by index value will result in the correct order. -// There are two types of variants: specialized and general. Specialized variants -// are only applicable to certain language or language-script pairs. Generalized -// variants apply to any language. Generalized variants always sort after -// specialized variants. We will therefore always assign a higher index value -// to a generalized variant than any other variant. Generalized variants are -// sorted alphabetically among themselves. -// Specialized variants may also sort after other specialized variants. Such -// variants will be ordered after any of the variants they may follow. -// We assume that if a variant x is followed by a variant y, then for any prefix -// p of x, p-x is a prefix of y. This allows us to order tags based on the -// maximum of the length of any of its prefixes. -// TODO: it is possible to define a set of Prefix values on variants such that -// a total order cannot be defined to the point that this algorithm breaks. -// In other words, we cannot guarantee the same order of variants for the -// future using the same algorithm or for non-compliant combinations of -// variants. For this reason, consider using simple alphabetic sorting -// of variants and ignore Prefix restrictions altogether. -func (b *builder) writeVariant() { - generalized := stringSet{} - specialized := stringSet{} - specializedExtend := stringSet{} - // Collate the variants by type and check assumptions. - for _, v := range b.variant.slice() { - e := b.registry[v] - if len(e.prefix) == 0 { - generalized.add(v) - continue - } - c := strings.Split(e.prefix[0], "-") - hasScriptOrRegion := false - if len(c) > 1 { - _, hasScriptOrRegion = b.script.find(c[1]) - if !hasScriptOrRegion { - _, hasScriptOrRegion = b.region.find(c[1]) - - } - } - if len(c) == 1 || len(c) == 2 && hasScriptOrRegion { - // Variant is preceded by a language. - specialized.add(v) - continue - } - // Variant is preceded by another variant. - specializedExtend.add(v) - prefix := c[0] + "-" - if hasScriptOrRegion { - prefix += c[1] - } - for _, p := range e.prefix { - // Verify that the prefix minus the last element is a prefix of the - // predecessor element. - i := strings.LastIndex(p, "-") - pred := b.registry[p[i+1:]] - if find(pred.prefix, p[:i]) < 0 { - log.Fatalf("prefix %q for variant %q not consistent with predecessor spec", p, v) - } - // The sorting used below does not work in the general case. It works - // if we assume that variants that may be followed by others only have - // prefixes of the same length. Verify this. - count := strings.Count(p[:i], "-") - for _, q := range pred.prefix { - if c := strings.Count(q, "-"); c != count { - log.Fatalf("variant %q preceding %q has a prefix %q of size %d; want %d", p[i+1:], v, q, c, count) - } - } - if !strings.HasPrefix(p, prefix) { - log.Fatalf("prefix %q of variant %q should start with %q", p, v, prefix) - } - } - } - - // Sort extended variants. - a := specializedExtend.s - less := func(v, w string) bool { - // Sort by the maximum number of elements. - maxCount := func(s string) (max int) { - for _, p := range b.registry[s].prefix { - if c := strings.Count(p, "-"); c > max { - max = c - } - } - return - } - if cv, cw := maxCount(v), maxCount(w); cv != cw { - return cv < cw - } - // Sort by name as tie breaker. - return v < w - } - sort.Sort(funcSorter{less, sort.StringSlice(a)}) - specializedExtend.frozen = true - - // Create index from variant name to index. - variantIndex := make(map[string]uint8) - add := func(s []string) { - for _, v := range s { - variantIndex[v] = uint8(len(variantIndex)) - } - } - add(specialized.slice()) - add(specializedExtend.s) - numSpecialized := len(variantIndex) - add(generalized.slice()) - if n := len(variantIndex); n > 255 { - log.Fatalf("maximum number of variants exceeded: was %d; want <= 255", n) - } - b.writeMap("variantIndex", variantIndex) - b.writeConst("variantNumSpecialized", numSpecialized) -} - -func (b *builder) writeLanguageInfo() { -} - -// writeLikelyData writes tables that are used both for finding parent relations and for -// language matching. Each entry contains additional bits to indicate the status of the -// data to know when it cannot be used for parent relations. -func (b *builder) writeLikelyData() { - const ( - isList = 1 << iota - scriptInFrom - regionInFrom - ) - type ( // generated types - likelyScriptRegion struct { - region uint16 - script uint8 - flags uint8 - } - likelyLangScript struct { - lang uint16 - script uint8 - flags uint8 - } - likelyLangRegion struct { - lang uint16 - region uint16 - } - // likelyTag is used for getting likely tags for group regions, where - // the likely region might be a region contained in the group. - likelyTag struct { - lang uint16 - region uint16 - script uint8 - } - ) - var ( // generated variables - likelyRegionGroup = make([]likelyTag, len(b.groups)) - likelyLang = make([]likelyScriptRegion, len(b.lang.s)) - likelyRegion = make([]likelyLangScript, len(b.region.s)) - likelyScript = make([]likelyLangRegion, len(b.script.s)) - likelyLangList = []likelyScriptRegion{} - likelyRegionList = []likelyLangScript{} - ) - type fromTo struct { - from, to []string - } - langToOther := map[int][]fromTo{} - regionToOther := map[int][]fromTo{} - for _, m := range b.supp.LikelySubtags.LikelySubtag { - from := strings.Split(m.From, "_") - to := strings.Split(m.To, "_") - if len(to) != 3 { - log.Fatalf("invalid number of subtags in %q: found %d, want 3", m.To, len(to)) - } - if len(from) > 3 { - log.Fatalf("invalid number of subtags: found %d, want 1-3", len(from)) - } - if from[0] != to[0] && from[0] != "und" { - log.Fatalf("unexpected language change in expansion: %s -> %s", from, to) - } - if len(from) == 3 { - if from[2] != to[2] { - log.Fatalf("unexpected region change in expansion: %s -> %s", from, to) - } - if from[0] != "und" { - log.Fatalf("unexpected fully specified from tag: %s -> %s", from, to) - } - } - if len(from) == 1 || from[0] != "und" { - id := 0 - if from[0] != "und" { - id = b.lang.index(from[0]) - } - langToOther[id] = append(langToOther[id], fromTo{from, to}) - } else if len(from) == 2 && len(from[1]) == 4 { - sid := b.script.index(from[1]) - likelyScript[sid].lang = uint16(b.langIndex(to[0])) - likelyScript[sid].region = uint16(b.region.index(to[2])) - } else { - r := b.region.index(from[len(from)-1]) - if id, ok := b.groups[r]; ok { - if from[0] != "und" { - log.Fatalf("region changed unexpectedly: %s -> %s", from, to) - } - likelyRegionGroup[id].lang = uint16(b.langIndex(to[0])) - likelyRegionGroup[id].script = uint8(b.script.index(to[1])) - likelyRegionGroup[id].region = uint16(b.region.index(to[2])) - } else { - regionToOther[r] = append(regionToOther[r], fromTo{from, to}) - } - } - } - b.writeType(likelyLangRegion{}) - b.writeSlice("likelyScript", likelyScript) - - for id := range b.lang.s { - list := langToOther[id] - if len(list) == 1 { - likelyLang[id].region = uint16(b.region.index(list[0].to[2])) - likelyLang[id].script = uint8(b.script.index(list[0].to[1])) - } else if len(list) > 1 { - likelyLang[id].flags = isList - likelyLang[id].region = uint16(len(likelyLangList)) - likelyLang[id].script = uint8(len(list)) - for _, x := range list { - flags := uint8(0) - if len(x.from) > 1 { - if x.from[1] == x.to[2] { - flags = regionInFrom - } else { - flags = scriptInFrom - } - } - likelyLangList = append(likelyLangList, likelyScriptRegion{ - region: uint16(b.region.index(x.to[2])), - script: uint8(b.script.index(x.to[1])), - flags: flags, - }) - } - } - } - // TODO: merge suppressScript data with this table. - b.writeType(likelyScriptRegion{}) - b.writeSlice("likelyLang", likelyLang) - b.writeSlice("likelyLangList", likelyLangList) - - for id := range b.region.s { - list := regionToOther[id] - if len(list) == 1 { - likelyRegion[id].lang = uint16(b.langIndex(list[0].to[0])) - likelyRegion[id].script = uint8(b.script.index(list[0].to[1])) - if len(list[0].from) > 2 { - likelyRegion[id].flags = scriptInFrom - } - } else if len(list) > 1 { - likelyRegion[id].flags = isList - likelyRegion[id].lang = uint16(len(likelyRegionList)) - likelyRegion[id].script = uint8(len(list)) - for i, x := range list { - if len(x.from) == 2 && i != 0 || i > 0 && len(x.from) != 3 { - log.Fatalf("unspecified script must be first in list: %v at %d", x.from, i) - } - x := likelyLangScript{ - lang: uint16(b.langIndex(x.to[0])), - script: uint8(b.script.index(x.to[1])), - } - if len(list[0].from) > 2 { - x.flags = scriptInFrom - } - likelyRegionList = append(likelyRegionList, x) - } - } - } - b.writeType(likelyLangScript{}) - b.writeSlice("likelyRegion", likelyRegion) - b.writeSlice("likelyRegionList", likelyRegionList) - - b.writeType(likelyTag{}) - b.writeSlice("likelyRegionGroup", likelyRegionGroup) -} - -func (b *builder) writeRegionInclusionData() { - var ( - // mm holds for each group the set of groups with a distance of 1. - mm = make(map[int][]index) - - // containment holds for each group the transitive closure of - // containment of other groups. - containment = make(map[index][]index) - ) - for _, g := range b.supp.TerritoryContainment.Group { - // Skip UN and EURO zone as they are flattening the containment - // relationship. - if g.Type == "EZ" || g.Type == "UN" { - continue - } - group := b.region.index(g.Type) - groupIdx := b.groups[group] - for _, mem := range strings.Split(g.Contains, " ") { - r := b.region.index(mem) - mm[r] = append(mm[r], groupIdx) - if g, ok := b.groups[r]; ok { - mm[group] = append(mm[group], g) - containment[groupIdx] = append(containment[groupIdx], g) - } - } - } - - regionContainment := make([]uint64, len(b.groups)) - for _, g := range b.groups { - l := containment[g] - - // Compute the transitive closure of containment. - for i := 0; i < len(l); i++ { - l = append(l, containment[l[i]]...) - } - - // Compute the bitmask. - regionContainment[g] = 1 << g - for _, v := range l { - regionContainment[g] |= 1 << v - } - } - b.writeSlice("regionContainment", regionContainment) - - regionInclusion := make([]uint8, len(b.region.s)) - bvs := make(map[uint64]index) - // Make the first bitvector positions correspond with the groups. - for r, i := range b.groups { - bv := uint64(1 << i) - for _, g := range mm[r] { - bv |= 1 << g - } - bvs[bv] = i - regionInclusion[r] = uint8(bvs[bv]) - } - for r := 1; r < len(b.region.s); r++ { - if _, ok := b.groups[r]; !ok { - bv := uint64(0) - for _, g := range mm[r] { - bv |= 1 << g - } - if bv == 0 { - // Pick the world for unspecified regions. - bv = 1 << b.groups[b.region.index("001")] - } - if _, ok := bvs[bv]; !ok { - bvs[bv] = index(len(bvs)) - } - regionInclusion[r] = uint8(bvs[bv]) - } - } - b.writeSlice("regionInclusion", regionInclusion) - regionInclusionBits := make([]uint64, len(bvs)) - for k, v := range bvs { - regionInclusionBits[v] = uint64(k) - } - // Add bit vectors for increasingly large distances until a fixed point is reached. - regionInclusionNext := []uint8{} - for i := 0; i < len(regionInclusionBits); i++ { - bits := regionInclusionBits[i] - next := bits - for i := uint(0); i < uint(len(b.groups)); i++ { - if bits&(1< 6 { - log.Fatalf("Too many groups: %d", i) - } - idToIndex[mv.Id] = uint8(i + 1) - // TODO: also handle '-' - for _, r := range strings.Split(mv.Value, "+") { - todo := []string{r} - for k := 0; k < len(todo); k++ { - r := todo[k] - regionToGroups[b.regionIndex(r)] |= 1 << uint8(i) - todo = append(todo, regionHierarchy[r]...) - } - } - } - b.w.WriteVar("regionToGroups", regionToGroups) - - // maps language id to in- and out-of-group region. - paradigmLocales := [][3]uint16{} - locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ") - for i := 0; i < len(locales); i += 2 { - x := [3]uint16{} - for j := 0; j < 2; j++ { - pc := strings.SplitN(locales[i+j], "-", 2) - x[0] = b.langIndex(pc[0]) - if len(pc) == 2 { - x[1+j] = uint16(b.regionIndex(pc[1])) - } - } - paradigmLocales = append(paradigmLocales, x) - } - b.w.WriteVar("paradigmLocales", paradigmLocales) - - b.w.WriteType(mutualIntelligibility{}) - b.w.WriteType(scriptIntelligibility{}) - b.w.WriteType(regionIntelligibility{}) - - matchLang := []mutualIntelligibility{} - matchScript := []scriptIntelligibility{} - matchRegion := []regionIntelligibility{} - // Convert the languageMatch entries in lists keyed by desired language. - for _, m := range lm[0].LanguageMatch { - // Different versions of CLDR use different separators. - desired := strings.Replace(m.Desired, "-", "_", -1) - supported := strings.Replace(m.Supported, "-", "_", -1) - d := strings.Split(desired, "_") - s := strings.Split(supported, "_") - if len(d) != len(s) { - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - continue - } - distance, _ := strconv.ParseInt(m.Distance, 10, 8) - switch len(d) { - case 2: - if desired == supported && desired == "*_*" { - continue - } - // language-script pair. - matchScript = append(matchScript, scriptIntelligibility{ - wantLang: uint16(b.langIndex(d[0])), - haveLang: uint16(b.langIndex(s[0])), - wantScript: uint8(b.scriptIndex(d[1])), - haveScript: uint8(b.scriptIndex(s[1])), - distance: uint8(distance), - }) - if m.Oneway != "true" { - matchScript = append(matchScript, scriptIntelligibility{ - wantLang: uint16(b.langIndex(s[0])), - haveLang: uint16(b.langIndex(d[0])), - wantScript: uint8(b.scriptIndex(s[1])), - haveScript: uint8(b.scriptIndex(d[1])), - distance: uint8(distance), - }) - } - case 1: - if desired == supported && desired == "*" { - continue - } - if distance == 1 { - // nb == no is already handled by macro mapping. Check there - // really is only this case. - if d[0] != "no" || s[0] != "nb" { - log.Fatalf("unhandled equivalence %s == %s", s[0], d[0]) - } - continue - } - // TODO: consider dropping oneway field and just doubling the entry. - matchLang = append(matchLang, mutualIntelligibility{ - want: uint16(b.langIndex(d[0])), - have: uint16(b.langIndex(s[0])), - distance: uint8(distance), - oneway: m.Oneway == "true", - }) - case 3: - if desired == supported && desired == "*_*_*" { - continue - } - if desired != supported { - // This is now supported by CLDR, but only one case, which - // should already be covered by paradigm locales. For instance, - // test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in - // testdata/CLDRLocaleMatcherTest.txt tests this. - if supported != "en_*_GB" { - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - } - continue - } - ri := regionIntelligibility{ - lang: b.langIndex(d[0]), - distance: uint8(distance), - } - if d[1] != "*" { - ri.script = uint8(b.scriptIndex(d[1])) - } - switch { - case d[2] == "*": - ri.group = 0x80 // not contained in anything - case strings.HasPrefix(d[2], "$!"): - ri.group = 0x80 - d[2] = "$" + d[2][len("$!"):] - fallthrough - case strings.HasPrefix(d[2], "$"): - ri.group |= idToIndex[d[2]] - } - matchRegion = append(matchRegion, ri) - default: - log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) - } - } - sort.SliceStable(matchLang, func(i, j int) bool { - return matchLang[i].distance < matchLang[j].distance - }) - b.w.WriteComment(` - matchLang holds pairs of langIDs of base languages that are typically - mutually intelligible. Each pair is associated with a confidence and - whether the intelligibility goes one or both ways.`) - b.w.WriteVar("matchLang", matchLang) - - b.w.WriteComment(` - matchScript holds pairs of scriptIDs where readers of one script - can typically also read the other. Each is associated with a confidence.`) - sort.SliceStable(matchScript, func(i, j int) bool { - return matchScript[i].distance < matchScript[j].distance - }) - b.w.WriteVar("matchScript", matchScript) - - sort.SliceStable(matchRegion, func(i, j int) bool { - return matchRegion[i].distance < matchRegion[j].distance - }) - b.w.WriteVar("matchRegion", matchRegion) -} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen.go b/vendor/golang.org/x/text/unicode/bidi/gen.go deleted file mode 100644 index 987fc169cc..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "flag" - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/triegen" - "golang.org/x/text/internal/ucd" -) - -var outputFile = flag.String("out", "tables.go", "output file") - -func main() { - gen.Init() - gen.Repackage("gen_trieval.go", "trieval.go", "bidi") - gen.Repackage("gen_ranges.go", "ranges_test.go", "bidi") - - genTables() -} - -// bidiClass names and codes taken from class "bc" in -// https://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt -var bidiClass = map[string]Class{ - "AL": AL, // ArabicLetter - "AN": AN, // ArabicNumber - "B": B, // ParagraphSeparator - "BN": BN, // BoundaryNeutral - "CS": CS, // CommonSeparator - "EN": EN, // EuropeanNumber - "ES": ES, // EuropeanSeparator - "ET": ET, // EuropeanTerminator - "L": L, // LeftToRight - "NSM": NSM, // NonspacingMark - "ON": ON, // OtherNeutral - "R": R, // RightToLeft - "S": S, // SegmentSeparator - "WS": WS, // WhiteSpace - - "FSI": Control, - "PDF": Control, - "PDI": Control, - "LRE": Control, - "LRI": Control, - "LRO": Control, - "RLE": Control, - "RLI": Control, - "RLO": Control, -} - -func genTables() { - if numClass > 0x0F { - log.Fatalf("Too many Class constants (%#x > 0x0F).", numClass) - } - w := gen.NewCodeWriter() - defer w.WriteVersionedGoFile(*outputFile, "bidi") - - gen.WriteUnicodeVersion(w) - - t := triegen.NewTrie("bidi") - - // Build data about bracket mapping. These bits need to be or-ed with - // any other bits. - orMask := map[rune]uint64{} - - xorMap := map[rune]int{} - xorMasks := []rune{0} // First value is no-op. - - ucd.Parse(gen.OpenUCDFile("BidiBrackets.txt"), func(p *ucd.Parser) { - r1 := p.Rune(0) - r2 := p.Rune(1) - xor := r1 ^ r2 - if _, ok := xorMap[xor]; !ok { - xorMap[xor] = len(xorMasks) - xorMasks = append(xorMasks, xor) - } - entry := uint64(xorMap[xor]) << xorMaskShift - switch p.String(2) { - case "o": - entry |= openMask - case "c", "n": - default: - log.Fatalf("Unknown bracket class %q.", p.String(2)) - } - orMask[r1] = entry - }) - - w.WriteComment(` - xorMasks contains masks to be xor-ed with brackets to get the reverse - version.`) - w.WriteVar("xorMasks", xorMasks) - - done := map[rune]bool{} - - insert := func(r rune, c Class) { - if !done[r] { - t.Insert(r, orMask[r]|uint64(c)) - done[r] = true - } - } - - // Insert the derived BiDi properties. - ucd.Parse(gen.OpenUCDFile("extracted/DerivedBidiClass.txt"), func(p *ucd.Parser) { - r := p.Rune(0) - class, ok := bidiClass[p.String(1)] - if !ok { - log.Fatalf("%U: Unknown BiDi class %q", r, p.String(1)) - } - insert(r, class) - }) - visitDefaults(insert) - - // TODO: use sparse blocks. This would reduce table size considerably - // from the looks of it. - - sz, err := t.Gen(w) - if err != nil { - log.Fatal(err) - } - w.Size += sz -} - -// dummy values to make methods in gen_common compile. The real versions -// will be generated by this file to tables.go. -var ( - xorMasks []rune -) diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go deleted file mode 100644 index 02c3b505d6..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "unicode" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/ucd" - "golang.org/x/text/unicode/rangetable" -) - -// These tables are hand-extracted from: -// https://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedBidiClass.txt -func visitDefaults(fn func(r rune, c Class)) { - // first write default values for ranges listed above. - visitRunes(fn, AL, []rune{ - 0x0600, 0x07BF, // Arabic - 0x08A0, 0x08FF, // Arabic Extended-A - 0xFB50, 0xFDCF, // Arabic Presentation Forms - 0xFDF0, 0xFDFF, - 0xFE70, 0xFEFF, - 0x0001EE00, 0x0001EEFF, // Arabic Mathematical Alpha Symbols - }) - visitRunes(fn, R, []rune{ - 0x0590, 0x05FF, // Hebrew - 0x07C0, 0x089F, // Nko et al. - 0xFB1D, 0xFB4F, - 0x00010800, 0x00010FFF, // Cypriot Syllabary et. al. - 0x0001E800, 0x0001EDFF, - 0x0001EF00, 0x0001EFFF, - }) - visitRunes(fn, ET, []rune{ // European Terminator - 0x20A0, 0x20Cf, // Currency symbols - }) - rangetable.Visit(unicode.Noncharacter_Code_Point, func(r rune) { - fn(r, BN) // Boundary Neutral - }) - ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) { - if p.String(1) == "Default_Ignorable_Code_Point" { - fn(p.Rune(0), BN) // Boundary Neutral - } - }) -} - -func visitRunes(fn func(r rune, c Class), c Class, runes []rune) { - for i := 0; i < len(runes); i += 2 { - lo, hi := runes[i], runes[i+1] - for j := lo; j <= hi; j++ { - fn(j, c) - } - } -} diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go deleted file mode 100644 index 9cb9942894..0000000000 --- a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// Class is the Unicode BiDi class. Each rune has a single class. -type Class uint - -const ( - L Class = iota // LeftToRight - R // RightToLeft - EN // EuropeanNumber - ES // EuropeanSeparator - ET // EuropeanTerminator - AN // ArabicNumber - CS // CommonSeparator - B // ParagraphSeparator - S // SegmentSeparator - WS // WhiteSpace - ON // OtherNeutral - BN // BoundaryNeutral - NSM // NonspacingMark - AL // ArabicLetter - Control // Control LRO - PDI - - numClass - - LRO // LeftToRightOverride - RLO // RightToLeftOverride - LRE // LeftToRightEmbedding - RLE // RightToLeftEmbedding - PDF // PopDirectionalFormat - LRI // LeftToRightIsolate - RLI // RightToLeftIsolate - FSI // FirstStrongIsolate - PDI // PopDirectionalIsolate - - unknownClass = ^Class(0) -) - -var controlToClass = map[rune]Class{ - 0x202D: LRO, // LeftToRightOverride, - 0x202E: RLO, // RightToLeftOverride, - 0x202A: LRE, // LeftToRightEmbedding, - 0x202B: RLE, // RightToLeftEmbedding, - 0x202C: PDF, // PopDirectionalFormat, - 0x2066: LRI, // LeftToRightIsolate, - 0x2067: RLI, // RightToLeftIsolate, - 0x2068: FSI, // FirstStrongIsolate, - 0x2069: PDI, // PopDirectionalIsolate, -} - -// A trie entry has the following bits: -// 7..5 XOR mask for brackets -// 4 1: Bracket open, 0: Bracket close -// 3..0 Class type - -const ( - openMask = 0x10 - xorMaskShift = 5 -) diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go deleted file mode 100644 index 30a3aa9334..0000000000 --- a/vendor/golang.org/x/text/unicode/norm/maketables.go +++ /dev/null @@ -1,986 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Normalization table generator. -// Data read from the web. -// See forminfo.go for a description of the trie values associated with each rune. - -package main - -import ( - "bytes" - "encoding/binary" - "flag" - "fmt" - "io" - "log" - "sort" - "strconv" - "strings" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/triegen" - "golang.org/x/text/internal/ucd" -) - -func main() { - gen.Init() - loadUnicodeData() - compactCCC() - loadCompositionExclusions() - completeCharFields(FCanonical) - completeCharFields(FCompatibility) - computeNonStarterCounts() - verifyComputed() - printChars() - testDerived() - printTestdata() - makeTables() -} - -var ( - tablelist = flag.String("tables", - "all", - "comma-separated list of which tables to generate; "+ - "can be 'decomp', 'recomp', 'info' and 'all'") - test = flag.Bool("test", - false, - "test existing tables against DerivedNormalizationProps and generate test data for regression testing") - verbose = flag.Bool("verbose", - false, - "write data to stdout as it is parsed") -) - -const MaxChar = 0x10FFFF // anything above this shouldn't exist - -// Quick Check properties of runes allow us to quickly -// determine whether a rune may occur in a normal form. -// For a given normal form, a rune may be guaranteed to occur -// verbatim (QC=Yes), may or may not combine with another -// rune (QC=Maybe), or may not occur (QC=No). -type QCResult int - -const ( - QCUnknown QCResult = iota - QCYes - QCNo - QCMaybe -) - -func (r QCResult) String() string { - switch r { - case QCYes: - return "Yes" - case QCNo: - return "No" - case QCMaybe: - return "Maybe" - } - return "***UNKNOWN***" -} - -const ( - FCanonical = iota // NFC or NFD - FCompatibility // NFKC or NFKD - FNumberOfFormTypes -) - -const ( - MComposed = iota // NFC or NFKC - MDecomposed // NFD or NFKD - MNumberOfModes -) - -// This contains only the properties we're interested in. -type Char struct { - name string - codePoint rune // if zero, this index is not a valid code point. - ccc uint8 // canonical combining class - origCCC uint8 - excludeInComp bool // from CompositionExclusions.txt - compatDecomp bool // it has a compatibility expansion - - nTrailingNonStarters uint8 - nLeadingNonStarters uint8 // must be equal to trailing if non-zero - - forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility - - state State -} - -var chars = make([]Char, MaxChar+1) -var cccMap = make(map[uint8]uint8) - -func (c Char) String() string { - buf := new(bytes.Buffer) - - fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name) - fmt.Fprintf(buf, " ccc: %v\n", c.ccc) - fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp) - fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp) - fmt.Fprintf(buf, " state: %v\n", c.state) - fmt.Fprintf(buf, " NFC:\n") - fmt.Fprint(buf, c.forms[FCanonical]) - fmt.Fprintf(buf, " NFKC:\n") - fmt.Fprint(buf, c.forms[FCompatibility]) - - return buf.String() -} - -// In UnicodeData.txt, some ranges are marked like this: -// 3400;;Lo;0;L;;;;;N;;;;; -// 4DB5;;Lo;0;L;;;;;N;;;;; -// parseCharacter keeps a state variable indicating the weirdness. -type State int - -const ( - SNormal State = iota // known to be zero for the type - SFirst - SLast - SMissing -) - -var lastChar = rune('\u0000') - -func (c Char) isValid() bool { - return c.codePoint != 0 && c.state != SMissing -} - -type FormInfo struct { - quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed - verified [MNumberOfModes]bool // index: MComposed or MDecomposed - - combinesForward bool // May combine with rune on the right - combinesBackward bool // May combine with rune on the left - isOneWay bool // Never appears in result - inDecomp bool // Some decompositions result in this char. - decomp Decomposition - expandedDecomp Decomposition -} - -func (f FormInfo) String() string { - buf := bytes.NewBuffer(make([]byte, 0)) - - fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed]) - fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed]) - fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward) - fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward) - fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay) - fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp) - fmt.Fprintf(buf, " decomposition: %X\n", f.decomp) - fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp) - - return buf.String() -} - -type Decomposition []rune - -func parseDecomposition(s string, skipfirst bool) (a []rune, err error) { - decomp := strings.Split(s, " ") - if len(decomp) > 0 && skipfirst { - decomp = decomp[1:] - } - for _, d := range decomp { - point, err := strconv.ParseUint(d, 16, 64) - if err != nil { - return a, err - } - a = append(a, rune(point)) - } - return a, nil -} - -func loadUnicodeData() { - f := gen.OpenUCDFile("UnicodeData.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - r := p.Rune(ucd.CodePoint) - char := &chars[r] - - char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass)) - decmap := p.String(ucd.DecompMapping) - - exp, err := parseDecomposition(decmap, false) - isCompat := false - if err != nil { - if len(decmap) > 0 { - exp, err = parseDecomposition(decmap, true) - if err != nil { - log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err) - } - isCompat = true - } - } - - char.name = p.String(ucd.Name) - char.codePoint = r - char.forms[FCompatibility].decomp = exp - if !isCompat { - char.forms[FCanonical].decomp = exp - } else { - char.compatDecomp = true - } - if len(decmap) > 0 { - char.forms[FCompatibility].decomp = exp - } - } - if err := p.Err(); err != nil { - log.Fatal(err) - } -} - -// compactCCC converts the sparse set of CCC values to a continguous one, -// reducing the number of bits needed from 8 to 6. -func compactCCC() { - m := make(map[uint8]uint8) - for i := range chars { - c := &chars[i] - m[c.ccc] = 0 - } - cccs := []int{} - for v, _ := range m { - cccs = append(cccs, int(v)) - } - sort.Ints(cccs) - for i, c := range cccs { - cccMap[uint8(i)] = uint8(c) - m[uint8(c)] = uint8(i) - } - for i := range chars { - c := &chars[i] - c.origCCC = c.ccc - c.ccc = m[c.ccc] - } - if len(m) >= 1<<6 { - log.Fatalf("too many difference CCC values: %d >= 64", len(m)) - } -} - -// CompositionExclusions.txt has form: -// 0958 # ... -// See https://unicode.org/reports/tr44/ for full explanation -func loadCompositionExclusions() { - f := gen.OpenUCDFile("CompositionExclusions.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - c := &chars[p.Rune(0)] - if c.excludeInComp { - log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint) - } - c.excludeInComp = true - } - if e := p.Err(); e != nil { - log.Fatal(e) - } -} - -// hasCompatDecomp returns true if any of the recursive -// decompositions contains a compatibility expansion. -// In this case, the character may not occur in NFK*. -func hasCompatDecomp(r rune) bool { - c := &chars[r] - if c.compatDecomp { - return true - } - for _, d := range c.forms[FCompatibility].decomp { - if hasCompatDecomp(d) { - return true - } - } - return false -} - -// Hangul related constants. -const ( - HangulBase = 0xAC00 - HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28) - - JamoLBase = 0x1100 - JamoLEnd = 0x1113 - JamoVBase = 0x1161 - JamoVEnd = 0x1176 - JamoTBase = 0x11A8 - JamoTEnd = 0x11C3 - - JamoLVTCount = 19 * 21 * 28 - JamoTCount = 28 -) - -func isHangul(r rune) bool { - return HangulBase <= r && r < HangulEnd -} - -func isHangulWithoutJamoT(r rune) bool { - if !isHangul(r) { - return false - } - r -= HangulBase - return r < JamoLVTCount && r%JamoTCount == 0 -} - -func ccc(r rune) uint8 { - return chars[r].ccc -} - -// Insert a rune in a buffer, ordered by Canonical Combining Class. -func insertOrdered(b Decomposition, r rune) Decomposition { - n := len(b) - b = append(b, 0) - cc := ccc(r) - if cc > 0 { - // Use bubble sort. - for ; n > 0; n-- { - if ccc(b[n-1]) <= cc { - break - } - b[n] = b[n-1] - } - } - b[n] = r - return b -} - -// Recursively decompose. -func decomposeRecursive(form int, r rune, d Decomposition) Decomposition { - dcomp := chars[r].forms[form].decomp - if len(dcomp) == 0 { - return insertOrdered(d, r) - } - for _, c := range dcomp { - d = decomposeRecursive(form, c, d) - } - return d -} - -func completeCharFields(form int) { - // Phase 0: pre-expand decomposition. - for i := range chars { - f := &chars[i].forms[form] - if len(f.decomp) == 0 { - continue - } - exp := make(Decomposition, 0) - for _, c := range f.decomp { - exp = decomposeRecursive(form, c, exp) - } - f.expandedDecomp = exp - } - - // Phase 1: composition exclusion, mark decomposition. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - // Marks script-specific exclusions and version restricted. - f.isOneWay = c.excludeInComp - - // Singletons - f.isOneWay = f.isOneWay || len(f.decomp) == 1 - - // Non-starter decompositions - if len(f.decomp) > 1 { - chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0 - f.isOneWay = f.isOneWay || chk - } - - // Runes that decompose into more than two runes. - f.isOneWay = f.isOneWay || len(f.decomp) > 2 - - if form == FCompatibility { - f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint) - } - - for _, r := range f.decomp { - chars[r].forms[form].inDecomp = true - } - } - - // Phase 2: forward and backward combining. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - if !f.isOneWay && len(f.decomp) == 2 { - f0 := &chars[f.decomp[0]].forms[form] - f1 := &chars[f.decomp[1]].forms[form] - if !f0.isOneWay { - f0.combinesForward = true - } - if !f1.isOneWay { - f1.combinesBackward = true - } - } - if isHangulWithoutJamoT(rune(i)) { - f.combinesForward = true - } - } - - // Phase 3: quick check values. - for i := range chars { - c := &chars[i] - f := &c.forms[form] - - switch { - case len(f.decomp) > 0: - f.quickCheck[MDecomposed] = QCNo - case isHangul(rune(i)): - f.quickCheck[MDecomposed] = QCNo - default: - f.quickCheck[MDecomposed] = QCYes - } - switch { - case f.isOneWay: - f.quickCheck[MComposed] = QCNo - case (i & 0xffff00) == JamoLBase: - f.quickCheck[MComposed] = QCYes - if JamoLBase <= i && i < JamoLEnd { - f.combinesForward = true - } - if JamoVBase <= i && i < JamoVEnd { - f.quickCheck[MComposed] = QCMaybe - f.combinesBackward = true - f.combinesForward = true - } - if JamoTBase <= i && i < JamoTEnd { - f.quickCheck[MComposed] = QCMaybe - f.combinesBackward = true - } - case !f.combinesBackward: - f.quickCheck[MComposed] = QCYes - default: - f.quickCheck[MComposed] = QCMaybe - } - } -} - -func computeNonStarterCounts() { - // Phase 4: leading and trailing non-starter count - for i := range chars { - c := &chars[i] - - runes := []rune{rune(i)} - // We always use FCompatibility so that the CGJ insertion points do not - // change for repeated normalizations with different forms. - if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 { - runes = exp - } - // We consider runes that combine backwards to be non-starters for the - // purpose of Stream-Safe Text Processing. - for _, r := range runes { - if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { - break - } - c.nLeadingNonStarters++ - } - for i := len(runes) - 1; i >= 0; i-- { - if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { - break - } - c.nTrailingNonStarters++ - } - if c.nTrailingNonStarters > 3 { - log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes) - } - - if isHangul(rune(i)) { - c.nTrailingNonStarters = 2 - if isHangulWithoutJamoT(rune(i)) { - c.nTrailingNonStarters = 1 - } - } - - if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t { - log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t) - } - if t := c.nTrailingNonStarters; t > 3 { - log.Fatalf("%U: number of trailing non-starters is %d > 3", t) - } - } -} - -func printBytes(w io.Writer, b []byte, name string) { - fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b)) - fmt.Fprintf(w, "var %s = [...]byte {", name) - for i, c := range b { - switch { - case i%64 == 0: - fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63) - case i%8 == 0: - fmt.Fprintf(w, "\n") - } - fmt.Fprintf(w, "0x%.2X, ", c) - } - fmt.Fprint(w, "\n}\n\n") -} - -// See forminfo.go for format. -func makeEntry(f *FormInfo, c *Char) uint16 { - e := uint16(0) - if r := c.codePoint; HangulBase <= r && r < HangulEnd { - e |= 0x40 - } - if f.combinesForward { - e |= 0x20 - } - if f.quickCheck[MDecomposed] == QCNo { - e |= 0x4 - } - switch f.quickCheck[MComposed] { - case QCYes: - case QCNo: - e |= 0x10 - case QCMaybe: - e |= 0x18 - default: - log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed]) - } - e |= uint16(c.nTrailingNonStarters) - return e -} - -// decompSet keeps track of unique decompositions, grouped by whether -// the decomposition is followed by a trailing and/or leading CCC. -type decompSet [7]map[string]bool - -const ( - normalDecomp = iota - firstMulti - firstCCC - endMulti - firstLeadingCCC - firstCCCZeroExcept - firstStarterWithNLead - lastDecomp -) - -var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"} - -func makeDecompSet() decompSet { - m := decompSet{} - for i := range m { - m[i] = make(map[string]bool) - } - return m -} -func (m *decompSet) insert(key int, s string) { - m[key][s] = true -} - -func printCharInfoTables(w io.Writer) int { - mkstr := func(r rune, f *FormInfo) (int, string) { - d := f.expandedDecomp - s := string([]rune(d)) - if max := 1 << 6; len(s) >= max { - const msg = "%U: too many bytes in decomposition: %d >= %d" - log.Fatalf(msg, r, len(s), max) - } - head := uint8(len(s)) - if f.quickCheck[MComposed] != QCYes { - head |= 0x40 - } - if f.combinesForward { - head |= 0x80 - } - s = string([]byte{head}) + s - - lccc := ccc(d[0]) - tccc := ccc(d[len(d)-1]) - cc := ccc(r) - if cc != 0 && lccc == 0 && tccc == 0 { - log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc) - } - if tccc < lccc && lccc != 0 { - const msg = "%U: lccc (%d) must be <= tcc (%d)" - log.Fatalf(msg, r, lccc, tccc) - } - index := normalDecomp - nTrail := chars[r].nTrailingNonStarters - nLead := chars[r].nLeadingNonStarters - if tccc > 0 || lccc > 0 || nTrail > 0 { - tccc <<= 2 - tccc |= nTrail - s += string([]byte{tccc}) - index = endMulti - for _, r := range d[1:] { - if ccc(r) == 0 { - index = firstCCC - } - } - if lccc > 0 || nLead > 0 { - s += string([]byte{lccc}) - if index == firstCCC { - log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r) - } - index = firstLeadingCCC - } - if cc != lccc { - if cc != 0 { - log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc) - } - index = firstCCCZeroExcept - } - } else if len(d) > 1 { - index = firstMulti - } - return index, s - } - - decompSet := makeDecompSet() - const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail. - decompSet.insert(firstStarterWithNLead, nLeadStr) - - // Store the uniqued decompositions in a byte buffer, - // preceded by their byte length. - for _, c := range chars { - for _, f := range c.forms { - if len(f.expandedDecomp) == 0 { - continue - } - if f.combinesBackward { - log.Fatalf("%U: combinesBackward and decompose", c.codePoint) - } - index, s := mkstr(c.codePoint, &f) - decompSet.insert(index, s) - } - } - - decompositions := bytes.NewBuffer(make([]byte, 0, 10000)) - size := 0 - positionMap := make(map[string]uint16) - decompositions.WriteString("\000") - fmt.Fprintln(w, "const (") - for i, m := range decompSet { - sa := []string{} - for s := range m { - sa = append(sa, s) - } - sort.Strings(sa) - for _, s := range sa { - p := decompositions.Len() - decompositions.WriteString(s) - positionMap[s] = uint16(p) - } - if cname[i] != "" { - fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len()) - } - } - fmt.Fprintln(w, "maxDecomp = 0x8000") - fmt.Fprintln(w, ")") - b := decompositions.Bytes() - printBytes(w, b, "decomps") - size += len(b) - - varnames := []string{"nfc", "nfkc"} - for i := 0; i < FNumberOfFormTypes; i++ { - trie := triegen.NewTrie(varnames[i]) - - for r, c := range chars { - f := c.forms[i] - d := f.expandedDecomp - if len(d) != 0 { - _, key := mkstr(c.codePoint, &f) - trie.Insert(rune(r), uint64(positionMap[key])) - if c.ccc != ccc(d[0]) { - // We assume the lead ccc of a decomposition !=0 in this case. - if ccc(d[0]) == 0 { - log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc) - } - } - } else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward { - // Handle cases where it can't be detected that the nLead should be equal - // to nTrail. - trie.Insert(c.codePoint, uint64(positionMap[nLeadStr])) - } else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 { - trie.Insert(c.codePoint, uint64(0x8000|v)) - } - } - sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]})) - if err != nil { - log.Fatal(err) - } - size += sz - } - return size -} - -func contains(sa []string, s string) bool { - for _, a := range sa { - if a == s { - return true - } - } - return false -} - -func makeTables() { - w := &bytes.Buffer{} - - size := 0 - if *tablelist == "" { - return - } - list := strings.Split(*tablelist, ",") - if *tablelist == "all" { - list = []string{"recomp", "info"} - } - - // Compute maximum decomposition size. - max := 0 - for _, c := range chars { - if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max { - max = n - } - } - fmt.Fprintln(w, `import "sync"`) - fmt.Fprintln(w) - - fmt.Fprintln(w, "const (") - fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.") - fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion()) - fmt.Fprintln(w) - fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform") - fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at") - fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that") - fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.") - fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max) - fmt.Fprintln(w, ")\n") - - // Print the CCC remap table. - size += len(cccMap) - fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap)) - for i := 0; i < len(cccMap); i++ { - if i%8 == 0 { - fmt.Fprintln(w) - } - fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)]) - } - fmt.Fprintln(w, "\n}\n") - - if contains(list, "info") { - size += printCharInfoTables(w) - } - - if contains(list, "recomp") { - // Note that we use 32 bit keys, instead of 64 bit. - // This clips the bits of three entries, but we know - // this won't cause a collision. The compiler will catch - // any changes made to UnicodeData.txt that introduces - // a collision. - // Note that the recomposition map for NFC and NFKC - // are identical. - - // Recomposition map - nrentries := 0 - for _, c := range chars { - f := c.forms[FCanonical] - if !f.isOneWay && len(f.decomp) > 0 { - nrentries++ - } - } - sz := nrentries * 8 - size += sz - fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz) - fmt.Fprintln(w, "var recompMap map[uint32]rune") - fmt.Fprintln(w, "var recompMapOnce sync.Once\n") - fmt.Fprintln(w, `const recompMapPacked = "" +`) - var buf [8]byte - for i, c := range chars { - f := c.forms[FCanonical] - d := f.decomp - if !f.isOneWay && len(d) > 0 { - key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1])) - binary.BigEndian.PutUint32(buf[:4], key) - binary.BigEndian.PutUint32(buf[4:], uint32(i)) - fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i)) - } - } - // hack so we don't have to special case the trailing plus sign - fmt.Fprintf(w, ` ""`) - fmt.Fprintln(w) - } - - fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size) - gen.WriteVersionedGoFile("tables.go", "norm", w.Bytes()) -} - -func printChars() { - if *verbose { - for _, c := range chars { - if !c.isValid() || c.state == SMissing { - continue - } - fmt.Println(c) - } - } -} - -// verifyComputed does various consistency tests. -func verifyComputed() { - for i, c := range chars { - for _, f := range c.forms { - isNo := (f.quickCheck[MDecomposed] == QCNo) - if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) { - log.Fatalf("%U: NF*D QC must be No if rune decomposes", i) - } - - isMaybe := f.quickCheck[MComposed] == QCMaybe - if f.combinesBackward != isMaybe { - log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i) - } - if len(f.decomp) > 0 && f.combinesForward && isMaybe { - log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i) - } - - if len(f.expandedDecomp) != 0 { - continue - } - if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b { - // We accept these runes to be treated differently (it only affects - // segment breaking in iteration, most likely on improper use), but - // reconsider if more characters are added. - // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; - // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; - // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; - // U+318E HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; - // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; - // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; - if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) { - log.Fatalf("%U: nLead was %v; want %v", i, a, b) - } - } - } - nfc := c.forms[FCanonical] - nfkc := c.forms[FCompatibility] - if nfc.combinesBackward != nfkc.combinesBackward { - log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint) - } - } -} - -// Use values in DerivedNormalizationProps.txt to compare against the -// values we computed. -// DerivedNormalizationProps.txt has form: -// 00C0..00C5 ; NFD_QC; N # ... -// 0374 ; NFD_QC; N # ... -// See https://unicode.org/reports/tr44/ for full explanation -func testDerived() { - f := gen.OpenUCDFile("DerivedNormalizationProps.txt") - defer f.Close() - p := ucd.New(f) - for p.Next() { - r := p.Rune(0) - c := &chars[r] - - var ftype, mode int - qt := p.String(1) - switch qt { - case "NFC_QC": - ftype, mode = FCanonical, MComposed - case "NFD_QC": - ftype, mode = FCanonical, MDecomposed - case "NFKC_QC": - ftype, mode = FCompatibility, MComposed - case "NFKD_QC": - ftype, mode = FCompatibility, MDecomposed - default: - continue - } - var qr QCResult - switch p.String(2) { - case "Y": - qr = QCYes - case "N": - qr = QCNo - case "M": - qr = QCMaybe - default: - log.Fatalf(`Unexpected quick check value "%s"`, p.String(2)) - } - if got := c.forms[ftype].quickCheck[mode]; got != qr { - log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr) - } - c.forms[ftype].verified[mode] = true - } - if err := p.Err(); err != nil { - log.Fatal(err) - } - // Any unspecified value must be QCYes. Verify this. - for i, c := range chars { - for j, fd := range c.forms { - for k, qr := range fd.quickCheck { - if !fd.verified[k] && qr != QCYes { - m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n" - log.Printf(m, i, j, k, qr, c.name) - } - } - } - } -} - -var testHeader = `const ( - Yes = iota - No - Maybe -) - -type formData struct { - qc uint8 - combinesForward bool - decomposition string -} - -type runeData struct { - r rune - ccc uint8 - nLead uint8 - nTrail uint8 - f [2]formData // 0: canonical; 1: compatibility -} - -func f(qc uint8, cf bool, dec string) [2]formData { - return [2]formData{{qc, cf, dec}, {qc, cf, dec}} -} - -func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { - return [2]formData{{qc, cf, d}, {qck, cfk, dk}} -} - -var testData = []runeData{ -` - -func printTestdata() { - type lastInfo struct { - ccc uint8 - nLead uint8 - nTrail uint8 - f string - } - - last := lastInfo{} - w := &bytes.Buffer{} - fmt.Fprintf(w, testHeader) - for r, c := range chars { - f := c.forms[FCanonical] - qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) - f = c.forms[FCompatibility] - qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) - s := "" - if d == dk && qc == qck && cf == cfk { - s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d) - } else { - s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk) - } - current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s} - if last != current { - fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s) - last = current - } - } - fmt.Fprintln(w, "}") - gen.WriteVersionedGoFile("data_test.go", "norm", w.Bytes()) -} diff --git a/vendor/golang.org/x/text/unicode/norm/triegen.go b/vendor/golang.org/x/text/unicode/norm/triegen.go deleted file mode 100644 index 45d711900d..0000000000 --- a/vendor/golang.org/x/text/unicode/norm/triegen.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// Trie table generator. -// Used by make*tables tools to generate a go file with trie data structures -// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte -// sequence are used to lookup offsets in the index table to be used for the -// next byte. The last byte is used to index into a table with 16-bit values. - -package main - -import ( - "fmt" - "io" -) - -const maxSparseEntries = 16 - -type normCompacter struct { - sparseBlocks [][]uint64 - sparseOffset []uint16 - sparseCount int - name string -} - -func mostFrequentStride(a []uint64) int { - counts := make(map[int]int) - var v int - for _, x := range a { - if stride := int(x) - v; v != 0 && stride >= 0 { - counts[stride]++ - } - v = int(x) - } - var maxs, maxc int - for stride, cnt := range counts { - if cnt > maxc || (cnt == maxc && stride < maxs) { - maxs, maxc = stride, cnt - } - } - return maxs -} - -func countSparseEntries(a []uint64) int { - stride := mostFrequentStride(a) - var v, count int - for _, tv := range a { - if int(tv)-v != stride { - if tv != 0 { - count++ - } - } - v = int(tv) - } - return count -} - -func (c *normCompacter) Size(v []uint64) (sz int, ok bool) { - if n := countSparseEntries(v); n <= maxSparseEntries { - return (n+1)*4 + 2, true - } - return 0, false -} - -func (c *normCompacter) Store(v []uint64) uint32 { - h := uint32(len(c.sparseOffset)) - c.sparseBlocks = append(c.sparseBlocks, v) - c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount)) - c.sparseCount += countSparseEntries(v) + 1 - return h -} - -func (c *normCompacter) Handler() string { - return c.name + "Sparse.lookup" -} - -func (c *normCompacter) Print(w io.Writer) (retErr error) { - p := func(f string, x ...interface{}) { - if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil { - retErr = err - } - } - - ls := len(c.sparseBlocks) - p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2) - p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset) - - ns := c.sparseCount - p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4) - p("var %sSparseValues = [%d]valueRange {", c.name, ns) - for i, b := range c.sparseBlocks { - p("\n// Block %#x, offset %#x", i, c.sparseOffset[i]) - var v int - stride := mostFrequentStride(b) - n := countSparseEntries(b) - p("\n{value:%#04x,lo:%#02x},", stride, uint8(n)) - for i, nv := range b { - if int(nv)-v != stride { - if v != 0 { - p(",hi:%#02x},", 0x80+i-1) - } - if nv != 0 { - p("\n{value:%#04x,lo:%#02x", nv, 0x80+i) - } - } - v = int(nv) - } - if v != 0 { - p(",hi:%#02x},", 0x80+len(b)-1) - } - } - p("\n}\n\n") - return -} diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go index 641c45c6fe..a1348e9b16 100644 --- a/vendor/google.golang.org/grpc/status/status.go +++ b/vendor/google.golang.org/grpc/status/status.go @@ -58,6 +58,17 @@ func (se *statusError) GRPCStatus() *Status { return &Status{s: (*spb.Status)(se)} } +// Is implements future error.Is functionality. +// A statusError is equivalent if the code and message are identical. +func (se *statusError) Is(target error) bool { + tse, ok := target.(*statusError) + if !ok { + return false + } + + return proto.Equal((*spb.Status)(se), (*spb.Status)(tse)) +} + // Status represents an RPC status code, message, and details. It is immutable // and should be created with New, Newf, or FromProto. type Status struct { @@ -132,7 +143,7 @@ func FromProto(s *spb.Status) *Status { // Status is returned with codes.Unknown and the original error message. func FromError(err error) (s *Status, ok bool) { if err == nil { - return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true + return nil, true } if se, ok := err.(interface { GRPCStatus() *Status @@ -206,7 +217,7 @@ func Code(err error) codes.Code { func FromContextError(err error) *Status { switch err { case nil: - return New(codes.OK, "") + return nil case context.DeadlineExceeded: return New(codes.DeadlineExceeded, err.Error()) case context.Canceled: diff --git a/vendor/k8s.io/client-go/pkg/version/base.go b/vendor/k8s.io/client-go/pkg/version/base.go index cc2c6906a1..9b4c79f895 100644 --- a/vendor/k8s.io/client-go/pkg/version/base.go +++ b/vendor/k8s.io/client-go/pkg/version/base.go @@ -55,8 +55,8 @@ var ( // NOTE: The $Format strings are replaced during 'git archive' thanks to the // companion .gitattributes file containing 'export-subst' in this same // directory. See also https://git-scm.com/docs/gitattributes - gitVersion string = "v0.0.0-master+d830efd3f" - gitCommit string = "d830efd3f73e85c6c205b6648d8fb4465b98fbd1" // sha1 from git, output of $(git rev-parse HEAD) + gitVersion string = "v0.0.0-master+$Format:%h$" + gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) gitTreeState string = "" // state of git tree, either "clean" or "dirty" buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') diff --git a/vendor/modules.txt b/vendor/modules.txt index 296dfef6bc..a4ab7004e0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,73 +7,73 @@ github.com/Azure/azure-pipeline-go/pipeline # github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e github.com/Azure/azure-storage-blob-go/2018-03-28/azblob # github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 -github.com/Azure/go-ansiterm/winterm github.com/Azure/go-ansiterm +github.com/Azure/go-ansiterm/winterm # github.com/Microsoft/go-winio v0.4.13 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid # github.com/Microsoft/hcsshim v0.8.6 github.com/Microsoft/hcsshim/osversion -# github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d -github.com/StackExchange/wmi # github.com/VividCortex/ewma v1.1.1 github.com/VividCortex/ewma -# github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 +# github.com/allegro/bigcache v1.2.1 github.com/allegro/bigcache github.com/allegro/bigcache/queue # github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 github.com/apilayer/freegeoip -# github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 +# github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb github.com/aristanetworks/goarista/monotime -# github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 +# github.com/btcsuite/btcd v0.20.0-beta github.com/btcsuite/btcd/btcec +# github.com/caarlos0/env v3.5.0+incompatible +github.com/caarlos0/env # github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd github.com/codahale/hdrhistogram # github.com/containerd/containerd v1.2.7 github.com/containerd/containerd/errdefs # github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc github.com/containerd/continuity/fs -github.com/containerd/continuity/sysx github.com/containerd/continuity/pathdriver github.com/containerd/continuity/syscallx +github.com/containerd/continuity/sysx # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew -# github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea +# github.com/deckarep/golang-set v1.7.1 github.com/deckarep/golang-set # github.com/docker/distribution v2.7.1+incompatible -github.com/docker/distribution/reference github.com/docker/distribution/digestset +github.com/docker/distribution/reference github.com/docker/distribution/registry/api/errcode # github.com/docker/docker v0.7.3-0.20190806133308-ecdb0b22393b -github.com/docker/docker/pkg/reexec +github.com/docker/docker/api github.com/docker/docker/api/types +github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/container -github.com/docker/docker/client -github.com/docker/docker/pkg/archive -github.com/docker/docker/pkg/jsonmessage +github.com/docker/docker/api/types/events github.com/docker/docker/api/types/filters +github.com/docker/docker/api/types/image github.com/docker/docker/api/types/mount github.com/docker/docker/api/types/network github.com/docker/docker/api/types/registry -github.com/docker/docker/api/types/swarm -github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/strslice -github.com/docker/docker/api -github.com/docker/docker/api/types/events -github.com/docker/docker/api/types/image +github.com/docker/docker/api/types/swarm +github.com/docker/docker/api/types/swarm/runtime github.com/docker/docker/api/types/time github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume +github.com/docker/docker/client github.com/docker/docker/errdefs +github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/fileutils github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils +github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/longpath +github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/pools +github.com/docker/docker/pkg/reexec github.com/docker/docker/pkg/system github.com/docker/docker/pkg/term -github.com/docker/docker/api/types/swarm/runtime -github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/term/windows # github.com/docker/go-connections v0.4.0 github.com/docker/go-connections/nat @@ -81,111 +81,108 @@ github.com/docker/go-connections/sockets github.com/docker/go-connections/tlsconfig # github.com/docker/go-units v0.4.0 github.com/docker/go-units -# github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c +# github.com/edsrzf/mmap-go v1.0.0 github.com/edsrzf/mmap-go -# github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa +# github.com/elastic/gosigar v0.10.5 github.com/elastic/gosigar github.com/elastic/gosigar/sys/windows -# github.com/ethereum/go-ethereum v1.9.2 -github.com/ethereum/go-ethereum/accounts/abi/bind -github.com/ethereum/go-ethereum/common -github.com/ethereum/go-ethereum/ethclient -github.com/ethereum/go-ethereum/metrics -github.com/ethereum/go-ethereum/p2p -github.com/ethereum/go-ethereum/params -github.com/ethereum/go-ethereum/rpc -github.com/ethereum/go-ethereum/common/hexutil -github.com/ethereum/go-ethereum/core/types -github.com/ethereum/go-ethereum/crypto -github.com/ethereum/go-ethereum/crypto/ecies -github.com/ethereum/go-ethereum/node -github.com/ethereum/go-ethereum/p2p/enode -github.com/ethereum/go-ethereum/log -github.com/ethereum/go-ethereum/accounts -github.com/ethereum/go-ethereum/accounts/keystore -github.com/ethereum/go-ethereum/cmd/utils -github.com/ethereum/go-ethereum/console -github.com/ethereum/go-ethereum/p2p/nat -github.com/ethereum/go-ethereum/rlp -github.com/ethereum/go-ethereum/metrics/influxdb -github.com/ethereum/go-ethereum/p2p/simulations -github.com/ethereum/go-ethereum/p2p/simulations/adapters +# github.com/ethereum/go-ethereum v1.9.7 github.com/ethereum/go-ethereum +github.com/ethereum/go-ethereum/accounts github.com/ethereum/go-ethereum/accounts/abi -github.com/ethereum/go-ethereum/event -github.com/ethereum/go-ethereum/metrics/exp -github.com/ethereum/go-ethereum/p2p/enr -github.com/ethereum/go-ethereum/common/bitutil +github.com/ethereum/go-ethereum/accounts/abi/bind +github.com/ethereum/go-ethereum/accounts/abi/bind/backends github.com/ethereum/go-ethereum/accounts/external -github.com/ethereum/go-ethereum/common/mclock -github.com/ethereum/go-ethereum/p2p/discover -github.com/ethereum/go-ethereum/p2p/discv5 -github.com/ethereum/go-ethereum/p2p/netutil -github.com/ethereum/go-ethereum/trie -github.com/ethereum/go-ethereum/common/math -github.com/ethereum/go-ethereum/crypto/secp256k1 +github.com/ethereum/go-ethereum/accounts/keystore github.com/ethereum/go-ethereum/accounts/scwallet github.com/ethereum/go-ethereum/accounts/usbwallet -github.com/ethereum/go-ethereum/core/rawdb -github.com/ethereum/go-ethereum/ethdb -github.com/ethereum/go-ethereum/internal/debug +github.com/ethereum/go-ethereum/accounts/usbwallet/trezor +github.com/ethereum/go-ethereum/cmd/utils +github.com/ethereum/go-ethereum/common +github.com/ethereum/go-ethereum/common/bitutil github.com/ethereum/go-ethereum/common/fdlimit +github.com/ethereum/go-ethereum/common/hexutil +github.com/ethereum/go-ethereum/common/math +github.com/ethereum/go-ethereum/common/mclock +github.com/ethereum/go-ethereum/common/prque github.com/ethereum/go-ethereum/consensus github.com/ethereum/go-ethereum/consensus/clique github.com/ethereum/go-ethereum/consensus/ethash +github.com/ethereum/go-ethereum/consensus/misc +github.com/ethereum/go-ethereum/console +github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract github.com/ethereum/go-ethereum/core +github.com/ethereum/go-ethereum/core/bloombits +github.com/ethereum/go-ethereum/core/forkid +github.com/ethereum/go-ethereum/core/rawdb +github.com/ethereum/go-ethereum/core/state +github.com/ethereum/go-ethereum/core/types github.com/ethereum/go-ethereum/core/vm +github.com/ethereum/go-ethereum/crypto +github.com/ethereum/go-ethereum/crypto/blake2b +github.com/ethereum/go-ethereum/crypto/bn256 +github.com/ethereum/go-ethereum/crypto/bn256/cloudflare +github.com/ethereum/go-ethereum/crypto/bn256/google +github.com/ethereum/go-ethereum/crypto/ecies +github.com/ethereum/go-ethereum/crypto/secp256k1 github.com/ethereum/go-ethereum/dashboard github.com/ethereum/go-ethereum/eth github.com/ethereum/go-ethereum/eth/downloader +github.com/ethereum/go-ethereum/eth/fetcher +github.com/ethereum/go-ethereum/eth/filters github.com/ethereum/go-ethereum/eth/gasprice +github.com/ethereum/go-ethereum/eth/tracers +github.com/ethereum/go-ethereum/eth/tracers/internal/tracers +github.com/ethereum/go-ethereum/ethclient +github.com/ethereum/go-ethereum/ethdb +github.com/ethereum/go-ethereum/ethdb/leveldb +github.com/ethereum/go-ethereum/ethdb/memorydb github.com/ethereum/go-ethereum/ethstats +github.com/ethereum/go-ethereum/event github.com/ethereum/go-ethereum/graphql -github.com/ethereum/go-ethereum/les -github.com/ethereum/go-ethereum/miner -github.com/ethereum/go-ethereum/whisper/whisperv6 +github.com/ethereum/go-ethereum/internal/debug +github.com/ethereum/go-ethereum/internal/ethapi github.com/ethereum/go-ethereum/internal/jsre +github.com/ethereum/go-ethereum/internal/jsre/deps github.com/ethereum/go-ethereum/internal/web3ext -github.com/ethereum/go-ethereum/p2p/simulations/pipes -github.com/ethereum/go-ethereum/accounts/abi/bind/backends -github.com/ethereum/go-ethereum/metrics/prometheus -github.com/ethereum/go-ethereum/internal/ethapi -github.com/ethereum/go-ethereum/signer/core -github.com/ethereum/go-ethereum/common/prque -github.com/ethereum/go-ethereum/accounts/usbwallet/trezor -github.com/ethereum/go-ethereum/ethdb/leveldb -github.com/ethereum/go-ethereum/ethdb/memorydb -github.com/ethereum/go-ethereum/core/state -github.com/ethereum/go-ethereum/consensus/misc -github.com/ethereum/go-ethereum/crypto/bn256 -github.com/ethereum/go-ethereum/core/bloombits -github.com/ethereum/go-ethereum/core/forkid -github.com/ethereum/go-ethereum/eth/fetcher -github.com/ethereum/go-ethereum/eth/filters -github.com/ethereum/go-ethereum/eth/tracers -github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/les github.com/ethereum/go-ethereum/les/flowcontrol github.com/ethereum/go-ethereum/light -github.com/ethereum/go-ethereum/internal/jsre/deps +github.com/ethereum/go-ethereum/log +github.com/ethereum/go-ethereum/metrics +github.com/ethereum/go-ethereum/metrics/exp +github.com/ethereum/go-ethereum/metrics/influxdb +github.com/ethereum/go-ethereum/metrics/prometheus +github.com/ethereum/go-ethereum/miner +github.com/ethereum/go-ethereum/node +github.com/ethereum/go-ethereum/p2p +github.com/ethereum/go-ethereum/p2p/discover +github.com/ethereum/go-ethereum/p2p/discv5 +github.com/ethereum/go-ethereum/p2p/enode +github.com/ethereum/go-ethereum/p2p/enr +github.com/ethereum/go-ethereum/p2p/nat +github.com/ethereum/go-ethereum/p2p/netutil +github.com/ethereum/go-ethereum/p2p/simulations +github.com/ethereum/go-ethereum/p2p/simulations/adapters +github.com/ethereum/go-ethereum/p2p/simulations/pipes +github.com/ethereum/go-ethereum/params +github.com/ethereum/go-ethereum/rlp +github.com/ethereum/go-ethereum/rpc +github.com/ethereum/go-ethereum/signer/core github.com/ethereum/go-ethereum/signer/storage -github.com/ethereum/go-ethereum/crypto/bn256/cloudflare -github.com/ethereum/go-ethereum/crypto/bn256/google -github.com/ethereum/go-ethereum/eth/tracers/internal/tracers -github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract +github.com/ethereum/go-ethereum/trie +github.com/ethereum/go-ethereum/whisper/whisperv6 # github.com/ethersphere/go-sw3 v0.1.1 github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswap github.com/ethersphere/go-sw3/contracts-v0-1-1/simpleswapfactory -github.com/ethersphere/go-sw3/contracts-v0-1-0/simpleswap # github.com/fatih/color v1.7.0 github.com/fatih/color # github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc -github.com/fjl/memsize/memsizeui github.com/fjl/memsize -# github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c +github.com/fjl/memsize/memsizeui +# github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/gballet/go-libpcsclite -# github.com/go-ole/go-ole v1.2.4 -github.com/go-ole/go-ole -github.com/go-ole/go-ole/oleutil # github.com/go-stack/stack v1.8.0 github.com/go-stack/stack # github.com/gogo/protobuf v1.2.1 @@ -202,18 +199,20 @@ github.com/golang/protobuf/ptypes/timestamp github.com/golang/snappy # github.com/google/gofuzz v1.0.0 github.com/google/gofuzz +# github.com/google/uuid v1.1.1 +github.com/google/uuid # github.com/googleapis/gnostic v0.0.0-20190624222214-25d8b0b66985 github.com/googleapis/gnostic/OpenAPIv2 github.com/googleapis/gnostic/compiler github.com/googleapis/gnostic/extensions -# github.com/gorilla/websocket v1.4.0 +# github.com/gorilla/websocket v1.4.1 github.com/gorilla/websocket # github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 github.com/graph-gophers/graphql-go -github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/errors github.com/graph-gophers/graphql-go/internal/common github.com/graph-gophers/graphql-go/internal/exec +github.com/graph-gophers/graphql-go/internal/exec/packer github.com/graph-gophers/graphql-go/internal/exec/resolvable github.com/graph-gophers/graphql-go/internal/exec/selected github.com/graph-gophers/graphql-go/internal/query @@ -221,14 +220,14 @@ github.com/graph-gophers/graphql-go/internal/schema github.com/graph-gophers/graphql-go/internal/validation github.com/graph-gophers/graphql-go/introspection github.com/graph-gophers/graphql-go/log +github.com/graph-gophers/graphql-go/relay github.com/graph-gophers/graphql-go/trace -github.com/graph-gophers/graphql-go/internal/exec/packer # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru # github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607 github.com/howeyc/fsnotify -# github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 +# github.com/huin/goupnp v1.0.0 github.com/huin/goupnp github.com/huin/goupnp/dcps/internetgateway1 github.com/huin/goupnp/dcps/internetgateway2 @@ -242,13 +241,13 @@ github.com/imdario/mergo github.com/influxdata/influxdb/client github.com/influxdata/influxdb/models github.com/influxdata/influxdb/pkg/escape -# github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 +# github.com/jackpal/go-nat-pmp v1.0.1 github.com/jackpal/go-nat-pmp # github.com/json-iterator/go v1.1.7 github.com/json-iterator/go # github.com/julienschmidt/httprouter v1.2.0 github.com/julienschmidt/httprouter -# github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 +# github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 github.com/karalabe/usb # github.com/konsorten/go-windows-terminal-sequences v1.0.2 github.com/konsorten/go-windows-terminal-sequences @@ -256,7 +255,7 @@ github.com/konsorten/go-windows-terminal-sequences github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.8 github.com/mattn/go-isatty -# github.com/mattn/go-runewidth v0.0.3 +# github.com/mattn/go-runewidth v0.0.4 github.com/mattn/go-runewidth # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd github.com/modern-go/concurrent @@ -271,23 +270,23 @@ github.com/naoina/go-stringutil # github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416 github.com/naoina/toml github.com/naoina/toml/ast -# github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c +# github.com/olekukonko/tablewriter v0.0.2 github.com/olekukonko/tablewriter # github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/image-spec/specs-go/v1 github.com/opencontainers/image-spec/specs-go +github.com/opencontainers/image-spec/specs-go/v1 # github.com/opencontainers/runc v0.1.1 github.com/opencontainers/runc/libcontainer/system github.com/opencontainers/runc/libcontainer/user # github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go -github.com/opentracing/opentracing-go/log github.com/opentracing/opentracing-go/ext +github.com/opentracing/opentracing-go/log # github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e github.com/oschwald/maxminddb-golang -# github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 +# github.com/pborman/uuid v1.2.0 github.com/pborman/uuid # github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7 github.com/peterh/liner @@ -295,7 +294,7 @@ github.com/peterh/liner github.com/pkg/errors # github.com/prometheus/tsdb v0.10.0 github.com/prometheus/tsdb/fileutil -# github.com/rjeczalik/notify v0.9.1 +# github.com/rjeczalik/notify v0.9.2 github.com/rjeczalik/notify # github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d github.com/robertkrimen/otto @@ -305,91 +304,96 @@ github.com/robertkrimen/otto/file github.com/robertkrimen/otto/parser github.com/robertkrimen/otto/registry github.com/robertkrimen/otto/token -# github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 +# github.com/rs/cors v1.7.0 github.com/rs/cors -# github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 -github.com/rs/xhandler +# github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 +github.com/rsksmart/rds-swarm/config +github.com/rsksmart/rds-swarm/resolver +github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver +github.com/rsksmart/rds-swarm/resolver/rsk_resolver +github.com/rsksmart/rds-swarm/utils # github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus # github.com/spf13/pflag v1.0.3 github.com/spf13/pflag -# github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 +# github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 github.com/status-im/keycard-go/derivationpath # github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 github.com/steakknife/bloomfilter # github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 github.com/steakknife/hamming -# github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 +# github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/syndtr/goleveldb/leveldb -github.com/syndtr/goleveldb/leveldb/opt -github.com/syndtr/goleveldb/leveldb/iterator -github.com/syndtr/goleveldb/leveldb/storage -github.com/syndtr/goleveldb/leveldb/util -github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/cache github.com/syndtr/goleveldb/leveldb/comparer +github.com/syndtr/goleveldb/leveldb/errors github.com/syndtr/goleveldb/leveldb/filter +github.com/syndtr/goleveldb/leveldb/iterator github.com/syndtr/goleveldb/leveldb/journal github.com/syndtr/goleveldb/leveldb/memdb +github.com/syndtr/goleveldb/leveldb/opt +github.com/syndtr/goleveldb/leveldb/storage github.com/syndtr/goleveldb/leveldb/table +github.com/syndtr/goleveldb/leveldb/util # github.com/tilinna/clock v1.0.2 github.com/tilinna/clock -# github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef +# github.com/tyler-smith/go-bip39 v1.0.2 github.com/tyler-smith/go-bip39 github.com/tyler-smith/go-bip39/wordlists # github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6 github.com/uber/jaeger-client-go github.com/uber/jaeger-client-go/config github.com/uber/jaeger-client-go/internal/baggage +github.com/uber/jaeger-client-go/internal/baggage/remote github.com/uber/jaeger-client-go/internal/spanlog github.com/uber/jaeger-client-go/internal/throttler +github.com/uber/jaeger-client-go/internal/throttler/remote github.com/uber/jaeger-client-go/log +github.com/uber/jaeger-client-go/rpcmetrics github.com/uber/jaeger-client-go/thrift +github.com/uber/jaeger-client-go/thrift-gen/agent +github.com/uber/jaeger-client-go/thrift-gen/baggage github.com/uber/jaeger-client-go/thrift-gen/jaeger github.com/uber/jaeger-client-go/thrift-gen/sampling github.com/uber/jaeger-client-go/thrift-gen/zipkincore github.com/uber/jaeger-client-go/utils -github.com/uber/jaeger-client-go/internal/baggage/remote -github.com/uber/jaeger-client-go/internal/throttler/remote -github.com/uber/jaeger-client-go/rpcmetrics -github.com/uber/jaeger-client-go/thrift-gen/agent -github.com/uber/jaeger-client-go/thrift-gen/baggage # github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7 github.com/uber/jaeger-lib/metrics # github.com/vbauerster/mpb v3.4.0+incompatible github.com/vbauerster/mpb -github.com/vbauerster/mpb/decor github.com/vbauerster/mpb/cwriter +github.com/vbauerster/mpb/decor github.com/vbauerster/mpb/internal # github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 github.com/wsddn/go-ecdh -# golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 -golang.org/x/crypto/scrypt -golang.org/x/crypto/sha3 +# golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 +golang.org/x/crypto/cast5 +golang.org/x/crypto/curve25519 golang.org/x/crypto/openpgp -golang.org/x/crypto/pbkdf2 golang.org/x/crypto/openpgp/armor +golang.org/x/crypto/openpgp/elgamal golang.org/x/crypto/openpgp/errors golang.org/x/crypto/openpgp/packet golang.org/x/crypto/openpgp/s2k -golang.org/x/crypto/ssh/terminal +golang.org/x/crypto/pbkdf2 golang.org/x/crypto/ripemd160 -golang.org/x/crypto/cast5 -golang.org/x/crypto/openpgp/elgamal -golang.org/x/crypto/curve25519 -# golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 +golang.org/x/crypto/scrypt +golang.org/x/crypto/sha3 +golang.org/x/crypto/ssh/terminal +# golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 golang.org/x/net/context +golang.org/x/net/context/ctxhttp golang.org/x/net/html -golang.org/x/net/websocket -golang.org/x/net/http2 golang.org/x/net/html/atom golang.org/x/net/html/charset -golang.org/x/net/proxy golang.org/x/net/http/httpguts +golang.org/x/net/http2 golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/internal/socks -golang.org/x/net/context/ctxhttp +golang.org/x/net/proxy +golang.org/x/net/publicsuffix +golang.org/x/net/websocket # golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 golang.org/x/oauth2/internal @@ -397,49 +401,49 @@ golang.org/x/oauth2/internal golang.org/x/sync/errgroup golang.org/x/sync/singleflight golang.org/x/sync/syncmap -# golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa +# golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 -golang.org/x/text/unicode/norm -golang.org/x/text/transform golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex -golang.org/x/text/secure/bidirule -golang.org/x/text/unicode/bidi -golang.org/x/text/encoding/internal/identifier golang.org/x/text/encoding/internal +golang.org/x/text/encoding/internal/identifier golang.org/x/text/encoding/japanese golang.org/x/text/encoding/korean golang.org/x/text/encoding/simplifiedchinese golang.org/x/text/encoding/traditionalchinese golang.org/x/text/encoding/unicode -golang.org/x/text/language -golang.org/x/text/internal/utf8internal -golang.org/x/text/runes golang.org/x/text/internal/language golang.org/x/text/internal/language/compact golang.org/x/text/internal/tag +golang.org/x/text/internal/utf8internal +golang.org/x/text/language +golang.org/x/text/runes +golang.org/x/text/secure/bidirule +golang.org/x/text/transform +golang.org/x/text/unicode/bidi +golang.org/x/text/unicode/norm # golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/time/rate # google.golang.org/appengine v1.6.1 -google.golang.org/appengine/urlfetch google.golang.org/appengine/internal -google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/base google.golang.org/appengine/internal/datastore google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api +google.golang.org/appengine/internal/urlfetch +google.golang.org/appengine/urlfetch # google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.22.1 +# google.golang.org/grpc v1.23.1 google.golang.org/grpc/codes -google.golang.org/grpc/status -google.golang.org/grpc/internal google.golang.org/grpc/connectivity google.golang.org/grpc/grpclog +google.golang.org/grpc/internal +google.golang.org/grpc/status # gopkg.in/inf.v0 v0.9.1 gopkg.in/inf.v0 # gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce @@ -454,10 +458,8 @@ gopkg.in/urfave/cli.v1 # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190703205437-39734b2a72fe -k8s.io/api/core/v1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1 -k8s.io/api/autoscaling/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/auditregistration/v1alpha1 @@ -465,6 +467,7 @@ k8s.io/api/authentication/v1 k8s.io/api/authentication/v1beta1 k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 +k8s.io/api/autoscaling/v1 k8s.io/api/autoscaling/v2beta1 k8s.io/api/autoscaling/v2beta2 k8s.io/api/batch/v1 @@ -473,13 +476,14 @@ k8s.io/api/batch/v2alpha1 k8s.io/api/certificates/v1beta1 k8s.io/api/coordination/v1 k8s.io/api/coordination/v1beta1 -k8s.io/api/policy/v1beta1 +k8s.io/api/core/v1 k8s.io/api/events/v1beta1 k8s.io/api/extensions/v1beta1 k8s.io/api/networking/v1 k8s.io/api/networking/v1beta1 k8s.io/api/node/v1alpha1 k8s.io/api/node/v1beta1 +k8s.io/api/policy/v1beta1 k8s.io/api/rbac/v1 k8s.io/api/rbac/v1alpha1 k8s.io/api/rbac/v1beta1 @@ -491,45 +495,44 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 # k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76 +k8s.io/apimachinery/pkg/api/errors +k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 -k8s.io/apimachinery/pkg/runtime -k8s.io/apimachinery/pkg/runtime/schema -k8s.io/apimachinery/pkg/types -k8s.io/apimachinery/pkg/util/intstr +k8s.io/apimachinery/pkg/apis/meta/v1/unstructured k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/conversion/queryparams k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/labels -k8s.io/apimachinery/pkg/selection -k8s.io/apimachinery/pkg/util/runtime -k8s.io/apimachinery/pkg/watch -k8s.io/apimachinery/pkg/api/errors -k8s.io/apimachinery/pkg/runtime/serializer/streaming -k8s.io/apimachinery/pkg/util/net -k8s.io/apimachinery/pkg/util/sets -k8s.io/apimachinery/pkg/util/errors -k8s.io/apimachinery/pkg/util/validation -k8s.io/apimachinery/pkg/conversion/queryparams -k8s.io/apimachinery/pkg/util/json -k8s.io/apimachinery/pkg/util/naming -k8s.io/apimachinery/third_party/forked/golang/reflect +k8s.io/apimachinery/pkg/runtime +k8s.io/apimachinery/pkg/runtime/schema k8s.io/apimachinery/pkg/runtime/serializer -k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/util/clock -k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/runtime/serializer/json -k8s.io/apimachinery/pkg/runtime/serializer/versioning k8s.io/apimachinery/pkg/runtime/serializer/protobuf k8s.io/apimachinery/pkg/runtime/serializer/recognizer -k8s.io/apimachinery/pkg/api/meta +k8s.io/apimachinery/pkg/runtime/serializer/streaming +k8s.io/apimachinery/pkg/runtime/serializer/versioning +k8s.io/apimachinery/pkg/selection +k8s.io/apimachinery/pkg/types +k8s.io/apimachinery/pkg/util/clock +k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/framer +k8s.io/apimachinery/pkg/util/intstr +k8s.io/apimachinery/pkg/util/json +k8s.io/apimachinery/pkg/util/naming +k8s.io/apimachinery/pkg/util/net +k8s.io/apimachinery/pkg/util/runtime +k8s.io/apimachinery/pkg/util/sets +k8s.io/apimachinery/pkg/util/validation +k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/util/yaml -k8s.io/apimachinery/pkg/apis/meta/v1/unstructured +k8s.io/apimachinery/pkg/version +k8s.io/apimachinery/pkg/watch +k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/client-go v0.0.0-20190706005506-4ed54556a14a -k8s.io/client-go/kubernetes -k8s.io/client-go/rest -k8s.io/client-go/tools/clientcmd k8s.io/client-go/discovery +k8s.io/client-go/kubernetes +k8s.io/client-go/kubernetes/scheme k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1 k8s.io/client-go/kubernetes/typed/apps/v1beta1 @@ -566,25 +569,26 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1 k8s.io/client-go/kubernetes/typed/storage/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1beta1 -k8s.io/client-go/util/flowcontrol +k8s.io/client-go/pkg/apis/clientauthentication +k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 +k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/pkg/version k8s.io/client-go/plugin/pkg/client/auth/exec +k8s.io/client-go/rest k8s.io/client-go/rest/watch +k8s.io/client-go/tools/auth +k8s.io/client-go/tools/clientcmd k8s.io/client-go/tools/clientcmd/api +k8s.io/client-go/tools/clientcmd/api/latest +k8s.io/client-go/tools/clientcmd/api/v1 k8s.io/client-go/tools/metrics +k8s.io/client-go/tools/reference k8s.io/client-go/transport k8s.io/client-go/util/cert -k8s.io/client-go/tools/auth -k8s.io/client-go/tools/clientcmd/api/latest -k8s.io/client-go/util/homedir -k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/tools/reference -k8s.io/client-go/pkg/apis/clientauthentication -k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 -k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/util/connrotation +k8s.io/client-go/util/flowcontrol +k8s.io/client-go/util/homedir k8s.io/client-go/util/keyutil -k8s.io/client-go/tools/clientcmd/api/v1 # k8s.io/klog v0.3.1 k8s.io/klog # k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a From dffe42729cf97ad1a568c64c3a9bc8b25a46e44a Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Tue, 12 Nov 2019 14:21:42 -0300 Subject: [PATCH 22/49] vendor,swarm,main: added parseRnsAPIAddress and updated vendor --- cmd/swarm/flags.go | 4 +-- go.mod | 2 +- go.sum | 4 +++ swarm.go | 34 +++++++++++++++++-- .../rsksmart/rds-swarm/config/config.go | 10 ++++++ vendor/modules.txt | 2 +- 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index 523405ebf6..c3289700e0 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -126,9 +126,9 @@ var ( Usage: "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url", EnvVar: SwarmEnvENSAPI, } - RnsAPIFlag = cli.StringSliceFlag{ + RnsAPIFlag = cli.StringFlag{ Name: "rns-api", - Usage: "RNS API endpoint for a TLD and with contract address, can be repeated, format [contract-addr@]url", + Usage: "RNS API endpoint for RKS domains contract address, format [contract-addr@]url", EnvVar: SwarmEnvRNSAPI, } SwarmApiFlag = cli.StringFlag{ diff --git a/go.mod b/go.mod index 3ed0a7e834..6640bad59a 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v1.7.0 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 + github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tilinna/clock v1.0.2 github.com/uber-go/atomic v1.4.0 // indirect diff --git a/go.sum b/go.sum index 5f1f6a511c..5d1e99f48b 100644 --- a/go.sum +++ b/go.sum @@ -310,6 +310,10 @@ github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 h1:saHKOwJeSkV5PzZeTnw97JMLycaDBJnF2P/1sDVWuq8= github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= +github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba h1:+qGsAO4EkxcOZeMqUmiA5iQlqWodeo1TLa8HH4FQlWo= +github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= +github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 h1:yAkrytBxYgRMCXmMjpSRsepX2qnTqUzxkheFMMdkXeI= +github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= diff --git a/swarm.go b/swarm.go index d62eef281e..060dba4bd3 100644 --- a/swarm.go +++ b/swarm.go @@ -184,11 +184,16 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e self.dns = resolver } if config.RnsAPI != "" { - _, endpoint, addr := parseEnsAPIAddress(config.RnsAPI) + var emptyAddress common.Address + var contract string + endpoint, addr := parseRnsAPIAddress(config.RnsAPI) if err != nil { return nil, err } - rns.SetRSKConfiguration(endpoint, addr.String()) + if !bytes.Equal(addr.Bytes(), emptyAddress.Bytes()) { + contract = addr.String() + } + rns.SetMultiChainConfiguration(endpoint, contract) } // check that we are not in the old database schema @@ -312,6 +317,31 @@ func parseEnsAPIAddress(s string) (tld, endpoint string, addr common.Address) { return } +// parseRnsAPIAddress parses string according to format +// [contract-addr@]url and returns RNSClientConfig structure +// with endpoint and contract address +func parseRnsAPIAddress(s string) (endpoint string, addr common.Address) { + isAllLetterString := func(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { + return false + } + } + return true + } + endpoint = s + if i := strings.Index(endpoint, ":"); i > 0 { + if isAllLetterString(endpoint[:i]) && len(endpoint) > i+2 && endpoint[i+1:i+3] != "//" { + endpoint = endpoint[i+1:] + } + } + if i := strings.Index(endpoint, "@"); i > 0 { + addr = common.HexToAddress(endpoint[:i]) + endpoint = endpoint[i+1:] + } + return +} + // ensClient provides functionality for api.ResolveValidator type ensClient struct { *ens.ENS diff --git a/vendor/github.com/rsksmart/rds-swarm/config/config.go b/vendor/github.com/rsksmart/rds-swarm/config/config.go index 1884f140ea..76b6384e37 100644 --- a/vendor/github.com/rsksmart/rds-swarm/config/config.go +++ b/vendor/github.com/rsksmart/rds-swarm/config/config.go @@ -36,3 +36,13 @@ func SetRSKConfiguration(endpoint string, contract string) { cfg.ResolverAddresses.RSK = contract } } + +// SetMultiChainConfiguration overrides multichain endpoint and contract to rns node +func SetMultiChainConfiguration(endpoint string, contract string) { + if endpoint != "" { + cfg.NetworkNodeAddress = endpoint + } + if contract != "" { + cfg.ResolverAddresses.MultiChain = contract + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index a4ab7004e0..905233a927 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -306,7 +306,7 @@ github.com/robertkrimen/otto/registry github.com/robertkrimen/otto/token # github.com/rs/cors v1.7.0 github.com/rs/cors -# github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 +# github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 github.com/rsksmart/rds-swarm/config github.com/rsksmart/rds-swarm/resolver github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver From 9fc20e0987f140cc94d28c1991563c1fdde3c1ee Mon Sep 17 00:00:00 2001 From: santicomp2014 Date: Tue, 12 Nov 2019 16:52:13 -0300 Subject: [PATCH 23/49] vendor,swarm: updated rns-resolution --- go.mod | 2 +- go.sum | 2 + swarm.go | 5 +- .../rsksmart/rds-swarm/config/config.go | 24 +- .../rsksmart/rds-swarm/resolver/resolver.go | 85 ++--- .../resolver/rsk_resolver/RSKResolverABI.json | 134 -------- .../resolver/rsk_resolver/rsk_resolver.go | 319 ------------------ .../rsksmart/rds-swarm/utils/utils.go | 4 +- vendor/modules.txt | 3 +- 9 files changed, 31 insertions(+), 547 deletions(-) delete mode 100644 vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json delete mode 100644 vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go diff --git a/go.mod b/go.mod index 6640bad59a..09703ba144 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect github.com/rs/cors v1.7.0 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 + github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tilinna/clock v1.0.2 github.com/uber-go/atomic v1.4.0 // indirect diff --git a/go.sum b/go.sum index 5d1e99f48b..b2703a9745 100644 --- a/go.sum +++ b/go.sum @@ -314,6 +314,8 @@ github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba h1:+qGsAO4EkxcO github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 h1:yAkrytBxYgRMCXmMjpSRsepX2qnTqUzxkheFMMdkXeI= github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= +github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595 h1:2JkrJLVP8n6pzVpUMoCk0GfdJgWrbSKFxV1y0pTcmFo= +github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= diff --git a/swarm.go b/swarm.go index 060dba4bd3..ad846aab96 100644 --- a/swarm.go +++ b/swarm.go @@ -187,13 +187,10 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e var emptyAddress common.Address var contract string endpoint, addr := parseRnsAPIAddress(config.RnsAPI) - if err != nil { - return nil, err - } if !bytes.Equal(addr.Bytes(), emptyAddress.Bytes()) { contract = addr.String() } - rns.SetMultiChainConfiguration(endpoint, contract) + rns.SetConfiguration(endpoint, contract) } // check that we are not in the old database schema diff --git a/vendor/github.com/rsksmart/rds-swarm/config/config.go b/vendor/github.com/rsksmart/rds-swarm/config/config.go index 76b6384e37..b0dd58f2b1 100644 --- a/vendor/github.com/rsksmart/rds-swarm/config/config.go +++ b/vendor/github.com/rsksmart/rds-swarm/config/config.go @@ -6,7 +6,6 @@ import ( func init() { env.Parse(&cfg) - env.Parse(&cfg.ResolverAddresses) } // Configuration is the struct that holds the values of the network configuration @@ -14,35 +13,22 @@ func init() { // it corresponds with the os environment variable name and also its default value if omitted type Configuration struct { NetworkNodeAddress string `env:"RNS_NETWORK_NODE_ADDRESS" envDefault:"https://public-node.rsk.co"` - ResolverAddresses struct { - RSK string `env:"RNS_RESOLVER_ADDRESS_RSK" envDefault:"0x4efd25e3d348f8f25a14fb7655fba6f72edfe93a"` - MultiChain string `env:"RNS_RESOLVER_ADDRESS_MULTICHAIN" envDefault:"0x99a12be4C89CbF6CFD11d1F2c029904a7B644368"` - } + ResolverAddress string `env:"RNS_RESOLVER_ADDRESS" envDefault:"0x99a12be4C89CbF6CFD11d1F2c029904a7B644368"` } var cfg Configuration = Configuration{} -// GetConfiguration loads the environment variables into a Configuration struct and returns it. +// GetConfiguration loads the environment variables into a Configuration struct and returns it func GetConfiguration() Configuration { return cfg } -// SetRSKConfiguration overrides endpoint and contract to rns node -func SetRSKConfiguration(endpoint string, contract string) { - if endpoint != "" { - cfg.NetworkNodeAddress = endpoint - } - if contract != "" { - cfg.ResolverAddresses.RSK = contract - } -} - -// SetMultiChainConfiguration overrides multichain endpoint and contract to rns node -func SetMultiChainConfiguration(endpoint string, contract string) { +// SetConfiguration sets the configuration for the blockchain endpoint and resolver contract +func SetConfiguration(endpoint string, contract string) { if endpoint != "" { cfg.NetworkNodeAddress = endpoint } if contract != "" { - cfg.ResolverAddresses.MultiChain = contract + cfg.ResolverAddress = contract } } diff --git a/vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go b/vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go index 0699762308..bd937c9854 100644 --- a/vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go +++ b/vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go @@ -5,7 +5,6 @@ import ( config "github.com/rsksmart/rds-swarm/config" multichainresolver "github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver" - rskresolver "github.com/rsksmart/rds-swarm/resolver/rsk_resolver" "github.com/rsksmart/rds-swarm/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -19,24 +18,14 @@ var ErrNoAddress = errors.New("domain without registered address in RNS") // ErrNoContent is returned when there is no registered content through RNS var ErrNoContent = errors.New("domain without registered content in RNS") -// Resolver interface is implemented by all types which can resolve both the address of a domain as well as its content. +// Resolver interface is implemented by all types which can resolve both the address of a domain as well as its content type Resolver interface { Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) } -func getPublicResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { - resolverAddress := common.HexToAddress(configuration.ResolverAddresses.RSK) - resolver, resolverError := rskresolver.NewRskresolver(resolverAddress, client) - if resolverError != nil { - return nil, resolverError - } - - return resolver, nil -} - -func getMultiChainResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { - resolverAddress := common.HexToAddress(configuration.ResolverAddresses.MultiChain) +func getResolver(client *ethclient.Client, configuration config.Configuration) (Resolver, error) { + resolverAddress := common.HexToAddress(configuration.ResolverAddress) resolver, resolverError := multichainresolver.NewMultichainresolver(resolverAddress, client) if resolverError != nil { return nil, resolverError @@ -62,63 +51,29 @@ func setUpResolver(resolverConstructor func(client *ethclient.Client, configurat return resolver, nil } -func resolveAddressFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) (common.Address, error) { - var emptyAddress common.Address - - resolver, resolverError := setUpResolver(getResolverFunction) - if resolverError != nil { - return emptyAddress, resolverError - } - - resolvedAddress, resolutionError := resolveAddress(domainAddress, resolver) - if resolutionError != nil { - return emptyAddress, resolutionError - } - - return resolvedAddress, nil -} - func resolveAddress(byteArrayAddress [32]byte, resolver Resolver) (common.Address, error) { return resolver.Addr(&bind.CallOpts{}, byteArrayAddress) } -func resolveContentFromResolver(domainAddress [32]byte, getResolverFunction func(client *ethclient.Client, configuration config.Configuration) (Resolver, error)) ([32]byte, error) { - var emptyContent [32]byte - - resolver, resolverError := setUpResolver(getResolverFunction) - if resolverError != nil { - return emptyContent, resolverError - } - - resolvedContent, resolutionError := resolveContent(domainAddress, resolver) - if resolutionError != nil { - return emptyContent, resolutionError - } - - return resolvedContent, nil -} - func resolveContent(byteArrayAddress [32]byte, resolver Resolver) ([32]byte, error) { return resolver.Content(&bind.CallOpts{}, byteArrayAddress) } -// ResolveDomainAddress receives a domain string and returns its RNS-resolved hex address. -// It will attempt to solve the address through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty address. +// ResolveDomainAddress receives a domain string and returns its RNS-resolved hex address +// It will attempt to solve the address through the Multi-Chain resolver func ResolveDomainAddress(domain string) (common.Address, error) { domainAddress := utils.DomainToHashedByteArray(domain) var emptyAddress, resolvedAddress common.Address var resolvedError error - resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getMultiChainResolver) - if resolvedError != nil { - return emptyAddress, resolvedError + resolver, resolverError := setUpResolver(getResolver) + if resolverError != nil { + return emptyAddress, resolverError } - if resolvedAddress == emptyAddress { - resolvedAddress, resolvedError = resolveAddressFromResolver(domainAddress, getPublicResolver) - if resolvedError != nil { - return emptyAddress, resolvedError - } + resolvedAddress, resolvedError = resolveAddress(domainAddress, resolver) + if resolvedError != nil { + return emptyAddress, resolvedError } if resolvedAddress == emptyAddress { @@ -127,23 +82,21 @@ func ResolveDomainAddress(domain string) (common.Address, error) { return resolvedAddress, resolvedError } -// ResolveDomainContent receives a domain string and returns its RNS-resolved associated content hash. -// It will attempt to solve the content through the Multi-Chain resolver first, and through the Public resolver later if the former results in an empty content. +// ResolveDomainContent receives a domain string and returns its RNS-resolved associated content hash +// It will attempt to solve the content through the Multi-Chain resolver func ResolveDomainContent(domain string) (common.Hash, error) { domainAddress := utils.DomainToHashedByteArray(domain) var emptyContent, resolvedContent [32]byte var resolvedError error - resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getMultiChainResolver) - if resolvedError != nil { - return emptyContent, resolvedError + resolver, resolverError := setUpResolver(getResolver) + if resolverError != nil { + return emptyContent, resolverError } - if resolvedContent == emptyContent { - resolvedContent, resolvedError = resolveContentFromResolver(domainAddress, getPublicResolver) - if resolvedError != nil { - return emptyContent, resolvedError - } + resolvedContent, resolvedError = resolveContent(domainAddress, resolver) + if resolvedError != nil { + return emptyContent, resolvedError } if resolvedContent == emptyContent { diff --git a/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json b/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json deleted file mode 100644 index 513179bdcb..0000000000 --- a/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/RSKResolverABI.json +++ /dev/null @@ -1,134 +0,0 @@ -[ - { - "inputs": [ - { - "name": "rnsAddr", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "kind", - "type": "bytes32" - } - ], - "name": "has", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "interfaceID", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "addr", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "addrValue", - "type": "address" - } - ], - "name": "setAddr", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "content", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "hash", - "type": "bytes32" - } - ], - "name": "setContent", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ] \ No newline at end of file diff --git a/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go b/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go deleted file mode 100644 index 3915ef1747..0000000000 --- a/vendor/github.com/rsksmart/rds-swarm/resolver/rsk_resolver/rsk_resolver.go +++ /dev/null @@ -1,319 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package rskresolver - -import ( - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = abi.U256 - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// RskresolverABI is the input ABI used to generate the binding from. -const RskresolverABI = "[{\"inputs\":[{\"name\":\"rnsAddr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"kind\",\"type\":\"bytes32\"}],\"name\":\"has\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addrValue\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" - -// Rskresolver is an auto generated Go binding around an Ethereum contract. -type Rskresolver struct { - RskresolverCaller // Read-only binding to the contract - RskresolverTransactor // Write-only binding to the contract - RskresolverFilterer // Log filterer for contract events -} - -// RskresolverCaller is an auto generated read-only Go binding around an Ethereum contract. -type RskresolverCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverTransactor is an auto generated write-only Go binding around an Ethereum contract. -type RskresolverTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type RskresolverFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// RskresolverSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type RskresolverSession struct { - Contract *Rskresolver // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// RskresolverCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type RskresolverCallerSession struct { - Contract *RskresolverCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// RskresolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type RskresolverTransactorSession struct { - Contract *RskresolverTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// RskresolverRaw is an auto generated low-level Go binding around an Ethereum contract. -type RskresolverRaw struct { - Contract *Rskresolver // Generic contract binding to access the raw methods on -} - -// RskresolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type RskresolverCallerRaw struct { - Contract *RskresolverCaller // Generic read-only contract binding to access the raw methods on -} - -// RskresolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type RskresolverTransactorRaw struct { - Contract *RskresolverTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewRskresolver creates a new instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolver(address common.Address, backend bind.ContractBackend) (*Rskresolver, error) { - contract, err := bindRskresolver(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Rskresolver{RskresolverCaller: RskresolverCaller{contract: contract}, RskresolverTransactor: RskresolverTransactor{contract: contract}, RskresolverFilterer: RskresolverFilterer{contract: contract}}, nil -} - -// NewRskresolverCaller creates a new read-only instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverCaller(address common.Address, caller bind.ContractCaller) (*RskresolverCaller, error) { - contract, err := bindRskresolver(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &RskresolverCaller{contract: contract}, nil -} - -// NewRskresolverTransactor creates a new write-only instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverTransactor(address common.Address, transactor bind.ContractTransactor) (*RskresolverTransactor, error) { - contract, err := bindRskresolver(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &RskresolverTransactor{contract: contract}, nil -} - -// NewRskresolverFilterer creates a new log filterer instance of Rskresolver, bound to a specific deployed contract. -func NewRskresolverFilterer(address common.Address, filterer bind.ContractFilterer) (*RskresolverFilterer, error) { - contract, err := bindRskresolver(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &RskresolverFilterer{contract: contract}, nil -} - -// bindRskresolver binds a generic wrapper to an already deployed contract. -func bindRskresolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(RskresolverABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Rskresolver *RskresolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Rskresolver.Contract.RskresolverCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Rskresolver *RskresolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Rskresolver.Contract.RskresolverTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Rskresolver *RskresolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Rskresolver.Contract.RskresolverTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Rskresolver *RskresolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { - return _Rskresolver.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Rskresolver *RskresolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Rskresolver.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Rskresolver *RskresolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Rskresolver.Contract.contract.Transact(opts, method, params...) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) { - var ( - ret0 = new(common.Address) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "addr", node) - return *ret0, err -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverSession) Addr(node [32]byte) (common.Address, error) { - return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) -} - -// Addr is a free data retrieval call binding the contract method 0x3b3b57de. -// -// Solidity: function addr(bytes32 node) constant returns(address) -func (_Rskresolver *RskresolverCallerSession) Addr(node [32]byte) (common.Address, error) { - return _Rskresolver.Contract.Addr(&_Rskresolver.CallOpts, node) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) { - var ( - ret0 = new([32]byte) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "content", node) - return *ret0, err -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverSession) Content(node [32]byte) ([32]byte, error) { - return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) -} - -// Content is a free data retrieval call binding the contract method 0x2dff6941. -// -// Solidity: function content(bytes32 node) constant returns(bytes32) -func (_Rskresolver *RskresolverCallerSession) Content(node [32]byte) ([32]byte, error) { - return _Rskresolver.Contract.Content(&_Rskresolver.CallOpts, node) -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverCaller) Has(opts *bind.CallOpts, node [32]byte, kind [32]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "has", node, kind) - return *ret0, err -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverSession) Has(node [32]byte, kind [32]byte) (bool, error) { - return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) -} - -// Has is a free data retrieval call binding the contract method 0x41b9dc2b. -// -// Solidity: function has(bytes32 node, bytes32 kind) constant returns(bool) -func (_Rskresolver *RskresolverCallerSession) Has(node [32]byte, kind [32]byte) (bool, error) { - return _Rskresolver.Contract.Has(&_Rskresolver.CallOpts, node, kind) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) { - var ( - ret0 = new(bool) - ) - out := ret0 - err := _Rskresolver.contract.Call(opts, out, "supportsInterface", interfaceID) - return *ret0, err -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverSession) SupportsInterface(interfaceID [4]byte) (bool, error) { - return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceID) constant returns(bool) -func (_Rskresolver *RskresolverCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) { - return _Rskresolver.Contract.SupportsInterface(&_Rskresolver.CallOpts, interfaceID) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.contract.Transact(opts, "setAddr", node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) -} - -// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00. -// -// Solidity: function setAddr(bytes32 node, address addrValue) returns() -func (_Rskresolver *RskresolverTransactorSession) SetAddr(node [32]byte, addrValue common.Address) (*types.Transaction, error) { - return _Rskresolver.Contract.SetAddr(&_Rskresolver.TransactOpts, node, addrValue) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.contract.Transact(opts, "setContent", node, hash) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) -} - -// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6. -// -// Solidity: function setContent(bytes32 node, bytes32 hash) returns() -func (_Rskresolver *RskresolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) { - return _Rskresolver.Contract.SetContent(&_Rskresolver.TransactOpts, node, hash) -} diff --git a/vendor/github.com/rsksmart/rds-swarm/utils/utils.go b/vendor/github.com/rsksmart/rds-swarm/utils/utils.go index c831dbf4c9..9698cd6ba6 100644 --- a/vendor/github.com/rsksmart/rds-swarm/utils/utils.go +++ b/vendor/github.com/rsksmart/rds-swarm/utils/utils.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -// DomainToHashedByteArray takes a string containing a domain, hashes it and returns it as an array of 32 bytes. +// DomainToHashedByteArray takes a string containing a domain, hashes it and returns it as an array of 32 bytes func DomainToHashedByteArray(domain string) [32]byte { var byteArrayAddress [32]byte @@ -18,7 +18,7 @@ func DomainToHashedByteArray(domain string) [32]byte { return byteArrayAddress } -// RnsNode takes a string containing a domain, hashes it and returns it as a Keccak256Hash. +// RnsNode takes a string containing a domain, hashes it and returns it as a Keccak256Hash func RnsNode(name string) common.Hash { parentNode, parentLabel := rnsParentNode(name) return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) diff --git a/vendor/modules.txt b/vendor/modules.txt index 905233a927..cebd3a5270 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -306,11 +306,10 @@ github.com/robertkrimen/otto/registry github.com/robertkrimen/otto/token # github.com/rs/cors v1.7.0 github.com/rs/cors -# github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 +# github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595 github.com/rsksmart/rds-swarm/config github.com/rsksmart/rds-swarm/resolver github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver -github.com/rsksmart/rds-swarm/resolver/rsk_resolver github.com/rsksmart/rds-swarm/utils # github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus From 65134e0d8d7c674e726ac66b0a737af8021ee289 Mon Sep 17 00:00:00 2001 From: mortelli Date: Tue, 12 Nov 2019 16:56:13 -0300 Subject: [PATCH 24/49] restor vendor folder, go.mod, go.sum from master branch --- go.mod | 40 +- go.sum | 125 - vendor.zip | Bin 0 -> 14385853 bytes vendor/github.com/StackExchange/wmi/LICENSE | 20 + vendor/github.com/StackExchange/wmi/README.md | 6 + .../StackExchange/wmi/swbemservices.go | 260 + vendor/github.com/StackExchange/wmi/wmi.go | 501 + .../goarista/monotime/issue15006.s | 2 +- .../goarista/monotime/nanotime.go | 2 +- .../github.com/btcsuite/btcd/btcec/btcec.go | 24 +- .../github.com/btcsuite/btcd/btcec/field.go | 129 - .../btcsuite/btcd/btcec/genprecomps.go | 63 + .../github.com/btcsuite/btcd/btcec/pubkey.go | 59 +- .../btcsuite/btcd/btcec/signature.go | 22 +- vendor/github.com/caarlos0/env/.gitignore | 1 - vendor/github.com/caarlos0/env/.hound.yml | 2 - vendor/github.com/caarlos0/env/.travis.yml | 19 - vendor/github.com/caarlos0/env/README.md | 119 - vendor/github.com/caarlos0/env/env.go | 436 - .../deckarep/golang-set/threadsafe.go | 8 +- .../docker/pkg/archive/example_changes.go | 97 + vendor/github.com/edsrzf/mmap-go/mmap.go | 21 +- vendor/github.com/edsrzf/mmap-go/mmap_unix.go | 50 +- .../github.com/edsrzf/mmap-go/mmap_windows.go | 64 +- .../github.com/edsrzf/mmap-go/msync_netbsd.go | 8 + .../github.com/edsrzf/mmap-go/msync_unix.go | 14 + vendor/github.com/elastic/gosigar/.travis.yml | 3 +- .../github.com/elastic/gosigar/CHANGELOG.md | 43 +- vendor/github.com/elastic/gosigar/README.md | 1 - .../elastic/gosigar/sigar_darwin.go | 12 + .../elastic/gosigar/sigar_darwin_386.go | 18 - .../elastic/gosigar/sigar_darwin_amd64.go | 18 - .../elastic/gosigar/sigar_freebsd.go | 45 - .../elastic/gosigar/sigar_interface.go | 42 +- .../github.com/elastic/gosigar/sigar_linux.go | 25 - .../elastic/gosigar/sigar_linux_common.go | 25 + .../elastic/gosigar/sigar_windows.go | 114 +- .../elastic/gosigar/sys/windows/doc.go | 6 - .../gosigar/sys/windows/syscall_windows.go | 252 +- .../gosigar/sys/windows/zsyscall_windows.go | 198 +- .../ethereum/go-ethereum/.travis.yml | 31 +- .../ethereum/go-ethereum/Dockerfile | 4 +- .../ethereum/go-ethereum/Dockerfile.alltools | 4 +- .../github.com/ethereum/go-ethereum/Makefile | 2 +- .../github.com/ethereum/go-ethereum/README.md | 16 +- .../ethereum/go-ethereum/accounts/abi/abi.go | 6 + .../go-ethereum/accounts/abi/argument.go | 26 +- .../go-ethereum/accounts/abi/bind/base.go | 2 +- .../go-ethereum/accounts/abi/bind/bind.go | 84 +- .../go-ethereum/accounts/abi/bind/template.go | 4 +- .../go-ethereum/accounts/abi/bind/topics.go | 13 +- .../ethereum/go-ethereum/accounts/abi/type.go | 25 +- .../go-ethereum/accounts/usbwallet/ledger.go | 3 +- .../ethereum/go-ethereum/appveyor.yml | 4 +- .../go-ethereum/cmd/utils/customflags.go | 82 +- .../ethereum/go-ethereum/cmd/utils/flags.go | 42 +- .../ethereum/go-ethereum/common/bytes.go | 21 +- .../go-ethereum/common/mclock/mclock.go | 30 +- .../go-ethereum/common/mclock/simclock.go | 72 +- .../ethereum/go-ethereum/common/types.go | 6 +- .../go-ethereum/consensus/clique/clique.go | 10 +- .../ethereum/go-ethereum/consensus/errors.go | 2 +- .../go-ethereum/consensus/ethash/consensus.go | 4 +- .../ethereum/go-ethereum/core/blockchain.go | 52 +- .../ethereum/go-ethereum/core/chain_makers.go | 2 +- .../go-ethereum/core/forkid/forkid.go | 27 +- .../ethereum/go-ethereum/core/genesis.go | 25 +- .../ethereum/go-ethereum/core/headerchain.go | 11 +- .../go-ethereum/core/rawdb/freezer.go | 8 +- .../go-ethereum/core/rawdb/freezer_table.go | 22 +- .../go-ethereum/core/state/state_object.go | 58 +- .../go-ethereum/core/state/statedb.go | 168 +- .../go-ethereum/core/state_processor.go | 10 +- .../go-ethereum/core/state_transition.go | 15 +- .../ethereum/go-ethereum/core/tx_pool.go | 112 +- .../core/types/transaction_signing.go | 6 +- .../ethereum/go-ethereum/core/vm/contracts.go | 71 +- .../ethereum/go-ethereum/core/vm/eips.go | 7 - .../ethereum/go-ethereum/core/vm/gas_table.go | 57 - .../go-ethereum/core/vm/instructions.go | 24 +- .../go-ethereum/core/vm/interpreter.go | 2 - .../go-ethereum/core/vm/jump_table.go | 23 +- .../ethereum/go-ethereum/core/vm/memory.go | 2 +- .../go-ethereum/crypto/blake2b/blake2b.go | 319 - .../crypto/blake2b/blake2bAVX2_amd64.go | 37 - .../crypto/blake2b/blake2bAVX2_amd64.s | 717 -- .../crypto/blake2b/blake2b_amd64.go | 24 - .../crypto/blake2b/blake2b_amd64.s | 253 - .../crypto/blake2b/blake2b_f_fuzz.go | 57 - .../crypto/blake2b/blake2b_generic.go | 180 - .../go-ethereum/crypto/blake2b/blake2b_ref.go | 11 - .../go-ethereum/crypto/blake2b/blake2x.go | 177 - .../go-ethereum/crypto/blake2b/register.go | 32 - .../ethereum/go-ethereum/crypto/crypto.go | 9 - .../go-ethereum/crypto/signature_cgo.go | 16 +- .../go-ethereum/crypto/signature_nocgo.go | 2 +- .../ethereum/go-ethereum/dashboard/README.md | 4 +- .../go-ethereum/dashboard/dashboard.go | 2 +- .../ethereum/go-ethereum/eth/api.go | 5 - .../ethereum/go-ethereum/eth/api_backend.go | 59 - .../ethereum/go-ethereum/eth/backend.go | 4 +- .../ethereum/go-ethereum/eth/config.go | 3 - .../go-ethereum/eth/downloader/downloader.go | 35 +- .../go-ethereum/eth/downloader/statesync.go | 2 +- .../ethereum/go-ethereum/eth/handler.go | 7 +- .../ethereum/go-ethereum/eth/peer.go | 90 +- .../ethereum/go-ethereum/eth/protocol.go | 44 +- .../go-ethereum/eth/tracers/tracer.go | 4 +- .../go-ethereum/ethdb/leveldb/leveldb.go | 48 +- .../ethereum/go-ethereum/graphql/graphiql.go | 2 +- .../ethereum/go-ethereum/graphql/graphql.go | 248 +- .../go-ethereum/internal/ethapi/api.go | 68 +- .../go-ethereum/internal/ethapi/backend.go | 3 - .../go-ethereum/internal/web3ext/web3ext.go | 6 - .../ethereum/go-ethereum/les/api.go | 14 +- .../ethereum/go-ethereum/les/api_backend.go | 59 +- .../go-ethereum/les/{client.go => backend.go} | 133 +- .../ethereum/go-ethereum/les/balance.go | 8 +- .../ethereum/go-ethereum/les/benchmark.go | 48 +- .../ethereum/go-ethereum/les/bloombits.go | 3 +- .../go-ethereum/les/checkpointoracle.go | 7 +- .../go-ethereum/les/client_handler.go | 403 - .../ethereum/go-ethereum/les/clientpool.go | 625 +- .../ethereum/go-ethereum/les/commons.go | 69 +- .../ethereum/go-ethereum/les/costtracker.go | 54 +- .../ethereum/go-ethereum/les/distributor.go | 51 +- .../ethereum/go-ethereum/les/enr_entry.go | 32 - .../ethereum/go-ethereum/les/fetcher.go | 75 +- .../ethereum/go-ethereum/les/handler.go | 1293 +++ .../ethereum/go-ethereum/les/metrics.go | 108 +- .../ethereum/go-ethereum/les/odr.go | 5 +- .../ethereum/go-ethereum/les/peer.go | 56 +- .../ethereum/go-ethereum/les/server.go | 343 +- .../go-ethereum/les/server_handler.go | 950 -- .../ethereum/go-ethereum/les/serverpool.go | 61 +- .../ethereum/go-ethereum/les/sync.go | 80 +- .../ethereum/go-ethereum/les/test_helper.go | 558 - .../ethereum/go-ethereum/light/lightchain.go | 8 +- .../ethereum/go-ethereum/light/odr_util.go | 6 +- .../ethereum/go-ethereum/light/postprocess.go | 30 +- .../ethereum/go-ethereum/light/txpool.go | 11 +- .../ethereum/go-ethereum/log/README.md | 4 +- .../ethereum/go-ethereum/metrics/README.md | 4 +- .../ethereum/go-ethereum/metrics/gauge.go | 38 - .../ethereum/go-ethereum/miner/worker.go | 2 +- .../ethereum/go-ethereum/p2p/dial.go | 145 +- .../go-ethereum/p2p/discover/common.go | 5 +- .../go-ethereum/p2p/discover/lookup.go | 209 - .../go-ethereum/p2p/discover/v4_udp.go | 169 +- .../ethereum/go-ethereum/p2p/enode/iter.go | 286 - .../ethereum/go-ethereum/p2p/enode/urlv4.go | 12 +- .../ethereum/go-ethereum/p2p/message.go | 6 +- .../ethereum/go-ethereum/p2p/metrics.go | 10 +- .../ethereum/go-ethereum/p2p/peer.go | 8 - .../ethereum/go-ethereum/p2p/protocol.go | 5 - .../ethereum/go-ethereum/p2p/rlpx.go | 14 +- .../ethereum/go-ethereum/p2p/server.go | 35 +- .../p2p/simulations/adapters/types.go | 8 - .../go-ethereum/p2p/simulations/network.go | 122 +- .../ethereum/go-ethereum/params/bootnodes.go | 7 + .../ethereum/go-ethereum/params/config.go | 82 +- .../go-ethereum/params/protocol_params.go | 36 +- .../ethereum/go-ethereum/params/version.go | 2 +- .../ethereum/go-ethereum/rlp/decode.go | 168 +- .../ethereum/go-ethereum/rlp/doc.go | 121 +- .../ethereum/go-ethereum/rlp/encode.go | 127 +- .../ethereum/go-ethereum/rlp/typecache.go | 62 +- .../ethereum/go-ethereum/rpc/gzip.go | 66 - .../ethereum/go-ethereum/rpc/http.go | 1 - .../ethereum/go-ethereum/rpc/types.go | 93 - .../ethereum/go-ethereum/trie/sync.go | 17 +- .../go-ethereum/whisper/whisperv6/doc.go | 14 +- .../gballet/go-libpcsclite/doc_bsd.go | 4 +- .../gballet/go-libpcsclite/doc_darwin.go | 35 - .../gballet/go-libpcsclite/error.go | 182 +- .../gballet/go-libpcsclite/winscard.go | 22 +- vendor/github.com/go-ole/go-ole/.travis.yml | 8 + vendor/github.com/go-ole/go-ole/ChangeLog.md | 49 + vendor/github.com/go-ole/go-ole/LICENSE | 21 + vendor/github.com/go-ole/go-ole/README.md | 46 + vendor/github.com/go-ole/go-ole/appveyor.yml | 54 + vendor/github.com/go-ole/go-ole/com.go | 344 + vendor/github.com/go-ole/go-ole/com_func.go | 174 + vendor/github.com/go-ole/go-ole/connect.go | 192 + vendor/github.com/go-ole/go-ole/constants.go | 153 + vendor/github.com/go-ole/go-ole/error.go | 51 + vendor/github.com/go-ole/go-ole/error_func.go | 8 + .../github.com/go-ole/go-ole/error_windows.go | 24 + vendor/github.com/go-ole/go-ole/go.mod | 3 + vendor/github.com/go-ole/go-ole/guid.go | 284 + .../go-ole/go-ole/iconnectionpoint.go | 20 + .../go-ole/go-ole/iconnectionpoint_func.go | 21 + .../go-ole/go-ole/iconnectionpoint_windows.go | 43 + .../go-ole/iconnectionpointcontainer.go | 17 + .../go-ole/iconnectionpointcontainer_func.go | 11 + .../iconnectionpointcontainer_windows.go | 25 + vendor/github.com/go-ole/go-ole/idispatch.go | 94 + .../go-ole/go-ole/idispatch_func.go | 19 + .../go-ole/go-ole/idispatch_windows.go | 200 + .../github.com/go-ole/go-ole/ienumvariant.go | 19 + .../go-ole/go-ole/ienumvariant_func.go | 19 + .../go-ole/go-ole/ienumvariant_windows.go | 63 + .../github.com/go-ole/go-ole/iinspectable.go | 18 + .../go-ole/go-ole/iinspectable_func.go | 15 + .../go-ole/go-ole/iinspectable_windows.go | 72 + .../go-ole/go-ole/iprovideclassinfo.go | 21 + .../go-ole/go-ole/iprovideclassinfo_func.go | 7 + .../go-ole/iprovideclassinfo_windows.go | 21 + vendor/github.com/go-ole/go-ole/itypeinfo.go | 34 + .../go-ole/go-ole/itypeinfo_func.go | 7 + .../go-ole/go-ole/itypeinfo_windows.go | 21 + vendor/github.com/go-ole/go-ole/iunknown.go | 57 + .../github.com/go-ole/go-ole/iunknown_func.go | 19 + .../go-ole/go-ole/iunknown_windows.go | 58 + vendor/github.com/go-ole/go-ole/ole.go | 157 + .../go-ole/go-ole/oleutil/connection.go | 100 + .../go-ole/go-ole/oleutil/connection_func.go | 10 + .../go-ole/oleutil/connection_windows.go | 58 + .../go-ole/go-ole/oleutil/go-get.go | 6 + .../go-ole/go-ole/oleutil/oleutil.go | 127 + vendor/github.com/go-ole/go-ole/safearray.go | 27 + .../go-ole/go-ole/safearray_func.go | 211 + .../go-ole/go-ole/safearray_windows.go | 337 + .../go-ole/go-ole/safearrayconversion.go | 140 + .../go-ole/go-ole/safearrayslices.go | 33 + vendor/github.com/go-ole/go-ole/utility.go | 101 + vendor/github.com/go-ole/go-ole/variables.go | 16 + vendor/github.com/go-ole/go-ole/variant.go | 105 + .../github.com/go-ole/go-ole/variant_386.go | 11 + .../github.com/go-ole/go-ole/variant_amd64.go | 12 + .../go-ole/go-ole/variant_date_386.go | 22 + .../go-ole/go-ole/variant_date_amd64.go | 20 + .../go-ole/go-ole/variant_ppc64le.go | 12 + .../github.com/go-ole/go-ole/variant_s390x.go | 12 + vendor/github.com/go-ole/go-ole/vt_string.go | 58 + vendor/github.com/go-ole/go-ole/winrt.go | 99 + vendor/github.com/go-ole/go-ole/winrt_doc.go | 36 + vendor/github.com/google/uuid/.travis.yml | 9 - vendor/github.com/google/uuid/CONTRIBUTING.md | 10 - vendor/github.com/google/uuid/CONTRIBUTORS | 9 - vendor/github.com/google/uuid/LICENSE | 27 - vendor/github.com/google/uuid/README.md | 19 - vendor/github.com/google/uuid/dce.go | 80 - vendor/github.com/google/uuid/doc.go | 12 - vendor/github.com/google/uuid/go.mod | 1 - vendor/github.com/google/uuid/hash.go | 53 - vendor/github.com/google/uuid/marshal.go | 37 - vendor/github.com/google/uuid/node.go | 90 - vendor/github.com/google/uuid/node_js.go | 12 - vendor/github.com/google/uuid/node_net.go | 33 - vendor/github.com/google/uuid/sql.go | 59 - vendor/github.com/google/uuid/time.go | 123 - vendor/github.com/google/uuid/util.go | 43 - vendor/github.com/google/uuid/uuid.go | 245 - vendor/github.com/google/uuid/version1.go | 44 - vendor/github.com/google/uuid/version4.go | 38 - .../github.com/gorilla/websocket/.travis.yml | 19 + vendor/github.com/gorilla/websocket/README.md | 10 +- vendor/github.com/gorilla/websocket/client.go | 4 +- vendor/github.com/gorilla/websocket/conn.go | 112 +- vendor/github.com/gorilla/websocket/doc.go | 47 - vendor/github.com/gorilla/websocket/go.mod | 3 - vendor/github.com/gorilla/websocket/go.sum | 2 - vendor/github.com/gorilla/websocket/join.go | 42 - vendor/github.com/gorilla/websocket/proxy.go | 8 +- vendor/github.com/gorilla/websocket/server.go | 4 +- vendor/github.com/gorilla/websocket/util.go | 132 +- vendor/github.com/huin/goupnp/.gitignore | 3 +- vendor/github.com/huin/goupnp/LICENSE | 2 +- vendor/github.com/huin/goupnp/README.md | 12 +- .../huin/goupnp/dcps/internetgateway1/gen.go | 2 - .../dcps/internetgateway1/internetgateway1.go | 208 +- .../huin/goupnp/dcps/internetgateway2/gen.go | 2 - .../dcps/internetgateway2/internetgateway2.go | 396 +- vendor/github.com/huin/goupnp/device.go | 10 +- vendor/github.com/huin/goupnp/go.mod | 7 - vendor/github.com/huin/goupnp/go.sum | 6 - .../huin/goupnp/goupnp.sublime-project | 8 - vendor/github.com/huin/goupnp/httpu/httpu.go | 6 +- vendor/github.com/huin/goupnp/soap/soap.go | 40 +- vendor/github.com/huin/goupnp/soap/types.go | 11 +- vendor/github.com/huin/goupnp/ssdp/ssdp.go | 11 +- .../github.com/jackpal/go-nat-pmp/.travis.yml | 7 - .../github.com/jackpal/go-nat-pmp/natpmp.go | 17 +- .../github.com/jackpal/go-nat-pmp/network.go | 27 +- .../github.com/jackpal/go-nat-pmp/recorder.go | 6 +- vendor/github.com/karalabe/usb/.travis.yml | 4 +- vendor/github.com/karalabe/usb/appveyor.yml | 4 +- .../karalabe/usb/hidapi/windows/hid.c | 4 +- .../mattn/go-runewidth/runewidth.go | 838 +- .../mattn/go-runewidth/runewidth_appengine.go | 8 - .../mattn/go-runewidth/runewidth_js.go | 1 - .../mattn/go-runewidth/runewidth_posix.go | 4 +- .../mattn/go-runewidth/runewidth_windows.go | 3 - .../olekukonko/tablewriter/README.md | 41 +- .../github.com/olekukonko/tablewriter/go.mod | 8 - .../github.com/olekukonko/tablewriter/go.sum | 4 - .../olekukonko/tablewriter/table.go | 66 +- vendor/github.com/pborman/uuid/.travis.yml | 5 +- vendor/github.com/pborman/uuid/README.md | 2 - vendor/github.com/pborman/uuid/doc.go | 7 +- vendor/github.com/pborman/uuid/go.mod | 3 - vendor/github.com/pborman/uuid/go.sum | 2 - vendor/github.com/pborman/uuid/marshal.go | 10 +- vendor/github.com/pborman/uuid/node.go | 77 +- vendor/github.com/pborman/uuid/sql.go | 4 +- vendor/github.com/pborman/uuid/time.go | 87 +- vendor/github.com/pborman/uuid/util.go | 11 + vendor/github.com/pborman/uuid/uuid.go | 89 +- vendor/github.com/pborman/uuid/version1.go | 28 +- vendor/github.com/pborman/uuid/version4.go | 13 +- vendor/github.com/rjeczalik/notify/go.mod | 3 - vendor/github.com/rs/cors/.travis.yml | 9 +- vendor/github.com/rs/cors/README.md | 20 +- vendor/github.com/rs/cors/cors.go | 147 +- vendor/github.com/rs/cors/go.mod | 1 - vendor/github.com/rs/cors/utils.go | 9 +- vendor/github.com/rs/xhandler/.travis.yml | 7 + .../env/LICENSE.md => rs/xhandler/LICENSE} | 12 +- vendor/github.com/rs/xhandler/README.md | 134 + vendor/github.com/rs/xhandler/chain.go | 121 + vendor/github.com/rs/xhandler/middleware.go | 59 + vendor/github.com/rs/xhandler/xhandler.go | 42 + .../rsksmart/rds-swarm/config/config.go | 34 - .../MultiChainResolverABI.json | 336 - .../multi_chain_resolver.go | 996 -- .../rsksmart/rds-swarm/resolver/resolver.go | 106 - .../rsksmart/rds-swarm/utils/utils.go | 35 - .../syndtr/goleveldb/leveldb/batch.go | 5 - .../github.com/syndtr/goleveldb/leveldb/db.go | 22 +- .../syndtr/goleveldb/leveldb/db_compaction.go | 11 - .../syndtr/goleveldb/leveldb/db_iter.go | 43 +- .../goleveldb/leveldb/db_transaction.go | 14 +- .../syndtr/goleveldb/leveldb/opt/options.go | 21 +- .../goleveldb/leveldb/session_compaction.go | 26 +- .../syndtr/goleveldb/leveldb/session_util.go | 4 +- .../syndtr/goleveldb/leveldb/table.go | 2 - .../syndtr/goleveldb/leveldb/version.go | 3 +- .../tyler-smith/go-bip39/.golangci.yml | 44 - .../tyler-smith/go-bip39/.travis.yml | 24 +- .../github.com/tyler-smith/go-bip39/bip39.go | 43 +- .../x/crypto/curve25519/const_amd64.h | 8 + .../x/crypto/curve25519/const_amd64.s | 20 + .../x/crypto/curve25519/cswap_amd64.s | 65 + .../x/crypto/curve25519/curve25519.go | 881 +- .../x/crypto/curve25519/curve25519_generic.go | 828 -- .../x/crypto/curve25519/curve25519_noasm.go | 11 - vendor/golang.org/x/crypto/curve25519/doc.go | 23 + .../x/crypto/curve25519/freeze_amd64.s | 73 + ...{curve25519_amd64.s => ladderstep_amd64.s} | 420 +- ...curve25519_amd64.go => mont25519_amd64.go} | 2 +- .../x/crypto/curve25519/mul_amd64.s | 169 + .../x/crypto/curve25519/square_amd64.s | 132 + .../x/crypto/openpgp/packet/encrypted_key.go | 6 +- .../x/crypto/openpgp/packet/private_key.go | 2 +- .../x/crypto/sha3/hashes_generic.go | 2 +- vendor/golang.org/x/crypto/sha3/sha3.go | 23 +- vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 2 +- vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 2 +- .../golang.org/x/crypto/sha3/shake_generic.go | 2 +- vendor/golang.org/x/crypto/sha3/xor.go | 7 - .../golang.org/x/crypto/sha3/xor_unaligned.go | 9 +- vendor/golang.org/x/net/html/atom/gen.go | 712 ++ vendor/golang.org/x/net/http2/hpack/encode.go | 2 +- vendor/golang.org/x/net/http2/server.go | 52 +- vendor/golang.org/x/net/http2/transport.go | 26 +- vendor/golang.org/x/net/http2/writesched.go | 8 +- .../x/net/http2/writesched_priority.go | 2 +- .../golang.org/x/net/internal/socks/socks.go | 2 +- vendor/golang.org/x/net/publicsuffix/list.go | 181 - vendor/golang.org/x/net/publicsuffix/table.go | 9962 ----------------- vendor/golang.org/x/sys/cpu/byteorder.go | 38 +- vendor/golang.org/x/sys/cpu/cpu.go | 36 - vendor/golang.org/x/sys/cpu/cpu_arm.go | 33 +- vendor/golang.org/x/sys/cpu/cpu_linux.go | 2 +- vendor/golang.org/x/sys/cpu/cpu_linux_arm.go | 39 - .../golang.org/x/sys/unix/affinity_linux.go | 46 +- .../golang.org/x/sys/unix/bluetooth_linux.go | 1 - vendor/golang.org/x/sys/unix/fdset.go | 29 - vendor/golang.org/x/sys/unix/ioctl.go | 41 +- vendor/golang.org/x/sys/unix/mkall.sh | 4 +- vendor/golang.org/x/sys/unix/mkasm_darwin.go | 61 + vendor/golang.org/x/sys/unix/mkerrors.sh | 52 +- vendor/golang.org/x/sys/unix/mkpost.go | 122 + vendor/golang.org/x/sys/unix/mksyscall.go | 407 + .../x/sys/unix/mksyscall_aix_ppc.go | 415 + .../x/sys/unix/mksyscall_aix_ppc64.go | 614 + .../x/sys/unix/mksyscall_solaris.go | 335 + .../golang.org/x/sys/unix/mksysctl_openbsd.go | 355 + vendor/golang.org/x/sys/unix/mksysnum.go | 190 + .../x/sys/unix/sockcmsg_dragonfly.go | 16 - .../golang.org/x/sys/unix/sockcmsg_linux.go | 2 +- vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 36 +- .../x/sys/unix/sockcmsg_unix_other.go | 38 - vendor/golang.org/x/sys/unix/syscall_aix.go | 39 +- .../golang.org/x/sys/unix/syscall_aix_ppc.go | 4 - .../x/sys/unix/syscall_aix_ppc64.go | 4 - vendor/golang.org/x/sys/unix/syscall_bsd.go | 4 +- .../x/sys/unix/syscall_darwin.1_12.go | 29 - .../x/sys/unix/syscall_darwin.1_13.go | 101 - .../golang.org/x/sys/unix/syscall_darwin.go | 40 +- .../x/sys/unix/syscall_darwin_386.1_11.go | 9 - .../x/sys/unix/syscall_darwin_386.go | 7 +- .../x/sys/unix/syscall_darwin_amd64.1_11.go | 9 - .../x/sys/unix/syscall_darwin_amd64.go | 7 +- .../x/sys/unix/syscall_darwin_arm.1_11.go | 11 - .../x/sys/unix/syscall_darwin_arm.go | 12 +- .../x/sys/unix/syscall_darwin_arm64.1_11.go | 11 - .../x/sys/unix/syscall_darwin_arm64.go | 12 +- .../x/sys/unix/syscall_darwin_libSystem.go | 2 - .../x/sys/unix/syscall_dragonfly.go | 59 +- .../x/sys/unix/syscall_dragonfly_amd64.go | 4 - .../golang.org/x/sys/unix/syscall_freebsd.go | 48 +- .../x/sys/unix/syscall_freebsd_386.go | 4 - .../x/sys/unix/syscall_freebsd_amd64.go | 4 - .../x/sys/unix/syscall_freebsd_arm.go | 4 - .../x/sys/unix/syscall_freebsd_arm64.go | 4 - vendor/golang.org/x/sys/unix/syscall_linux.go | 175 +- .../x/sys/unix/syscall_linux_386.go | 4 - .../x/sys/unix/syscall_linux_amd64.go | 4 - .../x/sys/unix/syscall_linux_arm.go | 4 - .../x/sys/unix/syscall_linux_arm64.go | 4 - .../x/sys/unix/syscall_linux_mips64x.go | 4 - .../x/sys/unix/syscall_linux_mipsx.go | 4 - .../x/sys/unix/syscall_linux_ppc64x.go | 4 - .../x/sys/unix/syscall_linux_riscv64.go | 4 - .../x/sys/unix/syscall_linux_s390x.go | 4 - .../x/sys/unix/syscall_linux_sparc64.go | 4 - .../golang.org/x/sys/unix/syscall_netbsd.go | 39 +- .../x/sys/unix/syscall_netbsd_386.go | 4 - .../x/sys/unix/syscall_netbsd_amd64.go | 4 - .../x/sys/unix/syscall_netbsd_arm.go | 4 - .../x/sys/unix/syscall_netbsd_arm64.go | 4 - .../golang.org/x/sys/unix/syscall_openbsd.go | 39 +- .../x/sys/unix/syscall_openbsd_386.go | 4 - .../x/sys/unix/syscall_openbsd_amd64.go | 4 - .../x/sys/unix/syscall_openbsd_arm.go | 4 - .../x/sys/unix/syscall_openbsd_arm64.go | 4 - .../golang.org/x/sys/unix/syscall_solaris.go | 34 +- .../x/sys/unix/syscall_solaris_amd64.go | 4 - vendor/golang.org/x/sys/unix/types_aix.go | 237 + vendor/golang.org/x/sys/unix/types_darwin.go | 283 + .../golang.org/x/sys/unix/types_dragonfly.go | 263 + vendor/golang.org/x/sys/unix/types_freebsd.go | 400 + vendor/golang.org/x/sys/unix/types_netbsd.go | 290 + vendor/golang.org/x/sys/unix/types_openbsd.go | 283 + vendor/golang.org/x/sys/unix/types_solaris.go | 266 + .../x/sys/unix/zerrors_darwin_386.go | 3 +- .../x/sys/unix/zerrors_darwin_amd64.go | 3 +- .../x/sys/unix/zerrors_darwin_arm.go | 3 +- .../x/sys/unix/zerrors_darwin_arm64.go | 3 +- .../x/sys/unix/zerrors_dragonfly_amd64.go | 1 - .../x/sys/unix/zerrors_freebsd_386.go | 3 +- .../x/sys/unix/zerrors_freebsd_amd64.go | 3 +- .../x/sys/unix/zerrors_freebsd_arm.go | 3 +- .../x/sys/unix/zerrors_freebsd_arm64.go | 3 +- .../x/sys/unix/zerrors_linux_386.go | 123 +- .../x/sys/unix/zerrors_linux_amd64.go | 123 +- .../x/sys/unix/zerrors_linux_arm.go | 123 +- .../x/sys/unix/zerrors_linux_arm64.go | 125 +- .../x/sys/unix/zerrors_linux_mips.go | 123 +- .../x/sys/unix/zerrors_linux_mips64.go | 123 +- .../x/sys/unix/zerrors_linux_mips64le.go | 123 +- .../x/sys/unix/zerrors_linux_mipsle.go | 123 +- .../x/sys/unix/zerrors_linux_ppc64.go | 123 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 123 +- .../x/sys/unix/zerrors_linux_riscv64.go | 123 +- .../x/sys/unix/zerrors_linux_s390x.go | 123 +- .../x/sys/unix/zerrors_linux_sparc64.go | 123 +- .../x/sys/unix/zerrors_netbsd_386.go | 3 +- .../x/sys/unix/zerrors_netbsd_amd64.go | 3 +- .../x/sys/unix/zerrors_netbsd_arm.go | 3 +- .../x/sys/unix/zerrors_netbsd_arm64.go | 3 +- .../x/sys/unix/zerrors_openbsd_386.go | 17 +- .../x/sys/unix/zerrors_openbsd_amd64.go | 6 +- .../x/sys/unix/zerrors_openbsd_arm.go | 11 +- .../x/sys/unix/zerrors_openbsd_arm64.go | 1 - .../x/sys/unix/zerrors_solaris_amd64.go | 3 +- .../x/sys/unix/zsyscall_darwin_386.1_11.go | 93 +- .../x/sys/unix/zsyscall_darwin_386.1_13.go | 41 - .../x/sys/unix/zsyscall_darwin_386.1_13.s | 12 - .../x/sys/unix/zsyscall_darwin_386.go | 114 +- .../x/sys/unix/zsyscall_darwin_386.s | 10 +- .../x/sys/unix/zsyscall_darwin_amd64.1_11.go | 93 +- .../x/sys/unix/zsyscall_darwin_amd64.1_13.go | 41 - .../x/sys/unix/zsyscall_darwin_amd64.1_13.s | 12 - .../x/sys/unix/zsyscall_darwin_amd64.go | 99 +- .../x/sys/unix/zsyscall_darwin_amd64.s | 10 +- .../x/sys/unix/zsyscall_darwin_arm.1_11.go | 49 +- .../x/sys/unix/zsyscall_darwin_arm.1_13.go | 41 - .../x/sys/unix/zsyscall_darwin_arm.1_13.s | 12 - .../x/sys/unix/zsyscall_darwin_arm.go | 77 +- .../x/sys/unix/zsyscall_darwin_arm.s | 6 +- .../x/sys/unix/zsyscall_darwin_arm64.1_11.go | 49 +- .../x/sys/unix/zsyscall_darwin_arm64.1_13.go | 41 - .../x/sys/unix/zsyscall_darwin_arm64.1_13.s | 12 - .../x/sys/unix/zsyscall_darwin_arm64.go | 77 +- .../x/sys/unix/zsyscall_darwin_arm64.s | 6 +- .../x/sys/unix/zsyscall_dragonfly_amd64.go | 5 +- .../x/sys/unix/zsyscall_freebsd_386.go | 5 +- .../x/sys/unix/zsyscall_freebsd_amd64.go | 45 +- .../x/sys/unix/zsyscall_freebsd_arm.go | 45 +- .../x/sys/unix/zsyscall_freebsd_arm64.go | 45 +- .../x/sys/unix/zsyscall_linux_386.go | 30 - .../x/sys/unix/zsyscall_linux_amd64.go | 30 - .../x/sys/unix/zsyscall_linux_arm.go | 30 - .../x/sys/unix/zsyscall_linux_arm64.go | 30 - .../x/sys/unix/zsyscall_linux_mips.go | 30 - .../x/sys/unix/zsyscall_linux_mips64.go | 30 - .../x/sys/unix/zsyscall_linux_mips64le.go | 30 - .../x/sys/unix/zsyscall_linux_mipsle.go | 30 - .../x/sys/unix/zsyscall_linux_ppc64.go | 30 - .../x/sys/unix/zsyscall_linux_ppc64le.go | 30 - .../x/sys/unix/zsyscall_linux_riscv64.go | 30 - .../x/sys/unix/zsyscall_linux_s390x.go | 30 - .../x/sys/unix/zsyscall_linux_sparc64.go | 30 - .../x/sys/unix/zsyscall_netbsd_386.go | 37 +- .../x/sys/unix/zsyscall_netbsd_amd64.go | 37 +- .../x/sys/unix/zsyscall_netbsd_arm.go | 37 +- .../x/sys/unix/zsyscall_netbsd_arm64.go | 37 +- .../x/sys/unix/zsyscall_openbsd_386.go | 37 +- .../x/sys/unix/zsyscall_openbsd_amd64.go | 37 +- .../x/sys/unix/zsyscall_openbsd_arm.go | 37 +- .../x/sys/unix/zsyscall_openbsd_arm64.go | 37 +- .../x/sys/unix/zsyscall_solaris_amd64.go | 5 +- .../x/sys/unix/zsysnum_linux_386.go | 2 - .../x/sys/unix/zsysnum_linux_amd64.go | 2 - .../x/sys/unix/zsysnum_linux_arm.go | 2 - .../x/sys/unix/zsysnum_linux_arm64.go | 1 - .../x/sys/unix/zsysnum_linux_mips.go | 1 - .../x/sys/unix/zsysnum_linux_mips64.go | 1 - .../x/sys/unix/zsysnum_linux_mips64le.go | 1 - .../x/sys/unix/zsysnum_linux_mipsle.go | 1 - .../x/sys/unix/zsysnum_linux_ppc64.go | 2 - .../x/sys/unix/zsysnum_linux_ppc64le.go | 2 - .../x/sys/unix/zsysnum_linux_riscv64.go | 2 - .../x/sys/unix/zsysnum_linux_s390x.go | 2 - .../x/sys/unix/zsysnum_linux_sparc64.go | 1 - .../x/sys/unix/ztypes_freebsd_arm64.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 266 +- .../x/sys/unix/ztypes_linux_amd64.go | 266 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 266 +- .../x/sys/unix/ztypes_linux_arm64.go | 266 +- .../x/sys/unix/ztypes_linux_mips.go | 266 +- .../x/sys/unix/ztypes_linux_mips64.go | 266 +- .../x/sys/unix/ztypes_linux_mips64le.go | 266 +- .../x/sys/unix/ztypes_linux_mipsle.go | 266 +- .../x/sys/unix/ztypes_linux_ppc64.go | 266 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 266 +- .../x/sys/unix/ztypes_linux_riscv64.go | 267 +- .../x/sys/unix/ztypes_linux_s390x.go | 266 +- .../x/sys/unix/ztypes_linux_sparc64.go | 266 +- .../x/sys/windows/asm_windows_386.s | 13 + .../x/sys/windows/asm_windows_amd64.s | 13 + .../x/sys/windows/asm_windows_arm.s | 11 + .../golang.org/x/sys/windows/dll_windows.go | 22 +- vendor/golang.org/x/sys/windows/mksyscall.go | 2 +- .../x/sys/windows/security_windows.go | 602 +- .../x/sys/windows/syscall_windows.go | 74 +- .../golang.org/x/sys/windows/types_windows.go | 112 +- .../x/sys/windows/zsyscall_windows.go | 1193 +- .../x/text/encoding/charmap/maketables.go | 556 + .../x/text/encoding/htmlindex/gen.go | 173 + .../text/encoding/internal/identifier/gen.go | 142 + .../x/text/encoding/japanese/maketables.go | 161 + .../x/text/encoding/korean/maketables.go | 143 + .../encoding/simplifiedchinese/maketables.go | 161 + .../encoding/traditionalchinese/maketables.go | 140 + .../x/text/internal/language/compact/gen.go | 64 + .../internal/language/compact/gen_index.go | 113 + .../internal/language/compact/gen_parents.go | 54 + .../x/text/internal/language/gen.go | 1520 +++ .../x/text/internal/language/gen_common.go | 20 + vendor/golang.org/x/text/language/gen.go | 305 + vendor/golang.org/x/text/unicode/bidi/gen.go | 133 + .../x/text/unicode/bidi/gen_ranges.go | 57 + .../x/text/unicode/bidi/gen_trieval.go | 64 + .../x/text/unicode/norm/maketables.go | 986 ++ .../golang.org/x/text/unicode/norm/triegen.go | 117 + .../google.golang.org/grpc/status/status.go | 15 +- vendor/modules.txt | 377 +- 581 files changed, 23937 insertions(+), 33207 deletions(-) create mode 100644 vendor.zip create mode 100644 vendor/github.com/StackExchange/wmi/LICENSE create mode 100644 vendor/github.com/StackExchange/wmi/README.md create mode 100644 vendor/github.com/StackExchange/wmi/swbemservices.go create mode 100644 vendor/github.com/StackExchange/wmi/wmi.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/genprecomps.go delete mode 100644 vendor/github.com/caarlos0/env/.gitignore delete mode 100644 vendor/github.com/caarlos0/env/.hound.yml delete mode 100644 vendor/github.com/caarlos0/env/.travis.yml delete mode 100644 vendor/github.com/caarlos0/env/README.md delete mode 100644 vendor/github.com/caarlos0/env/env.go create mode 100644 vendor/github.com/docker/docker/pkg/archive/example_changes.go create mode 100644 vendor/github.com/edsrzf/mmap-go/msync_netbsd.go create mode 100644 vendor/github.com/edsrzf/mmap-go/msync_unix.go delete mode 100644 vendor/github.com/elastic/gosigar/sigar_darwin_386.go delete mode 100644 vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go rename vendor/github.com/ethereum/go-ethereum/les/{client.go => backend.go} (78%) delete mode 100644 vendor/github.com/ethereum/go-ethereum/les/client_handler.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/les/enr_entry.go create mode 100644 vendor/github.com/ethereum/go-ethereum/les/handler.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/les/server_handler.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/les/test_helper.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/discover/lookup.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/enode/iter.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/rpc/gzip.go delete mode 100644 vendor/github.com/gballet/go-libpcsclite/doc_darwin.go create mode 100644 vendor/github.com/go-ole/go-ole/.travis.yml create mode 100644 vendor/github.com/go-ole/go-ole/ChangeLog.md create mode 100644 vendor/github.com/go-ole/go-ole/LICENSE create mode 100644 vendor/github.com/go-ole/go-ole/README.md create mode 100644 vendor/github.com/go-ole/go-ole/appveyor.yml create mode 100644 vendor/github.com/go-ole/go-ole/com.go create mode 100644 vendor/github.com/go-ole/go-ole/com_func.go create mode 100644 vendor/github.com/go-ole/go-ole/connect.go create mode 100644 vendor/github.com/go-ole/go-ole/constants.go create mode 100644 vendor/github.com/go-ole/go-ole/error.go create mode 100644 vendor/github.com/go-ole/go-ole/error_func.go create mode 100644 vendor/github.com/go-ole/go-ole/error_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/go.mod create mode 100644 vendor/github.com/go-ole/go-ole/guid.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch_func.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_func.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_func.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/ole.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_func.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/go-get.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/oleutil.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray_func.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/safearrayconversion.go create mode 100644 vendor/github.com/go-ole/go-ole/safearrayslices.go create mode 100644 vendor/github.com/go-ole/go-ole/utility.go create mode 100644 vendor/github.com/go-ole/go-ole/variables.go create mode 100644 vendor/github.com/go-ole/go-ole/variant.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_386.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_amd64.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_date_386.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_date_amd64.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_ppc64le.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_s390x.go create mode 100644 vendor/github.com/go-ole/go-ole/vt_string.go create mode 100644 vendor/github.com/go-ole/go-ole/winrt.go create mode 100644 vendor/github.com/go-ole/go-ole/winrt_doc.go delete mode 100644 vendor/github.com/google/uuid/.travis.yml delete mode 100644 vendor/github.com/google/uuid/CONTRIBUTING.md delete mode 100644 vendor/github.com/google/uuid/CONTRIBUTORS delete mode 100644 vendor/github.com/google/uuid/LICENSE delete mode 100644 vendor/github.com/google/uuid/README.md delete mode 100644 vendor/github.com/google/uuid/dce.go delete mode 100644 vendor/github.com/google/uuid/doc.go delete mode 100644 vendor/github.com/google/uuid/go.mod delete mode 100644 vendor/github.com/google/uuid/hash.go delete mode 100644 vendor/github.com/google/uuid/marshal.go delete mode 100644 vendor/github.com/google/uuid/node.go delete mode 100644 vendor/github.com/google/uuid/node_js.go delete mode 100644 vendor/github.com/google/uuid/node_net.go delete mode 100644 vendor/github.com/google/uuid/sql.go delete mode 100644 vendor/github.com/google/uuid/time.go delete mode 100644 vendor/github.com/google/uuid/util.go delete mode 100644 vendor/github.com/google/uuid/uuid.go delete mode 100644 vendor/github.com/google/uuid/version1.go delete mode 100644 vendor/github.com/google/uuid/version4.go create mode 100644 vendor/github.com/gorilla/websocket/.travis.yml delete mode 100644 vendor/github.com/gorilla/websocket/go.mod delete mode 100644 vendor/github.com/gorilla/websocket/go.sum delete mode 100644 vendor/github.com/gorilla/websocket/join.go delete mode 100644 vendor/github.com/huin/goupnp/dcps/internetgateway1/gen.go delete mode 100644 vendor/github.com/huin/goupnp/dcps/internetgateway2/gen.go delete mode 100644 vendor/github.com/huin/goupnp/go.mod delete mode 100644 vendor/github.com/huin/goupnp/go.sum delete mode 100644 vendor/github.com/huin/goupnp/goupnp.sublime-project delete mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_appengine.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/go.mod delete mode 100644 vendor/github.com/olekukonko/tablewriter/go.sum delete mode 100644 vendor/github.com/pborman/uuid/go.mod delete mode 100644 vendor/github.com/pborman/uuid/go.sum delete mode 100644 vendor/github.com/rjeczalik/notify/go.mod delete mode 100644 vendor/github.com/rs/cors/go.mod create mode 100644 vendor/github.com/rs/xhandler/.travis.yml rename vendor/github.com/{caarlos0/env/LICENSE.md => rs/xhandler/LICENSE} (85%) create mode 100644 vendor/github.com/rs/xhandler/README.md create mode 100644 vendor/github.com/rs/xhandler/chain.go create mode 100644 vendor/github.com/rs/xhandler/middleware.go create mode 100644 vendor/github.com/rs/xhandler/xhandler.go delete mode 100644 vendor/github.com/rsksmart/rds-swarm/config/config.go delete mode 100644 vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/MultiChainResolverABI.json delete mode 100644 vendor/github.com/rsksmart/rds-swarm/resolver/multi_chain_resolver/multi_chain_resolver.go delete mode 100644 vendor/github.com/rsksmart/rds-swarm/resolver/resolver.go delete mode 100644 vendor/github.com/rsksmart/rds-swarm/utils/utils.go delete mode 100644 vendor/github.com/tyler-smith/go-bip39/.golangci.yml create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.h create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_generic.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go create mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go create mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s rename vendor/golang.org/x/crypto/curve25519/{curve25519_amd64.s => ladderstep_amd64.s} (76%) rename vendor/golang.org/x/crypto/curve25519/{curve25519_amd64.go => mont25519_amd64.go} (99%) create mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s create mode 100644 vendor/golang.org/x/net/html/atom/gen.go delete mode 100644 vendor/golang.org/x/net/publicsuffix/list.go delete mode 100644 vendor/golang.org/x/net/publicsuffix/table.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/fdset.go create mode 100644 vendor/golang.org/x/sys/unix/mkasm_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/mkpost.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/mksysnum.go delete mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go delete mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/types_aix.go create mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_386.s create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_amd64.s create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_arm.s create mode 100644 vendor/golang.org/x/text/encoding/charmap/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/htmlindex/gen.go create mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/gen.go create mode 100644 vendor/golang.org/x/text/encoding/japanese/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/korean/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go create mode 100644 vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_index.go create mode 100644 vendor/golang.org/x/text/internal/language/compact/gen_parents.go create mode 100644 vendor/golang.org/x/text/internal/language/gen.go create mode 100644 vendor/golang.org/x/text/internal/language/gen_common.go create mode 100644 vendor/golang.org/x/text/language/gen.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go create mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go create mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go diff --git a/go.mod b/go.mod index 09703ba144..de1a38c1dd 100644 --- a/go.mod +++ b/go.mod @@ -11,59 +11,85 @@ require ( github.com/Microsoft/hcsshim v0.8.6 // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/VividCortex/ewma v1.1.1 // indirect + github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 // indirect github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 // indirect + github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect + github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 // indirect github.com/cespare/cp v1.1.1 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect github.com/containerd/containerd v1.2.7 // indirect github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect + github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/docker v0.7.3-0.20190806133308-ecdb0b22393b github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.9.7 + github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c // indirect + github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa // indirect + github.com/ethereum/go-ethereum v1.9.2 github.com/ethersphere/go-sw3 v0.1.1 github.com/fatih/color v1.7.0 // indirect github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc + github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c // indirect github.com/go-kit/kit v0.9.0 // indirect + github.com/go-logfmt/logfmt v0.4.0 // indirect github.com/go-ole/go-ole v1.2.4 // indirect github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/protobuf v1.3.2 // indirect github.com/googleapis/gnostic v0.0.0-20190624222214-25d8b0b66985 // indirect github.com/gorilla/mux v1.7.3 // indirect + github.com/gorilla/websocket v1.4.0 // indirect github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 // indirect github.com/hashicorp/golang-lru v0.5.3 github.com/howeyc/fsnotify v0.0.0-20151003194602-f0c08ee9c607 // indirect + github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 // indirect github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883 // indirect + github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 // indirect + github.com/json-iterator/go v1.1.7 // indirect + github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.2 github.com/mattn/go-isatty v0.0.8 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416 + github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect github.com/opentracing/opentracing-go v1.1.0 github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e // indirect - github.com/pborman/uuid v1.2.0 + github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rjeczalik/notify v0.9.1 // indirect github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect - github.com/rs/cors v1.7.0 + github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect - github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595 - github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d + github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 github.com/tilinna/clock v1.0.2 + github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef // indirect github.com/uber-go/atomic v1.4.0 // indirect github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6 github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7 // indirect github.com/vbauerster/mpb v3.4.0+incompatible + github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect go.uber.org/atomic v1.4.0 // indirect - golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 - golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 + golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 + golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 + golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect google.golang.org/appengine v1.6.1 // indirect + google.golang.org/grpc v1.22.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/urfave/cli.v1 v1.20.0 diff --git a/go.sum b/go.sum index b2703a9745..c0fb5f80eb 100644 --- a/go.sum +++ b/go.sum @@ -10,50 +10,27 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7O github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs= github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI= github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6 h1:9uC+gZZ11spzCoystXtG2/fSO0kmGO7zUK3pnfavJCw= github.com/apilayer/freegeoip v0.0.0-20180702111401-3f942d1392f6/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU= -github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks= -github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb h1:gXDS2cX8AS8KbnP32J6XMSjzC1FhHEdHfUUCy018VrA= -github.com/aristanetworks/goarista v0.0.0-20191023202215-f096da5361bb/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns= -github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= -github.com/btcsuite/btcd v0.20.0-beta h1:DnZGUjFbRkpytojHWwy6nfUSA7vFrzWXDLpFNzt74ZA= -github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= -github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -64,14 +41,11 @@ github.com/containerd/containerd v1.2.7 h1:8lqLbl7u1j3MmiL9cJ/O275crSq7bfwUayvva github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= -github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -83,22 +57,13 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s= github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= -github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo= -github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/ethereum/go-ethereum v1.9.2 h1:RMIHDO/diqXEgORSVzYx8xW9x2+S32PoAX5lQwya0Lw= github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= -github.com/ethereum/go-ethereum v1.9.7 h1:p4O+z0MGzB7xxngHbplcYNloxkFwGkeComhkzWnq0ig= -github.com/ethereum/go-ethereum v1.9.7/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethersphere/go-sw3 v0.1.1 h1:czLnLSU0/XJLJt/GyPiEAds9YYnIgZZzfy+OQyiYQtk= github.com/ethersphere/go-sw3 v0.1.1/go.mod h1:HukT0aZ6QdW/d7zuD/0g5xlw6ewu9QeqHojxLDsaERQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -108,11 +73,8 @@ github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepB github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c h1:gID5iWto0hEmbyMl+15Rkju0P+8uvF0jSn1cWdyv+5M= github.com/gballet/go-libpcsclite v0.0.0-20190528105824-2fd9b619dd3c/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= @@ -146,8 +108,6 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20190624222214-25d8b0b66985 h1:MSqFuS90bN+x1aGLZpPX9Iprdxbxw7X5Jg9WfjS/bYk= @@ -157,12 +117,9 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 h1:9WiNlI9Cds5S5YITwRpRs8edNaq0nxTEymhDW20A1QE= github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= @@ -173,21 +130,12 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= -github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883 h1:HsZXaxH4mZRDDcxGk5m1+o3R/ofaT5YrMG+aR0altIw= github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA= github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= -github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -195,14 +143,9 @@ github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8uXRLnpdSb9noCEj+vHacjmhp68= github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 h1:ZHuwnjpP8LsVsUYqTqeVAI+GfDfJ6UNPrExZF+vX/DQ= -github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 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= @@ -222,8 +165,6 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -244,20 +185,13 @@ github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c h1:2j4kdCOg5xiOVCTQpv0SgbzndaVJKliD6oRbMxTw6v4= github.com/olekukonko/tablewriter v0.0.0-20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2 h1:sq53g+DWf0J6/ceFUHpQ0nAEb6WgM++fq16MZ91cS6o= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc= -github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -270,53 +204,32 @@ github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e h1:omG1V github.com/oschwald/maxminddb-golang v0.0.0-20180819230143-277d39ecb83e/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7 h1:Imx0QZXGB4siHjlmDJ/kx/bU+D36ytDj5dgy/TkIQ+A= github.com/peterh/liner v0.0.0-20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 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/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= -github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= -github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d h1:ouzpe+YhpIfnjR40gSkJHWsvXmB6TiPKqMtMpfyU9DE= github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= -github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430 h1:saHKOwJeSkV5PzZeTnw97JMLycaDBJnF2P/1sDVWuq8= -github.com/rsksmart/rds-swarm v0.0.0-20191108154211-89cd67d51430/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= -github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba h1:+qGsAO4EkxcOZeMqUmiA5iQlqWodeo1TLa8HH4FQlWo= -github.com/rsksmart/rds-swarm v0.0.0-20191112152320-2590c5db7eba/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= -github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2 h1:yAkrytBxYgRMCXmMjpSRsepX2qnTqUzxkheFMMdkXeI= -github.com/rsksmart/rds-swarm v0.0.0-20191112160200-4f0ed2c3b8a2/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= -github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595 h1:2JkrJLVP8n6pzVpUMoCk0GfdJgWrbSKFxV1y0pTcmFo= -github.com/rsksmart/rds-swarm v0.0.0-20191112192732-7dbad3f71595/go.mod h1:Tp+xzZM1NtWHm9RCQQ8T5nHK/PDbY+GJtBTCYzSMC50= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -327,8 +240,6 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= -github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= -github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= @@ -340,17 +251,10 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965 h1:V/AztY/q2oW5ghho7YMgUJQkKvSACHRxpeDyT5DxpIo= github.com/syndtr/goleveldb v0.0.0-20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= -github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= -github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= -github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef h1:luEzjJzktS9eU0CmI0uApXHLP/lKzOoRPrJhd71J8ik= github.com/tyler-smith/go-bip39 v0.0.0-20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= -github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o= github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6 h1:x2aYRH9ayk4SeB/gdpG0HTkyL798WfmJC8zMr6KY8SE= @@ -361,39 +265,27 @@ github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tL github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= -github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6 h1:VsmCukA2gDdC3Mu6evOIT0QjLSQWiJIwzv1Bdj4jdzU= -golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc= -golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -405,23 +297,17 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII= -golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/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= @@ -434,8 +320,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b h1:mSUCVIwDx4hfXJfWsOPfdzEHxzb2Xjl6BQ8YgPnazQA= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -445,10 +329,7 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= 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= @@ -457,16 +338,10 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= -gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= -gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= -gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74Ck/DJYc+R8zpq8KGm7uJvpdLRQED/IedA= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= -gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/vendor.zip b/vendor.zip new file mode 100644 index 0000000000000000000000000000000000000000..0fa8d437fa036a2111f505fdb70013da9d8651ae GIT binary patch literal 14385853 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

iHv*uKeM1>LKC4f zcMbcFc-7MWKh_5?A96on-R^l!R%(g2B<$69qSyrmz`RB7+L(z2rIw^AAPM0aFmi8P z7;i__bKEZv*J*!kq6k^2D$2(n0Hiu(G4O7NHoy9xcJ;WXw8k zl$Tl)UKyt>jbB>|sr@j=NJsjGTSp?G#uVtfzkZ*FVVB|VtnY!p$58K7HuzO+5-P6E zORBSL{~=R?djhsP$;9#?Gm2i|P6s9eE>l#dXR>Z%fBB*&xS?Jjz6_3_rEm(0jj0OI z+Og9{jUb~+C89qk7yz;Atfui3HKeECZQcR4{b!+*j_wE0kd6=@PIkX%L38Pi2`G0V z!LF1mq$T(~PYawe5OMQn{0eJV;+@p%cR5p08a!M_c>ft1wv{IK+9CNUO2RUg1eF7F{+PHaSB)U zp;{HV`aDU&YaonM#9x3N(&>?h-*)~ZvgN45K<{Q*C$aP4ISzGI`r}QEw-3tUMeAIk z(Seq$W6Q!qHL&NH-KJ0cZNO?xFn9^@Vl0gCN1hJH|8Y z`rLLusu%lys*nJ1`5ffHX^PnfGbsYz3X;5;7Jy8!jM{r^g=r z;Jw7=SXPcYZx~c}M!+-i4ai zOb~_$3T|jqIWWxYwE*D1{?giu7tDtAFW;I|S@Kg$ok^3AfPm!TUMn4>+4%C;-Im>o zg8G(cCB#w955rPQyAWVB6N!`rgT;%f;sgh6tM()entm)+=Yk-7~vQNeLz9Q zRT#rHo4sG|dU^kX9n`ABr*YphJke1H)4{_)V8MX9HAUbxA6Q8#(rI>`Z0rm^`}#1M z;?9i+2n$TwYJRedePh*gPTdHtcsGmqT-1h$)H9g*DXgQc3qgTL&@#Hv9Uyg<=tHM_xaHCYcntyT0@<29~8vc&x(X8d454feXgKJd$GYex3D*G z_E7kx-qlvBI0aLiIiI3{G^#Gkfz?F@47s8dG8}9IcHqdK^EQJ8!@=vl`KDVPH5%X_ z+gWAy2@|7>P(TeWB>!OSh{zawC%>X9nwqWhbZ|g?N3hZAK(NLruAI2C>r597gsJlz zKi>A>_QjZtDt>#cK9Ibi(K4JgRMr-;WrL%Q9y9m)ex2LV+X4?DoFR>&kg@d0{6tNd zvB_^0C{6ku{-(PF@E#&YOIk?rHBO&*ww<)WVYWdGWDA#H{|s@8F;Z~+v;(EE`x*!( zdfWBJqRaO)j@7)HZO6F-Qaj!~liP}0f8{*`4Gm1F-c4cj4-4^d)1d3M=EddPpO9OozB3phA00xMAVuCTc!fh+_w+e>~ zdbyfSCf3k8qf@6@n-*gbLa#>0XuPKVG>{UsG({cHln9pN@v1wjSC1+XCQZeWfcR9p z#iyd$Rp8At;yr-dIm~xzt4i^s94jaCXUcXDMQ=T^nFuf~*r%%xeY|53)g*d4|@UZQmGQvC>~pgFmVs$}sV z{Zgje9fwABtggoPY)$MSW&#rh^y#nor6^!FckSFw9`aO?bMJg90%zzpyAYa%w;Ma|i_NmI2@mlz7k4_(;O*%rP ze50cd`mU(V3%Ib?bQg@*MxkL~y>@zMh$_LNf3E!>T zOoQFrwFg}eL6qzqUk!@N;o9&qImg=_P5aZE4{69xfsQUzuy$||NW>VyX9s z+XFHHz+cGmUxSgWe^|E zywH)GO69bJ7oznEy{DeUG|*ky)4m)TIk{81y4gLMvpspUx+TotAI$F#d|90Iij4k->$Hqot`$O&!MoyXGdM z1;)H4RUnO&pEcN(A~py;hH>{j3}^xOw5Su7RQj!s*R}W*$R^{hH@{lqth3#v=onpq zqX#h6mpz%4M_^IbHsAT_W=ReLjir4$?|1|2N6v@ z6I)M?NHoRLZ4H@tS}E3tYU+gPMZdHu!yQ$w{$Vi_pB63#vpk90b{>q2&kg6J65F`# z2zM|hdDDNA7gLQNkNDcqz&3xH>r!WlcD7kbw9&9P3>J zL(b6}qpqfT%}fAj7WpxY^XVYq_<XXo%$`HJNio1Y z46z*)Gb&%IzwUGALozZtf*8GWyX%hbYo!V4b`|Vkh;yrmPG+-ws3w zEeaI2$Va!7&wTNJzj6{Kl9FvNvKP~x0ISnkp?jq`=0fxPdUVYw9u>WeFI8md#L56N`?amx60biai{MAC9RGjTf+oBi+ZpZ3hl^e z!`iHFk)@2qbCsF+qNkXpVq+W85Wy8;3&jR@Wky>7AdT7a?aHvY_GNt`F*Rz7M-N1bM2kVMm-Q_)!-> ziG;*WkTfGPP~if=Acfv#6{^%!8^%hETxQRZg|;M7azeG(F2X0?JT#!FKF{O0z2eCx zYWq7_O$2%_t*788UG2b_tC5xWiAgSNB7)hADqpavwE32$+^OaT)4uV;=T9B_NAB(v zRx7|O$yI0W0&Y5!7*SfvSFd{;o;k_3xb?z|Muf|pS;fiC=eFVdM-w6HfMXb~@U$3o z3pKgdm-U~lTpZHQ0eM-rq<7y!T6^6NS0PHPIvhMqj|$d0tm{eNqYziWxUq(J91H>} zvz3s~xwLf(z| zxf7g5E#v>-o-VMYZpvbI8Oz9m4HJn2BW!2rX}JZz7$m;f@Ck!KFHt^R@etylr@5^h z9<0+F!aLouIQdLJ5Dm9lpQieOZHgySxC&5@uT^K}p9MkjQ^-bk$N;T6D&@<}%WF@NH4wFu zsKpw-?s5-K>N?ja3{XTK5hijB?oVZ83>HvN@Xbldo|cJLph*y^{&^faI#IA=P2E=U zwLx3sgFzMA<4m<${f-5beB4+lcd+Npnh!lKaYOT=wW+$Da3Fr;Hc(xZuKg%elOuSl zwmftg(`XB0;gXQJj)6?71Tw|=88Yoy)#5Rl(xL(Y8l?EtICo8E7(NGDcV#Lu%lJ0c zia41h$Bz%>`_o61RYyjtQFa#@C?K0ILOC@(lDQtGYb?AwkOHcw*u?@?4Cn;3YJ5+c zx+x6(alg~1lVMFL5Vf^+s1qIgx~3xH=JEpJl()A84|9U2ebyj)coW< zMRSJwR^=bv7r63Ty;eM=9_--uYKw)OLYc5KlN>8#j9d1?ahLw2dM zlJ@)V>C*V?@bawjMr>Q#utvGfCG8F9yYCAXh34L2a_BTK%<_EeoKOu^x=a^|@EUb+ zDdPCu%1F}lDLZ5bPL!3Do0W_z?ch{u%sq7oLa1N5P7yC`J@hIRg%k2>=w`-SNx|K< zwPygZ$=C(*#b@7|jk4eW@WrAtyFGLj=Z|AYh?Hw5y8pKJPIOrZ1rd^oEyGSuFm_pv zkTa+wF5OIyFSMK6>2Y=QDNlG+lso-fh(k7#Z6aQWQlhN93sSW#mer}#c`_p)pOhOF zx5C=6R1Z)eZaupQGFzDj4nI>}nl0#_N88<(g79F>xRFp*eV_?Vt+NTa=G6+;tDetxds*W1BlhJLe)5Y;E{ zM;16;oR-ipZT|Q2Qv9*)O79QN0O|wNfIbc-TT#>YUiwFY^|jbwuexaag02)x&!Vm~ zlwFmkpdTl@P?&Er&>!xAulpy|2Kugwl`sfkvjb!12f*hKh>oY(`h9TWe)yGnKdOZ1 zW3#}e%B)sUey6m(IDd8N(m8krNY*%l45^$Fxd~*iCdP$&uEC(Hz?olJ&ixc~cfF#h z|Cy+@yWD<#{z`I5g{niER)Cx0xMme2%8mQR(=lG7YbjaD&UPbj`m&@ zwD%4<%Q6M3gp&-~=A|t7fS(<{ebIarPv&f;u^`okSC{`a5uSzL>}A?9+TW)QJ^3@7 znOh&_ATU~H`{)$eQ#${^gSc2BykaY{o&s883rSDBUT!zFDSRQmjn)Bk_)nK-_~0EJ z7wSl*&gvB@PAz&=9*~kj$$`sC+*i9GM9{|x-{cvb+S>2nwR;0E;B;I5#K*9e^UvL~ z9rIZ_{t?3iQ}MjZUUgm$n0zio%L5+`Yb4KO#I)DLvSrU-wea?|eiX zDu2`)z9DbkMf>a~TRJ&5=$d(1Q9sN+b;!4S_#w2birHMfYvZnH|Fmpe*;-@$W8AM^ zBDik@qS?NyO8kD{P z-IS?9ezJ%E&7wXjcki(NVEtyjvv{C0i7~<{d{Lu?HG~ zZxD!pm}Ckyxtzrht&%Mxp_<9dKdi`d9XU-Y+=m=7nHLf3v}o_QWJBP$25>UHpvCSzi9HG~mwK=4L0&cH8c|)k>81x?hM359Y(8 z+6eB%g^X+8`{pN{v8ux;LV0yhA>1Xf+%H z4uYe3dh3Ee{@7D}zPhJjPSTJdRjXq3_W@8k7>;tKZRoy6C@@=hM#DUZIjY-(*0r)3TVeIZXAdbXMm$AC3pr! zhM*5I$Z|x}q2Lvz?!9}6MrCj#fXWnvM(M}#F1~FMf~+22*fNk=KB=fdDRnQwQ;xMN zb*oD@&^dI(Lx-HA_G2zeWSjT}betu{OP3%=NUkG_QS3}1w0sA{t?iWBX=&vDA*`b! z34dbCU(Y~)o(SUHsyaqS&N2(%>=3dYgTfuHB)mZ?L0ux4)Y0)l1#?uHZ7YG3QzezY z$`|4}E`YLQtz!`i292eqop;?{+2*QUmh1^fjPf&5)e!0p`q3p`gb)_1PFA4R9D=Hw zT1`e3-#9^2$gA8HiL2T)Wnj?E4t@jXgkdSZZ*cx`o4ZAF&hSeEdTrMjri_M}E&bK~ z_x|Gfl##088iJZ5O_s(Pv623dR;`~7)9t24JRXFh zuVbW;IBN4A502($KNvy7_c9RjNWD5gt2H1mnj;p37ncWv`KhJMaZhP5GX3^uGsJ*# z-;u%?e*lOtAuLe6JYRjF>u1MJbS12-zsc@XlVmyVRK64)j$)I)1{2FV*>*?|3wb9_ zNyI&9Q?f>Gqe)i&TCKZ$HMv?n>DG(;R2VfGXB2M79FEd!lv#{$dFY=6aYfQ%H}h6u z3GE(Bw}Ap2XD$$6^bRF-i#S&8q~q(+QRcb~@CHP6*FJb0%_kR=C^o7f;VEO=2v zNW|IZ>y!#`(GvD>xW1OrAIPM@(poU%!D37Lx_==_uqlYh+D7Vph%*U79OR%bNCtHQ z*P`;$hI#EYl}4slwh*y3`Ya8Lk2Eh*U@gX+d~k*n8CW}u2kJ)z+Q9AE;1 zlo8kJpBcy6Iis{}0GloxJNI^m$vc9QIF9Y1Ay`dXr2kb5svksW8M#C)`KjWlvl(*m zM$L57VwMYL(ZZDt8CO(zNcT&e5xT2*BMRinq`NFCdV))w?}v_@PHy%Fc~WJ3#) zZ-KSihpv@2Lh8EF)Cv_xw0(;VEU&i;@ zdB5yV`#-Y)%>p=wv|P-py_2QXt$I^clQZnQ6XY0B#z}@K?vhuu0{7$UzwPSBy5CB= zv{>v4w<$=~jZVFwUbOGi*d5?bN@a3ReIzjMmv@|l?LfpMX={-7J!^#WW{9e6r=n%K zVj1Fx) zH{vZ8vJ2KrbRg$iSh9qJ@<LarVeVx}3Lg45&_AM&rHezv`XLYwt;>oX`FBl@%ZkdL@?QFMrZa^o+*JZOF$MS@bK0vXh5$@|^ zP|Q>%i!>`Pq~^Ez$jCOrT+zTIue#g(dG1YIi0S7*wyuqhB>V;K*7rjH(&Ns>8hSu3 zLey60%9}0^J=o>D^$L~D`$fPsMBTH`<2fs6C9Iquw9%$;AHWzcQ9@e%iNKS{PR@tp zz20A`44s&ueaatmfWN21e|>IzLIMC#{12QP|6u2O2KM%UUPJwVeP~qQRr-Ux_&$H4 za{EHKj__s4E`XOhhsHOJ!^o4xpEb&oZ(3d#M->B0hkkc=E_^olxE9D@_WkkbySi@e z%mV>E)LT~s@RDZA5lNVWw!w)m?2otlH57z>AaD7*CO9jF3|ovtSF)8VDgDCR^;sQ@ z(df}jb4d_WX_kOB^v!1D-ppUqb;RrAOE+?XtjQPj9y-r;b2{inAy|3vz5d zXlfEiIfHz_Uss?3?j{|0289HuS{|+ya4>=fxU2veOFU@sS#}?`EA;S9ZW_Gf_4r<= z>7r`)2?lSWlU7XFC5XK2f zgY*dIQ-Vpb!0mF4!|_7MT2RAG@_NsUrQEa-P-=!*f~3LJBt1O0i(c)(7dZ%f|8TU8 zP4D!GK47mT#qw;uK4j04FagYSdXAa6Ck4o=VD9t@>zpd0NVMWLwgM3iXHPEr5EA9; z{=$-B=N{lt66<^a2qn4A4w#4|7}L!VPHLuw$POKAU$PPPGC~={m*U;td_*>v1oHR>p1p7KVSKL{2 zT6RVqsTD{5Sj=eF1p6h%Fhs}VPvaipYGiHt^Tv4JJrP;e>Xar19OPiQ_HIO7jV_K* zL8VELBDE4^W8wL_aM$vFG#1Y#6UfDWb$(zc6l;Xi>J*1mut#d$R%F}$ag&1`|FWpe z4cUnd(J1T1N$x4!?t=x{(jW0Q6>@e`pesuQF(swb6u)f*X5e=z?9m3qQb!0|J9;Uk zWQu=^QwVRywBoc)wv=ttGW5wTY|wf}z0gecBG@be^;FK$z)a+V47?LwAg03$z%nIj zUf3*TwYQvaS9kXpg*sJqjsP9b!;YRRaBPY zQ<)2?dJxvY!EvrP-02hOF47Qgdrc<9)zR%*32tIwK%;5N)UT-*qQdxH&#bGVQ?Sw} zP|7}T1vO8&y{kO!)D{%GsB?t+laJho!e~<VUB%IQe26&Ma@~4xo+(% zZ>2ZS1LIGfb%^Uhk&ex*e8jB%{3@DhS^B@{R0z*4kmy9;xvB=8{k-1Hi(~nXoVFqE zRMO4Zl)&HkU6;bNTDHnjGu>^?#zpOqIwp?7>_{hp9tUH*QPA6-T!)wNM|vytxedDN zY+4~;L1g!0O^_~>5kj0@I`5twj*rc#K6TohbPjNXQ)9DK{bcb&LoZ^24KJZTO?WpZ zef(;#A;rPEdhkDVewsA|C1(kv0@aEvDt#IqSnu zCZlR5u7++B$e1W!Ku`p%yzFUu@@h(H{}O#qTJ7!0>OCQPF0+qYv_aFeHsDV3LPAZ% zRL)-^Da3-Ozm=Py*Tg`}L~g_yEc<<$taKxB=wi)ie8xQjXN91oTX zc>CA;-1x8z`g3sGFVU0=KJiR7?w+PBIQ9GD5UxR>Pwc;~$E7l0c=He7|F^;X>(*0C z3jiSXA8I}S3{?CZmFu+TA1MhNns2Nx=y{m(gu3G5_H#eCul=R-VTLwOeJA%jL_&NB z>z{UME_(Ocd&3D10IAqiV{=K8VY1bOV+ot#%-ya9DYe26($X|fyu25&qss{HdA`Wa_t2S^*&(6E&9BS$7r4l&}D{ z>PT!e;?@e0!8tA^v)JwE-2KTzAt1XIzF1p{z86DWc4IMna``TfBJ^)mfx;F=okZmp zqzrAzgd{MWA%+7b+G?W|I^z}th3|E9jVhV~J}_dYS3j`X_i9V@KN%r0h)R+wrS9lH zmP}*+T74jCde|LlqWyU}M|Nv!$K>g{Ie!h{>K^M0lmW!7ZWde>6G>yc!3!QCVH+gV z)oC9@TH^piR@gt){XwRGq(+d3Wm6APOuXuerUqvF4JIJ|PJRuJ{Y*&U6t8UBC9sBsp5hv3356ZOr4cCMt}z|Ii`klbbwvnE zEa^l0(bBdi6*ps@2x#RX%m~Y-n#a#Ahp!pu> zgmqh>W?5RipF%{*dQZ~13@>OiRS~s8Hp%O+YLwWM zEeEJ^{`~Y*tjc<2DI3Y_V%7I4sD9NMm1ljvSr=2YlBwtx&$DtwfK=NVYR=Z4U@e26 zCS;c%ifw1O30N-JX4lNn-6NN4-yw-T+M0kCV(q)%J@BF!}{xD6+p zRg|cczqoUh*m%J6{6QSw%BbFzZrUbQYw2G};dZP@Ga;wcc(S_N+c++&_=*Z?qKBE% zuoY+0dO&n4x?k!=Ui}2%ooOl@4{Ll8s_`#<_rABtwC&Ny?o|cIdc@N|2|EvVYMVhL z_y~9NEBTv;8HTVcz-t$XUc2Cdw0k-9zj{F@Ob#HTA%yFa^8}LmG3LCX6dd~IAoEeo zBM!6Rc^h%bO*hRbZUN=9_Xph_p_6U9?Fq+332{om%w48au2N*r0|+Uy48aV>9k+m2 zo)P7wicLU`n{VORj#-}s)3#{pIA@#{1b&UkEZtj%EvI%0L`Bjd7B=li2>4P!krimg zZCxRgK+ayw@Ce$4H3sj#6%g%(q}1DL@%sRl1#mlom4aozaEB!hwnlCgq_!>dM5whW zZMncagd?KIf=w)rDgyVw43j<(?$l7Km*rc4!$=d;@s8=ks$rj=)y$BLzReVt4QbU} zi)$;}K{z2YI!q&&g2k~zPOoH52Z*;pLl#7tWF!M`XSY@sc`R4lUNK1^R<7zZY6gw! zlbkXGO$!*&UL=AN19*Egih_$Y>?>cf&nfvmVW0sP!7i{7fkQj~%2d%r%^HV^eM``A z!U{7DLKzcuQ4+E{Oo?RDdIP0#`@MhZjSosRzJH^6Y##`4G?WW!(dr0?;8V2yfidy) zF=k8+c@j>6r3;on-zOil953_JAT7{ZQw=~V!BrgM1?Q4oR-!)iqI%G4vbn+SO z_O5_rG+GAy=E9kP>U&Zx_jY*z7_Q{{{`nE{gJbITxpeS>B~nk~!jmmC(;j7* z+qP|6vuxX%W!s)*+qPY^Y}>Z2TmL%uoW1Xj9V^bmiV-nJL?17`NBeqf*|L3^8FNZy zzB7evr&YYN(g;p(Y2rQo@)AzP&{jcyIrgfqf2xSvKi(W(>ge&k8!+3&jFD3A1)I)b zR{O$@I}sM`yKzXr+|Npv&E@WowpE+dvlx5Mx7cs(*SJgS;!4shWQ=nn92IdfwmmDz z-LmBT=N&(UpdkUe_tBd46EdyAx9jT#U$tUwsS_Y#M!|5}6AEgFm2*a3ZFfU4d1k@H ztpbLLKt+o_r4;^#5Yhw2belbXYcnSaaM{_6Kab|tv`3s>&)YntV7fHh&6~xN77ClPCPys|@w!_yzhd z*=V?5=Px6+WOuW(EH4T=n^JEQQ?`&kYOb!29)_Vk0sStAn_a!bo0*eCGl2q&=s88s zE=>15RQs|-q9SsCisf%`ImN4(Gn31L6a;g`6Ip74vgeHyO73^Yf5ts%<|Tl z_R&Y{Q8;xC(K76!JC}?HT8R&*g8p#vs~mSLUa4DZ&TS+5>wF5O5k|TdO?`ab#%0Ud zYvwBDi<|Q>k|8{rbMU?{5lH-9qkV^YAcXfLG`Pi`ol#^t6ffAZc!3^HXr2zj{xe#@O!H0ic=EsGLFQ$*UF|+QW`2<9rnDxpXjOJciJc2Kfe#;k9 zWBLn}CD10#4;6v`#=E$S*=lzc5#3!n0Eh%)!#9b|A*GeD`Fbb_H+bN0m6nYmEC_-l z`<`0VM!WKsL@RI6i7HQW3x^M*-ZGec)cnsiEiAh_QX`%Tv_enpIYr`gVRBg{w$(!o z-q!P&^HM-#5fYYdh$p!v1YGWpG7Zn10{g`&JoBZkHJ?5qhRl)E7r4{o^r=@)kP_u?=X@hRZ_pQL8u^snvqQ)p=DpI1 zhi;x3HCGOJf?!((91t}}tZT&0NAV^?1ETvU@C^Tq7Gp_PJOGBf(p))L{{dz!P^u_7QOExRjGL}d>rXWX?Kj&=I#rAq%}xl!H%Wwc&3 z+F;(?EWT_k%#+z)y6mO{$<#K(5UH=JlqqTa%q81_cB>}~CfRr}gZ0m*R71T*eAy4s zt+4rOC=45n-KfjA(#8E%UhW^lCH?K{!4VQ7LN z2CC$=453vHa{b!i=AmvabWy;2)lRXsS7Q)L@-y9GM^?nAzX$(zEr89QptBezI%@s| zp&Zm-Nk|!RTpY-#z^NIJ%y>ciG>xFPu*CJ~(?iTP52-?bk)U$}e@S_k-K#1S-8R>V zjTPED1LV{3&FJ?q8bAjV<#y7kC;?$T3cwq0)EqFEy5%ohmCks}n^3}T=JYqv-MnNGzAe0aX1@4eifgdr(V3v_4yEMyj^HUOQ*9e~_G0M+qYm7k^d4o%-bi-x- z3^{WDV%&aj2A1&%;;h$C;K3DtfTuL*$`}-EaW)e$6uBh+#Btl0lj2yVf+j62ED0<_ z*1hIblLBn&73P_{&E!@C=B^j(QuD_n_%W3K_SMFPqSH%;o>@ZB^Uj^wakI{~)-L-t$qf~+7 z4(>Wh`$dkn^^3!xJ%br?dJG@c2OJ2q+Bw zl&^|ozU*&42d_W3c-&he(7{o``jRM$_Hr~E2Y5Wdtbulw^b8HCL#)2gV=C-$l z3-e9o65pztZAI?+63@E*Fgf>-ESufzmvG&vyS%}#j(_7!Zo}Lw1l2L5wJAUb%nnX* zWgbJ3K#^;?cK%%8l!Z5jMeDE) z0IPsH=&vjmYaE}^h1DIC#?@Vjch>07k(p4xYyr6`;XM*3 zLbNgV-_ut|JIrZZiFNBxeY#hJCr^WLgfVk210e&sO9RB+T3;RJC`wBY<)5dLjrZ^l zXsTJXZ&?rvH6_bYzw99V-OBf?p#Vd_)9osgUTdo1< zczDFP8SHCHlC6Wh*};QLi`l+5FfF)qtQo#U=y(6Hid^VzJ#@)_>qy2N(oRgqtBtZM z5JX}l3GVH8kLTs+xlWWMiwpt_E4a_}Rcyav@^hHYda{0NR*554UaW#I8FtRnxv}{~ z!};y9RHU+O_K@~}<2ckEG&69R)_%g3D8v0(!xeBQg=r&9ZQ`y!r-aQp;@6L@;XfVf zAi1pWa%79!ut%J*k#n~g@_>P4C3reLQ1}gQ*H~A>Fi?5%s!BL$n%R`B#tQ`+gOKE8bQ;un7VYs$xx3?I2(EXlCM^^l3 zV+Bf^RW~Pl4m~XcxLx6LDe5h)k5-BkHOdQ%s`~*%FI}mQ@?**Ji23_%OIlgZFP<`E zQU{HQgd#539C-1B*^`IFtOjU=(cN&L_aoBz{JH+HIjkW}zS@Y@Bz=+?9gU*deij%5 zp6SIZniT6Q%L}a=MOEjiDt#p59T6F(`g19#M~sT|g?jjcK$eu;YE*Z@ZE^h3_T{~1 zW|~DHkpi2nVaqRkz&XpnG_8b~v}a70=a_-Q zm>)U4$CMRoTg=}EbBplvanL8OE<;jj`^$k)IDcZ`sgv*SM(W#olLtmmc8r)0&1Sgg z&dFlR1xcM2`j^@-DBgC&_>8We#ji=hah}*%JU{5hDi!NRO8n4|tSm9?(_MQxE?H#d zhuo07{Fv{K3d85KkK?dnJ z{VBe~Rzn4_ui3YZ*;0Y_z~F;)PmCseS{mLP@;f1n=9t7Qm1(m%lvGyjsbIdO;>t0; zw8CAS${E}{UOww8qw!3t1HO$7^-_TGB)fY(J#noVd|IaJWcp9GrcDl~cvFO{obqL= zPQA*!Cxb~-{Z(2^yQPc%63hmJOl9k#fjg?SkCW!$7$13sVHbBi72chstY{WHC8~5g ze8HO(pJ*xc@iX0@wK>oh?;Vwmy!P^tlCp9^qz>)gdE4P+RMM{dlcnVtI7q_ zE^uTvKHG5=q%W~lsU)x!+D26mCS}4#Q<=IK3un9XLO8${bRu*=t-eR@`Sp~RTtDs~ zAs(^Y0;r>MqLA^e!)5vOkvkefO7d?%kVs{E;I;bnvslt)N44D}P7z=zUpJhrDY^X< z9L6Z(ST1h<{$-hbgW|vxWTqhW#7drDbm%p$ztk>9G2f5U>Gh~bD0;rHG;hXDt(3Qj zxC8+_c=7s2sTwyj1|zWQPb0SF=@L)gL2DexZQbC)(JT)Vg~5h~SP4l|isoz{&pwYM z%vrvZ#=_9l>SYW}9d4Ux+GBnEeG|>+4&KktHMSKXlSYIxO6ROk);+f8(StfsHo~|I zW%^hsy+M|s7Z6B2J9tj~yD~P8Cd>_1ZrtJJ zke<+`38&d~CtTw!5$$gwX(mtX@%Wvho$d==HIzWsx5@ozBhsA0xhWC)EaTIf?99Al zn*Vy}^JDL{il;%Zxyl}OR?J0ia^$kG9-pPhxzW8&dzB^Ldn{AjSk|E9s0soXE0Q-X)a-}GCv(upuLfI%WW^}oI*MgeSF6bP+m9|1Z+{uk{2JOY`Y}+ z)w)`uJu)7b&ZQbyJz`(WHvK{RH@U588PQH(kKg1N^TYmqnetsh`s45kSm_C=`NO(e zd5iZWWRbW+N$=+fRnr-TwVSeKvpmj zFxvqTgHQ$ve=CUA9R@t;t! zzje#WA#AbwHLq+e+!r2I8s?9skLmX_GH$HVJ}QN5v5Wb&qwFW8gD>*Qwc2Ae5v67q zC-m&%p*xTO7>KrlA&pD68C=lQJ4=*O1|3zLwpn?^LCsGeQR6YI&Z})}Hmj?e-+|%r zpAU|{xBiA^Ik;NZ{W;Y*-Vc^e0K!2gJ#&fTaaS6}*(E(oiqLaFXD86vWrq&}Nt^bT zv1a*>jQFayBC78LOhSM}rgRroekxz*J^ND6u_Zftf1zAB2%z>r9UJub6Kcp~5u}Xg zOW=(S$zjA1m*V8{OjGE+;&YmrK}o)z)Yi6P^R^*V)MxE0F9w@C!WMH9%of!8tY21S z&)_rdIuVOnof~IgexFziZ%C+QczN%ICvnDmapr0jgc^`BA`W%vuZ?*bi*yXJ4|(W6 zhs1_}1DuY3Lj+ar!b2KTKh7Fl$nInd@P+bjaD(sT@LvHEVGpd)RP|iG1iZFn4J2Ps zHwH;r#EPs-c^R{G6njEgtT8ir91X>6qL6tGcnY$|!s)p}w?Wnd-`@?U05jA(w4~yw z%enfq&fSl+KAEC`S~OaI<@pWvL)36jws5wn8EWis2kwr*M9A8U#dOFo=c0AvG5(k$ zBXw#Tz80JY|v(Ac^=0(>r zOX=_QJ#3FF)3Vm6G6h#@9mO(Fp}Va&qa<7J_t`oi+e{Q?J;iu{;r6BgFrch{Y2v`% zKkq5LS;9CVXY5P}us+iHn+d)ffdFB6@9BBs#`x!1*l-fL*0xIa^0nfgg?`GjF5t&= ziFn`42?71`w{_2gRKCM|6Wlb4yF8Pv2PfqnM-(An)W{S7MTL%OR3L!)^WjNB(I%^Q z{%utZPQQ~;?khC(EVvc^Bri55lrJ{`RjWntkYvN@C_f5qa2gz45wB)iR2d$NB6E*$ zI}9zLr1qlQO$>-TlMjxNUOe|`1_X~}CCnF@d52K9>`as$2;c-(yx)C~Z4aL#46y|^ zv}c{M`(^H((fVY)$(R&=l77UbF$p~IzgieO2~A%c=XmRTA2qc^>=cVZ}jY_Rvi z{XYKt0;fefb4j=5(qzv<9UE@uLGD9i@+lxm2(Rx$t~kDN>42z!w?z(7^1{} zTop7uxitTCN_cYMw^P=N))3Gs#c%<$pPXj13%B`3$a{j#KKMN#uVR*#uJzE^S!ui) z0AP*7-6p{S-L9_o;sPfR$(bUpY&B{=bT*n+H#YNwdh4$%@^;;d-`;~gujbpMo~w*auE2b;^#Xj>vD1#XyO-ix?Io~qauwT!<$M* z%sDQhxzy}f;96h*)d$xka70e=qdffAUPT%h1O))%=kwqB+b`<>+%Crc$5s0OL*M?p zT@2Q`!#dm3>Kjz0X}W|)cs=(ipId&GWLD#(Or{61*%Ky_AhcGzKHyAD!sx#m66oVg zrIE>3SHZPN=#G5`0HyK1`|LpW@srau;lP;albWqrI53CGYxlZv`;F4)W0hZe5L{GG zVeq3DYtLLb{Eo3L)E1c{RQNo<^5zVOZoeB7i$;tIi`gyFvO@!J^#QP93DYN6P~&cx zcS^QBsbLaCiHu_8Tu9Xw4yE(bq*mvqnWm%)Js;**WB1MN>md!M^etxqeMh(TRM563 z*l0L?>F=qwdrj3g>Qm9JDN_-HollIiO(v+02%F6TSgyxpZVQ7gekz~*;^JZW4gAEz z0T`curUd`(AYy|554J5g1A1 zY!Sah6K4s_Z-_MJ&D)}|wiId#7$s|WT@`NTDic5JKLSA00anIvFpk|ZIggn_U_&8< zBegf7T4-rptaEuC>kVQpN2499b?%@lqb$vLTmUSERY}vAvCaG$oCcd%DX8M%H4T)d zO>`5MsP{B0aW$65u)!_#;`|1dk~_~w{BMh>|H`1SyP(!VN7?bU=E+b&S=dr)P*}>TA3(YQfisYFGi&}m{!hVFa~!g z)iE^G*U#%f*>6M}zGuH`qw2Kk^-}T^pg!TtA@aWnB1W>)Rlm=owq4pSFRS%HW<%JJ z(V!v1*=Sf%6jW3oEAw*=s-iRlgkueM|gRk#IL(O-lcEvjAN^Wc>qNJ z8AfF4nbJ_ELO=*JS^(i?Xh3Mm7dt_A;p)@p2K2$J$~=MggmpLXPk&Akg>gb;_PsYB)5EBSmK+xX{*cppS`@%|tCd^1ah4 zztf5ooO$g*3Y&f-MH+PheU{M(3t0>uMvucBkO0kHlx3HQT0Pdccv4Q|!pS(5c)K{O zNcs$jB$wqL!8HtEO%*Ma>B9FRAedL^VdW`reyZYdVB5N>bk_<+8Z45ofCt7~UORIny=d)&JZHg$8?#lKi8Jme& z&QgBAf8V}zjjG1A5xd8fdCA^mW>=E4t69vE}@U<>!HrIpK{N%Bdclct@*~ z_4}*uB64TZE!pYqu6OHIZM)ZiD`3JFwBXy|p8Gr*EG{dhUYD4HO{$wD+rG+-0$^*m z6{Ht24*Co(!?(<;f#sB^mSuu;yImbE8m~Y(v)#T4h5o4t+?MDpROBzO14KOpk%BkMYwPXoYtR3mRCrv0%a*(IIW*lD~P)O3%XVdhN)7c{p%ikR* zKkmY2Hf#{NCM_2V8GYB=QGjCOafF|HuOjoYr>eM*2Dx?e+T870qi&17g_!()bpa2h zNer~CE=pAw?CQg_U)BA9DiOeo%b0#;_-yM-z8S7sAdz4D+efBnA-?Z;g2Y1POm-*R zL^E_jm&vFr%6bj+!^O7qFI&FfyK}flYXB`;P_Brb9S@wa?Qo+@#S1$Jxedo;hD$QNCk)hpqy`GS(jqE`3EH4oiLr$)KEiHFBwfNL;WEo z^R4RD^Ox)QR)eXo1?kz5u6-kp*dSE)u*4atG9LA#YW?B-{fexPoCCFOs1d5yZGNYM z3ZOJqxE)5os~A5Ya92b19r5gGwY`xnkQ`{o%@>x#RKm-joq+_j2j}+zfWRX2Ns}OS zmxK4mkHq8e3@r z>=3UIT;URcBErICWAOAs)e?H)mm^-y4WGRWd8Ejuv;T7ZX{5TbjJY6f;Mu6nm1R+P z6tj4;wiC@Y(Oa_F{SPNP$cXw`f%LW&Ef$AJ@Zf$F0-M8duGVwt+6cIZTv-Cve8TNu zC&ebgq#3utz|lBOp-0!@9&DwWl47(Z;m7;i1KPEii%3a*8t_p!49*rX(~tW1gbGN% z4`lU|^%gwVu`9q85HS}VMfB5bw}M7>LMQI9xuetA)KF-H%Meqo^zf=K){n=U1Dx0_ z%MK;5TW-FDkLxi7i}$mQ*aLKMgIX}ILNud;c^}oZtN}Xvl+17O^mTKE{)}JZ!tH9Q z-}c;}eK6##!8@aX;`<1(KnOX#Z*OW}TzO(|Sy(I!Uf(7P$a_ngMu#h`1Ke5so7*c7$ikO@C2=(W5?u&i6^y zc#LR*bC=zC57y+4x*TvzRAe^>CY~?jRT%Zy^ptz<;uqZZ&iHg)3%aJh1zNhQ_YItV zF*skV-6@oB7R*e`@ADmchm5U7I6x986H;f7kW6(?h z2gxr9U9O^Ea*Ixnprok;@IvPJ^je*h$^_jrqQrOI9%BMqG$Gwpu&9SKBf-F-V4uNH zr`t2~TFrgH;q;BLD_rXO@(c~!Tmm22dc6lK=c`VU@`R5wsy^6^jb#Hx|`#50iMr zZnZhIOP+BRR`0L6MZ>YvX9Z$xg)vQ>ss$Dw@&YFoAn|=SxsnUeR!5wZB`>A{FrY2q%8RQxshiNhJj(A!1 zJK{fo5ZB8)6{+ui%M_7nJXLcHj=gkDEP6jrCJ*=N1sFro3C%w%M}E6CdOf`z`Ta+}+ z|HL0?YXcZ2hnW+JdS|s%6}aPmsa}g=t$$*?-K1qJ0_PC&mqjdMgdmBD2I8mx*dz|y00>=%vks8PLF5E%Tnuzw*Z&*+dh^iI*$1@j^Vaulc6wT(t1M+T_CBo}v5Kqez zKwB&j%Srurnd^pu@qitTv1Ol%I<%*E&B9h#ea)m4mF#WYAhC9^p$Bp^`MTjno##|F zJv;Rg4Fjiy!WtwC@_vffl{Ot~ztXDSzfKqNC@AYyhT{9zh9-*V$66`<$r&s3tbJwnd0`lwCKxA}>GasLn&mecBbOtOI?S)M! z`~2y)A2ACm9-J|(=yucaq)88Ihd}Q+wS{%4(>>C_P?0^CD=fqa=m3&B6nNt5ChWCc zeCtB_TKQLrww{qo{tOXP2f_#r$`@4B~dsUEFnaX3xq;{pTj#9_EaZ3Xrl?CEL zAi_em;>M_U6^k8I8u1u3*2;*SbR@T5p;DYU^bB_6STLa5EpKJw^Lt=TZ72>bX@W8g zE3$?k|;+EBP%);y9TM_&nbjv zN-+l2Wg@!+me>-*ahe6>WGtIM=a!yq=o9GrP+OPL?r2=sjW0O{zfNK&DRS}CHm{Y0 zV?zCH!R~7?11#K3LC_LZH9(@be@5?7r!{(j@rHjj?QD*Gk;;)6jrP?fwN71^nsY?S z@wv*Bt=p>EWpp!kRic$QnHKklN~T( zZn1th+Fn3Mv970cOYQFuRu<(beYI>dcMSNNTP$%j>)J>47`lo*MyI$ob8Zg@2fDq# z#gqMe#;C~_%4@Sp+ClBEX4aE6slHBQPR7{c)pTdkjl_D`azh*V@el>H16aONP(y45 z9I-;QN^ED2zDi5}^ugA1jW*$W^&%s7pJ0kB(O->{?Kco!n9Q`Vj0~_Nv9Mk_kR-BB-ugI?Geqt2b4oVq}xz zf{R0shQvKHimoKL1;GD*;4s1MDLRMIqU=7rQLDC{TJQwk{4> zGE*=OmlM3?)~Q+(gww&YTwcFraE3# zxmsW4Lo;f-D^}l&$3RZeZ0o$CV%zKj#Xs>E<}ky6?6$TpBA8ds(`01IufF5{p(#7Vtw)SZWHul($nxuTzh7j3H1z3PM$-Af`}WFO#Ctu1-i zt{J&dFT-f{10EH`7iuSWT2O8NM41imERLG*lYj%>-VSQ_xVUdjJ>yU-J{EvDz#m>E zTH#;oc(@L@XLtDj0EONd8MEl0q@aJ`z<(XE|95MTAMGZ9)PLZB{r?vR_iy|>s3l~k zWM$-3Br2uGM&h5stK{iz)F!_GjmUO3^*fpyq|t7-xu?KKh5Yc!^C=jgygJ?O z$QZSG?pc9+wT?VSQ#Y_|ctxyP&@|mQUKtA>HQ#>K$pmdp9oYpBV!}U{{Q+|17+0`F#d!7Kzn&9!d@su^H>1}U{ObD|T4gr@6k zHt7%0drD`Ye)pqq2G&6yQrPE*E_7FFV}jq#f$ zC5K=G{@XkMD6I zytIQJKlx>%tAx)YHsj!Vb7mf2FJx}h+7KXLpSC&o3)gStei`N2U=6X#5%dXZMa|PP zw&5j4$y|ame_a2dmg|4LzawJ4$g)3~N&nRLe^vc|56c6_1OU+bk5|2;xxvpXpl4;` z{=W@+{!R4Ppt_FZdMm1Tvkz!_XsQeeRYyaIP1bL-PT6M34327(YZtOnCjzASS~5U7 zfHhT~uWMfPoe~mm?+QHYyStsO@%P{MeeosBUZfb`?IVwdEb*dc(MGc;`kgBr2E(lq zO%8iguhI>aS=m+4*-y5Y>Av6lawG^;i)qRgs{vZK^YA2!{gX>mNt4bd4(*K$``_Ha zoh|#ughRyIm4#YrktBu6X(}VA`{&J&1kVY%B zjL?j-M|7S_p}g*}_)Lt?mie;3dAQ=FdoJXLWh86Pa}T775rf>`7`PbvRmAGdJY}|@ zKX?seIehJlyu?@O&O6{&l@7MI%IZt3cKAS!=~eACMtB$>FU_sB5>Xxnf$KHaYY@ux5n1xoAqfj z=UCMoYwzSOqV`KbDr+32O!I?Iad~x9t&`Cr97R2dH7g_Y{Sdj-V7es;Uz)tB{+6xv z_;e{jPoIYfK7V1eF1;>({>C?;^-}?Io!JKwgfY^CNUOi}=CkP6MMltGj)~iKhlN22 zWn&vQrrXq=)?;p&?QFk`f^I&|Ug{P&+4+d{#ROmT zvizmv-&&Z~JeW&sLD8`UR+D@J3}juNzz#r0Ya=z8W5x){Q?MxXRab|JI0Z;Dx>n`! z%~X4FHF&&yo20^8CZ!Mm@%n(G>ZdJ*3*W z-ztab-$uO{zba#Lz6>O_Q&cvi138Si!>z7PR`!6|mls(75}IIe6(en0D2rFw!nQx) z8n0fXuAwT_j@0RZ8D9OV(`!Gl73^TW+fniN)D<|g2d*ZSl;}l45g;< zUB(9X5z^I1G?R$EX4uPs<|D+8SGW?^U@XGK&vi+uc;tI>@9(ssFX!Hl_E%NxxN^|r zv=Pl!orv`?owuhC?6eWlZa`1k_{UdQ8h#7euEuS8u{<8UGJok7HoQj{%)3YAx# zHrvA;-nTdjqZG~!>H4HwaZui~*JY3P5*?yx#hsqshEWYIsaZ$@3?p8)s}*!9V3RW_lF~8Fz?pT5{4B<_~(q>*$Bp{lFDm z5LlCP_T&ssusg?$7By&3b@UuzbRHv*D^ISMZlwPzyhizyKFLFx{ zLhclUV@-m)ipUC*p`5>5&wK&*O*Ur{_9BA&n&ic-b@J%~S+Gp>kKppdU$WG~#B9fi zeZMGku>=F#1)clchHB&hWj9BN0T#Rxi^pc>m*mQ(q^VOJ+*&pfPHh*aSue~k43oBK z;Pg1dt2J-$m0U^u?9@iRZ~X}@6#j=UlmCH2X!^mRTs~I*eW|~v935~dZ&ga^IPnmM zTigV@=qcMoY%=tpJ1Ayxc5A~P6j#zG{0nYGI7HH?Vy(JfG^vDdq3tlYnkrf%&%Xuf zsQBJ%@#_U)v{IfR$CTsz_oTjKNkgj%$9EMYLcEIt=Yo&cTz&@Sb4ik-^F*VIgPuV1 zxfn-(+Qr{N=bLw0CPG$eM&7!T(UcuQ>G?rdQ=0b}J`h}Wz803K z*QGP4qi?tq!$AmZS*B{5F%ymF3&L@f}NLc5KhH*=R8 zNn;M!f{rvBZ8!|*$tTBJW8h6c*?7Xp%I>UUG3llA>cg(cf}nE5K6N3 zK8`{6E^{gl6;spgKPmlbMn`8-TO9C(s8+Ynmi?*)?$DEvW_Qh;S7hoZ12ygJ&7pmq zFs_Nfqk@9;577@Sm}0>3Re@;w_i|1}^S|8#SGK`WJ$2JIT>HK)>?9_UHPRF`6`3Ix zc6vh*^UE5jIFDEG*KlUjuvw+>i7cRI#~D7Zp@r|ye4N15@{tc0Yq(C8aw)VsTn6Z^WN@@1oOCiGrE1K*IoNP-M zlt@=@tKcIEWI^eWvUk?*UNnV{>w*frAb=x4y{I${A&2R$<%)yvDtHzaGw~b`Mfj@p zTi+O>e=O+@{S`%jM5jifsz>g}P4s!sFxDdMGt?n0d~~3VdPcRF1_kf(9{wW8=(F23 z7lMq*eofd=xW?`Sws`r)ux7D|C3TW2sno zxn8nmBeW>==_1N-!U8+D!1#W!csd9-8*BLeK4-Lm4s%DBSF>lddc1H|?Mv;HyjbtvkD}0-N8pr;a!OD;g8|S3)1(51;!FnENl7 z_un@+w@3g0s{e7A=VWJP@_+KX|4kpkpt|%AuZzIp z%9V!m1MU!%K%fJXO=7=1dq4&LUcNUl`>{Gq?6o`gXaB_C{#Aq zp@zqi^VVP%{A5XY{9~wdK^Npoe z85K&pbE}qHd;Xm$GCK;XbB?W{i;*TBh6;+QfvK@yKqi<>PI+#+zbIq^t(Zz<8I4-i z`p`5|$#zZ>ebF8t`#6a;0TVKMtYSAf6-p-6OkRRJLN%o` zZmXfW**-~WMILz>L?uan_)3sY2TR$3s$p&NCRn%6*-_!b+HbF{tK`&IMRNjT_2*i5 zBftl3lP3>R+3TBWp|I11>mt|K2?z{tB$VQYcnY+%;PNt$RR@)s?EMfZNE8FN{`KeP zg{H#e(^Fy0P+(C)1o{vMM7L6xHyHu$rPap8rcy@nl-Do>u8fQ*oynHi0AY*7nkZ8?BDJ z_L|3l&%cB>wWex66A;-N$6V1H#ryz)d!f)^Vy#J#=pp)khf;DcWnC(t3Ynb8iJZ>M z1WVxTx;864cO)?Rvv@FKe8@9~E{)nVl5YWQsnU%@^7g@hURGSkO#yGXEr>Sg#RHb7 z>DBl2;;AH=-9NymK+J~SqdKHGa3&Rt)#X=8?wrh%j+E_w1xw;f-`H~D*`*b8LpEz~ z<3&*_Gg-_$J@+GCHyOpxZV}&blk2fiv9LJtUrEio!oDq=|GiM@tG~&x{QOoL>KR7f zCJ$}VJop_yWOMjM5bp-XOn`q#NBb~soI>^3EC*xbQ<6(5$NG)FOG+m^+4i#Ye-d{affpkp>q4EP%s z+VF~gO2?-;K1fc+%aqoLSE%gT0bfAuBUei{-eA=|PE@Anuz|>)#vWkLpgn#JpKQ#4 zlaWow{D6Nj~^HD(X5t4KDGB{WF0P50ttasgo{wh6;%Rt_G|7&H3 zQ4pbNDivSQf$u`d$IF%x!~Wc`V_a9kO-=ekKR@}^lV7h>2i>QD&~Lla>Re@639N$X zo-Tl`TJ}%3SGKM(G$dB&!eMBu3Xco4XsQjhdN(iLR;7i@D$pG0%ixc5os`_*B(hc&HulK1Yrc*n5$`U_nJ!SoV-(|R9&?ihS1XCpAM=H(-bM(m;Z2hHa4bu&bAhA z|C_-0H!5eFxJlUo285vL)e?1&2w`)&Fkqxm2^-MRuyW-+Klwuvm%1A{V{R(Iw<`_{ zXxg*Edb27!GqUlUdh6gy1*lCQ{a=@2<_F1jbBh45Ra>X&gr77;lz>5&QI8nHEKIg2 zvde7|Qk+0QI~^f;ia2_@<5SE4TW3(L>nMXXM?y?8QP|V{q=V6@*~x-b(SInhrf}~m z8hhGg6_~o7>^>v)ar`KmtfEO@KoyLl<^D*wySRCVzJKn&?)`4ll)0CDqegx8dUVR6 zFGikVn#i(36&^SDHfg*dK>C;#1;~k;_Un;LJRTfy@UTS}(F!xyS?_zO8x)!)gG&pc z8fxGoJ3#nA;2b1I1|b^vvU1+G*dQM54Z7@JRX0Eq1JT+n2=(~7-iSs*)encNYm5`V z``RA7*)S>5RQ`=1dF>0$|IgqWu$O!o zMJR)OoEG!W_kpvLch~1rNwPj?paEaJ^cUJ;ot2gM1fnHY=X71T zrl4fmDUZdnP6{^;CYD(SY7~SY#X=P0Fjx3T*s(&!)Cqolk4{|48oC4z*0`}2h<$5^ zy3-a`wl;|Vll54<2SdIe2!j5myD8d~aUd9gTxMATJYPdJXOVmLZiOP zK72eMO&;)v?CH3)W;GNEqREX``>)P8!*51jWt>$GP3yqh7RYF8M;Y)+6cM9GDVqtZ zOsxA82)UhITs-o(__)r#$JWSqN{5&u1Ns2oqAfyw4rTQ7igoti=*%&HlN&$NS8XoI z+ou|aT>aFDl{GH|?B=Y+*;bfeZ}(wq_b7%&NT$%8C%u6(+-Go?u#uOtdyC_*Oj71q z4&L9;ZnU14GQ+N-**m0@09>R462r{W5GMx;qxkgu(3h-_IZ2M3g2E~S$8Xwd%Ixok z=z6OM)XkSQ1kxvnJpoCS&ZHUcrmdSe4I9e`iXlCcqq=2R@9+_W4^k`Kc`$lpFG+cN z#v?CzeO|YlexSj1OJs5+Hf*@-5&x>wrf}B+$e$YhryBp~I%W8oqW(jZkiCVyiS>`< z@c&{G@>c!{eqw;(UGE7PFM5jOdPdeWW=b}grJtt%&3MC7?OqIY11OQC@#oEtR>P+bl4LlYs8p(WVKmGr( z_6|{^wMnyZ*|u%lwr$(CZR3<}+pbf#ZQD5Is{gzfU-#gyUjLvcd$OmQD>CDWh*W_p znQ^XoAaSv!ow=)FhIPL~1Ho^5?lTWEW0u=cjz*8e5}Fni8&h8!D)G;s!zS%SA7_1+F|k ziW|Ur15wm{779djTcUY@Z zl6W&54rO$>D&k2RxM26$IoS%@#OQ19p59;`W5^7a6im7vf+(Ja># z)VU)184Hy)F2>|&@t=p(uR(Q`y2bly*zJ5T>4SPMNU9I0@Uf4?r`)8E0s&Oc*-YS+ zNx~#$SS7Z)ffwFS;iJ(#ZO%()-LCpD!Aix{l2gZl`E zjEBDb9QOQdS|EsU|YAg`C|Mt~C-Se-$`uC?sK~w+$ zjsMOL>tJtVY3!-*Wa{W@>g=L#V{iU{JM2H?^R;LwDj#wn`NjE%l4&#iJv(FIc48O~ zsojL|r`!lqdO%Sfr=?`g=>U6_DG6t6=BUr!UD^!?X%FuP4`4G%tER5+yHoUcQJoJF z#*cOOc*AK)lMvOQPu(&eeaxJ#M}&#pP|@#E6ES}$!%k)6sEZC2OukAc_H&uNA~vdN z^5!kSpm0g6(qoR8qw0_2I;BXu(Oqv*tq7Xw;T;jTs?%0<552a@+96-cX3n%^K|`es zYp@xTbC4BFv(g|+!=)fpCh4MK?dcJtiPH*|0&}#`wMLvzD&oOjPuhC8UHkTl-}6l- z#c07D3PqF}xf3*I8QB&i>%lqw3m|%X3Pfg&2vJ3xX0PgZ#K~_W6b|91N6B;|zsMMp z*&?Oc*LS(kj*+hA`u7MoZ-R z76e55)Gg`iqDj=*k&*FSUc|V!BtpHe=HP$6^;)~Xx3H`n$(&HaYziEXJ0?dmJblN{ zpCRGQfo6;0G)Dinu+^f$e~@`tOB|9jHpZj}I9RbhHREq^N4qQl7#N1x;;INDHB?zN zzivs@gQn1^%$9@!pXx$@r*5Z@OfTaJa;DKJ2H6X(_Oc7Z`4I=;wN4tXUK;CV)dB>h zj3|ixe#Evr6-_ZVY@rm<7|1YPGl0Q4QmK?!q8V@&J|oT*B^BeXh5ugKq2xF&GWUb4 zY`|)*btTYT?;^)%_jNw)f8+#;D+MCrIHfv1gb`E;5+u4=-{Lp%nn0|(51Q`ZZ5|t2 zkHO(jGyqOzLWyQ!=kF0mQnBP=!6CU-o)!BP;#+&nBTWsfAl(aOYwrfOi7IX!(xMDx z`vqwLK*MbS5j@7jM4rFj@D)u)K~;6w$pAW4*Rg@oq|YTo5z4Ow3L*u)^>#0A)?g@E zSsi|M2M<0qTVlw66&%;9C3jUlTaqDhq;d=rPJ9xn!psFZ>%eCrOgOlY!i5f&`WCx043_7B>>A1$$wMtR_8thwpz3cW{%$1Q1y+!`n4bN zmf+cw!}03AbCZ7xNL%yLsaSysmw{c5i;7@TuTU7^(WRJw(UGFMn?rS0&oh0N)+EK* z=a>M89WGp{>L-AlhN>q_&QeSP5KjthW2H0&a4a<&1;j(HbkyJK>J&n!rtJ|%Y(?A4 z8>WezD`6rxjY4#Et6-a*J1=hD3jbk;5qhhdkuR8u1~=KD&ndKMaz9o5d{j>oG~r5j z0;C|TfR&(7Z-G1?V&1AuUX_ItH>x-OCVC*uA4v(172$4VWv@<)ogtojU_(bP748?F% zP(9&&K{$@tF2XD}O;18SbvqKNxtn{ziKWP-HrGJAinG<%9k2lxdkJ4^Lk@)YE8i5~ zMFadt2uin4SX!Px+}36mUW#kmgOE^VN`ISeaK0U+M8i6lM@6|&X~ZU_JafZ#*rYk4 zzT;ViK^GxG4RX?FfbY*tb{Brujh~3S?V6r=SNywWgO~(8pnzqB77LJOw*fvLen$Ln zS_L4Iz3h@R6e{W`54oW2qxksv=I12H;-1IB6?rm3wx}rK$Qo-J7N<SjT?kg$nMvhp_O0GWwd!t&=&4QtWsvC3S1fEuC&w@YPc5HK6#-+7Xz?1?_ zN-AW*gDJ8Rn^uB3`s@caLPE;^!oG}>SA^JUmM2b8zt&@WbsSvC@ExkRYsxzqJ)l|cpA6+u}1X}Gs9kvd{kFI)YXHjDK37e z4gru;Mdi2JCe&oMS#Ab0;`n0f!mr=&75|tNk#qCf@4vsc^W)^|<>mcA_w(K4eKq+n z)E^8y^4p5FmNPDYa51q`4PXvc~=L2!W=W~!ya}hM`ixNIi zk{nw3b-WR!mDxk~6A+vaS{G%Vxx!@mB#RZcBiWPPDX+cv%K zY@OOFTUhEt@_ZvER{n}ff`t$!0h-dWck z5T_(mLPX$Pwg*D7QeTg)UK?|*S%FZ)7eq;IG^}X*`@#1mZfoR9-eG{SO3lF{@Nyh< z70cQ%P925~nYmkdKvr6eH89nMQLibpot9F7CKUQO+gwBS41R1QFG9AW5uvaY)V2j^ z*P5`J^F6QzmJQsE_lrE3<5=K)H;soIH09ZmjR2^tP1oB%ee0kfchAGy9Nib#lH<*Z z=OV8;t>qEhV13w-f0XH_j^ah@!M@|Drzmc;2kB?1$97#uKmK$*25EY2z}^vGPd_JI z9aSUThW2K8nlNd2AdxloO*_GBO?n*E@ogs*4F-x>Kw5!=2w1}mx;+u%-9KIoSMrhE z9l@pd53YnJ%^6gXT?cV(N4WF0G4k2S6P6aaGXe$8t4F$H1_2B+N4$NX+uHB%5BR?v zluqY(`;Ul`IwYDwN>@tz(Ac_p!Wa&CP|H>Td|TcF_axB9^|;yXuIeSwli&Fl>_4k; z9TP{5>EBqBe+Hg^jY9uU=OeNHcY^W%uEPH_3b{D_k67bBQ28y|-p-pNEkD|yDAqfX zuoEa0>yl-};u(r09rw+CI+7VO;sIY&+B5AE28}JTROKQ=RmCz}_6w^1p(rGTdMElfT zBNyAAtaE6m9Rl=EG$D>r%GpNq1wK@jXSW_aGQy6_n0h;Rs zY*a4`YYzl_G@sf22HVo>!+`mO9LLUN{S40DK)`lOm7QT%KSnk(!oa_q?tj z3g#8p2G9ffQSy8Lpk>DC z48Ir{OvT8o6=btSHj9M%#D>DuQW_OEmm^8+zHd~@<8e%vTZu&RwT_A=8r=p!b~3BU zbHH2Iu6BRGLA1J5v+$BOZv1!3jB^*5umQLMdnFKahan9~l#s8x?-yXYpRJ7Qk7Afr z0kPWcj=nxl6+T)i0N7ThpczSzP8v#QYHJ`Q0}_C|Yt5)kLpXB%&_%#&nOCMgK}@EL zGHa7&s)<9N#usj}3iRet{gAd$a?-kK3c@T$X(!O>9PNI(Q28ZI4Z76s1r4~yAK?ux z4UmKqIW&_!67RiGh$gQ?d7b6f;yvw*2R3P#3OhU72@Qi)Q(2i>nr2`QY_erK*fGML zChVd@e%u45Zh{&V8M&S>wITiB98{Jxyy_>iHZI=sM)@!r>IBe8c0T(dgC0WTrJboufRIDe8lZm8=Ca`4K;Yax{pbztg-lAvFeLXxr%@Uh{fhyola8g{)$jb z!-Y{n@6AbK+UgSt2}GlKks=qx6C{s5)IjtzGKqmki5b$$j4dw0fH2%7>tz!&lbDPq zKFw4^U!h$bc7AadU#^KKctLS4?fAp(sT0stS%e}gqlii&>sT}E63XFHSH4spj+3-V zqS7}NH>cz*>l|hr*_O=4B{B>qRweIR(?B1ZwRuY<|;5&{Y!t5Ei66Ks@- zG<`qwJ?U7Va3!C`VjFN22?Ys$?Uga087U$+td&zuoG7qObAHLJ*_Vl>lm56^B+i?> zE$Mqcdhq-H1EsOfH(NxopSIt`gJaoK*jtoJEEY(uQH9I~2C)^A3qgyA==1rrBfYAt+yB6epHYn-dL8vJ<>LIccl!s?8pU918d*kst>&zkD0I?PVx(zC7h;Rx!F+%YT8Pj4wq1dC50N&w6tF(0fmQ?*QQ{z zm(uFSsl;5d&%`2r(zwKrCq@wpZ}{#z(hCrx(E-DsRcZGAaJKQuoa@nv#UsF8&$U(J z+)-bYB{xdHXgyG=X#OZvpr|H88|K=*c;n&%yl5p;n}+?!Yj{{w$xf~17&MOgoOnGy zSWCC``iCi&^x|(ZpT4)gZ($lqL z+tHqG)}I!XXDC7;r{=)o)HE4V@_5mvXCOgp)9x66w)N*NiqNtU#b5VI(ceyvyl*!L zPd>$RyE)P|*PW%IWWYU8m@1mn%fLdQ^ZSYJ=KYRG;)3?`vFpE>Sf7z@X8Q<+i}pO9 zrrZe}NI>TfU3s8N_UEKYXtZ_9(q?TTYiQ$DQF;`9PD8nsz@rY!ULSgiM%yOGLJQG} z>5X%R#!+mYWeVwFPSIEwHRWP4T!F(z&hjlASqGhv^PqFzJSA0`Xg@CQ93GbUrLjVq zU*=0qar`IqUrGs+i@>JKhXMr}M(yB#=Y7jXFJxgpdcXp2>4h&uM^%jfk zS~^<77DWAOERnN!$%Q|G_j5>RU}I&M)50aLD`<0mGGwu%N`TA=^7g75S-AN@Zb@CWfY|v6u`ny&C=+p$WyJ6qR30m zad}lYxbt@x2fFe6TpO>`vm40Ft4Z z@c5i@mQOO!rfJtA?k9AD7&v%5ZCqH9VY{&!y-DA51$yeYO5N4C-%qBu(@fgVX+Sur zl|oFwZb~8=05z;|ldw9)6HU|xtmIPy9Q@#s{G=JtpoCxSd z3h9YfRHn(wvD};az=j@$ma(zL`w;bWEN{ENEbka}=%QhtyAP`H0 zcQkPTB@UjGUgQh#%*G2BuQ9yT1lr#v*Kf8Bt8Lm5~%=RCO>mwTD2H`u)09leks? zu1T3kCL3uXxm>u!ux*-KfFzwuV`g9RsH6AC!`e3I)>Xv&?>!pkl#>J8jfQ!P=)l&+ z9KlwG<`$u-Kq}xUDJBoE@L*xja>MF9mV@J94MCuaktnpm5{dst5T516eqy-&SJXSydV(YTf| zCoA&OX&gP?TSD~GV8?tpf6Ml~x@$NxVf4#qJ|2`_RzlD$MLj7w6LGp`$DD+MIX5 zhV6=gjcUjAyLV*)`sze_7@;^0nY{9{okn^-vXNr4l7QeLVD?uXyxU)Z+uhDWaNaCK zLWQ?mV!7XYt!vAm=kju-D+J8$QeXQYIdtI zBQ;Q2JoJSEP(sC7K@f4GKydhTJxyr~Ki&GC^f+#-ZH)+-t*z&7mNXhrp-!QV1r;+9 zJiA}x3*6d$WM$4F5@(LAG)ayvUET#Z6>gxoth1HyGNNZ3Vh?od1E^UQHo}W=K{6@7 zW8y}M^k0zj*u*yaRpn~9$3?@GE+z`=DApLY%Sq7qxf0&UJT3Dy%nBaQX~nna)${UY zCv-*sZl;!{yG3n60F!~GofC!0)h?CzQreqC3#SsrcQFXq~IQPtv z`mT;vELO?Oyot>WoK#^B^-Dk)ojOZZZ|>`U%K5tuk3=6Jr5-jcFpKHfDZE$Qs>vj! zm1eR#A39;Wn7BB?Fwyjo2xTy1=5ToIoH(KK3D!5rt4odZ z$Q*lMxDHi0>TvB_YYER_bw7M^6B+pM{$$)Wurx)jnP(H+$G{ z$FJ_Es|Vqjq5HD27Ox^7(70p0r818)PjD#YL&^1v+lN|}f0N|BoZiMSo3iOIsg%WT zztXZo;>1V6r(pXM4}$fRjoBTXNpWpBn&#{h6s8L#kKmRnzbw!LYiHc&zvRypE>VXq zHWC;^g2O`U%2J*ufG(m-T{2aDr8y#r2WBrK`4bW>l!iM2!8iaSqLjCf-95TW`ve{}BOZXO}=|G3ytzy(Hp38tq*UIr!Nd(zrLaE(!F1g;} zFZZ#9#u&}$ZfZi>R-h~x)l(d4_&A4R()W;)UZ7vT@(F}IXV>VXPy70c4V=iAmAGGx*S660Pq#}D!>IZT&x z9`DYQIW1P}ba@kE=bNn*Njpz>jO7wwOyg11h=aJ^TZJCq|=3uyE=t^tN zCo1kf?k(ScqmVbONzv@Y#_o06FLI`bH$E_??a`0jqMo))T4QppywmRm(Py2tjRS(_ zC%e2N%gSCqhN6{~j7OimO7^*6c1vblPnv~q66#$!HWCusEn{vHH4 z!^X%FqkcY|U6i#Ii^^7qt`@f#=C;Q z^~GmY7t;~BMKj)`rCcpr4pSNG;WutK?p{>)SMD)N*W6}w^pM+^1Dw*aA75Z0(Fz>! z0#77*(?N;8jsoOVi)*3@DwOq4?=NOU7t~%?cr08t zgdUbl;I0A2qhPrJnkx{md4sbKidOM?#3|YkK1VW>L3&!QR`_74nL+y5eoBtx!oOpC zTHwmv!OT?{pmTyRc$1iC*vbM?v_A0Xq~#!xil4ffIM_QPdr9LB9y6lfv3AZ%Pf0vF*v9?igd^sRCn{x= zT369DN%8iVCx*NnUMZ7@iktEQH`yK$Ie1}50_APdDZN8hBfXGkRfc&Rjjp-y&EWv) zgfB09P3%qqE>B|N3rwLI7l{6F-YS9cEJ?q7+~KP20~ z=(m42O(p+*qx>(aY5x!X=3@F!Xz9OEaR0$C<*Kr6wz~>`tMr4-fpkl3ugh4hq|mYZ%0fh6`X}(oWBy z0i{25hbZV+>SNkaVIE5T)mrVdVEvjeFO{+WdW zkB@QHS51j-6F%lgo7^UzTCCydBHe}v@bH=u+8P7l?Ba8;;?45{`O6cxOMh(V(9+2TahWYv z(H8`}wSDGpl-O0`u=$15EJ##Z+mXyx5^NgWF(PW>$AZsju`TGW)$HNNdu_v^CEc*Q zLS;I=?}n`!x@UdA-~R9q;WZeu1)6Yi_hD@7=*;p@mDcl_(XSt&@JXj!#(r_>_RojN zuFc;^tJ5zGTI5@^6yvJSw5{w<)XAu4_GC?;2&m39?8zPn^l~M_Ux{%c9V{ALNH|0z z*l#%9LppveoyTYy-Od$gk>A_kmGy%84oYFa$1YKr5Qf(M5m@&%(uzJ|c&9ZUgUHPR0f{CQWvpX9OYv9G26^eZ`_YDM zKl34=5KXqYhY%kJy=Y5c*Vi`hF0;=H_iL53T-nCwxN6w>^4>ZVhL&5uM)~9AeDUtV zACWFpzTI$Fy|_yy!+XyGq8fsL{)D_e(=Yvks89t#qyV%>?eS&#lydO`uL7fQXp{2M*~)3ac?&F6dd%4a z(9O>nMx93nFweI-b4j{Vv8whkHHNh!cde)un{InwN0n%r?g^i7Nk8C_3}0QAunHV% z#TJ^=lPlsXThXe-$|vd^M;eIngkV?@VkQo@*Bl)0{E(j({eSy0IEnOR3;${v|EZb( zcQs)k{MR0Eoc@80zg1*t@~>q2|4>0C>azcMF?gfp(vlkR@Z zd&IgF;nI6lTHJWXB*itwrQhughd>_4Y~TgI!IK2Bc`{`yCPC9e)||P2aPR1(tYW=m z$B_HryVB!cu(NuL&>;LNm50f(_V@aSwcl$6p7!!>@q^fYm zIHEHg9^@Cx8LBKO8xAA4!4SA7dMm?U?OL$bPDN)`=*-NFr6O{+ z7y;^uf~g9MP*&ERIS5%Qy=ZMsR{^oUU{Sr`rQew&lS!vhcN0;%jnjdfYsQ%}a6pJE zJ0?k4)L*bn?vm~*chYWK4WhIbz$4Us1)X?OZoGqOcnawkdKhq=;B{cN(xwSjMXivUIWhJd@SE|j>s z;5&|v(`4{G2nHp2HGIitkCGRW`(VlU4)pf%TP*}r^D;S_j3O$3!$mGeXuzkhhW5Ad z0Y=|(n)gHd^Ie!-hV z%Tf&yi(*hy7~z|RMM>RDSx}BS=fUBQV*3JUKc5JVZXb-r^C4}Ov zY?}q6BOE6&ZIv3YCC4D8r{74R+eTc{vMKnNN7pi>N$!+X$Tf}}v+jZOD zAc5Zc;Hkv+>iWIs*xaBe`1rv-qB7jrxy|xHT~iwrEz0Lm9Mj&ZLS-p139JC0=Qv*k z#bC-#8!WW@NNvjqP zRk4lbtiAv^LCXj0G0Bafj&?;;-JiIExRqtv%lPGaAx(qKBKnTrH{p6prBe*Na3{TC zH6q7AFiL2^poDsc)urY6B^Nn_^L0f^dkC8Tu6r)E9N-n@DMa+gns>CUDPwdFUQ7^q z2YWI9^JzD zfqnTSpk=fStubwhQE&D>0=qQ%6Hha$5O# zy~XV%kxI-488>up7{Y`*y}!>=luGI)R!12NH=RjS9AYCyha#J|=-#5F8huT${q>zF zRevy1P0?C#Xn`f#gqdATSqIg^p-Ho*DyTwwhMlCY0+g&E*$FhfABFb!RQPGXkt_(^ z0UH(RlD9z+T4{nKU~xb)yq9G`JHyO6F_P~Vw91+TN+Xafy9lG+5CLUqi&9DUtQmFg zgvp@NZ_-(nq=#u4g$lD`6J|?VDXLbO*}RhO{`yK4Llg004kvP4Nh0DF>hs*QE528Z z*c}DJdFXn7HrYRKwvr(0Q=?AYe$W9sd8P^uppC_plNh?g`77zAsM8WD)D_C1;+(tSY&@>K3Do<4oYhi0(PTLf<#9p#3@Byn?bq}0xBvY{#oo3;#VGK@&f@tc_-qmZMQrm>Nf+sjO{GAyMR;j%?agI z?Ni=kY0OQ$U)Wv83RqIUR!UXyNd_b8OH;9s?Q7vfn);d{nW`oZm~i_HmwxTYRon9~ zZd)F%?;rd*K=Be9{)n2n-iOk{QFTgZl;e)s@8%yUDnvZ+$zo|EX~@r$**}dIg;^bpwh<` z{{28;qthJcs&r1XEDT<+za@`%Oh$)Hj~IY_aqWnnCP?!xrPZER;H-oU$Hx+=aU*W-;_e#EF!-US zANR_tM1SOPwt*~dlC@B*zN#f^I)xOl8KkE+eQpUrsw*ZMTf1j z!*EtDp#<9Bj+76(CVM8T1Ek>E6T`L#&zq6gGOTn_|$f07NxQh>y~VN zMW|!`;~UjEoagB^z*c~}Af%j?KSXH)j$bk7a$jBg5VdooP^9e~Dt2dsNlm?H--{D zat`U>iW({7TW2{G7bgO^t2pKLd%%Hgxdk(Ceg_n*D=pa5g93aNYrdEeE4#z9b!kCq z&1--es+E__Q&pS!4YAA`UFSH@e$OyjPTnohD;Z_*;OlK0=rC!HA9#<quM>7J?m0^-{4wZMF0x}G)l-qfx- zUSc=UQTeN*4mnpg%sf;M`6g8X*aRbHQp(l{P8^>eUJPR?M0zX+SThH;3({M!sIAGZ z-dmr@W?k{Q+4bmtSMjx3r`{OAvIwa4SJ26G-||;IN)H-%cjJZ^#XljB24ExTFx~+M zsj%qdLnLMb_gpG06_=}%xj_v+)!^RiQ6Vdn^%R(3k2|GaE0D(V*)qnu+;>%xh&n|CCaZKHtHtwg2V>)Zqt1j zEW?8}vCU8lw0nA_t2uJ|Q;aqT_>%X1{x7mos2=K9;a>p# z2PXdop#N@rI7a)gk&XWV=wHg=@4Dz<=wxX7Ki;?hV0y^W(2m~}LGj!9jIzYrz(69` z1{6(1tH@W=b=2`Qy{I%Mqf_4`0p*BXn8tVHS+9=7Y)h{*l`@5xnBzEpFlQWoo6rv=j&F;&bwzJdB zRkfMPsP&{n3qrRcM4ha@+d%$92iI=Is9xR2R2pU|PHLhmnD-;EV8BOaFYyCT-}|d_ zY6`}0`4#FxyP?{EH~8M6a2`QaPd+jPGcvDp!m1}Jb-cklo^cx@d3trL;w<<{>CW|D zq)9uOa&pk&^}v>PY2{mMu0w9!+73(Aa^;q}!656e&i6^HZ(j;7skzOf^0T-R7`Hw= z#(k`22NIhDHe7Epq~})GV!HGW@&W1ruLYq-p^&hUdL@Sw77SrqGmimdWB0)R>AJ0` zFuli%m3FdX#U9`b(8+_QY|&mGAw2)=?ngptB~-?GZQL7QC_^Mrsas9waiU#Gv%Sn| zA9(^x>fSMm1HKWzAdBJ3Z`K0wJdquylDK`;=#r3?cC*I z+~wgsi?90k@8hQVqxG}%rgamhmY*xYuHLU)-|zLK1uVlyH!eJMrd3NyC(;(3be6Q^ zboC;!c*9?q<}Dc3#Hd`+ZmhMVYWT}X#rG80Z>PjLme8NsDqjWrR^G`K)kk2mf#Yxb zJp6a4AZubfGeJ|iz;`y(#9Zq4aS zuc}nlXl({9Tz_ea}%VnhPv_T z*R1QM0IS3&ATvJ6iEDyDHqq!v3oF{-_-+jeY8_}Fkw*y31HwpCl5~V2)c`uxeU}{3 z!M{s!y_?5IwAj1z^ixc?&-4e7OV;K073S3Z==m?g0S25cLmmjN0WHmOTjSEc+I8^= zG=_`nvNMkP$ahwxaPR0k`%Zn@oN`*jK!imZWpY`xhH?1z5iBKVRVdk=m9n$yEjmT{ zN!=g>*rm7}!D&7&ne31^SRmLf<8FIxhn)BJJka~i2);O^Mj!_G!tS`H1CAxRgX}@* z4xn-lXQOVnHxA(C8D9fe$tGiyd=BtsTUhdjP7>Zr&%BJ_Kbvp~vj>k9wn+Hy-f2hX z1wsh;al7ktuBr|=6jaHN>zGo>RE8SX|s4KCOw+Ep0YkeetqLY~A-&k3o z|FpK66jyAgROaXGN`n`wT@nA#+)HrdIRiz~wV07yK_y)uoaU^*Oct^teHck+g0OSPlC1)%36kEiS8$cjG zB8~<}%Aa8w6DxcGW;I=fj`?AgC|_+Zr%$2znh=lYXn2xGh1j$TT*et7KPjg9{S3kV${Ldnq6RR{H#j)SdjhL<=b zL?v=mBy}&QIGiteW~$f&kEix47vP<;a_~j2?tSg&KziJ5{A9B={mQ*+P{`vku{h`N z&E`slPptW^Ise^?fBZ#&Khy?m-`sRPZvYOhXp7z|5VR?@QXR`{@BB8gOx^O4=U9Ls z`W#~C*rB6lq1zhuk|{ci8D`N;5RacnDR=22en9O#c7qhYyIUSE}RzDb9FelE1K>Bn_`t@;jJHn>+nZ}o^<<7g3vtR@=HCpe6?U|5$&lknyn^~ z;82tHUU-ZJ=%8<7L=Ww!u$)Wy9hvzYA{p&tQ90sOuPG#i+*8I27voOFDjQ&ecE9tj zy_N{pp|@*RJ^d#Oe7XgdFq(2l1MV9|Wxp^zPxs#^DRru3<%G|v>Ie+i>i1LPd3F*z{M0*;9yN`EiOm=b3 z@^su{ZG^?#%DG$zY0iKpK)}h*-#Gvr!v3aQ)a7q#<3H&CuespgJpd#4|Fyi*|C7+J zZ)|U3>iqX>Yis{Mu|EGH_aH}8R(Xp9f%o4JaFYRA-5 zJ)X7i%q8e*>D zD8Oq6UxE)CwwVt9+Wj588a{e?SftL#j!i^4%VTme72e3ijZwhK`h?#K-TemGM?+bq zCu@`fI~PamJE8h(uvNf`u?wjc8yOj5meEY=N#@L}>licq$m-%MsUpc5cBh5NvS@X5 z+FV*qxD`6>TQp4b9vZBTuzpnfDN}`VqFW zPZ#zCIaQ8?(kNx&jaa|pY7c_1bG27qR+RNN7V2r)<>jOt`6fnwEjbPp>?kj!f+KnW zoQMbVojc6!b(0>xcAXsB5r>6_}#{E42R8G#& zcVFl3X4l-qQ!@dQ8<3b0U5i=p>ctDV_=Gm=AzNf1ugq;lQD)=CRoC?z5^h=6#3nx* zPQmU#k@X*K=9VrHxPBK6A36B1n-74^>T6zX)C2i0IGmViA+K(Gc6D<|c?LAcG6a{U zK58mEVNS&x_XNG|UXJ)|yVpTvt--Q*fLaZJ=Ho3^57z zE)QB0vnsGC#J>PV*4B+jG;Rt=eUD6a-zgUH(#Q(J@y$BEb}tjS>1bO zAz#^xr1`g6-EAwM@B$lgV>L%sM_tg7k ze(03`f_+lASNX#f+R-@LU16-hfqrbQ*Z3)oo2&gL&C*?qrbo-ZQin99fd-G`)Ysv8 zWir|?w3c1TS%!Hspncmv9Q9{8(~&w zFmNjzW5HFq-dAV6sY6ySz0>pfEl22h8b>RbX#29A3rl~=U<3gj0YhxdJoEs)g)&~TuZwLP%5#)aW4z_fHA^ZxdH;P8Zir=mrLt%#dB92SlS>5e7YnJYvd z*0B1VfTZH^ZMb)<6g%hKaqjuYkaCSaWP>>}PFGN7_fp=`*f%pyD7n+Qrx6#0?LW-U zz<7}Y{tZx5@<@@%?ToO7+coEt!$1F^ILm^OINo0r{|Br8h2sCd-J8P#04V==WChMH z_D=sC_cL{Jvj3kO<^N%|k5$vQ|9fr4uhnljBd}G8eDZfxZ~L9_YVlgYPD1fnSThF2 z`PvFiB9$bmtMboFj<8bH6-)oap2AUw-|0q_5%mhhfwx{2PgG^8>V^=GZ0XxfVa5WW zX~Be4?dfi2W}kZOu|LwakFo8fxvT_+E<3bX%P&msrnYlFBUcTP*tu>3l>`6 zL(Ii)G@p)OQi<-4eBzE1yh2};#4G5fRn@>cmB_R%v;roA0F#ELN)gMd<+xd&^Yq^y zaP~qYOnS+bu|(L^9ZH>utx8O!Tp(bBG$)TrsASfaLexcSD~5qiD;b>YR;PtECxTuG zc4yjaGgD)~Gn83~`{zH=G}#{3EbQxE%#Vz21wyZWg_nr%Y8Q#n(xiq&_9%Kmi)u0n~URJmPYy*7z zUlClsP>dIbV-nh19To{wS8M?MvJ`YboIj8nMZ4~oapuj5V+z_$0K`oE4ufy?84hYg z;!8w9_t$Z4Jkf3DID{K{TPX$XpmbQY2MKDB3-mZ<7{bJkrp-MQVnDOM9leHgbrbWW zfe7qcH|)Q-cEn)>taIq9k`U>akW-mIoylpC~D27N}kGSEn^VGK4|y zF{ptEkx#} zoz$rf7_!AR>~=0gJzw)?%;8Mvv7jr-d9xZLl5cSbU?bMg85!rhNu9up_} z6@Ji^p673ld%KsqDv-^f$a)*o_T9%g__RfvxCmE)%dWjh zq{RUaHG@~d#+1)+h2JO6K0tQMwzM%_aky5$Q6) zT+P?6!aZ4gl>S(Jl9sJIw)+~}3w7rls!IBJV*k*GRnw3CSm$;t(#E1V{Ls3(2x#|S zPa2fzN-AAr7K{_@6kgZz%`Y%Y<2R%$rkoi3N&^2zYt(YMk&sD5}*<`)eHtf1hmHaAFp5)>irgVSpIN=mLQZc7l^PPWmFzZ*S1 z2EX$J`TYGl3OfCIOf(%2bY{hyXjfzzjlF7fg!fTz2&AidLWm`@+h=a~5eUE8=;-}m zk`|=nS`t`{#s7`vSh^6StfAx+)-gOtqym_dk48GdJ0p$-+QK&$!k!Ub^6mBprfsIR z=q}l%?);grP7cCCoc3}&@gAqG8zjR}919)ehPY7E*BVgTNN-d+G7bVG91cyf?CIEB zOuwy$44>bCcKOk0_9n+Va!6Zn@up>VtC4CJ!EAqMq-2s`Px)b$)p>(PZ$RgBcNNdb zoIt~_O9|ejIjJ7(MF{}%vDygeznvxo%e<%bEHpE@SCWk!bea0HAbu*Z8(?^u0P2k_ zD$H`YDvdF5VE0NHRibKPZ9nvk96?wCzI5|f3-OqPax3FsL9D9BIf9BsI4wvQW82pBOlME0=c9EC4` z-{n*?cTOKt$HB+x8)^TMrU)pjkB6d#_~TQBP0<=dR#UVo4l39m`}nx4H+Rvm+y-zN zWUp8)z#d^k!wFS^iTd~3%%^rC(18PIkOiyTmvRFTUtS8T7R0d~R1Z!#Rb9WjK9bck!!VgwFA045Dn`IE&?F-_Uf?sZ83c^)} z@1aa*?nLqVx5QaM2hL87mNk z$Bit7R}=W}Il8onO^Pyn4FbLJ`oRPy%62_<%-?U^ZAhuOl#ZQ%rFYDT4B&aALbkx; zFHT5VSxndwdTxmp^d&2a%GD)u>rRaH{Tl(WkT!PdB? zk-PdkqnUd1`n`hp=gJBuUCPle$lw_j%OI=qC1pg_(Heq)z53HV6)%=)@Qe3SR`2eu zQpTS`zeJVS=_Sk03MBGC1}9LHT=s-wioKVYavEP~)T9FS4OXRT(Wy)kuqY{?3a>w}Q#5*9 z=y(xvqf=g7kJnSJn&nTK9&>p=+gFp(hex3mRj_U|Lo%1C6G^JgR4sJgCg6i549*&8 zu{DQWGs~!7-HUhckGa15)!5p67qr|JoT|a*Cvf{%nHFK*Uv)t@>s=VIt$wqRIfJjR z_(X^xsrzR{U#dAP#!4n9IB;|WuGQw2-$D*UImfraqY?AL3S{)q;*&znrZsm-nYhf! zvX3-!oq9R|_kdDnnkCo%Dbu)*isojUUeMHtwe4}!zY2WMpkYGuegT4f&TTE@k)e)M z&At?t6)tI9>Y7DShsincI+o~f|D0cF=TBn~E1B}2q^!;M@mSl<`;z*IDd9iS?YDq-3J^!UQZ`_AmRcaNFE+U;hmazz!Fw;z|Pqs*ZtS75K0e<`(a{^p(&TvKu-K+FBQ9y-&f@ zaA_i`atBmLo?S<~HYxvd(`N*PmB!7{gzh|8(BB4$ab9y&#i2Mr-^Scpo%pX`Q_>w} zkT!g!sLC&NUFSjCJj&~tflmR{0ur~d`7vyQ*!8Ob+5jl^(dL0oT@6f%`5}DAHUrMh z-}qc%hiq^DMG?Tz9%YN`1H!}>bb>Y9g&q*>%Z=GyM{hoDS(-$ESn-La4jNTC?7|?Ww6=Tp6pfO@pB0yk9sX!26M*W2_z$7vJ z5e{KLfL91Hlz|4ujA^EgGFn^q=E;8Zq46^E?IKaDf!#)|d?xtR2i0x{`GxxrMw@;L zT(bEm)csGb|F8c768|_@iT@6a=A>(6YxsX4T}u9c5^?B!K|d1Mxf-@yI2)NV$%iFO zcruN&rEXec5g;YYB>bfOQqpyI9q9p(lCo_M$A{2(>26NjPcJScwKi?8p7+m&cYhvM z@rO;dUsl#P3=40q=(}4?Xjx^5-;$8K9V&d4mpj@zkX~gWHKBc%WZAi%ijj(|lln#j zy_LHalGkDdvF_hZ#L%&{sRE^bD7q=?dsGWr0?UI~)sznwr=LUVH{lCbqBYQmm*I!2 zY4DE(Am5#L*Sh0m4CQ2_To865RIs*Tqn{+Ldf>W|G~tWki$d-dv6s2J;7IM3Av=F# zsk#HVK0DUc%n;r!EHGAPF+*QYboBD}K49d^ZZh}#4?*=T%OLCtCOFuSVs_WhY zi37!=;|4?&8ff;Vdg;y4-H!(f;7EC`t~~($UKbAWDOx4?4|;Y? z`j3IwbjYS#q`dI}k?!)OxVfmyE#bmjW(WgHD4joJ#@hI*Qd{!vX8AH$;rY?Xe z^fKTD2Q=ZS3XVUdG18D&CV)GFRx2`2CaDxGW?S5;i3@M6mMoA?^xsR}$(c6aA2=zC zbD;e`+PG?x04ldaeUhZmk@%-)74qDt;C=x%z|rU}@H?CrI5ps|s#n;L-FRpY*a=2z z(``FfEH#_Z+Rp=`x2bvYMa%$^)HNeT^WfBVBBAQXq(uKr__21dTt?lMk!p+xoxvpockob*@_us*hoSE%#2lut9H#xgaWbM z1-{HNMoxI4-)p12qB~DqGMy|(Xj?CtD|At!$1Fg?!nBYNLbTu`2;fIS0J=6zZ_x}I zgjx@|`S4Bz#=5YEvd>KYm0!UMd0~Qi=Q@XlAFfEN$X8U3Oag|0H-^FVPH;mdxE{Ax zI;lOMKSrXYV)9cvZtg~E$)#qp0H<}J(U>0ql6pf!V`8VE(AI15QJx+{JrvX+87g5W z-0ukJjQft3mn**D=2V{TAhW!G4eOrad}c*Kg$$#n@&=52I`jOT|qeKzW!rf+J+wMcax|kQS1w(^q`SikY)%@Q<2KPBcM*FZ(Fk za(~Dn9Uy{L5t-PaVaYkIdi%-p&WBn#*ma>8vm?#65#5jLg6P+IPYf8jT1S|R)T1Go z>10zrGJ+&6N8$RUiG++4f~oKmyPMc6+oRTAjd)I9iULg(5~!gr-DNVha~}1Z)+&I= zw7alH$dIR|8r~D667vC}SPD{;I`Z8w$h@ZlGg&FryC&at)P=NZ)pN(14jW|7jj+q+ z(L~X$isiNmPrGUq_1ul4>N9v^k!%UPo)@%xP2guIVlme47^S@DCLR-%nc~M9y+t*> z4faI39#DGdn0H@RwAB-w5RSru=&uGK7dc*GamFB$1ZB|Ff+Au98VF$sp4`-?qK?xy z%DV6reuogsKp-Rn$rs|_N;WOl4hM^+a0}VcxBwfzmS^UXCgM3^*>|qoE3q05MwwJe zqF){B+N%^N=BuO2XcMMAXXaJF*D@PE>PNYdXjwYfV`ForrutF};}px9mLy59u@Xw$ zN?Mv6R>6;Y0+Gu_eh<0oE5z=;CFO<@or6IYusD!wZFu#6sIy20sV$){^z6T2?GSWHk&^`-#Gr8l&aR)CUzZ!@J=8>Rt!dQd7?C{GEuugnL%Ke^aWWucZ}2!YnSl;aqgwC(Do|n z$26+W*Y^+2OAHwe>mTy6r%F`IcTMiW+=apl=^s@cZ!h;mO%xLfZ*#<~6mEQ8ty_0&^e zO^={H`-;9u@(_V;Jjhfp$E05=*`$80F=kqKp!5dq&CVkHlneB=dEO27ITt@`NR&7K zIV*AxN0wbuYd0FqO-hzc9Je%`w+XF_eZ~93g4h>wF8XF!*9K15KBmm2hAubMrkxE7dR~IXGURQ=xXZV^vPkvl5f~cj z^_A^bh#0nTo>8jaNm&N{Mp*+d%D9Dr3%O}w9kpMtXiObj;JAB^-^An{32T<*-KmHG zA0>oBh&rOjC%o}kdd9a+vK+IQmG*3MmGAm0ka7L+$q_$OW~IpFg1b)JwM8NIwkXpR zKAN-JdT4mNbDD+o_;9S6{byMEUyo774F640gC4r3#x}+d|JVp4U41({ zV;dt~11npD|AWEmTEp6QQxxgP>NkRCd!MSE2(?qf|04q^CQB=NqdJZ%iAy2s)A@{4Dt18_?6~IgR-HlrQ7@I4st1#m4Y=PGg4Etn(<914axWmN4vcX7(slh*CL0 zm-BMsT~^>f6x_h@QGqlvDKkprHmh3dJcV4B9G#G8RDE)Q>WYxj2Fe#Onb`4A?iGw; zzb-I-m&p_;4t#D6zcg+R2sl@tgm&d1ZwgiW2NG!X3Xk11HQ-X-E_jvAMr%1IdP&7XcYGcim4|+iC`sJfDSx{961!@D*E27=E~=l z$(EthV7y7{h$;Zoup&1o{axXfKhFoIL@DX6fg(I2o}nB4zAw;&_+sAV@`%ON$VZKu zDV5s8j+7(Z#4F0RVzc~V$PE6Hjww4rv>jkO;1UG~xfLBJ=XF6rMVtVk!XA>362fe0 zjm0w4PR290L0YJ8oVM>Vu%n0oO*ylIP)nzz2~+_1RTHjKg|1<6rq@6(SUS)sL3^F? ztA$~2VZqo>BSF&4wO{TRM=d3pBSSFRU0{k}m;8k=%W@k|R8*D}E;m0kQ5x*P&In6$ zNKez_Ic75>Uz%PkKa?qvBQzTyjJN$got$J6@6$@1P%bU~1gFt64Zfo?s`V=h1JD0E zpG}OP~z|b!bD2P}pESdp?Ezl)nT?6PFT830DEX38? zvm|b~W!lq4#&QNdR0INL8$z$Ht_V?@u2Z=-fu2RxQl!hl6Pyt1(i5jP%a3OGZoGZA zLeB41$h-eYMc!MWEa;go^pgWIW(O^WrUiF?07jJ>kVGY#1~2c|dVZiJ%%3AeX+h-2 z%Z7Tm1m+&i12Qxz#rs$lZY%{jriMvupGYwmZ3e37omd<|QCrvJ z=BKbzky!rob3Uiq$K&>UqjzRGfcNAj8u{Cdq|nRSXF*lcYGH!y9UQvp|bIKu+UeFt?vi zJk{4dMyO0{Rcny?+{^V84*P~LME10$^fWn|pwz&e;-l!aMAswsspd?(?%I=Dc6HyJ z<<){+Wx5z_M*wdtX=1a};WXxlfP3Z-O8g%Wf}@>An)vw#)T4+hwVjXsLAdCw&RAEH zH87%ij0HG+h%kS3=T&Zcl@UKHarg>%#h{GqjMLDB1#h&U#8X0FFdjDi%k)w_aGxD) zd+X8{Pg7fZLa1t?xp`!kmYE;n2H8tehs(hu!b_QQf&7=q4<&LtTmBotQJmm`KK7ja zLEq#8wHH`E(*P{FMuMP4k=_($8VJOm0--rboD7NgZyqjCE$iR$yqN|0z7&L%*QoQe zxTpXQ^_h2;@WC9W&I?i^>H^!-FRK`EVGAoSia)YTluFdq7~y)EGmTgk){3QzOw-Ut zFhj3bSdFB4`&svdSWY^R--ZB_cNFuKH#xHoI<9?X$H&+YOqKchHz#YdrOqSQ>>7jb zMp$j_fHGh<-`!~b0&WQ}rqDcfKu?qpGrG~QukbyUjn<)O9wWd;Z%8 zG=+-dfK7iJYh)`Xa4*C6yWk>x+KboCZ6b&J1U-j-r(rO}Y7>@)Yz#YfJNrJoy7^b6 zV2khxS~SGHU;_( zSJB=!19Ur22U&AFJ)YSz2_4r)FQRzM12f>-N#z^in$)IlsUKd#$FLO}Nw1LZ*RlAK z2Z*Y$D93)-pUQrtEZrtO;!x=+rlhM1f*yXdM(T^>pbIC3)0Z=T-Nl`0C8_Sdqg@sWg= zBhVYzFoTI!Nf0@hW?0Tr^VKLr=^{8UiKKAvg|H_cg_P%7nH_cNWX8d=YvVB&*LVHFPDTh7peaEz--BfR zLm@L`3}~UKPEwf}mq96U#%xIsm=N5C|4)+55TGS{sMBE{PYd%WC0WFX4MMbE*&q`4 zAsSTY8ADPBtn7Me7Q-%#N8QpBFz-7%c`k-f!|aMghPu9ZE-*p6wI~ z%BPmJzBAVT=h`+~9|xXNB^IYG=QEl;RW)k3on|V|Pe@=#4ofOdvk`y@->u)Cs?cP% z$p!S4aaey?t3RtP5KH2z4WRW7fJF)P7;WA(w!pM#r=~zAJ~WHcZWB+_JEA<3`_*aQ zbcw_jSOz}mNz*1S{DspqjyAsc@a;#~^YgZ6mk(A=N)r^HgSkQfqpQhX_h$o)Sx z&*v}dHS5V5)ZBM){%qx4d#z*aw!h|`yQW%xf+H+L2B%=}?aEa>=KTt$Y4-hcOy#m4)`|u+{G4m(WNOT;STp-39`kP04j9#LlMQklKHJ?E zxY7%!*n38CZ&D|KT^Zl}-@adrQ`^o*!+OVqP&Md)JX#{W-D{}uXbkqDqTwOLOM|09 zOJY&DUo!@Wp$-iFGMgboL_Xk$liuDCbWWGfx{&TEI+&X6BL=gFn$y5h`%zSXP?E0~ z3!{oltkl02PWMf3`eQW|Aa}k{s*QJ!Y`R%UPd&rV{5a*i*4MJmUJNH|zqmH?O>t1V>A89*#JzV)JyG<{gXNembwW<8t)klXnzCY0aAzN?xSh&5R z0RaAk1^y>W_^*PPw^slF<^K+{^}nKo{|XQOH=E0AZEMF(_JkjtU#P5G3)u%r2gc0w zifQYTiTXs$RkHM~YpZ2#DplyjxTy$Xi#LPl#0lTtn-OS%xFiXw2IEZ4PW4ET`RN89H`uE-FjDlbTJ8LS@qkZS-1vfPDBYR z>>ny@(fhER?!A3s604Egw9!W4I)bMHb~K%dnPJdgn1ZzXInziz&R}XQECI3pv|{uC z_ch(PIyH=o!t884)>wnQu1BNQ$N}ZA^qYZPppNH2y9VDG|rMk3B$7sq+jX4^tEk&J~9E1`0Us&vlibwmdIh=QQy!25W@ETlL}aZU;MGf0{73*`rv4NTK~)vG*k zBK^DG`O(ByU{=!)TrvD5eD6;DJt{PFw9u7d+qqq?(7#ux9+$qV-1u36Q1FHC%bDyM zfTWa=U1N7tgOf0|Vvb9m2*FW@+HUl$=!8@qHT!;3=2UN_l7QjwdYJ+go`mZ3{LNRD zVZ>%=vU|2(23h`q0XA*3N--^wu^#+~Z)0Z2lwiDFa)022r%vphAo;xGn74l&*`-3( z%rM@r1nuxQDAvX7{{Z5ZBv>{858j96&-+IM;gUpLKPPjj!#x*Ibrzc&z&?nWmD1+3}hL9&od4JFixxr4wb9AcYz8g1YVG^dgBi|0gX56sg8C<1a|B)e~kc^c_Y zlB)p5R73jB-ML?R%z)lU_Rr!ky+^;VXL#yebTfWXE=gE6`R+X155ru5JY6c+!Y2YW z#v##-#5cw;MzmVS8Fs&p6kB>{Q1kE2vzQoS282sg1~C0IVFuXFGWMT+ik=S>y52Iw z58>7~*{$Zi$QnZbc?ZLb$L;-TIsBKbf}<9rBdx-yWw6L}4!I*4Pp`EQ z{f%yP=;fx?&;3Kpv|=PanH+*KV}}yF>lz*6dOT*lx@`t<{F_E*#eM%1*H$@;d-R|$Yp1Ou34}|7GwCcSOLufIu@7JS(s&&ba-6JD#-gQ^a*ao? zz9>FDv1UEMDM^BUZzHNYI#eO?Fv=kLf^k~%Z?W-k zVEY&o(!{sWgBThky%+(s2L#E0@$@AKdPLpaPD=Z>c&WTEc}ufNar@EE;#9!~H)Z0v zSz~=jU_;RiM{3A1gcRW%C{=7;E94bgpyep^AwW1Vk|<4Zg4}xgC~yJ+2r)$!reg&{ zQ;D-89S8_qyr1DoZ;y*wFW?o$Cs9b4cp-=-TNvZ~qBl$sP6T~XgdN%hfe#N5z_yb8w<7g(MHh)V6e>jN`H!VnaNs0)4{Xr@_(?5pjF1&V<2hBUI$ z92qVj3>XVkbfRM4Dq9%EgByB!kB}!Yw+A%<#Mu=*5=z#}_dJ2TeBfPWd(>RFwkVN= zeHScJx^~YDRi`x*Zf}Zj(fsOUH?{kh+OvKHaB0a1Uududs}no91wsW8h_?dB;B{5fO4k})yY?Z$)6m>6#(<&n`1_u<{g)Rj)ivar%7Z!fwH328F2x8Cb%BS@pQ_@-|M<`FH13mj zKXT~N%$N1QR2j0dlfEHpw^({y8vEC}Ar7j8z_7rv(bN|Q6 zCf5E969h5C6C+19gHgk}1UsSwe+6e5%`3ccL@Oe+3!-FHilabXK`nm{Owy|d((}%? zX||FXBtL(Bmz-iWz$$$|8@iz-atW!CsZNv+!kO!>?O2fFnSlSW^4A_i?9&+cD&TdBOfA4w3aOSb3$^&oXF|vBj25duE^EUf_0XEr(|gb!1{6XG z#xR;ZToj_<%uf75o_YRP<#;A#cH>e4A=n?2oj@3H+;UT`!1@$&%G39t>MTC40D~El z^4QC{MBOajPPWg(+a;Y7Vy`2*Tk(1CXFCGySOe;s2QuM5)=Buv#=WfyK6>#f%52&` zapXJVw=Wa$(g(ElnKH@vYC0{Pk1ICvzDZ8o%G&N%xWhq>!Jnxn?w_ms<&_Yt!;HijI%4<%D?U=!o8pm30hGG;(k< zgU9AbUqcyHS*J&+49|MbxX$x*{H5{dPTd0K2=7^?;MjeRVnTZ`0tG%$NZ^bO7)}9? zb|sM9-(*%-n-@*a*}N0rh+h%U7}1_Fz`glPgJ<2g?bt?~SCb}1)UPCfq*e9`hn~uu zQgx8w+kONrt09?+pEn7x%(Z#D^L3cAOOrEX-eI@UC`*d(Sl7x;hG^jLrt;;NX6@HKcRI zosPS$f~<1G7`SmgCW7EtYC!UtHR3+{erL>z3<#=T)O+cgZ_(Jc1`a}C1>zpCe?nCI zcgGDP4vvzg-{T)k#qTSX{8k&LEAr50ZF{c=os@_QEQ{ZM8LN7%)xcYE_eHB%vr>U0oRI> z2a%}}OLU)sCKoutATND$-4L$lYFZ#W!8-N?(6LSb9KuosflyL{fyjRY>8VpAgCLF& zw`21g^nk$PneqbtND4T*zFw3Wo&IDuK;*yI$U*-b|Eh+R2@i{V_)Z_;}%5jhrE(5Z=$}LQv%Vq4zFWHMy z5zFELB#q2KdkVPiQESt^dR_IJprQ#ohlSp&s#>BbNcB$`qWtyE1>4+M+1}RJ!HnC_ z!+Z2{5?8uZAu!RTt!y28fzjt(EA>cgsSbXk-qZuMqK@K#c&O|+`3&h6U4l0Op#%BE z?eYEcynboj&l7EdGLP@m_dVKCl71@r?#Ugq>AmYh%H!5J!sNK9&6|^ zr&|1+U%sRi*PZ6ZHx9^G`fFpq*)mY436;;8*spljR6KfX7Y!_j&M*TR5HN z6-rfswkx6AWgBl~chjPE*eu6eDBbp5A?B(ze3Y@X-H#L*JCI?8rT1_H=Aio&<+Q-| z5ifeHdC5<{xAxfqh}98SZDi_0&N$;-V=-{p*hWy!R9o0u>c%vyb zQjO&t#Vf(5E2^f&>Qoxm#4UO@a-lh1X6%o?RFGGwX+E~KTi)Q9&T$G{V`JH-DS@Kb zvOSFKM1*$G)t3~PxtaFxuZQa z&EpDq?Kx6FLLQEI%e{0#ic)8a8!{;mq|XkVu%g-On6BW!&VS|xD`wSA*P+HgU0kIu zCRA>$*Cq9l)HI(baFdHrbV>qQHu|uTHJzfNlyBH<7$`F*I42aTXzTn8l%YBxj8T9a zFNM~QJ2o%$JCTI%H!lMV;R@F_sFLU!Zy7(q(!HC>buxBpj|lKrXT+0{6&<7Ygy+h9 za6Hj0V=K|Lc^+`uHv3yQ`(JHb?wYe@8)?06eOBcneym42pBiO8Ff|jXZC5_|UrwT> zPU>Tl8Yj-6Fin%KA|XxnQ+j!`G)k&yu@bgN=r-#SZBwCK%J-sO7XSK`_;77YhITMJ zYV|Mj)O6KbsF)|Rh8WC~Mr$vu{paJRDN*Rc@k(R7WaSEJ*cqfSc@0<^DYB?0*Kn4R znMl>4=!`7FRLcgLbD`WM5?CjN)Jak=g>>tj0HI@|9--z?uu2lf_FxxF%i&}ie^O3p zhD04ytWylPmr#YZg8qmCtC%8;3cr~=s9&v-M~~snmp} zoa|jXx2A82%-zlPAwhb_p$e|wv#_pnTdmgU`k53?%Bmb%f98J$|D0g04aA8Hv3G^3VgCrNtu z!7kxmLSc0RRN0>G@AYb>4F@E}jSV!0V8Lb0rA|mNN>ckt#|&deT_Sbbr zzBSu_v9yZwtIJ7xHmq6zLnW!M9B|c?o4e8P$}F1E7%0i}+juQCZK$&^ElxW)0jf#; zQcCM-;pQkY51rqjj+2tMVE;OV0z_^`1IB74+N^X#x&0Ai>i*}6>AYiP>MywKpai(Z z{dIa;xVW?mEFOMJ!oFzrDg&GVX7P_Mvu0x~0^~6didK(GHyoPhn z`q%~W9h3dNogd_YeNMcrNyLSId*v`p!f+(X`cQW18_*px5Opk(s$i|1KtQZcBuJOILAoJ2A)YgO8+~?Bz>k)Y{}49=*bkdepffNT53j1Jn?P>dS~v7=YpRf!(`q!k zT?3HI)Sr_cQvmm4UylRHqW_Zf7<0a%rc0gQGe{Kru7AlS2C!o)`plHZM1YkVg?Own zk&g^T2lu?~G)ECV^7Y(Yf?lwzexqSQ3R-wZeLuBzg5JRyDMGA+~ftF^pRuYxb>9l32{rZ~Ukr8{9vsI;Vc;o&nV& zY{j^;Zvim-G$z_eCJWb(jdW&`}3_Q#R_Z!B=~A zDIzCbp$I=z506OB&d@x}m4XETJ!99z9pm7oJB|px#Z-9^0=!+AxX{ox$PHy}&!!(E z2lQ}3T`IRvJ!kSOtb9$Y|0t#ixL-vqcMXdv@#<_T@?{7Ua zc}5kOLKQ`wO=N`e?m>lj^LKdlOtea~J?}^|ZsNOS>o~km@ol6?qg7qic>I^)P+CU^ z$S4F%S7IzXG)JQ>Y9*FJ^I#dX3zg`!1q*zMUBMry7NE;Y91}~xZwoLx#P3RlI$+=q z4sT$RV~@#muV*YTXYkY-AB%~RNal*@7fvT-UKW@UA*I*2w2sgTI_wqRrRca57~_4U z6dRSeeYkP71$!u}tegoFtYk}eVL_VhvO?v0y0Xghc5oIJc63VI+YR-h4>%<%kB5*G z6IZn}z0S$N3!?PnT@w{}+KyV5=6apSSyp_Zb_S-&CwwTX0wa7j#(=OpBn&wOvhb1e zjj{Dx6&Ic+4^(TY=@iu^Ac&64Q3#wZ?!%SA+Af&A8^`6Uym{xNvYKcV2PIXM;jAV0 zs!Q@H&U6=NipwgYc}1OawBwt>w1jwiSX~>v;MmHxb=>`FqJ&@Y|15)8w~{|BF#!Pn zv-0_0FM|k7{+m2b{(s9LL(Bh03WYu9rt`H|hY6^;-6SKD65LYUQigkw$OW~M1Lg&Vb9zp6g z4x~fXU%(vaP8Sd$GaQgB#%Rh7yDowaI*PQI0=mWLOXTA(&2&rm*Wm#W;KG&Wnv{{}wHh>V-X-vN@|!_yXjhk}yU zC-i->hszKj5$RdYAV9}o0(Athp#UletZ&{jZ>jSgsGbhSQx-x10OtFJUK-1j!a&XY zTmJs%LJvgNQ6b5F!{-rgF1P8#?+x(wEIWOwUOJ(SfDBJe@6T9+Ps#AuS^3nQ8Buye zBzHkLV*-g<-Gng0bc!AdGb`C$x=AokM=aCY9o^c3)Xsl8$k7W9k5TInDSzTBM z0_9#@;xZ$CTtMEG<2@YlS99~y zW0RxC-!UX^s$jl7cGMuWP>>p-Icw_?V>GE4ojxNdr~ZK?g~oIm28_7g5WECX9{?VS z=DGl&?YPc}Reo@M4HySFQR;_?S_E>ClpU0p;eft4q3Cr;^OVUU`DS5;wK=ZpoGd*E zfT}w1A)z!VCLl5lS%M8e*kKj0KVU{xb97D3T=>s^y%cH?%7F7xP!U>6h*BtiLusPY z0j@%S>T;}l0|4#pbd>Xe5REy?Fw6W|ll}S-sB(Eg(2&y&aX?1p#MAM*(5}d1($L$} zwlVdr6vPrGD1eX2SvM4ikj~qbk^8iy-OyxEgf;9?k#Uxc(1w@MNyQxv2XnE2#~HAO z*8HNf1(jcPB%I#gq)8ODS^5b${QN!(W@P0Ld^uJ|L zYauTjaEMMiOA~JM4>H13)3&$_C&ChhRD+wybO`H&(02w{PiB&KWRKwq!B8+jnmw+J zYFPQjvyilUjxVcowf|}-R(4V%4UaAyyVqAuL8-w^t!+CuEl1Riy;5xw8 z2IbN-AL=88j5(p8feYr_$4WK+$ldQXeix@iM*PAg8@&E{!$BW<7zw?hA=Rj_sRG1E zh}9`nwn!a07Q{L)DicOF*c&cwdfWFsF!)~EDvVQYGaKZ z%29;;3Pp1v6zEK%xNST;a(`0NPxyqxtWU&FxravcJM_t6((1d^PZDeoWBX zaKeqqVTNPRjS!78QIMP*e`+N1q_GjlG-f5wIL4PsnEsSQAfpu{R}AeLMZ~#CLv%X@ zSmwbK>lTgMsPi*f)d?unO-dw2BNJa^xr=Auai2ae7sb~#5GE`IzXqCFfKIaWV;h95ZeFc=rfK|(gig{pe~Loy=z#u{ zTfz(p3RdphMN zZ{^p6b;^>0a(3d1;W&kLoGWVKAhWjH=EM<#1>^3}xgoX(-RAq&^BirjC$(**+bg)Z zR#l`T$dsPtikfREB$5}$`PJ!mbH-h~C89iU^^k44btMaaexWObG(#*I5i@|8mAh(U zti(hX^e&Z(pY}oPgt!W=|8NhQtK(2*XMa-lgm?;=z^04V4bFM&*345(MIW!L4NwED z0s#=(8Dycdr-#KbX05Leo;%`Gj3yXpx)8&6$b=ir24NAl?vP>|19FUt4s~cPks>;Q zu^z(KeTqP`@D2Cp)R}BArANk84_wO{3YP{mRFGPZwt(;FH6eC)3-|YRS@rj=kSW@= z5MM&hw=*zS-o9lfw6^1@~-wO6gVjuA9)tm*%ix&7v<0SKHUu0 zg`ePIH#LxM6}l^d?%UtETgdkM{GoxR^f^Lb3?-7=e03epq7oRFWq1VjgaDpae-7m# zf|jrg3g`9Aj6MfbI_4EB(7qDuFI6GnXX>Q--HM?8;3&>b3OilCL=XOFuFE?>hv? z?Pg^BwPQ1chOtlZTvA(MLhvr2XOGQ3AC({%bkW`E1BS;+y@b(`d6&IHQDn+d#@Nhw zYeS2c!2YFgErK!kE7TaE<8UqHTDsGEHH0m82st%VsT}_^eM?IIpryVP9!qkpA=h0E z!LvDQYrPQ=*wfGuYGA?-InGRyq4B4;c)`Qd{{8i)o*z?Xg3Z{{b1>Bz*g0xqOvGlq z&$uPq;Dt{v41lUD2t9wR&; zrT$0xveQ^5@lAyiqMWTZypOR4<>nbIAU3+m+TD}SL0?|WBu_QD9zVpIZ6)`)J{PFw zNAYZ|8dg@xORTUZK&KC@>*=|@Dc9O*FwBDnE~W{VVXLkn(+QW%8XCT1mL1nt5EL75 zS(65QbW1nY&1A~s3{CO2kkekampgaM4~>5UU+Hk0w3yOci#-%u$G}R@mXGzY3Kt-n z!=8%7lixP{)+0K9Kc`yCD(20{s;o9iij&dXAm7%IuqH9Qh2Dem;-;-EdmGGLIg2%$ zMS9@dcM)5-3b`y7lhV>q>m@tM~(qk`QA zvdyYbt4FwMmM5PNdr1~2><;LKY<7d6i~9vWyoP*DS~<9JK2giTL03->+CQUDJkqen zEKKjv%}KS|2Yyc%wSC6tF0U=m6Dl~5z^as4Y9s(kqo4;p=jb|m%+)T6!m0%D_whn@ z0ZJ;2D%UnpMAU}2qxbeAI?fahP)wf6G@{M*EPBX|-TCstX&}ZHKi$V7?5X=bs6!$|vRlKi{J|P_29dN|%+v~!q z9u%7=YHuXs=t?b>WksfOJgA|uObcO;7OQbpCTCn-%?qviV=Nn~x=m>`v@Y4C)zzvF zfjMqtXCb8NrZMYEYOnqTC}*Hc_(oUSEk@cchbFJM(y`IdEq8m5rWnOF)zx6t9Rz=D z*Ps~KKgQHpUJYrJ>i=}ndeO&BgiHbm1ijvC=jc2og~k6%*nw!EcmZ|QVRdr6WicSmKia)T0feJF2e(ZNDbcJwWSJR z6jkA?P$Br#g0YE2}kbHybqlKg(?v^~KD7g#G>wx-Qu&57d*B1P-$~cUStR{I@3CWO=Y?Xyo zGk;ckI-fn*`qx{WwLEpY@BoFB)c{sTqsTR9Q@u2O!)T1@Ds7<>5;NL*XXCK2fxrDy z?UE(yLi_Sq=e8N(GSv95lE79Eq)yMDwJt<&&Our+?ya0ke`2_*SW^$B=z@eMrOV)VgjX$hQpMDLF{uZm zf6IaCt6`+Phq-hHdYekWqyN%nYa6Hqa^u6A8EuvXI6|KxMD3PYy|LeAzkP6LY1X|3 zWw6=ypn~?QVcOq@_1m@nQY;2w<8`z2wfEgZ_MPYbR3S^YtzFu5TZVDfd0_fI%eY$Z zW{)xBU)R}54_#8nx0kIaZPNM$DF)+7l^&_nn+&6DF;|DVg_8);_VdD)oN4rQd1=_~Pw)J@~2-^@qzr zQ#DMt^-qkT%j(`23SNu!b5kky9sbr;vfx;F*30(MLbRv}%TDpvA2P_S>T7d&2e|DS% z5#nia3^h(4KX$mrpx$VpKpZ9{lNeG<>lw9zfmk>Z?V;BZS0p(PWpMSICG<7Gn*{JS zMps+s*>|?KA$9V@B(Vh|H;Bk-Vw}i=u{Rx8Cfw40>LGlO4yZ2<63jD%!0sM(9mZ}YN@t_ig4vX5I*{UTy)v!e%Ie29Hy9&YKEWdFsU z5sPXGk1$+c6N(mXzafQ@&+U+WJoT*^opR?6L$by>oq8&de}ms zQ!yoWhW`w@NDg1coaNd^eEnAmI+KDTw;T`v;6Eqkzt7VD};J4 zEPfX!|NksX>S#D^inji;0Y&ttm1)o8le0A{4=~CkQ_~b;uHA{va7T|Tm;*|~tq}C< z#Z9%pZ~swm$BYU>F;he|(x*rW=cg^2T|VaM(x>f+dDI4f`e2V9_Vfe+J79lEW><-m zFe>$;(+ywtOC2!h8W*~4pow{)=2bEu2GVutXGfRcD2tv_qA+zJS1N`Vho($E%)C*O+oUjIW!0 zVyO(~M|rLnPxur(&y?UB&hY!60K%yTe;i>7j&zf??e`3_XSOM1vr~Yd>45b0?Ev1X z0PFM^5nV10_E#?11^+?cZweSY&OgHnoJhB&kx?HUe84m@{O}E%Vt$Ak)Zd;EjsC8m&iMJT zzOdNYAPVsY9MqBTKo=&)Hoh|^gaX}jJl*nnClQiL_4)XWGO@$Z=1!<&ONQA~;h})t zst317TDhc_55{;cEI!`$dt*ZVJ$aHRw5UlS^+ zffvy&-xmm+IfPxXE(nJL**^Gk94v|ta%%aly(8Z}Mp1@mL79Gh@%<=YA&6v8C!k3K z3`^J8G|vV9oc0@l-Lom4%3lP6Ac#pmg~q)vRUJXetC-4P0Hs4=gSG&W;zp3ihKiDQ z=BF;Ho1{sKkjpG33TCUvNMTO=^)&f2a+Vb=Ry&F20VNH92NEd>#UCeTm^=K4UM!*M z@c=Vsg?nx)mpgw}?EVJb4W2aOs{Xgy{jd0y5|dtiNb$jJSXiMOlFncHyZwDT4v03p zY{MGlD-4Oy+O^d6uFTjO{uJGlIRtcut{C}} zZw>#MAxU>YoT0diL|$=F&A%v`aF_vxrpPFR4OWv1dQ~6VQ3Pno}dN9*@iWTeXh>Qs^u>@L6)$Hq|s*q z0LBgT!C|czlrbZ9F#03Ca}}8GYaOb2f$vB!8WU2^b8W2rNV4HZH(ePCUfB zhxr=M;fwvV8PMHU*L%X$`pHJgmz57T0^RxPr8}*~}^P69IZ}T^RhBs)Gd_efl z{fkgOkc#W?9#rl^)E|uSIThjwi))=aD;*RDT!0lBcnAGe_rr#{_rpCP#%{>eFeqm@ zyc0ynzW&WhA3fL9;mrPzRe_$ZqS#E-jzkODLM9pZ!6|s9jj%m&&{>ycei**z`%EJm z^S7K6{cDLBHQ1xk6@Su;nti!HEZxt^Y|{&GWHB!^TYEi&%DHr+fs@ZvhxRV!bAO-; zq0iJ%%Q&SB*zOeBNWV?i>tsEn%%k}ys&i4;^VQbZ4ZOS>Sfmd>TrVlPRJgh1bX5%= z0&eI>NHBWuFuIShI@h&JR-lNGN=S2uEwnP<=a@q6xs|tHwn(OiF7UeO1fxgokg1^XmMrf}<>`uu$N*IcxWE*6jHeP7O}Y_oEq?xvkw=c02# zJZlC^0}Rn-VsO6Ux$g}ysu$b|Bx<;TE>dJ2Kl&faU~ zSWp_}t-#eQ;w9BQd(%FsH4V3w8k?-R$8nrtxhP1|TtD*3ol!8Eg>%w4wT$nl>FF^Y zJIYQNP=`;0CkccBMBz~+E(xy4OyFXC`1E{A5o~d5aZT@cOsM9?#R+qeOs(a5wLK1g z;z&q4xgA^f?QL&bRzjZ|%K};S?|~q8)Ay92=Mk0YQISCSU^f@Fe5&8`VmL&zZoAVg zUSx;&NlJw(#0I<%Ru_iBCA$|xNl|DQmuQhOnjZA0d2~70It8WZveg06_}nnyd1u% zSpeT0ypamvdhwuH^C8;Pb-#11-+m@KS$6?^3T%bTtplDNOSN;czxjJx+kfvM0^15U zdikyrc;LdC8qkjX*&NN627Ll{T@|#+1<91#CDxjzXo~IU9HYM$L8Vsf5S-Nx z>xwp@07PT3D`3m>ftAm73vgN&6zw_-wOE==tUXEh))db+e*YE<^*TL4H6ZD_%KFzz zv#tujNcONwEN98-2nV~guBszGR#>7kdLTq3aWG7Qi65Xjh`$Uc{agiqz!}S;Ekg^C zm3}+Ylib3_F}B`c1c2i0B5DU828?$of3|uc4W1)=Us~Y)1Pe^B_H5Cr3RP-xq6nJE zDwX_kVVbdvX4mroxJ4(aZQ=+s>N|Eh?i>EQRGp)A1`B_}ejwZN1%Is4n57K_B^wZp zAgMAJ;ok}F$Y!2s|I`6f3s7VY%U*`o&f&wt_~7>Q z#Q5MMW$lG4(vSU5O88VFjzPQgX*M|C`IdqX`5^i&6+)TGD9j*t>q1#AP-ensn&^FwW^vAa>w7iVkP*}+trwkX&kP@eY=CuFD2O}ws*yd zIm%)CG3_@I)1k6p3sxqyP4nXtEY4Pcdeeq><3fMl?!NH+wn_0x=U3H~ari_nn~`5v z6c(=qHWP2s6l@~cQ24b1wba0(VzhU9CEWftlQ3@E7c4?e5g?ci!~r`97!97alZVu0 zCBUL$-1x;k=bIEKBIf_z=-fhm|DrFY_EAKFxDDVsc$pxSi^lrgz>io8TN^#TX?Ffw*#6ac}r97+6+440tehm_~YD8XvlA5uASg22o?eXV77>BE+nGI z-IwEA?F`jjXp)>zJ9aes8JO?gpD=pq)Pg+qQlkdurACuNpV_%-A))?;0(0irP zW<<<)S8r9Px4CZq`8fFWiPmkG2|)*j36-1U?NaQ;2ezsQ@pTU1+rGo3@LRay-O3n4 z2Dxk?Q+3qX;b*1-krRm7G0kVS}X_6TnQVYK5%Wzgk;uQ*)GVR@Dj=L%swwisU4 zy+HCHTTACP!&@jN-xGUX48gq6Gl1H8e=d1+?zTwXdFiB#MgI7FAUcMuTnA6E^iY6~ zORXuzrdHK<9&>wuUal_w#1!tO&30wGFUHcIhp=Jb+?p4+PhF{oMsGGmb+qlQT&z(mrPTS83LyE#I&$pf*Z1ge*MeWG z5ZKXlZI|;ezxK?OX+G&XUf3KaAAjBw{4@UPoi$&7)$(l2LFkh4nwCDB1Q2_fyrgl4Q}QhvE<=MXUqjBl%DaOpye{3d;*m#1^(sVupN-$BT*Il~HGWKZg2&RUo*pf!FS-`&Lzxr0DE z%aX#xBtLMx#E4A!M=^nqr~tbd5G6`fi0wI{-Zg}ySIdw>Ur;yl5N_CaC7<~6_yFSV zREj+W{gcS26&GmNTS3oTKSn1Rq8mh_U-*-Nwp+;tUK!|64qhJ}7}0su4T#0gIF3nu z{iUI-VQtq6{7T8t0QiKzD2i%BXxrG2Own)w{>ic#wE!%n`*6H-4p+~$%*CFu0b{b0biQ-6pWYS@9=1PZ~3_m!Dr(VHc{g* zH&&~eS6Q#Z%B`kgXNCdgvvlD6w>s`!cBpr@6cP9W| zpln*^p37P?jWV+_P%BY~oTI-4GPF?n*^{RR%*60{(bVu+>g?v{0Kd?y%yWh23jQT( z)Xh=?`P!`LgUpt1zhPp&M%v4I_4>*fYFHyn`?$5sWWvrPV?q2I570k!IE&VncK3)% z5Eo{f7FLtU6G9usOYppc;5UA#xnq|EAz+i5bqv zM;!W*kUN^NCB@OU%CQ5?REa%k1QG;D+BvQ3v1a%|o#tlYvh5{gT`q#maz^MFfVnd< z{sW_Bdf`6BbyH%gCaHw!AD?w@xfYR>S?%f?vqGC_YApWKNknH$lXGaFUS9b}C$$bq z*gCI5n?Y)-@4`;uL&TaNi5$< zk0B+I51g*sygOFkYX!*poex;b?N$EXhPr_E(VZJ7e75Ix__W3v{dcdRVB|2TXL!G@ zhFfo97M8V*js#LzDuHcM(bRn#i&|?8)LJCDe+qHioYsxNc+Y3FQX9*3PUb?o-xjf= zyDdnLwij})NSeC00okN+Mhr*ndK;4Ylyivl@WA)KR2Zm?(Qot)`S zxKj+?A7K2l8lbHZ4waoMfb1%$s{1iHI9lLDlferDS#TT9b0;(WSoDV~{iP>$wf-!6 zx4+wt#TA~{Fa9Uhj)$6^U(iM#z%KcGMDq9rRkblKByq8N82$u3_4sAxmXAaO-N5%* z{Df>i4$G^)Q?+kWuCANz$40K3pV6W?+Vj4fRzK0AAs|;z8+=6#Sy~da8`|eujsUlO z%5^f<4oPbZ@WDE0>|9oz5sgCT*9e-ON0wS@@YvO+^I30DyW0SE=Pp}f-YGz-`ddi6 zX${&e^yV1hEeZRwn~uNWgYT5Tt6vHIaN#>Z2sErO`#bHco@Ux#v?g1Dut`Oi_Py2v zAW>fq-ksCyD{44Mp!D?FZX4W3-nfLsK%>|I*XmJhZw4ae0e7`*zu}gNSs=~x=obwF z>`r^e9%*u~wV@{DavPJ(me5?UaiK1B$7WqLT6yeUmzTQTvfH^D(Z`MGnHJc}i>N(k zdz8(jJ@HJoQBzegm2u{%F8;KJ32=1+nX@We z400S7|Fh8jS=ZJp1m$n~mr4y=TiQxcx&hG`8dUTUa3z?R6Xzo48&Lw$WAHmcE+cF? zjX104#s(^xdA<+9`LT0!D(YamwT>fUhskdftb^RAYf*ukh4LMgm z8CeyIpXu|ppY4s^Ty8qGnh4es=m7xW045YWpSNvtZop@!=U|ZZm@}QOWQPAdKHr}X zv7ek!$k^^tA`bLUH5mM!&bn?3(MAG=)riSVw39@b`{H(rB{Y;rOmJjo;tG>obh48w zPlEjpf<-*0-0KcMBbDbFd*c$_brQ&@lM1ON6vdnzadt~ZFh<@8-xEzSWFi^^p(N>w z-ZOPip4D)SCUtph=GR%PiPjuExSFo6Y}x$B`4jaVtmR%zwTx)?dq&P zLw(bZn}{wC<*De9iuh7}7i*(@YLrO<{pg&kcuV|n8mhXxAnF08v&V_+mOc9@kExBt zU3{SIduR_9i76Y7>_L{ciO8BGs*+TY6QR{>EBI-H)AN^bMcX5>Q z-yDPhf!#d>yTei(i)xRpz|TKc@_Pttty@s35@_>(c0T_h*?cB;yyQfXe;{PZKKST~71%=;eG zR@2^HkW$=wVTke*!%DGJZ?2{{Cs_=875Obtq1qe~-&*0|Tj?YN4g{6LC=w@PbV#{_ z`Yg5M#Ls3!Op-zg7D`=G6LWM)0t01{Ahzt%FoR0(TYpiCX+g6vlZocyEN8g^n%}Z~ z#Qt7SDB+o*7-jlTsR~IRE(SmLyR-H}BeTo})9k!X`Rqtd5w+W2Oa^1YTcBk54|@oz zlFLYEKvT3G1iEN=zGk@(`9o*^kcAA2d{cE3XW%`Iq=N>k)Et~hwYWzX=^uMwhM7u1 zmeDjTPRboc2qYh=fu#l7WLg%QG0_6L3UeeB4_Ek!!%0nK4;;0?)Jyo-&8HgM)|HBNGXnq#Ko1gii*1Z;>*#D z!EC$=6xQDQ!3sHoZUx1L=8La33Ibw|ilnROG!e0J6=ZBlEE>&0;n_kmGtg%SnFy(- zlK#dyU$f5XOYH>X#-$aUbxhp~9Vq+JW68BqzCT~cIH<%K(ag(xK9&!>Ef2gbzYg5) z+3N0D>77%sODC*Tr=)r1_pQpOj*2Jnq<`R4xA3I5abTBmtTT97?GHW*D(Bopl+%5W zu>>7>D`N)iT99BJkNkQI$#=MeUPxFY^dinvZ%-P?a~|kCmsRsErJAQ1l|2TPEO!+f zlx3DeS(P?oZ*SUPC8po`-=FtwrZ5Ni6?B!WDR$^cMj|8ODG7h$4RNB4Dc#IgOa!7B z*kxjL>Qb9##-G1{Bp-h}<$vZy2w?RAgH?Gk|Dko z+d4=g+gRP=npOyvPgN&t^TZuwRWY(aXdm$V>_zk`+m0LBAn#_AD&6y@t( zFzVcm1|+gK%)K($l*43o%&z~WGNCQTw;*e>QkwNSML75CJJO@uLf}2Vrot66G`pHH zm=H=&cNQ&n6-3zt>7EJiT?My0u7Lkq18L6)-y>NEDw+(|o!obymV_3CX2rD=(yV$_ zkIpkO=0u?dsNE!#B5UXOr4l;vSV|h87(onl$x`tv%)4NU1hkAb|H*PqlLg&TV;0d7I|o7UDV~0} zv@leXLe9jrF|bsRjb%fp#{8FTY^U!kC`{#FxEk5#!Pi8pS*9& zWDTD0pq7NW$9tTDYo4wb*Eoe$7h~FD2b)iM!zx5{I3ui8CH9=?;Hy;w}STpBn*Q~MVtyZ^aq zx}Um>pilYg_B~irvaNQayr`)Es{pmK6}h=NM!57J;=%?Rfi3uwbw+C?8c=RtB(>F9 zm?E|dmQ4X8DfOs9!~zZqa!W!S1Rdg0&YyTo-$$y1!G$ZVtJP&4;f&{LvRHo6X23Uq z9nSp?z_|T;_Oy5;*6D+z^(7{k;EXmPOwlee2VpFo0PK_6mo>rwg8twDR|o3EZz%Lb zj;%0N4`aE)b{RI?;a_ad7@$@CgQHqjYknxbp|rp}|9H;!t&QS=ci+@zSa8i!StW$U zXbmMtcDXDQtt5cv<=bG<=4hiyrKp%}jIioTqgY&5cj3qs95q`kX%o*e4GJ|ccWCA7 zVqCd`A#k)>Wa_(UVQx_yUaB`)oZ#&j-Q*^)Tb<;fkW2LU$djxW<~S^vmd*QdfNEjk z!(zCGBiSUK&_a+sSQa8VdlJ3_fC z3Oy9))%`m@(re}VEp`*YYOu0XhPZ%OsDAn^p_=IK@N*ICNr6ZMuAuom=t=;6PXM-u zCRos$zjQ6822mi^BOPVQSEE~sB0ay?Nx~R+61z~4X7gNd%@q9b%}ud1?Vq)h zLIW*wARvRe12$&|u;?M=x3rkZyMW}!a@eyaiB0+C$bN7zy@$U+Fa6R7=v&uI6-ECk zyE)<)sv|rMYdF>8tU<9Z0%Hp}FfLq%vF^4z`%>b*?jZ5w#mH9(qh;>MG0JsEGnUY; z2$&chS}2r}bAa}CUVjZx3IuHsC)LCuSa?Ineon7(tMmiJ_AU5>q9#HTd zNP(x@TV*uUMzKgjCWluzQd2aim{`&^9cev?uY|zy!OqikXJKASOn82xItFmVrn`>$ zTP&7I-!w-Id{+*^m--e2A}w00rH@AjDFsa$y82F%V}`0c4xHTOzC+Q_n)aQg;)%m3 zlD4@qQk!GMM9F1p>qy8ugS3oh`%~xNZFFpGa@?01rABp3P{KtI1o2|si$pmiN2m9NviSMeX9Y$xu}ky4tiN^f3L)hng31(eck9X2m8zwW ze0cp`pg@g7P0eCVgcoQG4pSvgLgk3*>5qqbyGol;-5?5Y)Ec>$E}RH)G(Mc`+}%kXzJ}T zt29;p5bNEIzv}&!2=oaAzuT{;U+I;9gA%nXhSl=R4_pjF9z~Bh&psOFh&VEOFl>G# zfS83^HB(KCu>^$@{@yG^CDO?gfH@SL$B!Ps_kuOlUBR{geNbB6;fFRp_hT}K_e9+0 zgYg#kh0;V3Jkc84qJkHXz`rIpN$)9d%(FL#*NLkyhL|9QQRYlk$Pqb{9|LzciVvCL zV_$4P$>PhR{!wJ=!t@srq-RoB+zYm3QfPtoY+rQBQ*5o$oT&`DbJNnttQT_W4xDR^y=& z82ZFj02XBr&@X|OqR0wtf%tLIf*i+l^|?!mbw6mz>q1yIhcZXb=ne*R=0FUYI}UXx z)~n^%8|fv_VypZ4_logj9*Sx0DVUQ1K<2L$S6WaG5Vh% z%rW_bq#3XjIj0a=wnvnV`dUL0m&!H;F8VDs7LD8!Je{Ey>Aj`Z`Lz~p{>i!^NlP*p zi&n)=2Jfju7ayJEySwmiiCqO-whrj1q@j>9OK;AX5ZlC#XRBo2o-;TIEQ4@cXR=^n zbVjm0Qh0tOMl}3{qDKJKP5_YWe|@gh3xgfw3F24){~W~26n+0JkV-biPMfN+(X60~KLFjYhw>A@j6xQ^#m;Z!stOOWMfgHRteol2HPUxBi5GLKV2SfP6qg2g~w;1jKh_RXQ~H%LZOQwmIly z-CjR!J62}Y*;%nsTz$;Qa2j*9r>*rpZcq)j0&a{3UrDqk7-a?9JT3IDBn$o3XN!b3ka`C6$eI&B{$0 zWV}5s9w8a`TFe%{cxeD=j5{@xt&BS@o8dN2OHLBocnh9y?uwNrbn-%wCE~5Z7XGW7 zjSuG}z#cB6lQp7Vxpcz(rN#7q7p{W@5#_TO7zFr&#oib{@`E3%?_?ykPa5SFvmv-i zL!-sm;-U{7;uNqVQB_;uIli<%Dn;v=74j=&m_0&DOG2+`9RW|Gb$*80w?@sRCcfxI z5Jg}%4nu*|Ik-#eGV0GK0Z5u=RJtWzAltDCPVKP$g-s4oX{F$~H`EVMShJFke)?z09rL+68xjvuq$6qYCHzKV1utFqIoktrobs>{!D6IfT z2y`<}mbjiPJANcGKg`@>jZyVA5@fac9;PIE6G!ACeDB;+xnuL5_3S=1`plt<2Dzmr zjT?!)6U#OI*3R~_v2lV{Rr3aHIt=O3K2>RDB2uR*)gC+R7OW4v5yu%vs57R+POsm&@?ym-Q9_p# zfN!x=JZc-G9^@_IH~)m0#pd&xFaf~8VLfjrj|pN{@KDJS$SW4Rri!?Fe3H;Z8vVWtma-YUatPNs)E z?G-32ar4hi(Dd_B&j~x}ivY4VF>9LZ`Wg(EYE;zWtk{rWPTwxkcKv>yFrIgKrWBx^ zngd+<)r=MTVXk&3xoaX}!%}2zxU#!D!|Uw(`RCzDOw#Xu#P8H8V-dyS;xLWP98~%W zWS$vGps@+$XD}CZ~zKc*h=WY&GFSJzbYzYr5o0MRr^oI~Lg|rJ+64-wuD;eb!K>#!o z0-h|fCz@0~2;Tw3Fs28BNWRM*2x6F3Xat^}o7$1Tzan7BVx+9VVw3t-t%c509$RUI z-K^LE7R0uEYpR#_Pgu~1usH=#Awe<72MUZwHw7kGi0UJ~0z%}U7(Z|J=esZwjXQBJ z>h&JlsN=CmCZ^w|^ijB=69>l*S_K$`0R%K=Q}#a~D3FoT!9-yqJOG;;S;)7dfcyyP zX6X6@jb;J-@ji3*{YFG;{Po-YSZjU>`)nXD@xb;7hQ{b{16DZUZ=xivEMp81o8+T- z{!I%NJkDp+qPXq~;b-w#*RK7r0KZX=YBm;JGdYBD`1FgnzsU6gh9=@B%wx%M(CPPr z-~cSA$mPJ<7q&nGZ}lu<0|85ZNrPD*N?bTr1oTdI3QH%L(@t&!p35e0{Sc?kABu}w zA9kCWOdCv5?G_S0XE7c$QhFEg&hxjwwwS=-9OrMgIn8*bEja56wkL%Q5VqhoL~Cr| zF&dz5v*{*ajrxL@c7fUn2;J@#_(zaS@3JK~Rqa2m}}%#r+9~4Fiqa7z6-h zt&AFnwy4SZ8QP10a0YutK+84m>H(Oh`3(SL;Ub{vt%pWI$%Xy&{Q-Ua0|rcYui9hc z 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

SU18jqk)hhi0&pE)Avj|+ z6p+&Q9gfW>S@TLif%4@qy8Rg92yrdo8DTM#{m?i7fVN2%d=;vU%18j7=*3>9Q&(!M zj7hgvaT?Cb=1YvfZdo0qcUgmxg)#|D)l-dfi^*h=nVAjJ1E;kZ#&91kk(mX*QlNMi z?Q#)(bPOiV7aIFXRAK36Yp~kcE$#j)ILNh#O4hv$`9g(~;u?T+@B7PFi-K!^95-6~ ze9E6=&a>$Z$#yR9^kXs?+#?R0(>%)PCWpG}^Wu?MFf$OJUL+&SH3E&to;^}IdMSe|4p)|rJV)(I^|L-p} z-G3?D9^@!zhZ_HGEmq2*VSd5HA<&M$@MGvDGwCI6@#o2iTHp~C!V!RC?d3LbeZ>A{ z3~U4m(Tv_Hq1tpZ12&B%hx7w8wa3VwHLFW$?(xu&gqG}**00f}S;cWNy|da<_R?VD z(7Zi)Yvkc{NI;>5mS%IcyB;>izK6L)W21b&urWrfg-v}UYwk0`@Lugf7$e3nqxy1S z-JR8maej@SJVA^ms84kzyO6D2cz$uVnvFa=4b}Tn zKgK0KX#K&@NjQsbqO$#4Ubr>Vpe2%5>S*{a>zBnP!V&rZRnJJMu7!9^K;92S@6QJ7 zZtuJhO75Qvtt*W|)2Dn{t_6saHBg`L;ZvK%9yKv9_mNt`Dl0>l z=@e|-w#isL0U3ci(ES0K>3K`{O>=G5<&V;PSiC&F4Bbde?9BNUb@gTh~mzsTaJtXDXI;oOmb14w$F!?OMI6_S`BNcb1Q?Iw}yR^r5Q#?;eXdloGZ02 zSWNZrPBrn_ZO9@*LO-#^roY05p5F&%Btoko?b4m&>a75@nzQFOBMvJqG?M(HSD`Wv z+VfJYgl%o!UHT-h8mAYE8ZHNp#c|utP_Z>ch(r+%7CLsDDW#5Y11Cu}=5H>=D*BG> z=?N1+GO)VhK~3XWn;B!_-l_hf7!!|E#r$-JOXM`e{}7omO_7uPpn)l+lQ9x7%xr`5 z2gk``)rWQM1He<9g6m9RfWUJ>R;_i)XO|UbgcA!%GPa=DWsZNuuNk+y z?@yxjW(#BVaL(Bl7f&`gn;&7@6EelEmlpTw;uqlh_Ec9Ox(r(5v4aY|_bSlOE<`}m z;ls8BwjK?FZvT4IgfjmHh_ zd4XHu_C!w?rHiq5Xxn6Wel^ALR#P5QDbE8pFEsGw;tKc-_oeSL#FO^dNR6XA3+w+x zC^+Gl;S=Q+M~dPMz6KY9sLgn%dL(JPShGhxhPV7kpzWj1KaOK!)tJ=!9w&#w0pr^5 z6Gc`sGUfegQ{V1aq7j6Ki5OF4b$y&t@SAg2=}^OuD>N`o(%|C3lzCfxAaSa(b<6Lk zI`;KjSG6}Rv?MN2VSN}pURh)i7r@~u@ zT$CQChCg`zs4_8>ZENBJsKPEw?H^#YvS-j1nOp6z@Fx8H8(z zpP0w@%8m80$D!;~(L2MoW3Y3IGwGj@OTXWbK0)~d>gMm@w+ie4Mb-_KOt$B%A2hw$ zVyU&z*P+)CbuL*S3vSPZk{6upJS0ZdX9ByQ{X>qjoW}QLHIPJxc{H-vdglN4oNbbm zTLl7Ti2Q&GpDKMoPpi?1?P(PosB$z=`eo8FI@4}cQNN?Pyy^W*PEQ6iPBXu8S&FCH zZWB6dtV@HeGcuzPu`3IIA#>n8wEwBN$~yQcXdjl8A*UV8@r%>ft?uCS{wB-7PeTa` zY}jCnrvr>9*2WMELTbCmnV!3)kR->_=ep;gf#)}!29hsXxQbviJIDf{n{jn4k?B74 zmdkJd1!<*8D0Xhw^C59qKrvezZI*rUoCXYTn6FQR{vdtT%U>^F-;rl-R%i}TnyJs> z6$ej48?-thT!W>WA${=W+yHV?YvNN5DtUUP@|Q%%-z{492&_77$h++~nB;7ibzgF%*eyIjHLu2n8&)AKo80|FtXE zPIT%#!YgENsz@@Vigh!|ZM3QDbCP%Ze)yp3yS__BBTs5p5V)Og0r5+88|_G@W*aon zoBnMVTn4*)0O@UXT(~|i$(W)Tt@oLRVW3wT%VnGflLtiQjkC#&R^XHky@|(d+07XHWAJs3@t3VkMc5DCM-&czK!V7<$O(BAF3IIYXbdFRy_| z?hh?T`q@L~(J>;FQZ|GjcKIeQXX1>n4)-FFPm4(Iv2;5=Xa- zGTA?7XYyJ)=f~F)S(O>H)F(o3HIKT=hvbBEsS9As+%~!l_@_n6=GkI?m#%zO26~hbd85QJn zLoVduLI70Lppd#-U;l=1PC}vIepK>46UxKA2fyx5@@3t$cEUSGWB_RaIMm_rXFgAJEU7p< zRemXzpU-=lDgY(BMcU4MlAY2Na9GXvkBG}UkObs^e}Nib4C1G;w9NoXK(@c8if2eT zB|Xc)u11I+$2n;74tw>FAy@BL)LUitBm25HupSCE%y8pF`Ei{{g1=0?RgQ2RMZc2p zZ1;^z*9S)akpRud=bh8rO3ZW{;=do>fX&bf17GQ_vjNzE%ubk%7 z6*3A1Xsy(g_pOI?ic(DVL&hUN zd-C9`*LPfs4gyNlC@;g_avE@B>wa!e8JZdu*~Dkkwml#V3rqd0;9wPavj#lovSj`==5ze^v&;` ze3}ZzZI4ZBpkV>z%lNl)DeA>9(S?OHoieD%Dvt*&c_q>M(b>oYr`2(f&fVq2=~(N~ zL}^_8uTtM;K}H=Hr`YvQL5@L|;HEhoETfa8`yQ2?qxL_pOb*+7{t7fBd1aee98uz3 zq=y@e=IWn7=2VfdjO}beZpqP{z%RU+im@Ljl3r0tvyVSXjAC~uv&)jyYn+4J)kSq5 zKZwX3b#aUX#d4P;FLu?5EB*KhnWyuuB^$@b;)$F-Q z7>y3rHNuIn@#Hs{dSdvHQ}&e7wHeJj7Pj57j&?%kQt(J@Q^|&E^R<7@;5#=E^t8DO z+v}obPWvS>B%=h%LI3w4K2!VKh}#FxY=S6``agOi4$r7)F>zD@t|(N}G+Bn1t05ti zuyU@}IqAQ^Gq2eNtxuWm<}8ChDauSVzWwl*wYz4hKhDj$HM1SwAqa!csFgfFYYtR% zddpS*fj7yGJgv6mdxdqdD12MC~`KIBa(xMD19# z8~v!2wGEF2S(-)?2bIqNK_Wh|Kq;ypr5K|B-9U5uhwvSN8)qx;*vix1w@Unq6n|*2 zPZWn0YrRP?l-bwkY}XA~MT1}$EHQ|ocI!2-*z!W{)UV|7F*(u&<5?XL!s`U;XJ5i^ zrh_$^7);-aDum)2Kl4QKB413aeh8HNWT)WlK;#juWdBZ+@lc2BfM-pVUeG$PUR#Bpl--cNE~s0Vd}#wH<+x3Lwz=44 z;Gz}kw=T^WOZ*44WT7JQGn&4Zha)n7@LG<2JLOeNj}W=SYA_f%Gq@p~<~1mnRN&Rk zEEimTCt*vPB3tuwlzd!lyMmF~SQ7+%B3P1aKic~J>QH9+nX$m&`xU(DjLBLQ=rlZM zF5)}4UnLa^vFX{Lh~4^0JM}=>21U%1vQg^KV#W6QBkjEKl*q-8^o*5SdwjExIp;0O zNx6Lf0|%cp1TmdB^-hS;ph31CTiap8R^&3tC0YS}0{M{piban1WkF62)GfI2-bUiQeoLW5kFC?BvxhXk|p1!}t(bLHsc`Dsn>bQUIxp+^KWs6ayjv{a1CUG1(jwA^1#{(a&sZBWtKFWZe#jz#D*N_ z=l?%52|^Qor1ScJwio5DYO`NoI4+93WuB?VE|F?Z3?h$WTPu_{StaaY z4|;>6A!!Ib#wySzvE<<-E5QcMF@=&|7c-fkayDf_gsFyMy$6`i_suM2i)7p8sSKf9 zn{DxR%N}hdN~@VkKd67Ww1ffo6P4Ens%G}>USff~8?F0YeC>)ZPi;-oZ{wQGs__^p z{W>9`=Te)DQ8p>w0|py&G=j@w!=!{LQ zy)hmZs^o2y!N>P=E1ALqdlq3a^YV9{p4kk1f(l15{zA39+sE2pCWsEOY-PjFrsT*R z;IfZ1Ot9re-J@mLeOQrbqahmrYFxx2f(ca#|M9rm!vsuhGNmyvmU1s$gvbK1_2qK9 zW>XD()O<0Tm2RGDPnf2Q+s+{XW3`IWhM9r@9SVV|T*>gZx4Po4_NKLd`F&JPL;4Kg z)y{Uw0m{<2RB4blgb-9S%5NuIzTF5vHB)&YX8qLUz#H4Zw)eiW_+<7!8-ao~-r*o9 zheL=H(sqdjit40ie`t4XOfI50<|`{*l-E#eb!$GZ}4hU z6GB(l6K8VLSkaB4kJ5$;*>$2=8X>`4Vhj4BpNwc9ij#$BCx`q|KBVD@lziiSdF<7O zvSnk{ah|AvjCo4AYI)VHFV$=yPIeni47ys4mkXA(r9N|58^>_kH=b))1Je_~**`!g zzTAtY)RZE;uMH$9v8Mj%hz|zrs!s~v_g-4a0aVxuY}0B_B1d(ccFqEn>ZO-^89iyN z@nT!W;+9Qdyi8pm%mPT1=KHsw28RmkWnFkOt?W}tk^yb5v>5|6I?Pyxs8J3v zl>DaxCY*%e5~8!4Hbkf6`;Nf@knVWqdx)v($&%pzKWUn%1;3EznCquHqB?ywS|D4D2LO3I`Alz_ zK9X-B&B8l%ClWSEb3RH@>~F{}u9qF;c~A9X{R}n;qtH_QOeJXMmd?VmT=0m-jbfnD z%B_A1Ng+KbjV-4V9+wIsRjfk0!Kx0q51ei|>Hx8&A0}%~&ZABK=M>Y<~FNIrmH&*QeK^n?Uk^bJI28S}83$kKa_ANQ2)m{n1ufi@$=rJOlN z#b7_Arfea}CnWEULYhYX1vnt9_RS@pk5gKKxnf6v_op>{=zK?})jpk!=p4|!$Oj0kZ4{L6`YlUD2sL6P}gJ~PlxAtBpzBnnVx(1f`>@3zN z8bu8+*IJCQv{(-;hg*>Ss25O2x*U-Wnhris{3x)ubJu}M?jD*~)(l+*%@s2%>X=2a zbiqt8ij628Mm^j?ejxZos6k-qI}b6U*K(9|pI9OdD!XdnmobLF2O}{`l1G&_e>5t7 zXVuJ=`~gVyVHtH`8dv0WVJ*zS+6v}eH35JOi!FxE80#L+jklDK-kNDrIq=h${6f-{ z@Jp$Y69Zl-agX%kprZjweq6-T`A(@wrtOODwhp$qWN1mD+K47cJ5;GWO;BLu=fy=& z0QI^+l0_u;OysZM^ELPrUR)Q{m(y_QGo!IbY7yjzqz^$R5)0q?WjpC>Zx65TP7qbC zBS>WaBD5=atq(qFOkJqv?E|a4vkEU>anWLYCQ3ms7dhy>*v6wWisRLJ1^9PR(hd*s z1l$1QeiJN^MochW;K=7W!0>vH>u)OmlDY(Rle-jRafrcTUj+`CeI46PATU;?4=>NF zzJVM=RP<5)6tPiu2JlS*7e03T5zewN3oGq8zaVH_W);@}3^@o;6`2?lsX}7xt~M>R zy=UeSx(hpME4iidGYgUhmue4H^cNjr{+EhRCiOZWqQ2FkX>U{hkgU>n+~+T&S5+9e zg9M{oO`jM#-@B59^_FQF5daeft((5Uv*q-bZnIHE1s*$$NeNrHMix-9Sp=(W?#|xV4tUZfr|99;|OPnwwIA?Qqsw* zuppSE8xD`_IT82(Ua6Go2XR6ls!S0u>n3!!PZJg~;swZd#pNl3suDYF9{G;GPIo_* zouI+iQaUo%oB55vl7-FKn0+_QY;le|C)hFGBP`_d zBf?oQLnPOsNE^YueZCDNLpP1-^3a*dlmyOiPkDzOPlDk>bJ}&0B%OZZE=&Zj!vKBB zDrYs!a3sQ|z{a`cEYSUE%wKu-r?n{b6AHR>J1ASGF+!}f7W)p6e+g+NoDI2CHq3%K z6UvfGw6Ve_I)@N0LRB=x2{j9+s_*-8eA>qhBHVE9-B&!np>q8ILE0_4> zz6?MXJFpkvagKc|CNaP-ZuWKT?;L#b)XTBCC>{}5-+IwdD@1d=sRu+;xTo{Y+OJn> zwbp((()0A>WCPN*IqO6|l+`r4dR65#1sb2RWOK39Am1mDirL4WVUyMcnczhz-&VnF#T01 z4!CGO>i@jQv!Q1*K)?~U5W|?mFfdS*K=(R*nP$JwNg~0ImAZ5;7tSQR&-O7b#%19C zStYwkm4ro`Ggnx_mXR|UA-t_Dq=B+Wm2rTokwUf+NBsPvT(B{{s_}0tY}vOrr6g`g z%#@w#HjKfEhLDHsF;MK0DGtUSC_|p&xrwdDMvD07pa4@;+^1y3wU2*Xxoi>lir2*@ zTY1~Gb7zuNB7;!5+ZqkuuPqh2W!CxqF_3o3zeBKE`gi9+LVJ7m_jUCL2&Wqh@of(x30 z@n;7+bP|>xD-)0=iQR+}tA|>a>&#&APkHk zwjmc-Z_6+T;^{gmojD=sME3ZlF{>Z^`uPE5s3C}t%@4;0{!2wQYtENs+@jXFga;vf zL5L6rNR)XY(?YJ0@BjR(D8}JE$8GWyeLH0=L90bo_)irFNF>K|f5bW=Dd9o%g$_`T zoEu>vE^M5f9ME^}y;FEVitEij?u!nFJ{qPQ`i}qmX{N#a6o{nykd`&4rjBa`_?U*Z zShZ}1_`v;U4IX=3FM5Mkp%dd=mg9+#uD5-o;Ixv$t7c^KTHELsW4w*eEjEycEmBgN zE3$V>v>Q6R9YDR=Zp$0~I_nok3($?3NwwxA<6Gc2$a79Gw|iR@|98KV3h-%)Dp1P7 zU4VuILv_IB3-DKfHz^Kpdj|JWj%5IlX5Yy4)c`%gfi zBVY2IXrB`lG2d6h!2WSJ|>Bs$COBmLQdJMcQl5{-*)U&v@ zMw+Sy9CDMmw4fnXf&zo1r5@N|YeWOW zBOGP0pKHJ+H#+LX!3B8SZ%{{+>UY^=W`;WanwOCc&T_wj-(l5ys^30Dq2+@gpm-6( zCr1&(yf7nD%E87nrE}mKq;FZ1pF`p(ZN+5y<9*_bA5>e1p%}1o^$l#V)WcEYs<6e3 zntW?AC}xF1K1Y`>os#3fBN$EZx*B5dF2jx-p?XN@(!ddwxW)O5Qi{{Ky=A)8f}R)z znYGr6VDk-U{smZI zn4?j@A!gL{&meo`H5+Nm4uezNz0`CrT=jD)!wnRjcXWzr+Xcu%j<mi5NrSZkkk{Y-)* zU_6-6xlmqPW6#Y8y^1T@P63c>qCZuGl)o~?BiX{5A4%3cy$+i^M)|W~)!SsFi|FiG z09|+Us{g2(!|3K`czJ;_%0l>P_MCDW_9HhRhF`-|Z3Qe=>Gd@P`5~XsnAd zSBip&$%7<~Gn&a&PvEi>uj;e|O7-I#??T0XnRQE-=iJCcZtBNmRU06B47dlErf;c+m%Vxwd;5Nq{8Xx~iHIJolp&i$Z8Rtv3P;_K{89;X!Vqy8a5IZ1n@5 zhG+Bq5%s2DTbE$dfgeFR`j5z8z=40u>op8iU{2f}%*50sZr@_HUUyN9K|(mwx2X zF7b?`<1A^?QNvkX>;Eo0w8m)7!UzmFRYoJKi1w9QPZhhyQ%pXX8ZVwY-ygb}SGAc_ z`l%CKFX)yD`V4N6rW*T3q0&zFme5^C&FV`jT^-^nIDaCmd>VZdc!3A-ekhNC5(EH7 z9Kprq`;fyywgl&sgXE;sR=LeOtGd8g2z`Wsrl3SiU%AxyN_Xo=jU4>IN}i@!foxA# zbqaPp?g*8&h#{E4%gwnt48i7#zX(yAaQC~kIDgM$(WzzHD91h%A{?H*(X)npL~h~f z`_&T8BmKrb<}xGj_OA1O)Xn=`;~e8fsq_g3vFcHFhIHu&>q^37zF$~TOPF9vMOR(Y zuEqPX{QaOJW%qC>IE03oH%)?=M|)KC1&Lb_Dtp&n>D%Ks0~r0iH%>BM?^Jw={r@|< zCa$+9?nAn;;m97YzAGoLOWj8GdEEP@nDCFMgviam4i4^G&vPnan}n#cG&*1R^n6Vx zdx}|mOlur^ZAo1*(;c*#)N>Zi01=K$YktkwdpYL#tb*N-Et1ub$VM-|um%B(sj^)9 z5Gy^-btIdmX;g}L7={?X1lZo*@oV~79Fn7vU`XEFxeP$E4C#Rpah1}yHj#(P+NKU@ z3$0tbFSPw|D{_()w=?T-=^*mua z$ZV;N{lVf^TyvM(pJV`RaIZN2U(cLD?w~Gv#BUMNBA>CV!28V&D*PhgFxY4XgE}RI z3jrE&OApT`@MKGT$ODKkkSCR>vl)-tFt?AA!yOA8P^?N&74XutY&a#E`p<7ZYGAi< zShGAQrKraowq&jmI?A3c9l1$%=59{Qa8tac)$$MxS-F^K%SdJ+1L7Zx=^ME!P&6_9 zcd*&SMq08S;1e|86MxmELbj1@`2s?B;YReahe8jt-nIQr6Jj#t>(&=v$e2h8hlgR% z(#)f@l5_9`DB`OP)rkQ(_puM;iva}`OQ?4A0UFiLK@7-L^*=3n337wEnYx^XQhc~} zRm{=!>NjWlsft{q2f)jrWAy-aP>$lHi~Tfgz+L7h>jIQuwF}uwlz&i`R$CaL7-xkq zGJ@_0^_m)-vGv(Ksd2rlSo^M}55E&ewLb(`e)KOS5>{^Li_9D&x_DX#+l-n4+BUBx z6bf^Cu1U821`j=Oz=2gkrvtVE`e=I-mGs>uU!=;W=WPxT&1gp;5%sk7J?>p57C*VL z{)-$8_=tJAp^Wp%_63`kseGc~gY8#1NmP9h&-s5B`tI6RVBO>Qw>CO8C(OV^dh z(O?;1xDT zP#B>&eq6`&>yEBcVg(eqRKM*KIDcV&x|22CTtdfyMSOi5aV$l|&%G&Z&Sf6@$OQhIYT7JLOfTb~WpDWf zqH~ild3n`0#-K^`qx1n=1WYL=8NE_Ul?xJTpHH?ul_X+J<*6*LGJW$a->6pLCqjbB z>O|u?Rck^6%bPf9&vlWPcq+)tiU4@fnar0Dd^Wv)LBQSz^?5;&1U_scbaibc8R2I3 zgdvdG3;13aHGVG73{S3Ht|b$jmm-+p;m%w8L?ZV8y{4Rr*b7XE)TG)!dJHJ8ury>B zmE%X5%K1&jh`gsf_m(k)W7AK8tXa!QU{NpZjw%NV|2v(&rgzf@hFCBgXWo*>JMcDv zJamBLD&OO{Fm2U$My?EH#;1aBwo_su6ZbDmQ6Pw^dJ$nK0d<%JXHX#6t8(LKRx)+_ zeFq;tFbYG*oTJ}dy{3JuMzI~gFS{cVzwX?yps!8y>$9zd`Ax<-|>NX#8c;)%4xHj?JIHp|-It)}DU>F*g z;J75`uID27M9VY){xXiTDQuSQzMl5}c~q2W_rwNHV6hLBr5_*SjOOe#Yq!eY8BC7< zgfRP_1o$c+@mZyL8D(e(cT0Q;x^)K!ic=;I^(dpH$`xA-ObJSH} zbW3lA*_t!REyEX6gi=3(@sq`+C%bNQw7>m2O?U7Cp38ww5k`}P?V6z%ZoYj!!ur$fK zc;g9U7P^#gx0%uCP3j=)_5{W3y?!r)%9xD!l*RNUFBZ$)&O2APbZk^Mfmn$9eWXUf z>8Cxf;pZz*`8vxsc4t%>0GW-D)YV}>q;(J4q0^kG-==u`U83)q(w-O`>Y{Yqew~*y zb=L_I#cT8kI^3Oh34hoZw0WVu)>{we3=y?EFCAhIbSf?+izh!@Ro^Ox$zn)IQV=|w zohAjEufD@4Y6>~UDM^t}KG!ArY9%ui`lJ=;g@9+3MDH2bo5k(e`lpzbI`C}-a~NMy zE6|L)4x%5#ExRTdKsP&c1t*?|=-sbl$@y-vRw=>kyw9#!16Go08ZIc|> z*>A5S8znT|bmfX?$P)kHSGqORqPR_=HpQ@fwyd7*@gzx-_2(;xv~j)@HzC&HE4C;L zV^pdc86EHQSI0|pwb{kb6vnXOrEh;9iu(M(J(vO#p*GoztYkX|^Rv6?shOVVo z2~pU^VQsYaHh%m^pK_n@ir1jHFTqd194WCHIvo!sKtpLc;fjIfgj4bMLe+B2V;rkS z?^M)cwGb7j&ShaLh$5nIBEPeV>c>a6f#nHb zYs&qhxN-m9KIBgg+3NtvHg_Wnrho)AJ(sA`4m*zBdaGMmUFOqaQHJhM2@N4C{?ZbWc`%tH)Z~1 zD>TuDKQlY8Sn$XL*VRgK)*9jR;fx6)Z>c1)d9z_8MNXw>*hhi7Es*(IP(Ty5+;1~t zJ%;eN?GCT{Rh^yCe&99ZS3h37;68NgT9k$JaT1uIgu}*`+Kb?27L=SebO-C$|1QfJ zyZwz*>_Ir{xQ1dI?Ur9mDu=>eOd+&-sg`2>Z9;(@CYg)4<=A#xDDmDoqN6{jX5&M| zBk`@}vdsCxgIlQLE2F*1|99gsAi{Tc$Tbj9(nk*0u`+aumj}SM6i?mi^*m<0LpZ~A zu{jeDtwXEhY$RB?``&eC-2c_w>HVaWItJ-?k=XehJie(V=700h`)JdZErzK>zocCc zw*f~C8SNxO7x!njJvDP3 zo}tkeQ;?}X1ttK2r*eQl!`Sy>NXaiQ_Ge&XRFpr*dHoV)M||%aY7B_m^~J)$^dDP)0)B|l<$ zekkbjn*n$-j}&78EM}7yQABnq@@I=@=}bSfd`9&D8F=tOmix|7M*u3elRvHYUaj15kdsJCKcK3O1?3i12%U0-y^{XA;Vj@?XrZCf7~R@zM#he5b@BHf!h&5x|s)7T*Tkcjpyr`A1c=RHL+k+eyWaCKE^EJez`t;eij(@<(amy<)hUd^=2ejt$Ox?RHAB&OA~f3f}Zb9oJct! zg#!!sDjle-hla0(>2v*RGdNC&6dN7t4_;b+7Ek29{9C;gKPH?NT2^Ma=Uq_&nq&)J znaW3C348h)`S$tE*w7Ou5teUdcIQOzq5Fx`6Oa>$;^&94(~X#T3-s5slo@AyP=d=# zTE@7ur9W};XxcPk>G?}DH1!Z?_y(}OLson0ZJU5`8?`aX%%QFcmbkHfwR<1y`81c( zbJaQTO|hE;DU!bb+K%yQu=rr*aejehlONVrxmDl7WF8 zG6Dnj;3V1BRW*1IAGwUkVnz7WyFB&VbQOddeYES@SCA8#+tP*r4O1HXON0|`#rg8h zbj2#D#%!RE>l^DFH<}EZ9J?2;xp4jJqcGf-rIgqq=gl4TIiEF7T%AMVY&yv%%&+yS za}jS(8v7a5H$myd7e}baDdja9VXOs8SpPRD%E5ZIWUp^OZVgKMm`ZSB6OINlo#MT9 zW(RJio{9A4qj@&w-ZRp>bv&Jx+m?eJ8 z)9!`_20?Z{k7C5Opb>NQha}sW2EJ3ZgDia=W=)np*{RPS4+yJ#&K6xWfENN*4u2qS z`n6#bA%W;3ef$15evE)Tqs|iL%y!&Gh}BGAJQ>9k)5Xk2 zvdwyATOX&3UemFoMDoQs2cMpg44+&xWA&5>i$7VX(5md`= zsI^!=w|0eFGCcMyAdrL6(l~e#r0|_p7c`FS^Ljo2OB|+0iQ-g2DmsdUNiG$VM0|`z z+5mdqX6AZ4n-TY-jK{1@s(SnQfm(jm3lZ`z_$+Fd`Mo}*w}AZc{gBbeZe2o5Y&~Zb za0^P!ULqw%+gulk)vgnlq>$$Mor4+PmBmIt7(?U4SVMnxTuJvdMoArlo1lSDAZ^_8 zNwLz_KUqg~9~3Kuw-c1Yp5CS3L$N+0j2ru9AbcvBo{=X`3+mV#$}j`e`uN;bR&>RA zP@Yc2*a;^6%^P$*Wd5!M%+S|)WgNqSa`A}Y^(R{pL(LcRNjTDj=+T*T-`=IU*F)#@Q|HNDeVlMzl6w)=cRiP|Bn+58Ah`z##ky-=RqL(y2|gLO8uG+P=Fp%)&CBOj#a%I0C$iuTTIgjJ5bg(UatOr-S*g zY=qE;*U4YSIZ z(k)n(fn;K%feX*EU9mfnyGH0uBDaCYf5f0<>nX}2e}4$by5Ec2$1g5DYfDD}c2Fn? z7e;zg!{eu2t0-QzV6=>?Ed|Ku9r)?!#$5hvt7biy`4FC3`^QjcZV_#eMSn~7*oqzd1mF0L=I8_s%^!>ySn<7kPmA6wc8_tU)d)a|;}r5%vkihYEWx zm+i)fSU)MfQ(=mtoxZU6#J;Hy93KZ%X-vH*28?6#(`@eW(b4eQNrP(SGCcjwHg6n( zfza;z==4a(0W)B?p(Cf}0B~vrZPJkoGQu`i!lb zbt!U348}OGq`JH89}Fp^Ik)W(`Y6zEMl>$9^VAuV$*8c1Y&KH3&yVZX07j3e@uL@X zcwGk+5hJ@|_IoaIpp0=(w`QEt087^aiQ&Fgp(7ZvvEWzld0@K> z0xdU$tp25|szTqoE3SbSe&@37d7gx{jYw>F=W`Z`%JMpOi8I%+7{5r1zGS(b#AMdt?k zI=T8vJ3mVMU5021bN>Paii{Fs@84oK|0p_(EeC-hihd9a+?Ggy;BGtIA-H_~Fx%vu z8B$&K-hD~aIDn;Zr+zq+pJ_^g?upiRMw(|(SDGrrr#C@JE(GFigng+O5#%#BnL2E7 z-|>`Uh9o4;)l3iQC_Q6!?bHx29fXO{S5v)e7ag7d!sJ&H4w`O>B>(iAl0A;*Z7ZWf zVLc(_$Ns$#cJ&ZfE!>l}N36ynV?D_o^8W>jzGkGmL^DNk$?(98?q0c&O4U*`Bh*!C zoRJDCRI0`#{~OHTi}g@-IK4fQg+RahdN8>fS(mlz7BuvATkH9VXF@Ub`!9H~M2+Lp zwxPHE!1Ch(#recZ!_hoGqBJmu5|+G6gVIDq7GCM6(I-vlGHcOrmNGaOyyPTUSi_b+NpNwNf}HDA(K{JzO23l?X$ctW-)!*Pa5;-_q_0=_Mw!@1(bze4_=og9dCp`Z(e6Q zje?qxcTW*F1F+#YB9yIdXQ=17cTNrv%;C5F+ho5BYQq z%YKH;e3UWd6_}w&WtE48A?RenI9l_{J!NzB1D^LH52(Pc96&AH-1nCQ0Qmdi zFW?@gnVWg!szvEslyZOAfS>v)(5{3| zvZJnqc>HNL!Cqu0=n4Rr$#0)MWeWAkL|q~yRgmOX1f&2bTKmeLL@qK!e4)sYdX%^k z+4#vEoN~KyC_2YAQmQ#KGKiC)Dnf+|_m{ey9&Xtt+h2*<#~~zQ=l3x!!2IqA_)Q@D zNSGbS*nvlO22}_bV@3tJV0F6RKvqi01MD+E9cU8P%Z zs`l)ZaGMk;Z2D=7eIlqAjI^QC;54kDvRoj$;zFdo;~?DwJVXMsFuIMR^lJ-#&faQ?z>}oD?tKYh&b!h0T_ea(YnIt=seqN2n0ShB9 zK`4=Vbl#S0BTF8hs?mpvHODabpk=&%n@|$(&Fx~gM@eksF*`dkZ^cH48`GDtN>B=e zo}fzAFpE_8?$wVpxxUjA{~T$=7z9LyN_;%T`-+Og3Ew18E%AuYc3<9i+104NK?ohA zNyxX#ZM`$BdG1OZg}STZ6QXu!DP))J*KH5vyh`t~>nf<+-aqL}DFMHH2TrFtMgM%H z7ICv|moV@$qvopt^T`mn=}d500dZ^N|8@h zyygE7U5P-IR*9QXfdi3RXT0~v^!Z`GsJ)}rR)s_49dDNb3{;#r5pzRIGpM4}BhZ#i z(FNZ6EdfOzvH^DHjUej|OS`L8(ph`g9YH=N&4 z9!3A7DLd`N)izdf2_eU2VfvShNeEJ0tKBg?`}BwTP&zh8@}eIE9IU;^zg-`SlRwUy z;iudRtw9upNpIl`(eVtaD@nov28n~-sgK#PLX|Aze(Gw(}#)}?AR;Zc#$L0$8(0Kdy-}JiQUW5SjyPO z!aV`ywKsN>K9|K|+NS)VbDOyj`$Rn4l)jbDl8D&_P+cNi7g)dR)i6<&F5&ZJo~;Bo zV19LrYchgGWoE!ja`(eQYIfkN5VA1%eG8ISs`V-OcLL_u1=89*eSq50A82e`o^iKfdV)zBl+asM{5MD+bP*3A}P{(FU23SL&qla_MOxVc8Rdo z<0XwLG}AEoWz`Gn7(V2^ANvWxWh~Yo-zArk^~A{e*p5UJ5^se$qKBZLSju>s?QIy- zr?8o0)=lhOxQ)CrQ&{F1_v$6NH0ZOuTsw^FD4-l7^VVzNW}}PhmO)XZci8Vlu~iPG zIF{N;&HA1S7%%xT_hc2!s)Ad7_M5J9(zP{+QL+~oz)mnJN}vrDwQEzH$9j$IFeLDq zYvIt&-q?no16w}pFQDek{E!H?!un_6BNI`jn5yn8=9g|ex|EqlDV1cnFc90%F-GlEqPqHv*LnM?(WXq_0 zMW`oE2{~Om2a5(EZG852g7?E&dK2&^C0sYwhh9+F&`{ETA>Sr_b#HZD1Wjx6Xr>c- zL9=+kg@DNR3`3a-!AcYjXP;m-VDAkLtXd<~Sx#Ta1kaj(ml!na>3kD`0eDh8mTujP;ImANo{t^j4svy@p0xe=+~TrErz# zKvclTi%iB0q!p=mBX?&vQHxiS0n=5YyP<^>n7nAqx7dTz*?WFTT+L|p`$aeT38dfR zd!!(n+dlZ<|JPxu`&Qd7)d&zTi|pF*5g{$uaNVa*3fm5A$-6y1)1dKwjQ9DbC~e6R z6YFdN8@+R)l{>QiKk};qW%CN&B20n$ zJ41WM^%^io(S7h>`@xc7-FDS!mF;c=Wn6|-TDL!m@7fobDz5B!RF#WG_5uz<+D_v5 z`uWfQfq{wA@zLNVYwTW(=^XY&A*4ALy2<5}D*7bJA|lkYiRQdgO+E^yazS8TF?tpY zX#F&os2JZ4#n8Zp-q@zY zJAUQ-iWIi>Vso!F zey+>Q33xAU8a+oRDOnl7&r477DH=Qh%{p+tCzPhmp{gX$FCBSrETOH4gv@1>K$$3Q zm9qE3PEiJIO;5O)#;-+Mpb@@X$gnHbz!9eunfy|Tu?c~VPu1ACx3USBJ2R>|^2nN( z*Q|^lgI?_(U+~~uq&ss|{Fz9TdktSR;zC|#e*oSN8d96w{3Ju#-Yt)1Rk zKa@94PkBBVp7b>d*i#hRss#P)cB&k|yW;%u;^}Hga;nLpY|Hv6t_*Wfni-)0&}Hrs zMI3b}LxD?gRZgN(TKR)wUm*)%gDb>+O>5i4KQ}z4*QcY~S$LJDRznlw*|1s9!`2Pr z2M>Uxd?at%RYm3cz{LEtDu@YpaS4mRPn(UJk|JnnJ7sqzEK}H;33tP_e4=nvQ1drY z>kUeU?;*sfI|CR{e#?8QVTT zf4t}9lJ#A&gc%}&E+Y#oW>oJVH>Q|&tRJ6I9elJJ3ZlXN-ehZwU^fxTG_WyOHKBD)-}v$m5XiZT`Uomi2g zy{+c!o9VA0`wxXs#1ev(1a0Yj9ulTpi%VN(5VJK$B$rU42jNpl&>^K++1~~DP>j0N zKVG2+Hv_)WO1=63Pa zMi!vCrO>$Y+ajXzT`cqa)9I?68O1rqOGH4iFu0QGCeqh*8|xzur*G2Hf9?PupMl~F zigDpuhlAtuEk!8{sj}?RL4qlPa|aO?l=CdS)-p2?!FVGB9sEmiS;_RtmvPun+O#+2 zPUf8%>a8qa<>h)fqE_S;`IS07*tsa_>wP0cL6GsMR(ruE*Jq0+_Zz(NIrp?3gG~{< zPHQV>s=uR~q7GbUo@s*$wI_7Lk4nS7pGT;C_2&0ITbZvpmZ7uajNMCo&jzW!dvocl z$8_D%i4YDZ-I(&jq?+k95(w9BKz$#JVXQh-!?kpJi36ou) zbN~NFIMXVtRM#3sUqGfHH4qxO^61Wg13!8wzHEx-l1L5=<-pO!BS9uLu^sZZaEb~3 zUt>Ho_ba*}d{`#OmJxI4=F{hQcN__0&_;$|*`lk}UWqsRhqng2>6A@x60Ie1P$2dh zofKQ3rKPdu!g-7tmFiA?pj>W_q0RR_8Ju2q+i$#~qdkxZV#`XUIx`xx0Y$_I+W~ysqKF#FN3amFm zwr7|RQ_(T?YcG>LQdvJ$o>R7SZ9e%zSKT6wNQ!V$Kf23(0JRQ`JQSNzIo9UuI}O4w zbPi!qTVyakD<@74fa`ktZ*O!G>MPnzHOUqg)qY`Bpl;k>75Zk^I__u1yQM}QK1`Fp z#{I$BN?Uxk`X#LUCICdDC~Od9y>db6uqmN^3@9q-K*O&-&h!DpNk^c!*)dV8frSTw zSu8(Qv4A#q!Khzu;x-N5z?NCp_3kQ z*>31n4AW9bIvtS4w_7eF*0M4O$a!*3jlz11G+ZcLrP#XW@Z>FfOnBv(FKBTF^ zo<#Z1AH74(Tm6nUm&D^G%($XW{6UNbzM51GCa3zfHj*bUbuPSX#D7?kSOOU~7~jUT zKbiJkcUAsyiM#_hdyJ)?I`mzARJV4m`zj0lGXtG*jN@)C3rtu5W?hj=t=tmf`YQaU z2QRWVQOV0+e>heIpz<=_;f`ifU&qAH8rEWlk%ph2;tU$vpsKS?U^|g8f^sZW>CRyY zYSmmE(fbsihMDj+w@n*>GqchoxI#-%GiD(`|Ae-;jMe?c$mS=N7t-xGC4-8pRrdfT zD6|vxx?{%9zi8jk7@B=R2?1?#06sv$zdk}m(03su5Y7lU`1EQ}oV=IsE;}vk;9xml zJ_lq%yB-68%pgyfUjXW=a>~TDi^zW!*+wbNVL2O+(wsb)irrkzHRyqEt{295aDC@wm&1Xbu zugm9Tpq*TL3Yu;1OtwfpSPS+BoSa|E*n?-MZzRtnfx^L2#?6a+uN6})P!wo$nI=Md zPxL)&_V0j!knWNh66t97G4XTYX>ceR?g_}Fw)Dul$OmwXmCt}txM|bM_iQ(f^Z3>) ztzE48sZ!s9^+@f%vCKH%?{7k^gSEJJ`8t`Q0jOw|^c1_K4d9o#)S@JY!*DA!@`=Ic zS^4i0$v0|U!~JPUBzZlCV*w4-GV(*}+vVw2K6 z(!3)^{OsSy1U1+}$^Fe2tK?D=IXm;|l-{N~h|gHXb>U5#{EHpxyZMS=AfLCK(?ib8 zCYIwsw6-uQpT~1AStnypZ>~VuV;M6HDNOlc8tMe1?&>+E7UF_$s@r4}_1mayW1Zh( zLHEys`qo5&DrejxV9Vqza|O(R;BphXfYn-sQ!HWZUtDMaQZGfJdJL?fFUsJLodaxg z*`1rUEOYFGDqr4IX~vkTnNj(Mz|?oK%Gb_kSAUq`*ti1Mu4lPj{Mi8hH@q*i zf9UTgelJL74L{MS))Xm5bVU1~a%VC}a z3sE(3#0R^LjLH!N3XytkaKFmD1M8IbpLDkqWTo5Jh)8JcxaNk*8x)X-63;R!*VM%w z(zLgkR>`M>{KS;lj9t7?ZFm(7$LUDcuv-a?Qm=xE-Fc|;tqvk<6Rj>5KSp|J37hii zfM)>sA>-HBqr~)0@-q;8K(dPaGhrCgN<$Ir-stl?2)U!o1@7cH9=Qk>Jo?<1K=tcssVoAf%tEm8^O!0R`)DVu|1``Z zgAjvgYI^_2fHo}Ud;2g0ObD2or|7pXCgY581IaZ2Z1dmVE5bU`O;fl-`>vQiSfS>mjYH+O_5JPh7+OQeFZ5+3z%w@L$R1kk@8+8TgPYi2V8TLLi}`z1t?b~$Ro-a z`|j$ZNvX_r5PK#V*3`wbraxhJL;$Cz_%nYhwE%D(tHrKb4CJYa=W6=ul|BFkY~lmv zyEjPzFUuKWGO6}4%y+!>nqK^7`8Lk=bG{iz$N=`#dX}H}XYx=s54|q=zj=N6;cC%( zhi4vBi99Qe74AmO&LXcYzU6?Gqw#G;K*kETG9sS01xN4U{|Ee#5 zQ$VnFUkvuwTS9E5smpNElm))zTN!+z#!nd&(2Eo(eE6(ch<>I48v2if zvRt0v-sB9aaV)N=(vwWy2UoKjZ&d*%bI4S>7+hNSPmk{rdDd!5YGIYM3^&rSIZh`S zKiZ7Kcw06fq#SK)|* z{pjByw$D(l&X`9dj{mZ2V|CMdEN2T=a7{7!th$)7w#f_06BEiXy<*e;t(Q2;&eeo_ zhzCI~|86O|!KF2h94M>;?AbuCmAf~&02iPuL8i|V09 z4wZD`p(AmA)eooU>gaqCxfDl{ChC`Ygh+lp=!WkCB|j}utQ876G}pw$&;E)<%k|kJ zKH?!`Kj`7Y|L0F7rG(W?q5zAf{9eQG=#UWxojh$duhXnC!6{O^OT|*SV*?FTPfZMp zUz}uLF$mJ2N`IdMNxxmlYC#3oKkxn!Uwouwj;wuLGjV-%tJawPpGn8vCj!B49`%59 zTzKV`Oi2$ui~Z4?oLaXnJ>L1a6XgW6CDxoAdywLb6CTVwll-Nrb~7=4v*DE8KmDah zG|6VLI!ql!y%WT3fZ0XIK!rzqJ7=hzcI(yYo$ehJDqwLAx(H4>%~K8*Ak$Vh@F6D$ zM&3`-LB#dVe%8Vd_S#^5x1;0=Ki-1TO<$80C`Jq30Pg8#phEC*dKObzPcj;Xe9ZSX z=Tz|}8dg~w-o>F@a|z4JpKxc%ypQnTjvMEVt(h=5)e*<9W;2E~2vNK~&z=l8bb`jL z@aIqH;^|7p!{gWS4+?g14x_RRN>eVg--yINrvctVar0SLh5DqM@E9)NiV}RzMHqs+cMc%AUmbM1#nT&o8lu!@TEyFF-jpDUO^vLC$#jKzK#&6kn*o zk8__v00r$0+|(Xo*CJv%qts62dC!&hlwVi=7K0+7*ig=a+qW%UGISrJ)^221R0BBH zA}`XlWVXb)pp=99-$TDsq3A+yi>$uK<-U{aHUsJ0@OqvIeT31@nxeaz*2`mIJTaq=DO?}LMkJ5>x z8&;}XsyBvGf?&Eo6$@b(KuFp95q4Sw1;)27P`f}G=;(D1+(NA?=kdPAP`%OETI+rI z;5iWYU@%nBiRoprCc3zIQN5Mt>aD{@e`I&PiNI_IcCjW9o zFGZ!@nZfad!dLs#`r&}?P*`6Bmg(z6tQ|xP_P@i=z>O{odF|P&(BDK3!1@z6)Zd%O zf%P$D^v96qf$ofdmk<>0pXv@nrAj$a+ny&KxL-&GlMXTh>JUgotp=N(fbnZ6Z9Xfy z`^v+Ji-_>}?JIE(C7=kb7tvB_3IunNcEJ42cvwcLAKJwy8OqfVf;k`tffx074XKb7 z(Jh1&A?g5^k(b(DaW;693Mf-B&^8sS|K#W5kpeCseP&XSI_fUBCtMKrA6!DSs+HK+ z3}zly@l;>L;&;T~Qn!0#3BUv z3AfMLbdT|IQ<&so7$B+af{c`XGs97&XnJDz=cg@PWG{w$BNB`_N|6(Zv{7?1eL!6! z2+uq1oC+NZ>ryDgIv{+o*rmWHIwaKJZfdt7 z=&MsGVO7*K_aaPfimJ*uA9N{zNoWcgr&m?YK$;;GdZA@lB5M%@0*L~KfK2advSzZc zUm$Yue=Nfl)}G-tu@=gWhjP$?o5>U`2FARYwoF2weq(t=JUsZQzq*g zPPY)WprNGqZC4R-E0PhhVDb|>!nr`7s?2AaNkH|}vbaBM16GO1&7>|=R6QuhZ=!*K z(0f-SO&m16gM)6nPqTbd$}Bg>;XUzd_%8;%`J&TOAAiJ$K?J@S{Xs?!_LU~TtuFE0 zOl6vRaZDGbwQ;5l{eqI3RJvv}EEzo>b4gu)qB5m0E3l<(WPGD;Q;vXpAn0hw)aB$1P~a6n?Vo7<6-fIuHn>3N{)K zhhSj>N7i>3sLuNA!&eRUFoO<5sYyGU_-jq$Y~WrvFSZb#-A!`i!|>CU$`4_nJVs9yPzAY%|rmR@DE z3Z;%ne+6qP{3lT3+&GCia#?iMweh|&7&Oe{a^x<_vAblIg;w^y!1|T?9vBNofGI<7 z8RYZ;Jat+pOpSQDzLpa?$}5qMXN|fZ20LlbjNZ%)yp@}01W32*CO^lnEK7SniK)%q zB1BLI&hiEc| z3Xt^S_&Eg1^IKYC&J+qWw89RE7-c$%(P2!Ew9w8r3paQ*)?T3D-CBSJ;|)E6JLUini69}|Jxs!H)y z6U?hAO!>5H#p$Yx;nK)Hqs(;|A6d)KLBN zi6|h?EJZ#kw#7gY)787x+1IMnYKBrwY9vFtK|>}q54*lZ22myd!@7GS@J&IQ5lTMeiR z!TOF4|**k=9( z(9XT6!9Mro`wLD~>wF^5ck!wr{N04KHjIF$y~teGhHB87oYN&|$CDXY<}7E!*SPg4 zX!JerT9U(x_Az28L9V)-wL4v$5sh67Aql^2BU&X!c6J2*3INJE>>))x;85h%W2oPm z7tCtbh!T;ET<0|zpPoC;Q&vQ|y=%*1tBz@Nn8T3f7a zqnKM_AZqh-y{mHYm|-Yr_8923xC-sJgNr0eKVkzd?1`PN?c)e)!Ktx4S^FyN_5B)w zU4+hb;6e6_4;-KwYTb#g?u5Dou_pO=NQW%!ugh$D1)utte2LP2f@Y_gM?(OxD?0dk zvV`DR;-(5FH|PH4BvcpAxbdK*$*Etw#-UedVi*0!WBqZD&*atn=Z%pFm(wS7Q&c*d z#m^)FrC&VKMiC^;kfS7_2b{#VfMKcg`xb`YQ`{fl`}_DYW0-FBIB?8n`#wSr+@DVU zCR01M)*l9%!MNeq7Nxoo&q|Ce+QbT9FUj!Zqi_2;pH6<0i~Y5%@q`&U%jPqdX>vJ3 zmEeeUj4|oQ*b*U~(#crWhp9Y<{!-qzkx3!%TE`z^&z1#&>xID?S}A~klV`)8Z7bF$ z7+mcOT@!Pi6U(ua%mpy{L-8a<^+8g*WwvSniClq6*p`I0BJ9gC9)8i7ZiT;ES<6cP zh-~x0X-S!ioN~epbR=dGdi=@6Ys`>l!$vSvq#9S8`xj_Uzh z(z-4<*{KIZC+lFYvDU_i>C{kb5(C_7^T)iBsEJur;c2Lzr0$T|ST+oq@B&_tYbwVL zwqUgleAUV*hQYH8U9icxG95~D$8JtSUv`ELo0iTo#MU=rM;o_XbZ~J9uAudTiYAet zPLQ6%ii^iKl=q3h@n6r#S}Ow=lfhpF{xGZ8VOiR)K8!DUq<550iSUEno|nTC=ywrH zz5HYUm`Sz3Z2}RU9K{?I?p&23Vcac0qDG7lq&T1iOtB+$Q=t##o){yZlfI~aPi`QvhT;Rf2drcL6zaCg*cawLE_n#i)Fq%Z3U)8ngSkiCh}=Ls-9B_Zca7hJSjP#23W zRq3l-hd%|(1{Js)blIbjNp&AHA4*D%@ar+((hOnh3E%#U-c<8cR7dMlLU*1d+Jey@ zxAZLm@#Duc3UVEJppJ<$rOKZR<=FE0{TKeMq^WSSi-9XFI=1HG2(3i?!9WByy&=x} zw;+=c`yxH{RGHJC|7ZTqWuW~G9{i1>b_EN<#l>e;msl4Mr;HxOIE_R=+=|5Ux=_5{ zz7j+M`K}eLWN{*uI$daW>XUz^>yz=QjM`Ve(p~qaYzxt)l2MnRD6C}v2-1rgE2k5h z16w{81Ob@WWvID}qOyc`kf)h-&xV=vVzUPErcamq-eck zHRkECUiPCVnj~Jir~p}6p4Mi$$=H?XL=W4;i*sM9N#2F%E<0F#)0y8#V;=xW8obo! zX$Z-k5$G_%rhR=t_f1KAY4%88Vy<9;2_`qlqZ&oLe~D@T04%4U+72@)_p66g3yn~d z;C#}YQhk6A(RIXENJwUP11B^1Er!p0z0zP7!Yf>70c3vXnJQ}4^!NTq60cOO0C*)V z(aTXrI<*>hy=eBfzvIPY-pN3=?@sj3u5%I6>Ws9%fW#n-0U5Lry=;?D0xee6ImU&w z6i|liDHoAFpvJ=66y)_5MxxP|^Eq0nmtSo9%G>RD%yTnClJ|seAE0S(6U4OdhBthc zoJ@J+1y>G}k60*b6|bA+_5AImkzY3lS}72H`D~oCEvNjjn4^lysV^cETg%5vK?rH& zi27@4^%qPKg6mUzi*EttdbG(g9nCaYzT;Zl=tFGE*gC{xF*!o?0YgGy1|v%^;%lqc z8D$nrt|8}hFRegzd@l2SF7_s2sayxc>AL)WoK!}*NJ!a1@X#dr1ZXN(wB1Fnr622R zgG9@4zaATaI#GSLEvt*=U@= zU$C|MN!T44yhrC(ytW00=&hHdhJg)7=Gh|Uew%ifEbzPt$*cc+sc=d@3*ZX){=04{E~!zj zZTHNC+eNRE6jucvSt9gHAmw8QZ}`A(YCRfJ2b^M@4!6`(m+GDyYk$S(^;DP28%4aU zN;`K{OrCxpaByS8<3|oB8zR!ODq11-SoW%-g!adM=OYKOJbfXQKSw4>bfQHpy!GHP zXk}nA1D_DGg|GRRv`nJot8Pv_4f!W+5naVYp1-;EI^80vac8exQHw*{@T;V`MpQC6 zP6tGs;VmzfKe`7sUwG&!{+B*i_A>Q!hP=cQ8`8+t2i(yPxG7VnpOr7LG;Y}U(b zua@GBwRX@|Pje7QM`_Bor2Oya)?ah{NhlOjlnSne>gbGgIkY8d&kR-wt@XFo#%}~y zie3WyOFWac@?0Y`scA(Uw@FM?aL90{MkC+_(3LuBu+8w=hiZo9H;YRPL=?M$N&ef> zhjikOb;Aqa)x9wWn%;3%k>_8{zX{TDdmT4S6xPlo(^lcTU0eZ=Uq7a66Z;IK+DVKB z(-FNGzJFeNT^FUDum|qa5Zz3D0~_37lxIjjwpJGFQR2MmcONFdGIHJ5N>qYqy`HnFGx@bQX^Ug4yP%P7gnP9RcLwvJaG5 zbI>R~X`649d{|m62%~V(qLZT=GKA^b?ehmVW43q$> z81FeKQ*26Aol0JCQlS=#Cw>nA+0@Ps=cotpwh1u&QJ2N<*dB(}%p1DzNW*ZE?yVl5 z-jGc(bLrP1KykX@>opDdO-lOpi$SEk+lly!nMgJQd0xTCl6OG0XoWh|jqWZae13zT zZq0sp^u_ZK`GuM%ZhSV@Z5yaIDc zFfBKM{p14uCaO15|NEhpp-rEGHOe_L?Yu;=>60r+O~F!&EeG|LsjIvl9F}6|7h#zj z(OaYsRYd0zhIv?VrKM1({MJ2br<mxXw^7!y#0I4EhQLXdl=T(l1*(e6sKCU8E!J4+M}Pip!@@5%=jUF1)5R90<2``~g@e~hwg z-m+;KBHZk>qCt#+PBJSaduIKmp0_vjrds4oieamK6(Ef(Np!EAZRAgM_%C&@iHXzP zm6Rit%F`z?mhbsy$n*2L>-dBUxlAycWU25ioXKNf!6k^;yf@OL%=W9>l=HQ~URC@V zyV;{~+g+jovam^tWPe-+o`ODK-iZmPbRh)JOo;SmJ|BlZ6WLm}Orua^Pfrm3l;lPs5hwRm{fUUP4`&;)U%z{L0Z}ofRUo8yQWF(4KXl zH?419^?b9bF)yfYlh!9IQ;epWYW-10GrsBIYCynw z?1Qo?jD2Bbc=y5Um-J5ArqOMuFxIedI-mV7sMgq|eu<`qSn!92O+sHUKj|Z=X}~1b zE)YOp*RcfYM|mJB!f03u8&#PSzp)W*haUXQhuGR-oI2g9$#?ww&Wmap!X_PFheL z#07sF?;xp}s6e!{J%z~b2!CL6$nnRRigXS`$Q2<6K~@5o6NrF1tVRQd>S6l)Kh)dx3R*^sp7uWv%1Fx-qdSDg+`Yd zE*4F+A->C^YTX*C?_vz}#GaBW4n*W)%F;S-$IgGBy`I7b$vJ;9Sy-QuLiF~~uR}JX zn}yc?C_0ZV1%V)neh>?CT9T0*CG5ySa)z%TX6q4k=&E}6GD_prM~LWSrFsJZJ@O@_ zgNPd??e#@;e&V5%)rFFf}?5>8>NR0$acTC*O*t4CrMt(7D1dYEKlpUI4j~^^viQynTW-a>^zL;c z?FhjX42-W%cH*A4PJI3 zY~??8YQGgkvHd$3E)_qCy-pqE8@9S$++sjyFcG68pfDdu(AH`x{Qdh5D3Tnf%WK=F zMTC_sxNc`3Me}Gb=F|VL%n5g+VGA>EKs{(Wa*qKa!{XpbVG-hsv7CT$6%Tm2P4F9) zS2XocOy|PRoiX+fEz-5qRY6L#Bq|Fd8!xvL8hdqZ2dT^8;J-Zq zRqM-eQ!o>#$tq@UF^f#X*;2QmN8DN~JCCn^ekQn&P7AHtS zAvU3gbapW6YAJ&k1kF%(Xzn{2?!ufMsVT@Jp_k4p3H z)#dNk65`zS_n}?-25T->kmsG#B-(5}01{B_YbE);B}Ht3o&IIOdT(Pqd$gjQs+?_7{e z*3z1AyzEFB|FF(w>9}JZSY|qv3aNbrp=74lgl>5|_l75k6FLM>%xlkb=rvNAxTASr zLq`!ZQ#^2ipT9AWqbs%Wg9jWNeB{ka;$)v#4(3iL?*taY>N)Gl-}ia4W8!qj0~&8) zZPoRrb~cT5;E1wS1j}AqVzZaeT!P{!k~))RDCP-^7E4R*2!4G!N>&4r&PNuFcRWU1 z0CxWWw|YGT4C7lD4@3r<4gBdEKlTo;iXb4jqnsXwCD3!VYf&7$SrN?Ftc5-&$4H?W z2VT4DfcJ)+i5G2HW%JFIGBdUkCm7n>XpXhPc01@V&7nZ>(c8(}&GZk>umQ8A z*Ki%sCl6e$+b&^^ljQ!mwM}y8G%Awpwh#qmxxL^`>Oe{r&4M<9{$w!3Qk#%Uv7b~) zW%7yF-a#~;GxGq!F~Vefn=WOB&0s-*n*E+eabpKvzh+bh=$<+01g z!REKS`O0fee21a~O52rI#$>fvLB2|IMoR{xv|vx_b(C@Y98TsRc;^N_mTS|7aMz?y zkh#s*1Q998JFhiFn#eINJ#Qu#?>Sz9rq744Wml&qduD^#j*x9|Ae*)kgw|ly(=7T+ zhmV(pmIA_aN%l(=g0tR!Tq~(qEP(lTRu>t=)7_1?Mls|(Ig8@r^|c&8{Sm2;fh`PB zRRHEfW=?>IQeWpa6v%&0on5p%L^p_)J?B?Qr7x58PbI#DCc7BAMQYjc0huc&j~4;> z|2u#&P>sFyH^~BY@LT?(7g|2v3?gUW9J1nJuIR6m{*w z*BS~5ptk)YgG`agJ+`E{q51jGYRE=d(?!ybrEBxYnIq5?R;P!@`F1_V>k7% z)xObw$h!wejZ#23;o3W70{JA+w?n9m>Rj^8i#L2~;lpf_>9{AwX9sWPhLh=J-0&#O zjs?o2QoQTH4+&(0=u=>`%&6TcWlLBi$_q?sWAqsw>w-Q43MpWlHKvT#W~~~?Nx75_ zQN&u|&kU~TxE2ahE8n`}c~ur;rw4f?FGN~*4}n&AMe9+s&2EK>1|AOkTqgW| zRTYZ?GgW^-rZciO;Gy9OY(36DmOmCPHDz_HOMd54Nwp@qvky`r=!bVZ(nr$u7!!!CO#TEgEkkg zOQ3FE6|FNlg61U8A=hXY9K>80Jy6B9)RGbM;UH4X2^|F>fYDeI*`Rj7bH*3?nTdnD z;jH+vd%}QV4@SylCD^Jpy@rvmT9eRscdxKy!-J)s4is{317ZjhHQ~PIa4pi56$IwiD)d90jWV{WS4TKiqd!8?!#OVqBbe9^@Hm5exr_R~46m1vzT-7O^xE@kV-%GM6+8#|9aZ zqcv97dsDqX2EX02a3CtVjilw`wqG1 z<-sE$;MAjJ&#p9pb&Gx{r1QN;|57f96<(u*LLAwoCCM9^;kIf<`ELZSu_~jC_)<2n zwQcPX>2lCoGhDR&2{Q3D+KWMGRK_y;LB??wN3J{&! zkLB-4q0FGAAz3x$D%%oVFn-C|GcnzI*40IR!j>lj68AOvYYa26Owo#cq2Nkiwswti zV2Q46vtdHM!H6QO4(%M@Hd-55Qd}PO3_5Kd;$ijs{8&h*JX#9*PyQ}yTPUf){^TkD z5Gd?p7Jtay9QagIV6DY0km&`|iJ}PZkABv^`t%0Rd&(!IPc1{2>}RNbQ(C+z>a?`U zd&9Y><`I||>2{yA+g$k;BPMq*OH#o46fz5_`ALRRImM1#EnF&VyAhs*TK!%+++!S2 z+wj`DhbE;EyQ_!*aP~<^TxLjb4^>$f3k#Y9;5SjW%In|!c$X$eiUfBT)y{MNzDCRv z*;7bIlzTGe5aMCvb>z<@mXxx4s_n&K=7R#ouo zQoFVsBOheORnM8DB^!tUqtBMP)St7xXSL|`9XgEwYw~%DBArhowEiJpOsqR)aZIY% zB)f9uS_Y%n$_UwE-AJYzJhGmi%#B>e-aR-WB~0GX-Ui*8zjH6vU-^y=N%&6aXq?b5 z_rqg$NBK0f!ZkgVQ>~K_%4B#|m-mEk?Ky;`$dZX>oVn&cIN&0?z8E%t`kMY?@pdWv zNE4^J@P$=@O*FWYR#p7vm5bDJS-orPPm&P!#V?!MS5+h5Dsa6z6!2(nGG6Gv%MTD$ z3qCOd%Y<-xc;dXSQ9E{lw~6_uT^0Ae3}IC7h0ZSj9fuywL)h@q%rDmKSSEL4$Y38V zE7cvB`7!l4=?JQFZD*hdsdRiJs9_QUM=D!Ea2*fB=sA>guCg)|%B~ZhpD|N>n*(|L z(5ex#H-+hX#M_utGT-NpQ1u=TES!Jk!sa+b)2Og|6DMk5Yg40{uUhB>)WKpvWf2Nhb%n0=Bi6LxHG0AJrIcwDT;V}%zA{n=HE zCxinp&fuf=RcZ7 z!BS!v$_CrtAL@`cbd`sH`d(G#>cciDOU5vnJud+Cv{c`aZku)!w!-aRpojwbv+iNG7V)yF=kB;3D&?}^s;K9P;Q0GIr1KRgY zJCIe}oW4>4brszmF)t(6ARnrad|K8!Am-JIQS!2hchG zAWVR~B^`wUTegn&TNl^*oyN8hM!|8YT{30@3+CVv-!3$GlwgCJ61n0k{7z zUzd&StG%jTY56I4QVBSvG2~VN?bAl^nG}&XV#Nk%Z*HSixP1pL)qjvNoS*a8;MDX16G_ChS_@+N~U`r0CkE7UPx!f#*$*!TlOYOl7VUmw2CD?Me&3s%uV zpNdlaS;o>6X>n&}YW0c@Qc-KxsAlkOR7<=I%vVb^d(@N|)6i_Ut0>uA9e|BtN*cB#W)5h$*hb$sMFaFbLTAv!I|%i$R|m`pRH%5JK*=EjjK$ z(Q(YcC+?e-yzz3lx1ac^9AJoYlBRp+KC)_+@A2NC-@h=?SHM_{dX2_&6jvQ5o&7}A zYM8L0{CssK$nQd@mPNtVHtOAdsTz0#6aV&k`OJZc*`Qjvj!4%x6pmUZ|D|PfgA7ad z?fv_P#^8hLS83XJe17QctotFvRbfHGfEm0*t_l7@M_E6PmqoqYRJ@?U3U0Q_dwnO* zgsd4Qxi6LHwoa8?Di*~le*+TbW$()>rf~gE=L-zOF*4HVX70Ic>kaWUEI1lrQ{B3| znxUio50-XPP4;%!uA4hrE*A%EgL)+vrZSSZT@>oD9CbiFrFH3e_7mog+mq#ULU7k| zOCPY!!uzXiCG6HrXuvu>_ZdqIk}4XlGwK*Mlzm&HrQHB*8T1h=kj>7EQ`NkOqB{9V z#?4LE^u0GecYav*4ChR;`^t|X+ung4<<>idv9tGoz~|Mhd|ttg1_`(R-+p(gOWe3c zX1m6ec|yFFSDm|rPYSucnBcW(iQYrbna+_8#Sk5!$?0dc40x01(gh|7z z&&~=&3XR3P8jA+KZ)XT5gYQ{$zmHXvN)P_}=ZbUw^mX`H7O!%1sWv{D2^r(2UUK7( z-B0QP4#|5j3!5^>A|+T9KNTN4#h&4-1+7_f0&K8rFR)F1On#nQ-}HSUYLHkkKQ}Y~ z&iooz@8e~qrZj2b)#7K9HDfC|3`T+_F3tZwf>x$5!1wx*Z!-Gxr+FHoex>5HgRz6L zbU93L#>u}~`mVs8vzppwnKOpi{viHXnRQS(@l{NQF z588~OE-gkBdcjK}uyUMGV{dRKY!of){;ay+5dUN-6;Ua&&}D-LAW&NF!|XV8VC47Q zrE?WNPSE0VwRJ=-WtInM+U89!W&mme1-p-K)h7q&AQA!KD?k^t+7o;1Q5LAW*+f_+ z?ZZ?|*{WM#%^{laQjeV%r2?g_ZeAsX9U;Pfovx~V%V*2@8@=_rkx$=@Es5ZJ(=$MB zzd1Eg_eW%^?H4H$_d!wv_$g#p?GCo@n_(H(i$Y32VuOeSt(0P@>w<(1Qe=7xZgHgy z^41N&qdq?*1T#73&W_~*qjF;hBw~8Kd^u04Gfsv$RYRY7v*e0H$$&8|Xx`|0Oq47& z(T8qKi?xwkz9yZTW|Ogvg0?=H%lwAPYBjg*0bS_jn8@NPSPDiV-}0}o1~5jb`-R|( zJ#0A25YmQ16}%*NX5#Z?r&t8UYLIvkKu-@{2K$uHcNN1;SbXnm7sg^naSTh+J+^3> zI6;k2jugBYXhLFyv=gm ziy9dX<#DoWUHofF7ME-biQo2eIAd?-KF2e+!#-g;xa|j^#4o|IF^L0mT4qHS(lLJ_ zkEgrG(%~5J^+QgNKj)56JIJ0NhLd7D#;Ei+$~~r?@sBYUh#ZjvsJ<*?>}23LKvgNHpS(TLcAO#aDTto|I` zfOuJ!BuOlBU%?A`O{_l3*xi5lG_zaHf{yc$#wDqT`biJ(m0cxW-6(kZd6fi?2K@b! zScNTLhj7DhF)j77@Ka&FWs%rRqH!X~6Jzq-6&l8-^^>(D=)iJVJx^5wQgU2?;cbdS zx6iLkP^&>RuP>JaR1f@Vv+s}y4-cd^6Hqiz?f81r?zgOvwcCd$Y(cheoJFIRg~Qb6 z2`%Sl+F>C^O{e|tw-SZxy*X*iz*LTNF;>rke_%XPbn6Bi<9d;`2J2#XAF6Nz&6rRS z@W zZ40W^U8d);f8!pzw_jV2tL)dOb+dA2H8PI$D8x$#13_CH#e2W*UT*kkXjScCQKt&^ zFAsD-th?__ItC|$jwl{}>T!pAbgX{%oyQS-TW{Agee`VXK}4|+U|a7j>$x)^et7i< zGpjrf^Wb%(gc=+^(fawI;pGa5w70fSqssrU`oRWPE=$nHph!nw6-CwNdlOHnkz5hy zgCP9wXvL%!#%6x<&jzl0dLTqiAn_Ms_w00W9z!H?Jt5H2R=qY$a2&c|j+>zPl(18C zO1^J3zSa9`ErCnJ!P&9{UV{nwgh#|v9?y5#OF zhwK;aLbPvno`+;`WacIh-UXC$1dFNICHV;x6a+XDR z`;iaN?^H{^n-({8G1}x8gQV_38p@PB)%I6nPQPkmoKFOQ5aR}Ax4=*&z+*CCLN`=XIxZO^A~zFnuy#x($vH+#>7z~f@35ZETx_cs@T zXjOv-Rfkv|8pCrjF8~mda#ITa>T#caV6vFNf!8$h6YY$G<*%v6#-mV` zp#|Z{nphi~X+`%z*&gGHpex&geAFU+rcNicidiP?h+?Bs=uC#n0K{z5vdyNpItR}W z(0QhCz=}aVppS(kgy0*iDuB$;K|ZlMG9Ir=_IUt!2|)+w z+hbqFa;$5*Q)Oc3I<}9L>EPgbYE&11zTvw|2SA?IBKPBsjwAZNG_qLk(Ie|t0FZ^x zhd$xskoG!O=Kl@)R5WoK7A3BF<({HNk~}5!aZau}N4-F_=3eiS!t zNaA_4-lp51E(~=)ZLBdLT9c6`gEz|Y^O3SwR+{VZ}(IdjmX+^N+@!iO} zayO#ld4q7wLkkIDhtU*uHL|cirG(UL7W&os)rlJ1SSe%;=_pRuf*y@hD>FtAkea-@ z>5v#6E0bUdERk6b3MP_HJR>5S@dX0B)V}K&Sj1gZ0ziNSPFI;=hBJ}Jq{2@2AKP}0 zu)?&>TDWg6H5tSkrRVuPk=Sf4BPD?^hT`<3VAik!9M{`dRiT`1LM`~I0Zr?Wgz z^cEDtFi?@z`u3+9UZ$T#tWS4>%ef*n6^~+**|1>MstjD;cXW67C%H#66QuamO==O{prU*=vjl-#NpFQXA(Q&J?{%-_EUBHscA-AMgD|NL1K|sF0;~n#B@^TiTLSDe}_r(>{fz6T7d!6SMaCHi9V(d=I(upheb;l-7{ zYpu^{Y5y{nH-^Bq%iosb4stM(s)?x+Q6la$1LZiz`>s~oK83rR`~UYK;}d`Jb~ODY z1FF;@Osj%BMWq{d9E2!-o<8Res-@_fL`rBz)48gZuhBQ?RyrEy4C&VmAd7PI-8!D+Sg)#~ln!NXor?@1 zKJ3tZKj-g7Gw>LV3l3hj;W8!LkRH%+((%)w>@UEQ&&C~gXV@bZ4*heU)#b`RO7>7A+vR$f z#ovBplw}a6@f8H9C4eHjNkJrT^bY`^GNC957Qa4?bZ$e8NzjJy~C-7D&1RevWyR$Qljm4-g ziZ3kvP@!F37%Nf;Dgf!$bxpZr0cgd$)zI6Kg}bybS=mQKDA#kFk#smZp||o>68ZMf z@61!dT4tzD2R6-kW~)J^*Yd+~Rd4g>BR#3r%TK*i=2~T$vSNgOg`%O`QI5=Lz(2P# z27GpKt+s+h{>>tI!IP6)ymXw-r=6cOM-MwSLH3sV}*qzlx-eE7NSo1!}8!E>#eJgwM6@{^-!EdgkC~QgnPf z<0#X6xy$N(_nuc_x7dQ-++<#Pu(6eHhP3s{s(TMfymEybLmz_APpY}n6A;EVLD6VX z>(oV-HY$Tma*^;-hUaW}IF~ib>Ct^pfu*YYvkFXb;W~91i{L%!_o&k4bkM1QsUYVr zvaN!UR87wLJP$EJW|&alYRji@Z_#{vQaRlVj{R5>fCyo1nJ%F(rE=q(l$Dgv) zR9*Ojtdtt)$n`P`xV805iG`>yF?^h#CX(;*Nd3-CepYauHfj}fGK#0~n$byY6Fd#H zrfa1#nV3K1L~^F=zcUz*0lIHCYT?l~V~ppQf?Ns-3Dv`xu$)IYY9SHMje!cz9j_aM zc0U)s-sD$xPotD_B)8u&S4}eGl7>vmEt3%d zFn2-iyOAojRe1zFs5f(+I(aj(KG-Yuch@NQzt4_o=BoM99zG(?#Kj11j;V+zDF+vF zjw(DXB~h4u{K5H^=jl}4!Twe^g!q(fm6iFw%7eWEN)2a8W}hE%Y;XG16Y=x;|4UG0 zvI0Enq}LTFNIRW-d#e`|%*4*Fu~nOOyDU(ekClCw>*#tZE$qgtgN#yAp7!v270SCY- zB||CY)AHWS=ZkP-L8tHVx+U=J#>zlYJP?V89;gzstHJwn6gQBexNlynUUk~;rb8zyjt?n$w~Z(2);zEL zs>)M9;lUS{{0<{Su!efd73yLKu|f8KUx42WXZGb5N}laZSps{4w!^4ecf*j7ofBIy zxFunL4RhAd``U?#RM=}g{*8h8=#29VW@W`I2l3!R_l|G_ID;Q_-|#F>@TwvUo0GT1 zJ)h7bwQ-o&^Qf>+EBv*{MWnv}qQ)766nIZAZH{6$e()5kaUS^^lWE3yjra{Zu;5++ zkhxub1tIhxwd5~$t#-7*ZZR<2y2)0KU7rofIy8{P;L*w6r;mr|{LdF9&KTPJy7`R57=pp5bCa!{?;4EB2G2$1s5g}$|fG|Adc!*~BsQFz7 z5`pd9XqI+FEc0rz_Yg3FIqZ=)T?#&HecC<<^zp(yTloDM+K>Q7%+ zXBL32t^)N|bHj1C=8#x-5beBsk0N9HF)}sBK}dsE+Qw*Z z(V%2-&wMC>Q&gWQA_#2tDP(oSUxH>#ODE1#1eL>K?% zJ`~a-m0xmuq%5!Sn0Z_{-UKMMU3s=MpJKPU3w_?O8XygWwD=mWPLczp*L1_sNEn~7 z^~bSji03>x5W;~u)JT%I>fV_91>*Spp7C2i9~H1szx7AO1K532^&*FMHkgwIL(rTC zxOtsZN|gLh4l`nyZoOcBhb22R)&6SV&x+l>qJl#a1c0xJqe8|slKJY7>o5Q7hHX-+ z7@f1JHPXoYOiWzKJ&4kf!(9AYclEFw?!&Kcy(6@EP&a%RD@=4oq&)^J) z&hIa3^_bw zV|t$SuM7$R`-ng$=~nOya>aEaaRB`8q+m`%ar`ai)U`P(J?HmzXN9tIh1;Iv090P7#z+?O8dk&0+TO@7FN(WZ+c zeqjJ}nS|4f{p&)&)(J0MRS&YrB@0$@!^~zHJe8fmWbz5T-~hnI8U?VC7}*(3t(Q8J7GgTY|lP@DU$0WMZ=8gVPjt3cG;m( z{~Cd6o!K9B63HyqY9cYu*LJ@@X;L_=$-*=Gr1s1;|GQ%M^We6yz^f+kt7uT`k(w~EA zWn1KDSU?BK!GKLs?h)`17Xn$oq7V)O&zbT-tTE6KDPpKD$d02Uca3}Tc&aUU}Mul)RablPXmQsRZ~4-`uwYSZgCQa{uPd5H`%3d_LXNLJOx zEVgo``o1t~VxUu0IzkrR3sI1XQ0ok1`bw8=E`*gGzYNOAPY*(qr;K|$&g>PlbOAqz zfX2roW|@dbq0>+)5}Hlblwo4`*{eku^gDfC#6tB z>4BZABC$xZZ&kFB-w0xY-|5Yca-^*T0`H%~{R=ke5zn6+zGGJB~IFEU)cD@Ni zxSz+oKdQI|c~d)0G?kM3Rcrs#DgJxxH&&Bq9z|h7>ZtjB{8{LJ6aO`|z*Oi*EP3mt>6s-KZ?zU;$c0Jbmp~ZlyA4=`UiP<5NeU`d;9H}g z5GHs9m#pM_?~-d}=Ba&upAADc45Qt*Z60Mr(iH9-SF3JWqI!T&7g_Sd;G^aKQ2g5$ z0imkCUf!`n8ku{qI!2^Svp+Mbymm4A9pXM06YVDWvQb?~HrPmty&KZnYo3Anv)rxV=+du@ipZv|AWo6At1b?6!Uaw-Oe8`e1-k^IA7J{1EyaheSK}uNgB#^ zzKBV)%Ga@^!R+}5k9EKy=bwA-KttT~VV z?!P#M)K2}pSoM$uSRIndS?Ws3k%Az!)Z4CZ-!ZDCOZG0^LD~oFJ*EqPz$J?P4{cq* z;DA=z|JZr{5OO-+q6?GGz{`NRuREF**;tX~_9L0p%km^|Yq`a6oN=WR0z8y=V4tCZ zChY>6sN4O?p(g=`?FN0oKqI)k`sF6_Cjwr4kcL%bgi}9TX+Kep)a=$tOi*UTrkalR zXBo+$!Jtip6{w+vW`vS)4S z4P^+A8r69A`now)gUTrJ6(?OIKY);fq^FI^5V=J1o}U3kG|JoCY{F6vLQFma>h%5s zef^P87VI6320*SDJ1o1ZB`*dx_%T_E!p@EmkQzRac>s`k+ zz+L#ABkodWzFd4kk!`U%^%@9_mK^nb&H=Ru7HHU+ zXLk8ldF35&u=Ud>p146lt!WRAawW=Ok-%Ymg-;aJ5*-s8S@kyHkKyW(Ls?f6Zo=5q z{0lCLRZMJaM`X`AVERJq_W5OO>v$*Dww%c6C-d;j!z)CAp4QBtp*MK9UId{V5C`_2 zffcP6)!|ohBr=nuLEm%&i4yg`uwLZAa{m#tSx^ovFMug0W%TA5& zqM2R65!j$fT<=vdT}tX(6(=3VH^eTKL;B@)p;om>P>zGQGZV7Yr;=hYuX zyiln|&zeeK#wXxm07{IkVY4JKXB-DE#*ZonSo%EnoU-y!I~-O|yf`#t^B8buHV}F~ zN>@K^LVX+C00{oo^;x%=Bg7VG0NyTBt7Bo^qnqwPtGMLeF_ zwcqj?Xu6{erQtzt0WJ>t!L*u(ne{TE(8OgI*#^oHaW%bFDJ*B_fA{AwSfJmN=Ckf*8n@O)lNTIz^1X{Auiu%q3 zp0+x9>dKM+gIuu)L85*FZ+(V%m4xT#`(7ARL2h^V2!-VneCeb)8|UD5$;nv{#Nm2u zK;Daam6WQK{n7z+zUk@jEGK0o#a#6!Ok30TLBMfO*6>N<1ybG$*DPh)2PO2|)EpG) zeIl=vg$wWQTXnb;7lSD#m>-b9_cZ|~C+u(fA>_*EF$+3?yn9K5P1b2UxBM=5&He}p z0CbIs%(Ex=djTAH8!9!%Hvyy52@^c)hXILYad?yxK{^&8Xiu1YWEo%H}QyW(5c z^o2urUUT`;agNr@4kickyj)aH6F*5-`G73`y((i%{n97D2!KzN9jphHJR@Ac6kNm0 zGMdTxX(&WYG`OEW^D85GS%3;Du@fY1aDu094$9x7#^B_ca zS1(Cd*}r5_N}nfE8Io%p=4lJ!?#1VCx1N31hbG(o%S`C_nSFogsunH5@C7IqGp>ju z@0xdCaO5FMso3w9*w3&49|L=;@jmO0vWEdlXY0&6hxgynS5yrZycG0vZfYpPMSw@$ zD!b4+r!sd%QyTW%X9Q{0 zKYpd5|GArqis#PJ=}C`bxtu%b#q=w24)Oc$)e|kLlBjuNaW!6_7W6$@U-^0;8r9~Q zk#-K`2RumMz=n>_GWTG0)C}U4P>}L9%jFzfy_2ht z?NxalTn7lpe(19m`;5{=UY?8Xbzc~Tqna^64TT%>{%OeVxS;B~tf3`^et(>qcSRV+ z20)f^kRiO7G)oxy$wlMN@_Yu}DlY}2-_NOy0=EAj@gvQ-qz;)2uJ?bru6g}L)bFlPS> zcENC&Ex_D6#VMZnd>tSyXv`q*N_|9hH{=JB0nE&qi_|kp-&!-^Y(!~-gpMlAK)uX- zl<0646O-97-A0%_4~rARJ4yQ@&%*o;UQ4R@pdMpY4Wk;J_;@ORKc=iT(m6X_ut3&# zJ?blivlM_|yA15tz5vI1oZkf*zy4}b3tV+jw~wk)+p_M#UzMx6oy=p%JWlVJ<3mG1 z6KH8}V4n!NA1^d?58CYSAq8FjvDyMnt!>H1^4iCm7!8AAU?*uH4Fdm;13W0@=Tg_y z{Di3ah1nGb+=SM7$FgfDx;&HuO7YkNwaz;bJq;v;G}>V!=|O5ycR{*ZQT1b9*?aQd zI+zZDwF@a2SnW$Juzm% zH)FDhzyY+@WpZG|!A$!B99OL3v>{#wWm$+K)G2%S^mlBx%?I%T1Sk$|4`u+A<5LmH*7TGZL1iCh49-mkef1lrIdoE!I{jfW~49%-^$BN%Vi2oxNVneEJLF@=?hw?8h|*L zIexE;TQ;8{&xGAQYc<|Mvk_rv6yuoB1AKqFd4;fwNM7$OXKKC*DE2-}rhphom+Pqt zdgC=&@WCKamMI&sX$~oDN(J$F%;$btJ4Acxx4k`bt+8)u+8N*HWy|m}r_5z&Ybyrt znvh&+*wS46enUZt2jU2lCa~*;xl9OJDpw17KA5{`198P*#E4V)lr*4xB%^|v`1ua0 zFR*ADg0EaWnyLgaLbK>^`gI%-G1dT2JJ*qKBvRkNd?H|_4#&-v?zWhs;J17zSCa;z zqcwhV?zv7cwcFT|6Yf^_BH=x_GO^h6%%Rbx?HqQj3O@Hy9pq2ZZv?4HM)YcP(y<+` z6!)eB1(fG*X@0t44{TlCT#Z(0w$W6aE`W7j3S-RLo!GW?DRa}jP4){rjU~~L1b8sH zZp-RAgBsn5Oi*P&qO5OaO_pO!&PT2UIFph)%b1*biE}H|nFYOP;VD~^qBaMA<|AMl zr1IAZSSN9hOy}){RZ*jBn`E%M5q@ZBxuk~i7rvUN*|jdYKs+B$lR1|@ZE zYS^lUm7T8-KG{86;HRhb0cYF1KI(Md^}fDKP=F8CW{FI2B4l&Ymxd*VrX*gczT*+f zmw`M+?jq%SwVNqe5V~p@Xx`OzPztY4bww zOEq5Z+&ew7Kx!V5Y+XQG_MMtvf3^l?3z$3^3iPsX6b&_Hm7Rn*&)~2>ju?ARVl$$p zsN<%DBL;$M!cXAPFwd4UqXn8b<^WLmId>0QbEa-L=c!Yotqszp#$PA7dP~P=pspoR zK`v0GI5T(fP)rAQO@oY=5`_8RQmUz0rOZVAP6+M4${T*}G0AZ-$h+q}O_4C?^|)If z$8tVSZTr61>qOI*1DlV;b06@fHhYk<@NGneuKmwuB}??f7e%p+W^J@*Dm*`?lx7LP zRq+%%!aA+(V8zk#eklz?s-q{FtQN)c5g@^_wa_n)nICfw%>1C-OBRLQoz z{8WDBKUusrH_L5q*S>t{SU~)3S^Np8Jk?a=VKoIC1b%B+UJHDUsm3!6wG&#{BWXhO53JFJve}Nd0nDG+byefm+W5N?7 zbj^9)@vpUL3`jWBgm6&n-2%MYpG6YMfa_BUtu_>+Akg7!pv}R$v7M6dzQ}bA2{k{d zcCk!?G+M+5kBsdSn&;xAe45_np_Tf38^*WQ+7I-iO_?3G( {NEH3e78|w2Uv#2P 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

H-r%6ta`o(pxvsrfDP61!RSVSn`9B+ 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

F|Lse1gU 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

3o2x4PrV+4x-(He*#+q0$nJO`7s8r$Dd~ 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


Au5<8ybxCbt;ZQG_d2m_QpXHhUJY0 zH}?4AmAo`#UX#h~t}pvZJ`_)k)!`McTt-gm$QVw??J3Ea%dsx(?Tk>4o11$o)y;~c#N?-u3}^!@N(78yZLQ3lIMwC^OZaG8-3+Fy7%N$ zzeR3;m2^`?M^L}@+RNUuoM=%fHJpp*^W3rT<3_cIs2jA;^m80gJ$T3Y@$aCoX8w#4QyP3xjFcvm zM(vQ5VFU8>4l(0n8_pdt*?j%&JlnMklt?;_+$K!>$I}BY{ahfFgF7>-d$xW79f}`E zYG$DZ0KbS(KE9?cueOx@Q7nzrWuslRxCpbMpZ)=9T~t{O8PXSW>(A5eQ4u*HU0)wp9yfhKLBX^UucD!-ORDyq6*`Yr`PA`~0E@#f2BJRnLfZ$YxGFwEJ4X z4S*n>{WE`tr75N#I-alel*?Dg&weG{%giWqQ>BpR)C$U+*w`zBjKc*>vTW6*E@w9< zy69P?QGwsDQ`{GfGyN?tOp?v@W76f8`Y;~u1yr&6jhu!dX-ehJlJ**|in`wJh>4y1 z(^j%x(8mWY;OU}B4rPhm=xqv3qb^y5zJ+lwr^!)LwCq1lCHS2*iJb)|oc>YUycmV$WN9A-DPcEwCCxu)jnCvevCD`VFW#Lj ziC-{_oy^rm4bBqmz}euU7238cbDq(eN|3cWr!*>ov9_C^rPkYc5k1w5>jXMV#7tsj zA!Hsmz8XfKRfo&Ojp(xBaR4~9q|pJz7Scf-t+Eps+J2#87=f&?v}o?w<%&9yx-Pfy zkD{|!Zx9N?=mW99ZHWYTCp+9FI6QsnwqKft%gjILG;ks52=z<1{(0UspPwI_eJGMP zhTmsUXYVCiqcJ5k{620L`eEz-%!(E#eS8<3B}WNfSPUIcs_ajT zTb3}Ru{Cwl;tL_oy;w{f`W)Vl^m!h*dawcI2`Dh%Lhyt?Oqguj-AySek)g6W%Uo3) zXp@Xk-q$X&uqem*T)+G=$CU=4Dd5h=hwqjav$5VYUHCB^fn=*jQ#_Bv-&m|Gnp|Z~ z{?d4*oS5--Utq+%$1k;A!UK81jNbEcnL2O)u<(Yt0RTR~MWID(>N7S{?gO)YcX?#o z#V(2Hv!LI?MjsT|>pNwBXtc$A){QtNm>+bEx05?RtUdb(7TgYY<7^h9WCg0R4_(jF zLaVbc$8vKl{Q{uHpT1J)k63U(vR%4a5~$!@-7CoOWalcmoaY38NLIn zfOeF|%4=%q_ZxNIaHLx-io|iOLibeEWrB(S=?N1n4<;oG{<@7oL#K3;>6X= zPNWT(Wo~T#pFlGOs`G0f!i2t&Io7R8Y;nZUKRe{*h2{w6+zQph8?x-pm}h6swLxLh z%HKg?g~VoHUGH|C30iHmH=sM8Pp*9#KtJ_#0ieMKL@@sxgwVe2NrBDyf8$T1Xz*5} z0}=8A!f$%8+1XYzpjm}Vk74dzjx#83dl^B;o|W_2&lopev-eWk{{t>ySG=tgfZCFN zEbJWuRwfbZ%Z{jyqW)3+u3kyL`rW)^{Fw`i{@B=HztOaR#TwaA8v_^W9wO?{eo448 z&UW{`H1D4vBg9zN$-=5wo=spc(Z6Fscu8COCzh^prXOZ;=akm(64OQ_hKBOhvrHI0pp)!+V-2;FnQP z9Zm7234(H2LaMA>H%9c=<$yx^EoN<^W(rGhHK92fWg}irU?%KxtoKmh6S|A#Qr8=D zLB#3ZE(ePZB=GRY8RLjmeF^2@JR_2a3L}@iRCCiI1jR33C|@;zQ%8nG4GC3Os$xvD zzFYBY?wF}v9U+qCmC2U0NQ9k9?)zsvzWR^L|v;k$fRxlPPsu$LAiv z^|O<6hgnGX;qeY&q<}Q&)1~9^v;Edq$Jr@5*B4lc*7`P)D31bpzx_=MT-!|`ue|iV zS~YoTh4uZhUyh8i%qqjXqWZ4c>qw*MvHJ4NWkIRJ-cuEr>+f0iq_RS<8~Y;h+#}Fj zMnd%$!^cv;7ZA1QC+@5`p=dK$mWKJRWD95xoxxbBg>JagMkR{>H$2|t?HY??1tkTm5&N(d_b5;Vp#PyH zVnb24@ogl)!KeA4dzc}PDQvl#(AIFq$*T(0wOp#wDknB@PZ=lkEkN9CS?b)ffj8v|_ueP~I%#KMSncglTEZ56X5cpEI zNa7#E^sCILEt8XqXI6!JVUQwfe6wBK4bv)Egtik2^Au`#D%~=b8d?L01i~6O_>4g~ z=EauC6tZ+q+5@&)-@&L=tVaOzCn)5 z=SHmNmXVtj9g8%-v_3wnfxqeKu5alklw%CD|1__|nm&c6?z5ctSyJ5QzZkmpgydcE zio7<&V7U_OaE#VTXWy|>>GX^CH8Z~Rp;Z|FJvH!`^@^-mF(cMXr?gJJH-K;T7}$a+ zAFywntk=X1n~(3a=%=SR+$Z*+vVKZH^q$xACKV-v1} zOj%J0t$8*%;<&3bxfcofjUNeDTr?$wgX8Fftx93Nl0Qg*9&rY#o<~GP<%d_B0 zy`H?@I)mmaaEGDvW;hOgWco5X%8w)+xI{G7Z4Vl7E>Kh{mF%OyU%*@S!O3R|7&)hi zF88a>&Jm18dl+HLI5Y@k22w*Q`}39t6nLk96y_$2@GY$xXY=h0D6Cn|3oBFl%Wrh0 zsD8+6Y(NAW_H}1Pz0}~$X1hDKw#+`QJ}m_QGJ?O2uLF326u9M2KGol%KnB67GmS^} z+|4Z^=%#Xj1<54NSMNE;E3xGRX@Pp6Q(a^E#}5$LY>3I9g1YWLI}CDdL$Ax!p1c!VsBjvHPSGhg(*!CfbAwxO7mKU!q*!M4#IOwG{iFJ zqqVX^lE8V$LbCJi*Vp1uc9OSc@S7BQ-B`3wnNb^-(Ju7TY>7jpIF&cC?cSt*;p$dS zU+#AO&BXaXomOa7_s4oaT|Q&^PFh$K$roRtU)xwi1;$_4i;`!~E{gU|^#{pV(b51> z8xc12c-`AT6Z9K5I7}>E1i+%jb(%sEgWT@IA@uk5APH%kY&ASqQ9|bU5 zMF7mrVWa^H$e$?*I#^NidBPADF^Twrk5T?kOUM?eFad#khkTbjRl8k6lK#PdRB>RaL#OF{zf*ssV19YO>QAy$?d5v(@c0T z&JtK1%V-|n&5}mv`127Ujnh5wdG0wq*YY7Y3JZpX=&PGD^F+Hy!2k<+eNzBJKA584 zI4@FzLM`MSkq!Z`c?miA_{~_+vcj;b3fvyvqG{2rlN~%EVl$hQr?o#*Fj}a`D{L?H zg6!7sLVx=6L7h)VP4Apq^q@3;z0;OQRH(Q&rBwiS2?>s2oREyf%fT{<9SWjn89>ca z?@(QnWRzT_tbFehPMB*Bj-2Nl%1?1Ef8QFf55h}59Hj}GZS*+bu98>PC^QOp zttM);^s`bWXlEou{+XUb`MoxRTZg^1N(*v5$gm~QPEy@q|Ug_G4N99<=k!`Mz4AAawh;omGK{^g`oLM4M| z$H3cj?@E|4(HZHW&Wh#G0(IKQk%2;7sk!-?rAc?ai~AgDFEx-IPU8!yVolwN#M7W$#{l*qgFdrKIQl~?04x`S zzu1T>GP1|Tl)xrRDw4IT<@|zrLG<0^RmV^7+c{==tNfx?{mmXKH{WP&FTc{vG?lpu zW}Neb8FafqY)kFS&$>BSqTI5JwKCYN5zU#!o?_;ByDt;TH{>+#>#|ev6DiJE2JNc5 z&<9M$HS@JRiQ;+8!Nj|HvO-E72+NT5-z_;#r+Hl9bSl(&ylRxmor0UHOFCF90Q>?@ zc1Lwwu7!y~H*#vyoR02dT)65siCwROcJRxgV-OL4s5#nUfAjTdS-(By_>YXV1@eiM z2i+>fo4}>USJ}w~g?3c)!`DDxUf9$3t28>5Hk&%!EtX~o&++NJKN}VKe4OHRCibC>oMQEB^@Vmv7a)T}=%WU4#9GSIf4O#DK?+k^aeA7ofKk2pw%%BnFYvWNdz+=FYFn{dc7awK+FDOdT?e`})N5;Gp`t8zcdD+>VyBnj zqlzdE?-=!6Jq`w(S~6+q89#(8!?+yPQt5}2So58bdX>>HKUA_*e|SI6)35iwtzvFS zV;lj9dEIpYD?rr0Z|crhsINe!J{xMuyX34dE+QeeSheV_$B6u`knN`N1BtX6N5LLi+nORR1wMx)8jS^louxnUvqSFw>0 z)g$SHdjxByn1TAh${?iR&#$+GBGz>hGi`&;nWDwb36%~8tap8ZVM9JW1=>1fOh$P5 z|Hp+10B4EUKpQ`*dfKUsU+S;ih-^{j|wUr8NXd;BjIJFHux+Hz>F(#m({bz9Y!AZBuR(c;lTCsT=tkRMw&7Ge-2M0>EqngGrdS>sxfD#QklByIOq&G%N-vHNrkr(<5V*+xAmlgzh3fG*_ohF>_B6fsJ8q(z1Z`~#gC~Bp%(ha;ML-| zB9uFD*h2KQt|B)VGnV-mGzE4t-{DS~&zHIsX{Lnq%$1lg$+fH@=hXzIbtIv|%-U#9 zdoD$S9B*#(V)Nc3#|?}+8FGpk8!GyalGqDN7HIEGQFf@YvMizm)@4E~Nk6Hsv>sD)grJ8y&fbjZzeGN;-KKu?C6BJW=(s4h89Vr zLkeQmSo|2Oge}SkzT)rN3_FQ)``2BGiWf7~4Lq9M!Ir)RAfpj7MTMmBB^;U3LWg{F zU)PXs_|?%AcNnG`TIo-Hk2Hc|(BCRz*cM?R%+bE8uk?vy6c{aaTOe$SCgVs?_xk^m z+^_^JSQ2r^Wz!+rUGmCoX0?y32{%E$Mw~~tAbnXELl=OZB^;TLQRmx!6le}^m@u2s zolWa4ITv&yK(0&Jcy7+Jt*?6Tc9r z0L>8355;Zgs#I^NSRYt>eq}6&pO|jD&ke&8rcvLJlIZ!N<9b^hNK3##b8Nv*`*bmC zq)O#&By@2+M*DcwkLN;uRYzmlF~cTCaY)l5@I_ReH=EV3jIAj$1Rl1BjFq>LjTzPFD-RA|cmyH?b|8jvSLpO0C#ql~HWsK8PMqa(GH z6~jj8Z?_1KFY(OR&mBT?uP{zT;HQo;2=p=At8Y#um0TXu{AhKPy`e88IdmBG62Ayt zYbKK&5A=ewRPqOnPgc490-LNn3tcMUTqZ5K8~yLmD54zxFvnX_Dc^@&`c1q{kN7sK z{Yo;t$p=+#j!AoJI2o=qP>ysNh30xtjJ$nUsIYfTB(GmVWi@F{= zJ2WnSOZZ2kN5HBm#!~?N=wtIWdD6~}O6PugKEdTYr3~cNprG83l$Ss6PF{eTNzB8k zriWVYsU7$+)~CjQ1?hh+_={2;e_r=d8A6AD-3bJ}hB?YR90+PY^CdG5_M)Xj*F9X@ zNy|8uj8n!AD%;0`g+MBz_(%O;3OT3Uzjd1P2gcjGUDo?5g9>a;@)*zJd%#KKf4X?n zVBiLl0Ud?U%6)?L{s~UP#mD9VRfS>JBsi8t>o2|W6li-%&^wY!OiwKAnYh#{IAz;h zZ8mn~u385;Tpa*WtV2(}InGJWp#W?DA(sj?)qxuXm=8Z9FgpFp>TLbSDq^kjpaN9F{bn zB+5rF1COKHXhR~^Jb(nG4@NAZna?AFOSTfaX(XkVt+_{A%&(nTuRJ)}x;j<8Z>BzN zgo-_~*;o>nXHeb5X4tIFmp(VKb+dOXHT6xPwun@vhSzuQ!WJy$dK_!b3|9`ZV>JB5 zNJ%g-)`-ZlPOjis6nb%|J@j;YUJ39O->xq4Y*lRzQ3`Pox@G=#e`xZnz&yljyp}v!WaeF>Tmt|eexKsFK= z@v0Sp-ZdE4%2#l;zVbu)5C-*a-zmeA+AFc@LRFfUjUf+voPZgcnu5D$%!4IG6h9WY z!Jt2tpIHh$$KpDGEBviXuP6FhWR?63K+%?25Vk{CR+&Nvz$XxCxUe9s_4AIbJX}CS zEZ=5g(8!G2$q8i&(E5L*E{MqMK$SkACYR^6MFo`xL3Ak|dPMmw30L)c(O7#HflQU2 zU0_3fcu`N7MW(^2h+bgSpcl@!`9N;xn8+0`XP`~}fy0XoXp*!$N6;duWb?!b^v<}A z%8Q~jxhg@l$k&O6S0v^KF|1E{Q14qMg^gwRg(exz8ZyG_^v0Py_Z#H7EMB)Od(j4F zh=DG0KBr!BzwBVfayB4aRe*}<8RSbl#!F!4x^RgOZMxLr9{yH(nKTt3RmFz7W~@nM zRf+PxdrNBT)TCY~Het$ueN!7gbS|zl=Ig^`Lt=Sl{XJIhFhk5**N$mMvmR}a#K`qJC)ag8$Qwmy-_C5h{113 zCf}OBF}q{H04WFTn_I$;vq3*2iH)^?kQ*0kg!xVnf z4)^aYF2L5HpaU~jI-*Yks1xK}%}X$Qmmi0n-8Xk6HKVQb4!$>r35^4)TDZnNGOE^I z>K&$4*I_hTkQvu#$T&A9JIF^X$8z2X0*3?iMv!D}QGWt?Aij)5-k|Rjpq8%5PqtPR zq^em6-Hh6R4AV@0c-(LQ3lKYtV_D%XT#xhik+O=SMKP?~QHj2b`c#bNe}klT%Ngd! z6%}{MvG3X)J~^xa+x)+kBqa=WQy;gB3aia-KcmdOn6%X>)#SNg7WNiN`FbKkhneHY z=mhjr&yRa@p|;~IYs?Q&B~laqD!ZH@6i^)=P;~mp)%-!P)A@bCUu7-ecUK!d?K-?@ z1qvo)KQskXgdR%$kVoBN>j1e8UZ=JhK}{kCtpn0WHSFSmGn#Us6&w8ge$1oa6|s(RY(I0##;1PO{J6Z z+!V?r26iV~qWSNRu}WsERym^r(uXzNF_2EQ<*uRa1gR&DMtbNE=tSgqgu(keLWiuXmz$<`L*H>5( zyLk0n54t*nq>z(U6C8e^eJEzBp=2wCQJ{}H!>avp9S}->@F4F}pX(e{w@oVJ?D%?n zBwO}D&aWc)G_2+y)d1>9X&nGFH*~lH>5VHaxZ^P-^}m|h?``A_-tQ-uRJ#$OXe_rJ zCTJd_I*xs#q|^b^EJxrjx9xbvZ=EI^gY=zD6H3uYQxz48+ueXf5acz-)YWiGKKYHF z&JBy|`(Z#>K9+Wq=~?N;tdb0SxlD4mbfB`k18o28oP+N$f2=@l`pUQ+QhdcGUye#w zOXKk6gl%jAw1D8dN=RkLXsWfA%QZuP^i*$K>j={GKrRBk zRy2k2;P6f*cOaBC>ALpI)2CQxzaYEk+B@=^lN|pt2nb91th=YtA2R?Q5F_eK-4eqLy-zFo~ zjqCU1q9gZsqpPV#&HwsgEb31Be5@^SnV9MYl;uH>3rFH7NZBVK*{5;WSUBL%IN^e5 z2w_ua3M**)!Glt}B0SpqE|x`hYDMX@DSyBr zc>*apjkpLOFbr@TwNKOOEO_5V2N-J%#Mr|-Nvd${si8g1GXw??Z}6yzb`@$m6&n&t z9luCO%Mncc-w+i?O4{&v$v~L&E-5qsLk4QAL9$`)NK*Tl%<$EU@}p3a1fVbwhG2Hs zps!nQN`G0^0)$LeCV9n_AD5(0o!E!oxsftyiK)|QP?bEw(i{NV`+v-Pu?O>60!p|Ed2r99yrHJ;aw|Dz$X@pk9s zS~_Ly&7d8yJVB)JLl23fhA(t$-4$E)=|hjj1mp7+y$eO&%mUKHf)#&}zKYy3b-ts| z9UNgIl*)43l3`sNKPGOUT<4~=+4BMfMBzZT(^Q^s%TU^fUz`MQq4~#m0yi-j?dd4T z2x2QNq6mrkF6&eRow2fL-lf{?h~{C!-KxXUYM1flXYTVyO!E7ip11V>7@IB()3A6r ze!S;$mW}pHU!J9mAU92n0CAt5Tas)?%Qb2=#cv)~{#J4xS}140l?u?jER_VEx}PHS zUN*sY3U|{u>}XVimJi8$kEB$Q8QkaxCAvV83`7*d;=5b_A!1G#XdG^J@9U&Pme`B7v`A(ByUNvwqYq#B|B-%dU*veg^=U z=J`*csNnIr`ww{nMnfu0`c6%#`E3pXCJx&iGIJc})f~B#JB{3}y}YiMIO4H)T^nDjih!j@n#d9&yUslROX6^5NpHldP3EBf!lnyKs*GH-)Q4wJEuA;(v`yo9fWfYaOU| z>99xhOH+^4f50mn@sKS`UgX|7PTA;SoX?T^sohrRJs{>rNbx}5TnfSrKjJ{G;5Cfs zh}qp;(?1U~=1L9JRN{gz!*_GzJjiz&HvWrU^<)qS0~ag?4p03#U`ViCgB>u{`e9mU z1fOg|{jh`+2*RBSGu`W|S%|#b4v52>5^3*aG(#o${5NN4@?7Yr#1y>UN9-VfvKCK4 zoIi0qPEeb0pXO+%G8I3^HD+=)wy4Dx3yo2lt5wQgvL=5!0V3a|%||Az7gNX5AK_^v zr{{42_t_e62lzt+7*Jepq6eWxBoxVm3O^=kJ;1cZ7kEb+ z$9o1+$!7*EZWvZe+Yb8$rLCzGcx)B)V7}6A_6OQZ>+>}Z*t1(HLO~%eXirY39GLt* z>C^wO14vz3?(c@5(3?0tNA&v&!ajS&^`{HMABWnwOCR&@&iN`vN(1!`J`IN%eC_;# zjqp7d=oWxC8gecbn?Bx4pN_m5-~p`t33)QhjW~C zeGptbR;w$1Bas9tb;u+YgN8hVXGd{wdpA!WpqV#O-)OQlgtRf)RbLA(c?fvNXet_z~N;8*rf@+6WYUD&S;=d^(G1QIfuO6 z;yWN7OYWg;rc1#g3>w))pMx6~v`cYP$rm0Ji@J{YufP)r&qsRwgS?s6&U?n*DXl6y zi^N)WRt~a0AIU5#W{;#HO~;$Y!BjE`vpzoo1&%SKJz-Jn5jjw655{>gXj%Kke9H0$ zihBqofdr52Jg|#?5z$!Dy78_a(HC_ih$)fmIaXgi6diSN4O0(^d2Z@0z^5m5oq{m0 zw=?X~XUVIUFP|6NEwz)k2@p&M*Bc>8ZN9_6Kn0C*%McV(-F+71w1;O)o^D(}E*bqQ z3@DY5ECozn<2BD^4`b?vH?O=2&3E!$VQ z>4WCclp^|IGD8;dzF%ta^WZ&8Pmvl^{5NhfaKBLEHq)1+O}&E>F!?IyYu8CAnH#&h z<{MH<`pKR4v%b9#XDgDPfr^@uJJiG zhbQJe@ce`$1nmB8;Cs9dsC&}&Ie_Y~Z-xf#Qh~CX>mH|-zYOmQ&01R(w7fQBeX$R{ z*bhNbKS=`T9ry68Hlj>IH#wQKTy5K`|6v@`;)y6FmP9G(Fyn2geN0g9)hSJFhu5B% zQICA;#`v(?D&c-Uci|lYvqot>yR1RB|1;$=L8kR1XZuKR6Vq*Wo zU;HAa=I)vlR5N~Z*DtPJ0b6U&_b7b}21~qCykB-+Gx5{81EDhQHcYQ0JX=gdspd(u zo^-HG&aTu&!kk&tgsx!$O+S`l`ufeZ&h~>^!lLYKZ`eLLcV`c{DjsGHkn$0^FV=u3 zlC&9G^K8qHtmR_TI2y_ilF>YECl*)1-?_V7+F#g$2fs8oe)I1G4tq^aN{79|20$Ga zUMy=D_Skxu&zbXORM3$#yFd>NA(ZUKg4^Bh;bv%i(gCIUJC$<9xRsSqB0O(mF!CE0 zvm;!q74rx}q{>z}%y1J7TwjZ<7MjPugHS?bjZJ>7`31hudxD|85Wz_ou?5k^2Fx)C z8<}?qtugh{m2bxMUS086c@?j4dcAeO^PS1U5m94+>g}gR@B16;UYMtMx||XiXeAF| z7bwClr%N3_fIN6jeyI7RqtGpy^^A1De zgdQUkUHj?{gcXLEard|Dx-t)xmYNmkxLT4m$PuKh@9L8G@~z6|_VZ{t)fVa2JH*c$wXMNfTZ8+1OMC+8v`p zzQp>;dmu6Gc$R7#DNqkhP+8-tUv^KZpiY`}QeW#Tf8j-&)~=MQyL^P%xWYvLm_m$T z;0ce7^fbfI{+5Z?vlkjKg?c%*?iS!7Pl8Ql8%1YiL-13Nfx5SkMABQLHf|z&wQUpBZRc zob>cnm@iZav*jz0F#yn-epRZ!@CpC6|CbWl$R-$*T%!lo2@LCBQP4ich2Yc!O1R2^ z9#JT-*~lD5!vmp5dUjI?ad%p)=E*d=9B*0l~6;0>i#eeM-*_T_Ovm#F42 zsGEX=E6NedesrH`#UM|=so$gkaM?2zm)iV9$0Ihlsxb3QaPyca6I|1RV7^llXVvfn z16kdz-Wo{ZlSpr7#K7;V9K}Y<`8v{y<(_Punc>eGg%5&}si@D@o>jZ0NU0M9_?e&m zUdM0AAADfF(`)6z7HKLs@VFimzm`ladzXYQTUIj|LfRsbFn4>oAzRWd0-LqGpRF1I zocKapqq{UVxIx}8jR* zLyU153c9Fh&4TG7VtKb^rv}4CAZ2QDpI|4#=o;h#O+=Z|@)2NuvabM^Ynp{!2ywKO znE`3pZcY;+pWDD#&pj5Nm_bG*elf^5i@NPwx5Y2}SVorqk@v%nZCvFh^;lGmuNJ1Q0t?_`h**HL%{ z$@b!hOY|TmUzJ7xfmB7&Ra+B*Mhu|Pfv)#y%_TsRe1Xm`WG2`cwe(Mkn@?s7E@b4t z6nn{1QL#Hc3yD-}(t=S`Cc6WpIWk1Hn~cH~XZfRam%7~sG|YQGOhZ4fVI9|?b?ctA z*8hR4{^3Fdh|5?^*FME6-BN)Tiq5BxL7L}sN(T&ab|s{=-2OT^I*gyoOvrFRL+F|` zSpNu^FeH3(2qQ*xncd9fg_V26|9I){PP@y!mQvBs7p$z}(`0K|=VlT0OV3TAJA|h7 z7fb)B+~nDx2x1p$I^emT=brDs1A&Zs?+E8~@ffeCAd{aV&yL4-r`W@T{6Zte|%@5%q=G1s2AB+-f zXxP$8huZAJ@pY()^_#1H<&_@e#Fi{Ox$z{imn#Y6GX?}Y7(d@rS4$dvwSi;8OC7GC z8EoTn(;palHpoK7YL|WH90|AXkzPZZ9|-8DxS0MU)w*(0$L55*OSSw4Ik+v?fD#={Hv;eS_#|q@QhoG=>#S`ag^4k{F9ZAg$ zOWsWq%Ln*WSK4lW6rHuUgFqBTKZpXi5((}OUGU&;U;lVjsw~LJxqHK8CVO_NJSa^f zIxZyff(K(^F?k;1fosZcKLKcC>;ldzA)P*X$7`pU77A`si3iIjo5}g6m|C?Ai>K1! zp@+^W#xz?)owNLn(sxFGSI8|TDM9QAV_!SOIYFs)4amtAnyZwOp8$7jOGo z`RTc-^w?p`Jxt3F4;6+6m=p}bHKG-u$ClzLrUyRl6M3Pu8NA_BXtQYW8|X{JS8fQ$ zii59p(j4>zNh+*?;~gz4vM|yQr-7VxbmpMicC$SOV;*3EK7I}@#DyOb9Z;4|R&^bE z>?l*7kaFfxnA$I&9dqp#T{?26nVM1F6%0z zC|xRTr=}yDs@ybB_L}4e@f>tm5{Nk+e3I1hzIlQGn)`;G(HDoSCf4{|w-2XUE7i6% z@%yOXUq$MA6Sc*;ej(p+SmZ7j*Ix`|*zYa;q&ozsYT$WfX=<2g&31Do)H6M#rX`ZY zG?~Zk=ntryHrBmT=4cDwRKdNxXK9dc!33?kr&?;L@ zp5;GaD`{7B&Vk{wN<{4t4>_q{T`nM(YQ5Jr=TcJc*CQ}=ZA8}A$)8ix1=^mD9+N{groIcx9)Q77bRo)-|rgVSKNX*%7}A)iBY7 zSR=>ddgA<20Kl^>lD7~hNY(6R|0^-Z({M^z4;t1@PaXV5rqmUUgpn9Tq=6V;PcAKQ zu~tBFTyD!?fMdr-h-UQpe?{A?gQZzEppb)ebgoAJk}8g1{5$!JUoC&)#a?Ls=<;OZ zK+t`;3ao@-2gqNIliQ|42Y^E4C%c{uj4Q|Ttky))hD~ny{vfK6&V`n!@QYGc48iPG zkI3kd0}uXS$--$au9_~Mls8C+QOxw0g2WU(;zZoA155oiEgxWImnmdXi6zeo62nrP zdlAk)S1F8gxd+PQ{?esJdl%QTOyEz41(ybCx%-mU8FNeOg7XBR7;Kh$h!;*?8u;(y zq9X!0%K0TwB6kGFZ(_mL!SEf|E-;aFEh2UC`b~O4wIh6hE@!X!1N2t+`!vgI^H#^V zx^7*((FPRKno8(n^kq63{K9PQzI>bdXjb;|j<_Jm?%Lu!Rr^qe%?FFZxP-Hdt9&6<;bl%Y z1tx~{$c;z`gb=p6?H>mHrdat~KhG;Jb%f1;<3hmgYR2%V3AWmzIT-5XJBAQp($^(XrqodF$jn=l@li($Yqg>?5j$Hj0mpV zjcMy(`U^qXoKoxvw>MuaIS3h$Xh%bR!QJ^Ddf8|%%8cb);S`YCu(ABUb}hi02aWr9 z?vF;0(v(#Z5iO)-VYpRW>e8l9neY$&Mc!%snr6W?y6)V3!jIVmKt zbpxTo%fHQ{x%4?|Htg@8)&7LgSL@%C7(+>XOYkyK37Z&I9GS|Z*{!Wbr%&YHdb(oJ z2IM!CYuOz;MHI(IzT2NXA)T$NHe`JL%9)^#>-%jz393r=R;GY`VT@8r13fkRX3j4A z>;}cvK;+iz6K5c=%H3t59oO>W&1I7}JzWTzMC+s>X&DHH6Ss)|s~ z;<)O8QboFQEXf%2Bbhj~SU@S}ugB@#e7gV*$ep#UVt2JY^&M2#oytdB@&Dx^s*o2{;*seOx!91bRe8JeVw3wlQ z*F`I#{&06znGbPg6JW-^Aq+s%fFCe??NWyib9Y#L(BZYyHwn1HYLLe&vA8tg)(KOd zba;NiQ+8Q))+zo&C@$Y%b?Pwpm1QxnS$*movisfbdS>w>&V%tq)a_|=cK`+-SeZs_L<7@i6V=>NqOHKG%TbnK` z)@cNpa=AwzBj1=nuE4~P7kkg@qF_|kkFwj)Lw!q7^?tOL1Mdm;Y(a7o^kQ3e zLRj+4FVIm3uTma8K}%HF@5NUtQfth82*~nmw<*<0gC09y|Jp9Q{7B`(lb_Fft8zh? z;C?9!AtcidRQ{p;*mN}+V=+DnOX9GZtkk#PlC`lVl;5=*$kkIcr}~gF!XV+b`k47Q zaWd0RW|RzgSe6o8TV`G#Ad!^hYA9>~^l28DwNYm9b}8|6xf;C^3b1LJ=|!5@Hy@@& z4f^BbfGZW{Ol5}zh1Bz^2FhZ|eN+A0UuP5bSoRSAo0*a)_j%IRq7Y}#T2)r@CJ-_c zC3w0DoS&Y*Iu(DeR_;K$oPJ?}{J2MFRj58$6zatjWCSdeaIwoWb!p~rR!laEi)V~;E9{v%`K@J^h z+)BQ}vWBWhL0Km&fVSN9`L$~b4Ca7s<_81>Jdi1Q9j^@C@oxbCl;CMR$w}Q2Cd?nR z)1xeE56nJFShlQuK$Kc~14e$KGx%KJT9xU#tcmuqjl8cpSFh=g7u54o;;UG9@8#i! zHsaih-86&rQOMqTUk_hi3YN5BCg18yEgS_cUv^V$*WyzZhML#UHjf#p{}MtBckP@2 z)SsI%Sk^7$BtNrc`v~^a}}) zYjd1u`Ua^cuCD+PI^Mr!LWS_r${if@fugcs)bC>HIXf1Wr6F>pWgW4J8-7Ma z-0<0MRlj;)E|2RRG@ZpZxt^8;ucNGyJMVMD2UMHy!_2Z&wV(uj$njX`!>Z+7ij zMFN9D`bLfAT11_$Ify_g7B7C6m-SJl*^;0Nzu$+1*X-Ifm9Y(}AZX<%UienTziB<- z76dA`cP4m6it9}ov5y{AZ zB9S5M_3tdqQ46(9ArVwgqdkY#fpBg^4d?DzR8p0QjJ%ezo{%P{i&wq@FnU-}{qI?; z=aa}~*$2d|Vp>rC+4*FT%8xfhqnqW+$DPj5V!nXsc~50zNTg&)^AV?ZuSrjqOaua& zxdTX_!%4NoF~BbNV^Tlck47o24SE}`?hfI zHYzvQ969PYU@0uHF=9@l1p zsMee}6PoB(_z>UeM`?y7L6G{;h72VE^d@O6BX1cSGvmzp7Abf_wGCGbllzQdL*+%< zZd*`Yc@ID5k`rQqxTwhx3Zz4bnX@!(Efp%qsRF!-sGcP^$GDR>zZlO!QKDGNa@S$lYOV!R`q-GDo@&qCu`n|^pNWO1kCKKI2H>&i zCWLw>tG;Cdj&dS~;l1#G^s8IUzM$ZAS?xKU0S)&=!Wn;b8ErRqXaenHC3vcrOOS8Z zhU?@q(@upVZ{k{+=6qD72dx{4yUcHfD6x}a#o-N;r+Mpb`tH=&Oyf_)ZdhYv#7&xL zyHjDhRy+V^Y;&PYtd`+9pFO%R02P!h97L?w%!c#gCj<;?2n({p1kd_bKwK>Dx&r7b zzCgUi*#rt%cm*Z9*-|Wg1d475;gj;55lIK}2Kzlp+PyI;uyT-6Hc^R{GMheqL>Ii8DSCIxz^k|^=nS?-#ty6_ro1^aHJ4s8 za|LlGkARS$G%yhV2!$l7)^)PGt2*jQMibo%N;4^iRAnA-wrV_$6_U67rRfT*u@I>A+K>sACS>>%6^#o(t8j(^mg-gK z2Lm>_j*J896SKQUZYjRIsq&T2*r$0^Kp$4&`l~ zN_x6`1hTTV|*5^s*yPMxxfBEm>iN93aCDqwO0Z*fRa(joiEres$pvkA!oKCXyI_p_u$=~wQGK9<@gi*R(_no9y8T6tpK zMo8B{+QBAsQ;!X7rR*!ZKlo$A2g=X;$|-2b1n()(lh!lM#}SyX3~2!_`Af^u{pz`r z`aL#MyXG{Arg}HHNma5{T0-u(A2qpCy4PA5y@+Y(ueZjBHKwh0{3<2Rj2}teUiwQW zg+>t5tTY!LY(6CuPJxy;=Q`>GzvNYI(}v5rq}8=^BhJlIwn^MS>RX)?;WyzO4PD*y(J%E3-mN4pY)4oB=e^9+b!t3 zU3ILhqoXEfp-yo}(b}CjZ*mE z3+z=zqy;bswFC1Z{e&=m;%i@tK7dM++%Kq7p;g|Dvx9wgr_x%~MUq*UbmBY%)@qF; ziL7XCADz%EW?xoV$GwaEuIBEl<^&RxqzJBswPS&)N2)jQ)_Xv)wmyl$`IY2K<;H%t zC9!_u99J;>*+9I=>OH;oq#$n=A0MR1(Mm@VFr}(cQ#%DI&P-F_A8#iWX2`C5GTxd@ zpcXYXQv4pJ@j8hjPXJ33nkbtmU|1=6?LV$KW!S^`GCnWk9yU1#{x1z<+U!9Kp4W}JW6B~e3RI)jVQXvztX*m(d4}}Y*r}g zZ5}rZVT6?L9W6g-kF`VVELkX;&xeQ`H4+rrB=dEWBZ+lcjh-h#i*HW60*sKl=t}z3 z3#FysOu!JE?q?Prqtj?)6DnO8fuGO1Ixt*;v;tsRs02W3%fzzU^U%DLzL!D6`J5lJ z!xkcP?5C^B(1sTJh&T(Nw^>h>w~(%guJ3!c$wQG_Lt-Po@qQlTwpWDLQ8i1%dSnA?a{g}KCmvWdt+#6@$jhadHJ_r8v1;daI|~3sJ>O` zoDt&<`77O~1P}S}syvHG!6CI)04CUSUQ%k7_0nX*3p{1Uscrkc1p;LI-d=!1$*YVI z3sSP0D~^TsYOmz7Lo4v5`8!#JZM_V*W)>p?aUQi2$EfuM6(5wc@%e7rg2zfoH#*y4 z7(~cK0+ZsOxwiWoMND)G$il}cBOObVEiid5g=eY1sKYwKa7?i zC~~PZ#P|wt4F+;x04yedv9r9M-_IW}s`i$Ha?uV$+C1oiRn0;MK0%zd^ts@XFH;L) zkqeYGuGzPGFIv+XVOMKc|CZ|_f)d*f|F?@F4#_@~7ZsqMU%^HasG#w27F^mcyVr!< z=V0*X>InutdmxY&Q>t#CB&;5+er}<(`jd+d7B0WfwK%Ua59JqUQ0ZbbK|}CkZbqcX zTi%L|qv0V6(_ta;s@8PSH#9mQa=A&UjGw7CbqkKT5VQ-6emN-vUgPQffHn9);D|Ga z)_U4pT|%tfqslE^xpLO8COH6^{)L~|B7wrCvZUGrv5Xrz{{}+&EZBV{No*EpPbUDc z`}{D!?ab(X!oi~1RCuBu3ewW|ixG*MCqKBig60D{p$LkSWWR!6ToA=! zBsVAZ!!h;hN3rUOA!qfm5i8fm7FYl-a5~HX@ezLkL97g=G z)9-CG`g&-9lERWzx4hFp9i&sNxBLtM0q;(DQb-}%IRYC#HZeh zI4xaOdyO_0MO)DVoPL=Aeb6LEEdKwnRMwIg+iP5$hF?kaP(=Qxr!8_IWDPI-7)sJ2 zZprrtS_RSd7J7fGZOk#{nx7;C%u&D-9QO?@wC`SU(VEMfpLtxXVL&>F*#LgOT0GT@ zMB*)XByzJq(U^Ps7*l>+ZO&Ln z>bU=VX@;U9Lfx$mur7+BfZWBaj8Y>z&xKCi@vd#us{k&R@4r5v&yUKoBNoqHsQKS}H ze|e`O5qr1OQB+|0dbgy=J^LUi6?y<&1!R8qU^y5ti|S1qT$DVE7m-BfRaACQaPf*5zo{~@+cLeO@7I@};EK6f48 zwEY*s0MOnvBI|%2-%!7Uy7{bbiqYgFyrjPya=5K9W&clU)81rmjg zga_<7Eo*1h=@eyUVn`sVebKRdyfd0xLyvZ)nUch!SYjcDXUNU3kr9?Y(xcYMwj?5N z16>f>8P{+34*C1Elkfhe;+2W&{(%aOWIz80uwb{P@cBs@${O)e`6HB9bbCm_1Z!r) z&BGvO&hd*f%2hosH=B!d2_UbG(r_)aWL9+Q#jOLUvf}28>#>s)2J6(G%*YZqW7REM+M@1bP5Jmu z)E+^Zm03ExMdC+|6*Y^A8ishK`Px%;!;NgvI{cEq$V3s2pug1aoybxLEB6nskR+r6 zPVIH0f`MfKJwU?0ra#g<@ca%tYQj0NWb|EVQtxlMTsv@%U7=lT7eQlo;6N{0kVyJ( zlQ+qaMe*;Hk9a(l*` zHO$Ii=n-`V#JxDE$sbGx_s8%S_x=#&T%m>i0}sLch4$|reUgY?9KE4?JMr zv#i#+oT`QPj`F%KZ1qTg{oBXtpqkYHW6}tFbk>mhxq|~|bH!FfYsW1LH3Pyo^r%&% z+;8uzs|EV9>6+@dys6hYzK7$`?U(1(ul?aaeDTeBf~P=EAAt?BN_R%jfKR@cp z5{<($Zi$4k;JpO&iqD}jtLUS@28*)92B5$Yq#%TobR2Y z)Uo@M2-$P$ddeU;K=4jm8Vw;877w{nO+~BbENVlj z`kw;PYvBbN6g=n#ykG$2v8JIRk{zNR9SfSfH>C!>h%L`%eRBV!P$i!W=hS^bsQwx( zDfA~YeXb;aPqgzQSI0{+^>6P zrkDMH!|7Qz5z0!4xs7EEM+a)A5mkrEB>wakPpbhvLCJNTfTEAD}OBLG(cC6 z!v-nq=Tz~=v26B;`rL81WcBhBJ;zojhPOzy$Z=Q&OX;!tj<@T4Ceq5)wG%zR2sEvk zVIM+OO66-S2fkOpPU9RgRwA(0*^&gO5|Imej?nZ(a)(mhE$A98g!kE~*3ZW@^lIm)z0xT>8g6UyjBz)?-^#JCrztpI2=tnOkK4D)!i4N%xR2UnX!KhnXbX z#5E&x^5FwtbTes6WiR*L%#=ovic2YjrGrh~lknK0b`VE3GYIQ&V0mJmezglP4qp}{ z7{;6JLlr{aS0(YVVJ&oL_!;@B0H=us((czwY$CGv+UU&@{X*t#SX0EE4j{jpCmTe{ z8{cUy-lDhSIU8nd=LIF$z-so{CSOT;(&Y+W^E}B8&%=B+ zlR04=U32*2p8Amd&;ZB)uR>ieq&=x9=@(db{-uiUvVX{Lh5XWo!Vc>I{MxcwT2PX* zh6`5OHS@pCf#r1r!x+lzYK7RFelY*byTWuQ+O8<`(ZU}@Nl0S#BOI+5vHIOe#ybFy zY=vy^V!P!j=1&t^e|83?Dy2{F`A4KuG8j7CkYUy^%?_#zIXLr4i&UPcj0vG8_I7!zJcP$kR8zVSK6Z(cVIC3C)szmV_W3R@5N>9G# z#5uqk0DSVW0%n?Lb>uq05xZ9=iiJrTNb9@CZG=@}k`U>Qv0yV<7o|rHZbr-&@&7M} z2@>g;Kl3#hrC}3Y*M&o&(#`~DpY>8(+;Qt|zm(QE5vGh*9PIL^^7%up@xo9H-9_wL z=PTa0_98I`$)q@xtmoxg4wf8Gg|;}*vdGjL{cMqyI3?m%U}73C*xV(B%dVBKAmF~Y zL!;D{FQ=6nK5KSc^N979D*O!13Xiuc;HG7LafIILT9i94ZSLQxiA*vS`NuylvTJ3w z5w2yEszth@siCff_p&~5@zO=3mt!k}76w{de`JoMiQvIz=$>bYz#I21@gF)*#DJ{e zaOx*gtBZ(W=4;MRt~JH4QR{IYUV9~g!p#^2%H2($3{m?w!emDMq%8w4wqHk4$iP`X z%ANAUZ_T5jR-_l>UnYId7fK*Y5y7~|dLiNzrRunoSgwhoXUhCE{s7_2YVu0k$Lmmc zsN>V8;~$aS>v;|@)&&?eU~0R~z@%P%*qiqgeK`G$j^LT3Ild%$zivT;3`5@I%*qet zScQIv5|}pWd~cG^sNU7(137227Z+naOe2oz!F+#t-yTJT64xM~ZBxwd$yvdC{I4SB z#*N<27s+yOZK3HfqLq+F%BBG|ioL~(ovohmDt~UdX>ivb_J~7S=#tBqpB&G4Kts`y zJp-iXWATR$0AgmEhRA<==ytakS*v2QdX7n56_iYrhi0oh;ik0$#cfp6E5Gjl%Fh6{ z+7AX$di&D?p%?hJ1|{wL>(;Vb@|*V96*G)TBh4l=!Jld+E&}ac{bf|o_+lmhIMOeL zAt1$;=>n=QK$<b(7NDgK4p2yS`CROaJ3lu{e)fL5f6JVslhoZ}XLrl~y?X?TlM`RD z61RW})5onmyhiEEl^^wN|CMp}q7dwZZxB+t0$iEd$Z>5q5l{53+|Hw`iDYrSAK^qVne4tfuQ+d!qYAGCidptQqQ?2Q}17mDx zwSBlnzHcoD4Msf%=reqOsJwjEY_NdU`AAk%da%btMh}B#hdhH1pw0T0FY-Y?j#*!h zm86noQ3m{&Qs$BRv7K)6X?l9vF*~F2;0newCu^2Fo`d}$@lWcs3Fd>1xG9FsFCUme z%>OQnfP}>Vg5Gtry{quDYAHsq+n}U=rKA2<^A=-S)gRTYLc$af#VMok0rtm()^Sc{ z#n#+Zt;&*o3~v&Yl&2C#?Zw}7ZdEHkN#gR#h~Ctpg}BTbZj~j`aeCaPLHHpmNTh&8 zGX^3J`5@*Bk|C+pU~_?V{SE4pU*+otY1Rv-@D}3D?>X+-u0uOcx+&V#-sy1kWyyA8 zDxJ&1pY!g|zO`%^v%2v*%-NQ5~@MR{SNODA{IaYJ#g(R(qbqL!Cs)e#b~VvQMj z4;xebax8esJ!KE>nO5-5)RZEtN>(It)XdS9>(S!t)?q6)->Xp6J3qp9KdFB(r^xW_!jOz|GA02I()$85TS^|8v;3>Q2Hs@9|Z7uf9%SabR4-2?@q{!4Wf z=lI!Tysu$m|Br1h+vx32aMmj3r4IOYyu3D!Xe9fiYnUGgU5Dv@SnUT2qrCC1Sz|By zsLB@}_4((mWG4Kdby$IC2P+`j`!;8^E`0F%_vE0#)avSh^w%Ts#)Pu1BByYM zMyT=$U_miLfDeO!9D-Yt*L_o|1Nmb%9E1cC{y;sG!B1dOMVF9%nAwl03l}LA?hw!Z zzckCUrJ6e{zCdkZ=3nbYO&oa93nU(O(Fn_=H5yPNU;wxroL6yYrci}^+v!x@)PS5) zo?bI>h;e4RS#67H`=~*Ww3?6kFhA^Z^;Wv%G|*{Ry(h6>BynXz(-T5ESd2N!Ouu+p zBE1l(A&H&5zXOfAR}41uHfS(|7P$W7svZiZ>wnQLl(wM66Q~LK=TTSP7=j?WT-ZAr zTfqRk8q-2qMaZ*1H;J0S>jEOtE(n$_Z?eOxXmZl}dZf(u%d|C-JUSJM<8T%jAue~C zvdV|g9=Uza5sSE#XM;Bi9q#W?$Pg9d3Z$aT_HO@AhUvam)J_A5VqHz5+y3!LI9*qg zZC`UCbra>dt&WM-w1$1>C_NJi1s~2IUAzSPHV&52!za_?OU7*46rD5Qv23;@ zfz*=b4+H_-G^Z{o)(%%sHwS^X*Ql-Qa;7E&tE1~B-Fve`a|u~1BZRHc$TSy!iO6XTHwDO=vyggw-e=BGCWi>$H@ zwc5u7?qo_loQv7D4f#-Qz?B~zYqM-vzLCxFbOHFSWZ+{!1p(?`Q#@9;M~5i`kDu=# z@rcnx26)yaC~g?Gud%nCEt|&DMsU?RoO8j+>~d2WCWeavv(&D5Lz!O6N_-1ExcTpL z!v`jJ+lli_V53E8YqpT;xnOV2=_~vxzm*onR#!CYCm-#o3{$R}9^&m)=Qy9=81!7? zo?rxmizc_RF$#FZ@D~pJ?^ynYnz0=%<*=o!+aA%sRLIVey2q#N6{B?V;#EqOH#6vZ zuDO`gj)OSlpYXhX-&5tRYz9-9O6Hs)ki>0#87HtOGP3(upMHl!S0e{_%iR&wkLfG~ zCp7Hz!teh1vJtdH(`4A`X4*922IVs#ja>)@tL*1R%4)!VCWQzx>E*C3)RCi8!>z~; zU*Wu;Yn_CIHYm>~$YYw#ClLuaFq54}q4;A!pQ)jR;)@azeStZ1?F%wXV{%oyc7(!B z#6L>ZKsT?Qv0Yy{(61_U{rSR9_P&8mv9AH*(<2Wt=7)YfzAhS(dRyAm4JMQik_ zX*w|l`ye*l*i5Pn#LDh5%#RE}8liizUfMo(2(r@gU<831ZKnLQo%b$Ht*URUN~m`) z?Le9`l9pHmvtC7YW<1!GfUsAiq5X((?AwvkQv#(0i)6mv8XIjb;<%BFEGU{@BZ<~P z7Lke?s5~6m#zzc>qN%_mzp!1PCG_;OkBPHlj5jKitSZ5cH&fsAW_B#5F+DJ|Qd0~{ z+j;-Hik>YuH`Z6Z*jUlDyRrU4P|C+QC80+JNgpiHinRGnz8@h8{}f+EHRsfcAT~>? zGiJVgbfVQal__rh-@*{FwuZ^*lNC?b$Up?c6=TCsJuwKdDGZUuI$jTvmO!y%Ge5aY zgfcWxqd9`v6?5tj!E_b<>AiJyMt0nj#laze>Rjr+&V;JdEg%bAs?vT{(1?(PCUG>F zynqx3SpNCwPjNo%rB@uCC-jMv!GuUJ+aA^4a7HqrQH63T?cNAbSq4A+KIIXJqvYWx z^N;6(MqhbNG}-V7we9M96E58b+Bv0zV|IK8Zdi5w49ke~HigxQt9}QIYu^DPw z4dzvQ*qw^8-iY3EFvFj}DwUq;8tOX?;FQ(}q;lN_6O+>jiQjK2 zG?MMT8IQ?33sXR0A0xRNfl7~D1Mq{tl@<~*%>-2R&>sh6L$|9xBDz072+cyjp#B;{ zpPj~%siOgI=AhsN_wEIb0p~CS=6sQ?Z7eMU6)vC(lygny05a_!Z>oOdRI;EjGnT4UvEg&&84c z43Gox2_Cl;ANHBaOXdhoH^bacFehA{eXaKDvvyp{7unANfd^$YFEeAy()h2PNf3}A zqiUzi$ASZ8ukaA&@;u+yA>k?Tdib-P-$r6yu5~O4N|ER^Xqy|Zkc3QCV4D*=oE80M zUQOq+k8xC>SsJWm@p@F6Wbf#NLB0{b*w_+prIqcd`gw8W780y{i;;vA`L2PqE{Ozr zOFM91xX9J)t|1sGtv+0uIX(y|=*@ds3ub|EUy!|nbE2RJG{4uWWyZ}|?PDA*j*qlD zxr49c5#iK(#;P#8CN-cK*20VCkfYY7)Rvsn>Ss(Ia2E$iE1ulMPt#g&wsIR2T&&i_ zQ>lc)AmYz2FvMYqy&|A?vj`4`$E<*?;4G!o?AHO8`HOy-KqxcC zJ%{Tmx;FS~tn=BjxgUZavgRJf&vxCeRrN@!vevv!UHX&+HN$|$KVpO#&aYUjv5pgv0l#FBx)?YA{DwMB|-J9(bTCl1l7Zo+cIB<2%BOB^|xQ9s)V)^28 zA6RE0L!-pBI4=$2a`WBv?7L*>9|VD7BET$P-?ngW34R>M6wN zlj}YiTh~DH%FRQ^NTdX$T)|&&H)*6GGL#d$&Nuw2E7lt$KsbmRif@nd$@+IRjh?Fh zu9f-x>KRe;)4s(hV^jDM?(*paHR)^rokNIn37|7tBYUszT*nJ&fZXq+cQ>%wm=uB};B%A$LZ!jYk&x7;V5@@3=(a2iK0%L6( z43y+{fBxDtrPj4BQo3tY?mS`FDu?D&)A{3mEG(MT*^NK?m0c1$f0cu<s6`^XNK*=@D%ofEe122AZ!<^C$djO zTF(Sh^F(Y?9 zT;Nvo_>6tI6RBJZL9RfNCeoE%ElR)g^v;AiC}z?OIbyA}Ju9+@(P)qxQk#IM-*Vw_vfPXw;700eE00VnEU{L-E}(^%PzIc?QQG0L>;Fn_keoG1gNc0C;%3a{BK#Inaz&}RW?K@^j z=8`$oHZGYM1qP46lAA>IHwpcx71VO-ewx5^U*wSwiC-Q%jgyaOOvGOLU8g12G@KQ+ zofHQh_j$&W;__ehv zfzMe`Ir122Imsd3zv^`=i7E5XIQ3+HaGZ+j9Iaq4@}cGwZPd9bhLNf{rNj+H-_&az zT63w{AqEUwG>y;Bbr~y@kj-)piirMgf|zD`7TW0$lwt+{&5rt;KyX1Xc1`|WS>1xQ zE66bLJXm83>W?f>`Z_?fF$GU?iSK7LiNe=nt3JZ-JVtHIZGH-~F@T=~T6nnDj&(^P z04adDr%)%R2sANLj4kjjB-l|-3*xap(dIjlbMe`{B37x{+Jr*&{mcbl?iH&KiON{m zUrTo&Q-mcr$|0-wrHmK70Y1rg{`D7E2Rw7?39vuQ?4d2e9e&D5E63-G8dx#kgOCNL zzpBH?GJYEOX|e<|%ocZ8UkI~yUDuQ6swT&z0rRFECmVn$fo*QJ%ZEK0=#Ks?MTc^J z3RgoR(S6PUrFZ=L`yJ0PE%n=<_{JDW)fP<(Hso@I1hd`wjJPPE!0{}mykDX!6bvI7 zUv)m3&m&hnDo=Hf3>C8%_yuYe$Mt@%#=NBp0e0jo{anBBqVjcvMQ!|bMe+9_3XqGi z;5f;gjiLM`*Dt$U{KGUlhTmm?cBHCj=dkP?UTxmcs|M}!u-udnYhn$x?`W+GT&|X{ zJ6ZjCf}ac-y%5rikc|B1vmO!?KQUz~&_0V*d7S+D#PZdeF7PwJ)#$|E!kS6&984M! zh^4|-lY1ZM>*rVfD5+jOfA+x=(CUwLOG(D zYhQYRfNU7dF#9O*%w9U}QpWca;m=TQyBu;nAy8N461s{&# z-m1Q*{hnzv^N3(UN=Mhoq1Wc=8Wty*Ql35=u{lqI*}b0)Q29{4eOLkQpf~2Q=5Z}M z`(XB9aFHO<$#Fo8b_F>Jr2e}R^-gI-F?Mw6`qh_Qbs5t@YI)r6YN-XzVye+QYJr*(*{A`1b z6lr$w2`VhN;xoXWpzdT3YpZdXhNYw?EbKs49Z)Q(p)Bj*;$5#qM^DN!*!L0yY?zuY zL+JEb6ZxXKTV>AL=QM6C)(mU{@syrR_rI3zF4c3G+{Ez^Q1^N7)Db8n z*zNU8dC#1WwbKmnF$iVDJwwlA$1V< zD8AT=k^Vb(BDZVwpvi)utC@l*TOa?@SG{chCg*8Hg7B_os=WZyGJYFDT;bR!Q>B%~ zn!2t8%iAG*(7Q;d5l}BoKvR!T1*8#GQ)AFd#?B@(e*=@?d9X3pY30CLtqA<4NC$~~wszCvkdRS60a?tDkfjpW6lalkOhlc+U` zIMCeWwTAS08L_)iF{I!(Q;YrQ_gY58+uxiA!gT;+#*BB~BgC=2|UJ#y3Bg)0Us=cQZ`uAQwll&F6mc z=>Ic(v@FNQjUp*vpS#MW_w+q)r`W?aAyh2S^%}6qjV6I7ig_(U1Bx3 za0SL3@xb7cZl?J~+Jceh`Au5V3Hfeeyq9LjbxR)F+2OWb_&vH=5H^plD@)Sd?B|6Q z+%Z0CJv@0tra5f@F>?oCuN%j&moY_V2zUZNiR1WVAtctvSFJqLEhe~cxvYBsiJJzZ z%IuA&+EJszj{%9L6D&b-bgaHiWQGP9k;3t*Mul?Glm@a7lyyeqokNDHdyc605D z)A$3gkn=mCG?UlI-7EI5oST!ho1FGO?61B$O4nZR`ju72xFBo9W%XuX%gBN$9G~w2 z9&6Gsrm347UXrlPIKWgt`E}u^o^>kG5vqi-hX~N4mw3dI#>q0}E~2Khx2z$tox>I=p4?xi zhvW%7+|rCSbFWWzGG@zpd{KjUH9S z^~P9mqgw5hpXUl`WioAiEtd0B(ZY%)`vXA*;!%$oxX(Ju|fv7q(buC zFHu@m%}bg%y3?eV4t$IEBdzqlL9%@l9i>R}k5$)XU6DM{<{2ytR9sLIv+gcd0$TJo z?hRaIUdGb_)YV`A@6eccV_~mZj=J9fGCRM@P(e}C@Tg_rcT3UWSWD*<5vp&P@^w|M zD%RP-HNG65aHZiBo-nq2b3_We=K<>Plt~2t&L{WbDC#q4t+KvsLQ$CW8$T;B1>@ei z?kzW|?a+frD5A3hGS3jGrU42%oB8PW(l7u<&K+n6F=th+8$ZuEA;W>`jj;$d zPavCxJA0I~fzk1cjc19bTG=xhj?E_H<3}kwp1QGA6uy*TW!#lmJ;u{!m#1=viVT2A z$fD1k76@}I2|AxrP!((BUMJYne+;fHIwG5l^!sWeBoRRFjth#YKj^RPZ4*G+GG}#} ziLO=Cqu>Jdt#Zw-<(e>R3as%nkBd8nyFvOhO(Nn}p#UweejqS50ar;_DZ5FpcTu)G z9{@9p5!kdQ9gXdmR@}YWI0(-~)gcy?{+$ftT;|P0s)BcAreXkrm${vr3Jh>L1Xc3k zqy@eQIir2918%nSOT|W3iQNEbx#w-VIWKm>+cW)X|Bf!o>P44%Ur}npM9&l_w{+Ct z4-@<8k^pTq)z*zoH{xD|U(jE^Da3s>Nq|K#I?`9Ii6eFaC=}Y@h{1GlTiK3t52$m* zUd;FYG(azfKBsv_C|B)FJC2v(Y!h_t&w<)v@)(VCr-KnqCB#slE=`{?OY}BYQw`zt z*(QKPu#I^!(ooj6!c)S|HGYBDV!1F{1{;#&6onEDAA_7~O0-wV3jGksJla-~KLL~n zZZj(pjN#GRfp0ADCL7U++{gS08YcFIUm<}^Ffbwt_k=Jx3wIz=uN7?5uxpsep?T+`sb0K`OfuO8Fv?Q#62QuZJn!HVDJyH;bk%;ZE)1 z3&B~MXXp?}MAC9ww@2iQ(VJa&z1l63HdG3SI!!VZ>I&wjd31NVT}1qQz^tthLX>UJ z#?#9gY(3xNYXMmUB4S}Iz}zpIt@A$hDTp?fX+6addr)Y8Zde~d3ws$8EZ9UJF3f15 zzvH5xhya7HC@E!K4#xf2Spn^w(Xut2#a|Lx*Fy65UX7G_W%;csUY%3F2Qo)CMXZOKTZl3&u z(V=W@U{8HLAaDbw4Qv^4h=$irJOR?5%{~`fRG;+rC{u^Yxm*xaQNEi=aYpwuDnIq2 z*g9M`6ORxOl=1eC6$MT5O*`k|h*H*o;RE+Gus;}L3#t`@{MCG!+49)D>M6S;Mr1Kb zc-7yVIh1&;1}9e-t^(zA==ov>UiiH-5>fdSo}<@=$>KMC=rZOv?MUgeCQeWZx>^&+ zF!_2CrwVh5elC2N$+5Fk#y@@<5FJSt;Gw45%eO4B>H?dFgPhSTW{bl}V8qvFhS({! z9zE7%##Mg_E&cK#4e7QK5AnUNuceC1ML8=61aTgYH27$iDfy~AK7mnpt8UMTS$@zl zoDN$p>C03c4mHC&_i>V6QFw{d{O{zt3BZCt5oiXKw}`Tk-KfvI8~q@j#_#80cxZ>7 zwNQFi`Np(m0f=FI(>-O-0SD`N(}z{C-vmJDUy*}Rw9gyr;+j6^cK0He`&{ulh&S)- zwvrqS?6qJ(C>S@Kzn^`{L<+Rzg8bXAm5qd*a|mRkzLTXTNOk<7Vr8PC!-qM) zz@BsA$u8(Xu7crh)>i?sM$LaosrC))4v0-i$>++(I3@W50g{n-815#gV&?{=3DXUf z#lpt?O5g-hK5-WlI+;xBbZK4CD37Z3n+q~dhnI0Pf&2aCh+M;e!b%vPZeQD#-Tens ztQbg~HR~H7zt=v6s3qm&XU)o3Wgz@l&E?*2YyVx%(mfi|;{niPJK@~;aa8!G-uL_Z zDDXQafA1!XQF&df{!#+>9P0XGMV4D19I!sZLqN)k$X^&q)ZcI9y<;e#A8E3Z%)t(W zY6wagcoh`S^}|oA=YBU}%I9&ErG$?GOmUwUQ_G=YetiX)l|Vb1)TegyG1_WejqvCp z)VF{D{qWQ?LaW2=k3>QHg9~8Al|1=93x281d9(D(5x{=qGfE1A$gw@k%$mx zy>1k{NLM3l%lVGKGet!iGPe9|R!7wH69|8vWXb7ZZ;h8D; z)%8((e$*lFl(Z*j4>F3&dsvmbD*9=n4L1jgp*i<*uj8;u;XKI#`80TN0U#m9%8nFF zn|d)^t@w#i^zeC5QUUCRS~O>NcFVL z|5&EG=zKzcV`0Dx4#5op)3TMxvx0N^s_X+79I&sG-u)M_7K^UZ@LR^S8;58D<;{@8 z;r>E(z>iz$bV;}m{6Qhf*0{FRpF<+&amwsw3Fc`Vg;17?8VPS-X+vaxfpALoyn;Fp zf80@0%pP9uWQ1=^cuwogYv~)3PDDrCo$*bZUq8300Rtolfe6XN>OhR_d=#R6hNDHT zVW3f7Ucx~-!sAF65Xm>(L%z9LVd)v<`ZoyVh&!djvBWoiTyBvNLW>*pnI@hv+ZpPy zB+mZrC_0y_Ien_vNt}S zWS@G;R!)g%2-9b!muebh`tFcNmN$)i1dXUBBWEd@Kc9yZX2Yy(>Q)Vd0D;EYOgxg1 z`%_ZKy=vpe>0^4!zf8C&AO+nG=Dyl_WIAHtz=tuL<09GQ@!u6q)`$d6VjB0~vsJ#DcS0)8jt;`yPl+JKr zjIp&XOp`u@|AVZ_xicE)blBL6Dk9t5>@72c)$=avwBaKg9Q|AduXk<>w0+zgSd!wQo^U&uA$NJ{NLT@%qNhYMz=<;?lzz zQof0v43$ibmNDFc+~@JZ9}vT()6^FHqa?)=)6o-Yi8^CFZReD0eo8)D32El|tU`W- zCa=<%xfb4pT+#?7Xpxu7Odb3+u%YwjL72&WDUi~8RxTSgqcqkBw(;t#i4Yr*%eUP^ z0s-Tfw3vOh0OD1iKS^}hv#wl$HH_M9o3j5X24-6Jmvt_(7lpHbZofjb$8B|udSy;1 za*cgR1Se((0r*qvnlVo-FQ46gtOtf#rn=KFN0RYV@q{qC2MU94%6n#AqP!?4ob43QnWkIL~YCMe;w zaee8-hFc9K@r`@oX!{xzP<=T?jALO$f<&G=>}Ryt(<31(i_EdvToWdesKri_ew%)q zYd^-M6fR~!D6#a6ABR(8T!(T1y-yG}2Z}=9;qFnRn6c&=~Lmbw|81BCd zHA->@!W+PiP{MzNC15@d^*}MaE!r)%eXKSn;Mft;~^- zdt|h5!Xwip-o_u!)o6$NBnUYRG{8>|EC5{kl-644X>3Rl#rUY^Yz=sZ#rmiOQz~xc zEcjD0ufYGk(~kw|VXeWDU*BroBIK@e3)ijTO`b{4niVXQfY7x(+LPX><~_3>Da$kV zwGQ7E%~LwPfHr})a{}Mz@Ec5s{ zH87x%)X=%8;IbE82F<^Q_?JdQvw=np-uIZJTbztQlD^va(7$f5a1WjCgK# z9>t*%9FA9bPLt-B>%*xe0aP&HLdKYAfAo`}bwwthR=3!i8 zzrCRtME#szar`QZ7x+S5iZ^{2qQ(*LSIo25c(%7D;-J>K@N4X_>e`Rgac|fuvGBY1 z6xIyXpm>Hu_wMe{Mr&s}>xg5{x|;-3FCC+3O8iDHySExMf#&!zB-NycCRw#fnpUck z3NudGk7v;0SlP;p<6!E+%Har21Kx=L#Gw}(?Xyd$CH)2X}+H|ZQ%oR zuhTf9L2;fRfOU9hen=o6_rQq=1=%ZM=RIFw<+Saj&a1?OMpXeN(Gvjr&$6vBSjjng zklGeF0s={^>0i(~ijop8vBIxf*d)ieAZ}8vxxv1PunYKy_9J2zf%gN*N)(iVc~|wl zv%n?3*0T-_-i@2JXyHJgx0W^g1!V}gqf&q`5ojS2pE{!bkl|$TKae=Up1G z&sL~`<~&Wnh;8y;hb;RDRE!rLTO`Eg6Oq9;Hr;jVzZkTmhV=VJ{W1fr`PO9tt_LM6 zi0CxKG3ps^qF>Zv&N_CKwhp7waBhFP?4rzH)KnX|w@46co&o+51A@pGxOW+eS>ztv`gO(nk z;)X&S=vH$Jw7Smn<*%uHu$N&C4*wzTj;<+M=_uoN^z^$28?;*+6)|%t*~fjJD}BHKYKd|FoPDZ3+IYU;J%03kb)jIgieAk`*)HT{nsa_CqBe`|EE*LUKQlcCGb~zDy4(S zrSW6%eqI4^SWWvGUfsTN65N0QI~l&G$KdA!1%l{0JPKo(>9DDA z;tVUeK_+>!3XvrMcR6$%63NdeDm-QAPsP}*%yB;3dAjR#vm6$tQ+p(}N=4Ze)iy)r z<+@Kq?;5R)z7z44w$T5G9uzR^1cARgC;jWsZS*m2&41M;}uXPvplgp0%MW4 z?7N`aWs!C8^GVScD21pj&Cu`etH zCohH%O0$0jazK-;_!AFI&H7KWtO+D(I$>c$x`NJvRi!DQ;@;TD1%CZnH|I>^Qxjm> z9~nTZ0gHe(eRZ4st#`&e?oE*bZvSqAkP`o z-rMmZ9F29S1PR4Qff_D~UXPTRBc!1naYF^}j>rgR%c^kdbhO;rAMzCJgB`wCA$sY; zyQYo7yt(0Z2BAnt1x~;3v1fd*PQ%E_mFU37Lu9c&$zz#DFycQU;d5lBo#u)=-47VQdI78@b@q1Pyp z4+*kZB-WHvnBuM~S@Fek`$#0)j28Z#!zH~oQbqwZp?UjzwgEsqk=Vy@gWj312gbL7uh@%TH z+$Z#+Bfm?yPgf9MX#Opn0;||A%TR!Sw9l3t6y^sYMSgiJ6LyIz-*WZy-gw5>j*23; z$%*!v*ad^?XKNq1nW&f2H%57m+vm#VARkF6fUw9h1IK3%_LPbb*>6~ig0uBJdHLV( z)6hJ2NNOy26YEPEhcfU(yU8Kx=m_F=jO4EAPDd5Ff|2I|H(Q#`6ZrZQ!Y$ zFh|Bmr_v2F9dlcIG~9cNwqH7Y zz`Sssas(FNp#}=74O8RfYIufnS-B|uCF=7f+7teafiG_IntMS?1MLx$K|qaD>DUaV zq!cUtjtiC)fzS^bPYtuqo;&BLH!{wweOVo0DVg@gd{5S;8-FH$FC$e16^t5}7Uaa% z@yr8B1+*Qk+2T_MBuQ9ioF+Z1Czpw%DNq(Tf+Z+T?3U1l`|W}B*2Ks8nEufDUvd-n zf~>2l4D496jyMS|Eo7SC8<$!OeIL@Sfd63feg})T$#G5;gfc z&857hHN5F}vsDWA{`FXCx%RjxMaBr-jrS4V7a8D z_d9NM;B?>Nc%07UR*%I@pYZAIL4(iPi##FKXZtFJnXd;oLwK}Fj@C66Lc$AL6G3rM*u)SZWF2he&v{o1toM+NcCp8J!gIWz}zuLWbpK3EPrz86GjfMd)k!AsmIa4Q1sA7vAYG`kwcpF-GyR zbI34i2M0xe(3mTPh#%QOgcii1B8mx%*+t0t79>&NC42hsTP)=X zXwN?R<&fCQmr6r=gp{ywb<)cRq>UHUtLn(3RJ(qI%kn!#myz1tAruBD_RC8Wpwz}1pW7p^)vk_KEJ7>4D(nrenq} zwgogSI|CrVg8bZ0z!ySsz~;%x(rC*(jc+|`bDOeF37SKL<0=%N zK(DqAo-zbjmd^DURIm{W+5rVXX3H&XRBx(+?R<7j(bS;76xv4$#@rt4>x-e06o|7s z->VKTv5^!R3A#YWn+uoZxvOI850KwC^%Ob3*kuCh8NlaJZvnyPzNG@JRgA_o zA|7$o#A$o1olSl)h>pmsrsI$3K^6`@&VTqx2-4 zK(u!&y{cDjcZcR;wlUd+6NS`ur;j<1|HUN(`l=!(;pkn)S2|f;_hYP)MhDw{(=;Lo zx8QEsfr|w>SeUBnY#wLr*GM*_BU8-P#W#GU$A@t;^QU6gk^0io4cGugCGs5zT`8b~ zbkjDsifItO70}-kKA2ZPFU3=7GYv;ik1+JR1n35oOS{!dl=<%O(5mUzW$I3sP#5B6 zn0~^DETQgOhJKeVK`k3J>@e0zsxAT8002QizQ38EJG&ILAVYF~7t29W5uO-SV!z@c zdBy&`N(r2$xk>zP!85J21_z}ffz##5ozn@;oqdt7b1nAgdTBMq`~?<;@W;;-kGc1F z3|9U*AZWQ%H(?)vY#*;6iA7rRmuw}n%kaiA%K^wFpM}TPr==HMmyM#iA&H(1@Sf*m zdTVjY2cS#eB3^Y|o8(gG>z4p==D7C2@hs5aSSct(2(KSbFzl*5Q9KmM^7%n# zOm;sI(N`;Z7ciG7Q?i{Qb=tkIyu8Hn~MojX!}Vbez`v{%jLBB^7xc{x23YX zHGDsv&U28zx#E%92bb0)-=aMPK+XMQpNk*@M^lF>N3q(eq*r{j7n6SNf^#WJ=hfN% zU})iI%}74YSM(?|&;0;U$(fcXI$yVW(zJ=)X8C3i54Sqw1C>-?lK66jE?{h0Hn~Ii@wuCRmV(t0N3h>m4 z;lPsx)z;q@ojV^ldN1?n(EX=PF^q$q_)KQ1(_Y19tYPwzh9E`jB>ZncUt2mY`B4+> z3$lojx$&>XT=bX58_t5D_Ia!N<@RmI$^|~yLO+o%B(mP6X616upUiv}3NUR;#OJJB zBL>^Ehi+&OnhL=k?g0Eude@QgO6>u5=tA@|41m zZ}fs!cc_JBpbWrXWB$Z`Jbq&V+c~eG2p!PtZo4d6HCCj1OP87CR5AxVs|0Mgvir>) z`H9^!oz56kk>-7546U7K;h5DRhQM=J6>gqzo|nocAsTjT2aT{pz?SWxQ2fEh;b|Ru zH&kfMa{lt61?z9CxWs_=RTnqTv0bC%mWGJ&T2``;B)?QQ=Gf4qX_NeVdkeYstlPc@ z$=rJn_sCV^5i=`G`TJuhUsxgKkwQN{LfHgZXg8fS%A?ze=UmX1vfn_7Efr(H5KM_G zmgu=XYow;zFw7=PB4iPSJUMaq(4-0l^Y|1W8BHJ?N_d>- zXrGJb?T8@d6kcjR60;AhH239t9#S%}h%bCqt3M!0O1UDb$RTDBk601z;Aj_hzL7za zLGvTV*raOY1lec~0iHfogzkZ!(@BgtD{-&z4E{<_Ew=*9>Hz3lk|Jy(J=9!--gCWZ zUf-dWc3&6ZNDt4wA@9lEW_!3655wGv*Y_f$%efnI5dSG4wZhkR{0t4dqDG$%s7zZW5#1STO4lbzrk>*Q`3cK-fTC$$ zcUc;DXHZ3WVZpw_X77VHTtpwMdN>?H4M$u!H)fZY$?(5%xI)d}*@uIIaWmT9AI)cu z`3v9wt!Z0ZRdAb zoMvw`_akRk#89{1o{cl5T5_LW2@&)xy z9cTQ2%2miC+}2gSNn9Wlg!XLnjT~Z8f6sY>?A&cg()De5N%a9Z<=W;X8cuR-Dkb?m z@Vb?I(0S}P+02^!?rQv_KLg z+Gvv`RIs7WQ@ksuGH4L)@hAymskcGcR!`j4RWq^!#PXId0_q8omFp`7vU2sx4q|(~ zG=7<%S+%>%FR6;+s24QytrQrZbq=;X=kWVw1VonVKA`5Vi^hAj?>6Hp@22&{;J4%B z;z<3Hf=b-1Mf#{JZOokb{;V!&z9tHfCZkr_P0rITS*vF!c?z!@jyFTyU-lAw_cETh}ufqin>qm#RfdQr}BX?tBNE|hr!AH3I zVvOYRvd8aE3$kJ(0{{;=3t?P;aD-Nt}rX$OKt0VVdJ{b)a3o zqn0KG?63S22g0kGO$V++>!(VU-EP_sp(_X#IJDIOK2up?x{KG^5*VU>zr`#tEvx-% zipW`R?)GMTg{=BMi0jjE)BhmlW70g2+iwRsmMcqM!fxdb9PTPP2q^8CN0;3 z%bm;Zfeqqz3w)a_JE?w1j_&{Hf*e0jZi0zyTSe zN8~KtHThR3W|egx9wf41Wr2QZUYtnl{|AczeM|hzsLHh5Zd19lRn7b~=Y%bdK>FA1 z8E9(kXCsuB(ELK7j-O=vJkKZBWK~`3P{Y6RJJn_vCVwJ4}fv$xi3gmf%q*^ApyJSNmv(fYewXjhpXO3MV;@@;7YGWrxrs zr^#kL4Ny=&Za>pXcyvv+6cs}JbXLBNbV#xj%p{JcTD)C^nl!$~ z(box{!uPndvPWKT#NP_Nh1pIl5bh<5`FJ;h6>`jf8|eaUeAhb}aECbfez4D02m8+w z@55?1Lmo-pQOCWMfk#3@AUmotG-!p)S)UvEHx@B0lRlBH``#6%qRo>Tf+t0jn@CN8kK;G|L{B}j1?~RgWumn$CC_vyQ?b!;9ZZ{ZtYAMa zWq+an+>QPVqpF_KzM*&?Qbb6Dy|TG?qb|ZFL&l`*=BQ)0@v!QppW&b`<*6oT3>njD z)j*zq@-hfBN;8fat*vu&X)idKqa`SsNmK~S`0Z}oSkAUg)ni;i(5I$}(M%-kV!Txt zQI;#cONyUazOSOklF^S$E)uA6{rEWa8HHmm@8u%h#(D`orSOy0Kb#X{1Ck#`JrBsY ze43f!cKjD&5OHT6_e)#SLVWAhxb&FZjnKniPh#h$5-YDDE*cL-_ViCghb%)6hYQi0 zG>R3C73D3JG6OWFwStH8V}nyEgtK{-;vsCia>3Rt?ujH8a@Z))q(09jH%SFM@)A=> zQy#_i6YrQQmhl|54h_>%iEsmdXc8MCRmtk{WPbU2R?LZpVrBV2X*2YBt#Q<$BZbBi ztu?-A=~;&B*c6XlDxpS0Rx6cpKOF^OW8&-v{yg&w$=Qru!j#hEC=u8rLnlz%Kv+f{ zs1_-BWq6W>Bkb0s+DmaeA5t_Ml{2ico%$<4(JgZ)+}DKnUN-=dGx&Ivj;~=j61#92 z7$OWszD?24hO7P9F1!U9`G2AIBdJ~{%c3L|ExN-Eqfy#i^&QDwSQ!2oo6Lh8)I3Xn z?Zo2di8z&@+#Xwabo`jfq00|tjJxKkQ+s0?+e2R*(Yn@HtV}GH7@S0w>;Pcg@9FjUM|6kB?#3JHBLSQ95i! zF~bUe6>E|tOz_x_w#055<_HSQtwSzcJ=IgMhPky2dSMbRR8s5O-m0-w!?(jJK>xQd zWq<||+-;6}^3UE#wwjt78+2{I-`uSHw7$+m^_8Mq2 z!u8c3Zcq&iZux)%ix|q$b@z)&baFFGk zqrgH0+&X|PAaO&5@a8kJJ~bcF(Fbc{>&inK> z0SlL&1{)0kZNs{QwZQAWS4Zh6FTcqo8wua+F{tl0dHa-D@VlNuNpMEd)7=WI~KOk}vpuY%D(esx|kZ?c?v#bKZE7 z#O}<{2NS*@KN1rWb@Z_F^vGQ^}Pf zQMmqYw0?fdY|ZNL@<5_ft{DoVCkaj?)Nc}PFKmA-t289|rq8AVWjl4n;`g^FknyPY zs-y3zQhBSFkX}i?$WPR>pLHy!#SLHFU9^2`WJbB_DQST0tsU(d%=ijnEXVnEtVKQY z{PxISuGHa^X{ykt4Ewuy{L9Jqab`0`cLq;{5BYr#?KydI7%#1qI}QHaVj_s1;?@wT zA3SS9%L;Onm{}W?SA(g*xCNL*z)^;eMM5M;lti9 zeVK2|+cxl2(mI=lE%Zy!@9@J7)3zT0PF)MgfyaAlDwtsKV`0l8R>rt+dMMA51yVzs zkSk<|F1(ic=%Q}ZlnGkM=dZW3)Q18&>PJcksdTWLa`QhHLoJ^zlI(9n@v&84DC z4}+b)7qVn6;|rZJO6u@R#}|!XAJ$}bN)@NOV4fM^EkuZ?+49AhI#bPFBUyiDOcA4T zHt*TTIn)+EGKb$RP3D_dk?3#96E0=*m|k+>+{8W8264=y|>B& zclP^PPo`;^{b6BLEIY4oqA+}=>u3*4E>4w1$kh$S7axv@S?44JW%cA^4PlEWgL;E% zhhE?y-lQ8hs9$EP3!kQ=YjRPU=l*QTbgtDSbq#E}Vz8!Cx^)@EDPMtxQcaQit(}A> z4!>yPrv2gqjdjng$}eCS(CA4e)d`yH&m+o^E6j%BKDtsT=7;n@6<)hT!c+kIY3rFV zL-(cVns~G2M{)J%WR-=>msUXs^n8;6)RjNP$b)%$3n$ZEu&2978O8@7e#qqIbn@u z`3ExKw)}pv+Gvgoa3SNQQ`y@;iuU=U4PtjnLBleIYk+UR9K|N5Z9Kyrflri$vkG2x zmv==S#etw`HtL|$#5S< zzHwtEpj@+J;Q%g@t^<2avEIfqH2~B#w=pE{$g*A%$2zp?^Tnp=&WNwu?AzrEb86H` zS(#P;qZk{DURm=pEJZ8|5uFc&FR}$SCuK(g&MtRc^JC2^APLdULwiUbF8|NMz`vzz zoqXz;4I~Pe<0mGCDBfh}SShy~=o00{B_jfhX0aEWT)@VG-@)V|G?Ol|`C)s`1MaIc>*h6(jpch2hnn_8oqHYJ&2}@u{{wlls|hC=X%53=sVQiu#oW@MdUQ=`Pu4uA`?(``j+Ete1@xxqA^lasSQ;(DK4CV9dEAUosAS{tWaU% z!dL)e=OTogx|T$~amzDJlpp`STmh$nP-j5V(qN(+~qJHV} z|B3BB@iKP(9o+rU%#@YkD1sY!_CkB-K=%7J9xTFbD<=su*Q$_48(LdPL(&jQyFntr zPJ6$G)oh(8gO#8bkNVNdcIPKogI&&&Ck0lL`ve{O*ZV$KJoD+j1-bK z$$`roUlR*XUOs$KXf4{6{7&WbvLe!O(}N(B=%B5n!EVdj2-{F`09`S-P4l@8RANKQ zL_jMbsOe6#oklcd05zt0xO{EE+LwVyA%XMf!_5Jdk9H67Bx*M*pLPoxP>_^VMSj+$ zfuFai?S=^cT*atHqk3lr;&A8a7G76e5DG+T?Ij5p&vW|?RP*z#{gt6r1F8J)^n7Bw zKZUXm5Qwu%UOu9C=BsxYUyc9C{fGT{Z_j*Jej0@g^8IBai%=Ur(j=j zr!Xmf51GvOjS4iaO^_g~npk9#ZfdmoOgxOfc1Dg+*wW@(J#fsUq?AlVQNM;jc^d!P zPtFY++|r6u*&k=|V1pT+KK9u?B)8X|7Lq{);IYO=E_bB0>65F-&auY(o%rSR9Jj0v(*%FubPR&pep{TPRa+>P#uO~3^rC;R0w2m_dnYGlCiZ;^{N zgKiXhy+mkGDqmTXW?#CY7EA>a(4fVExdvftUWJ2l(VMGCZ#v zTx#Y^uV}M#6HKg+%X`6n{#spi>X1RQrlz;ohOm*#asz#X4Q?7j6iK$(G~G4_nla(G zwPgBt@7G}hJZl-CqcntsMOLLm)ydZBHsK6jm}JMZaZCBcIm;2vC)!AT94M&LX zIqzh4t?y@JrXTckGPq?qJle_#JMf*=^;B;?GOdsMlD}nU5@uC0I$2^D3nh_!cx}ym z(v0qeo3vC#EVIp}G79@(s%+r;6^&%ejUMbW-o#{Jyxet@u=&F;)%RSpG3%%eQ_Ha$ zRP{W*c_9G!SM8Im{o2z~qiX%e14G$*^;@A3Nc476pJV4E5pRNJiGGU}t${Lc$z9p! zowD_tWoxxl%@0h?8`edu9#FZB%B*|62&E~N-vfm|AdS=GUbF(VKYruG*`Vl&U8&{% z)o-Q1*8~-x{LgJ*za9pfC!|NUwU6D`Jf&G~=!}xEdrvTIm08=l`RU2E%3acZwDTgT z%UH9fdJfYrB2fyzuDOzhn59k|z!=axzWB@R?&0spyDbht>ftY@z!M+BpCJa5b7S^kCQ{GuVi~-+JJlrUB2i~ zx50@H$`ci3rqF;PS|O322lkZ$Nm0u7$wN@`|BuL%y4`}z6?LcELlc3Xw)1$?@GlHr zx8mC(m!;e=_^2%()m7r2c!ldQ2>A&=_13U{!2!awj3r?zAX4Y*R*zdy1y#(46~pS& zR&jIY&N3GqESbSl%dg?Xp1cFJbG%tjoV_)Uy=!zXazn2tU=YZ*- zP&5#+=Xu-1T-l7UA^NrGAZu97Ui|h9Qb=1AWlv7epD-q@;Y(RGTZC_5CaiH{>b^iT z-pV6reI=?)JtOKm;6RCxgT9=QWD3Af*g6I_Dl+R@>C_NQG|GS?lX^dlZo)*aA`UK_ zG&QA@!7@tzzxmQP9p#ms&t0w%vNPVj&DthDIit07pi z=0=vE1LL$=L#>I`B_FWfzJm+nE|}ikkAW*aM_I1RRxN~$y~S>`mv!*}_4a2U^#gs( zE&GvS=B^ykOuPBQM^HeMg5#7aWh@qan}0SnD1t&f_;#(ju$(J=wD&lEgE;FO)Jv1b zZ>}4D_|#i8SLjsT*S>O<-{fpkbU>^4dbwo#3m)X-)S0p4p0HjuWzs-(Q)!ckeE0i0 zL@`nYkUe-ERxWTJYw{4AOuVynx|l@tWBwAa23Sj^H|bzEte;$U@5;PfRe!eBY9h%j z3_q`u4xj26^a?R5kqhI* ze@Qc%cCspoHeLgQ)*XWSRJ3~dDCCO#%_z+_1kHVBTpRgbe3#+qMur)cPm04J_-8uTEt&W;Sa}oJ_ zz^NW5WBd|-f&A?)J9GOp^7)jXe}O$o`860pyu7j&mOsaDa#{E6q12#d_yp8FchXx{ zsof^R89>mt;RxS^%nu+Qo2-`{KJdI}fY|TJPr43KV-E8Jb1-DJ+3S8O6{4Ej29CkS zjjQv%+uhJXrA|^7a2_f{Xgj`<*mLA`D?hN>y;w=g5TU^4^5B$UC)3bLNwgKxo~7>U zK2u*ch6LbwV!TBN$^toDM6OM7Hb-+^YJlc50PH|jYanciPzaXdFP=Wsc-IRfI)QiADKpAM5BGr}D4rz}q+euSITJ?I?xP_P7Pb!~N!;y~J zePC>ptd8a+B@#`*s7^Etp=$>P(w>Dc$BuXVX1-xugtEwRsY^V&)X@%-lc}z1Zq8|e zuW*`9@drOp<#xFUBOl>?T*me^fmp*Wqni`a*t2k#T8MGuu!Wm+KjqMcaw?W1x)LR- z+OHi;uR4CTSj|O7%@TOHxPnfI`^hj9IAewQRGzK$wzou@ZI-lcB%1T~xrOjn)*suL ze_I?|yhxoNz`c|szi892p^1%FjvGSqx&2r}13+LMDJtuaSj3Tki#cFzey z1L^a8PdA5NyQ;x`hANS}h6lIyL8>3QERhtD+$(sXUrsb5XX%h_k)k_;gY$Wy7o};+ zl_HCC+V&L^cx*Pu#N=zK;iTxWvf7bX#3&5mKVHUMzoN-Z>SBindcArjnlw+WNYvLI z{ueX_Ag5LPWB}#Wd(U{d2q;0}k7vw5CriN2ZQ?^>Fz9zG=5LGICWd++tI^btv7#IBoZpKaEnOcm@f{C+J9%VvYcoL?#UWN551vM2w?Dv{lt{eAzBEM0gr2V1 zN&n!O<$9*9-8JpEhH0!zsr4MF@deV$z2IpW|L=ZlXsg;g+iN+q8@IQH^g~S=MM1qc zf)zDqFt7iO(z5!{$8vlhEUGh!<0C)6=~C0{Q@Bmc)c$iW+Rssu#bk+=15XLss`2~l z8#jRe-z3I}1ejg$dZ6X6))m@j$eg=n+xpe$F`*V2SM8k85p_kdBx0ZA;zN{N3cNZK#kzeI9LNV-|kB&urX4+Xyr-(>@=G;%RYTmr- z*d%6#jxM)aFXe7L-><41kRc~5KNIcjJ}+k>dqBOi5>{45#jI~rV`Y}wu+$46qZ*UZ zMA#ss`5V4|s_bn;V$HqIKa5jNfHjd}+{4=tsEK)1uQi=i+Y-=tq3S2LZOp))AsO#k zVA;b6=i}Hxv@Dih;DQ1NH%z-~SaAn_->ni18zigiTr3ndV7v$? zPpG8oh!}AyDu5XnB&^G&U|q@i)EhbG7+))1*8vOWk6udM`5QFRj^r&K0+n&8Ez#;K zEF9fDY_@lKK(>8zZj%{u{Qmp!64$k)ZDG%j4L0)KYA1v$xEH0;?#no~bkx1RU%khg z8Cd68!=?{SYaf^6&C|_zlYeB@>VK|4=G1jBrPa?DOGO_*M+HOrRT29qd$jH zKMvsB@pwIgr98o@nnTvt3%sB~peRTyAI_;Aa$Gjkv7X5@&QkDI>KI?^6 zd5o<~AVU=V3Zkp*HthkLYu?T1eDe!nxVYUhi#d;eiWgn|{m^tWNCm_BUr3Y3cOH4F ztb9vytzAzHxD?kVv+5PN;eo?}D=(2d)-3$7F9TRgq|NkNnuiVQtbD5I&i`QPL4Ahy z6d37#r4*yl7gOvHrTtur%&p-SN^Q#!)9z>h%By=#`Nd$9!keNRw3=`mUUkK6MpYXm zQTb?@@nL8e&#&?Qb|qg$Y^j9>3Xl||BbiG=uZzuUJ}`Z{fTN@@U32qyAH#L#i} zX2B>Ja1bK7Uso-^A6!2)_e{fA!Ni|x)%(UX^nEM1M4kA^jYjbh(f`|fV&XN3$hzXQx(e?{EJxII$Yu2-_R^Xob6@tvX&ITB#-#wG zZlL&6cVHwx%d>t;(@*D%CcMnDOkbtix&-&V^scGI{JO(BZPpabjk11=YP9yMaN&BXYWxdQcIf;Hc@lRh=PsP%W#gs2ksX5=tPXWZ zt9TkFOH9!cfGZgD0^Inb>?_>nN_pgp+))hm_Zu%#D?U&QW=$Bh_#gn3lIEIji!g!XKCGK**xU_frp-6P){Wp= zzQH&%f$S;1PXKV}$`l3Z^BkfPehUg@u2ziA8b3cDP(mP_$;Fl3Q=ek z#2o$FGZO-m|5J9zj1%$EIOg{=ln5-`fI2KpqosMfMw_lsu^8_VRasR2l!_L!TK-eY zo;cd?Nc5L&NFlV*W@9DUZ}n5l1=ALM<$mjbAa9pnG@qZz?livJEXaQ`Vm9t#?IWwi zhwyXClV3Q%kXQZUsNeu!0%zGp@wpAVXBqQ~+eP!n4OV=I`o7t`TbvwU3PkhVJ9QA@ zsyIo4#yz?~zN}x^j;L&WmW;>jVjmnBcMA#sG(KrT@vN_)aMW1=%6Ifd6o1wjcdF)y zH9qY|wqF^J-Vva&<}axl{Eyhtjy_) z9nGuk%bQOMe4;J*rr!n+6iwY@>U7nztm#v^L)!=4H*@{+m2e@PwsO);6B(~P^}~&W zD^dM)L?lyMGXmP4soG1RfZE8+ga^?^khTxs32N9h;sIAGeB+??4+wjL9_LGYq7a>A zhF82*#3I@&3bX5xUm4jG`-5mOfb@$0NfI0)hZ?u-dTL~euBgVLeP9Ybp#2bXL`&AK z3b81Ty6K{ZLxsF(<^-PTyCH*D>1uiz*IlCHz-v}o+Q|UH#;|DHUy9iz4*I@N+00 zzcXVn?UOE@o+d9OrucN=kZ&qPWzOh0!=eT$0;bA0Z8F)XE7cjGFX$vgME+VAoa|B_ zAtFGzfV4XgKgQmt?}fhZq*|pL>~2zxd6oAmh~lF{S7VoycBqU4f5y_mhL$7x7*=Ew zrx3R0=(}TMY!G*e7UfwJdMpEA-FCt;Py0tS2ry9Mw2VKOM+ioI1_6Y>)_1ZL0iQ

>+t6#_UC`g6i4|S&2wQeo6n}I6 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%0A)t*8rvk|OeMng@$Zs9yAGPkFcH+DavmvB!D* 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

Jj% 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

5D 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


w8<4y7E7Q2FN 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%0A*WFjp}?=78lnWHBZIO3`-Eof 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

FlZ+ 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�Ff`z4%*_+QNJgT_Ww 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

%g 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


T9DTJL+l`MWK% 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 }0OeVF3Vi{^?MxzC=7m#tyn) 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

-X)56q2k@p`dD^T?wQ_^T_WWO>uTSK9 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%0A#ON5r*a3+>EwhLqnRg`0Op?qwJe*& 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≷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

oA(lc^Q{#}<_AXqQ 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%0DcQme?DdY28cEy-Grp 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

;Z*tD)uH@J|0&NxqHc9;M1G!9Nr;Cj6a|H_#SP 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 D+hx0-y<@Q)a$7KN5u3KxTE&BoK!}ktqDX;aO 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�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